1
|
|
|
"""Data structures for computer information.""" |
2
|
|
|
|
3
|
1 |
|
import uuid |
4
|
1 |
|
import socket |
5
|
1 |
|
import logging |
6
|
|
|
|
7
|
1 |
|
import yorm |
|
|
|
|
8
|
|
|
|
9
|
1 |
|
from .base import NameMixin |
10
|
|
|
|
11
|
|
|
|
12
|
1 |
|
log = logging.getLogger(__name__) |
13
|
|
|
|
14
|
|
|
|
15
|
1 |
|
@yorm.attr(name=yorm.types.String) |
16
|
1 |
|
@yorm.attr(hostname=yorm.types.String) |
17
|
1 |
|
@yorm.attr(address=yorm.types.String) |
18
|
1 |
|
class Computer(NameMixin, yorm.types.AttributeDictionary): |
19
|
|
|
"""A dictionary of identifying computer information.""" |
20
|
|
|
|
21
|
1 |
|
def __init__(self, name, hostname=None, address=None): |
22
|
1 |
|
super().__init__() |
23
|
1 |
|
self.name = name |
24
|
1 |
|
self.address = address or self.get_address() |
25
|
1 |
|
self.hostname = hostname or self.get_hostname() |
26
|
|
|
|
27
|
1 |
|
@staticmethod |
28
|
1 |
|
def get_address(node=None): |
29
|
|
|
"""Get this computer's MAC address.""" |
30
|
1 |
|
if node is None: |
31
|
1 |
|
node = uuid.getnode() |
32
|
1 |
|
return ':'.join(("%012X" % node)[i:i + 2] for i in range(0, 12, 2)) |
33
|
|
|
|
34
|
1 |
|
@staticmethod |
35
|
|
|
def get_hostname(): |
36
|
|
|
"""Get this computer's hostname.""" |
37
|
1 |
|
return socket.gethostname() |
38
|
|
|
|
39
|
|
|
|
40
|
1 |
|
@yorm.attr(all=Computer) |
|
|
|
|
41
|
1 |
|
class Computers(yorm.types.SortedList): |
42
|
|
|
"""A list of computers.""" |
43
|
|
|
|
44
|
1 |
|
@property |
45
|
|
|
def names(self): |
46
|
|
|
"""Get a list of all computers' labels.""" |
47
|
1 |
|
return [c.name for c in self] |
48
|
|
|
|
49
|
1 |
|
def get(self, name): |
50
|
|
|
"""Get the computer with the given name.""" |
51
|
1 |
|
computer = self.find(name) |
52
|
1 |
|
assert computer, name |
53
|
1 |
|
return computer |
54
|
|
|
|
55
|
1 |
|
def find(self, name): |
56
|
|
|
"""Find the computer with the given name, else None.""" |
57
|
1 |
|
log.debug("Finding computer for '%s'...", name) |
58
|
1 |
|
for computer in self: |
59
|
1 |
|
if computer == name: |
60
|
1 |
|
return computer |
61
|
|
|
|
62
|
1 |
|
def match(self, partial): |
63
|
|
|
"""Find a computer with a similar name.""" |
64
|
1 |
|
log.debug("Finding computer similar to '%s'...", partial) |
65
|
1 |
|
for computer in self: |
66
|
1 |
|
if partial.lower() in computer.name.lower(): |
67
|
1 |
|
return computer |
68
|
|
|
|
69
|
1 |
|
def get_current(self): |
70
|
|
|
"""Get the current computer's information.""" |
71
|
1 |
|
this = Computer(None) |
72
|
|
|
|
73
|
|
|
# Search for a matching address |
74
|
1 |
|
for other in self: |
75
|
1 |
|
if this.address == other.address: |
76
|
1 |
|
other.hostname = this.hostname |
77
|
1 |
|
return other |
78
|
|
|
|
79
|
|
|
# Else, search for a matching hostname |
80
|
1 |
|
for other in self: |
81
|
1 |
|
if this.hostname == other.hostname: |
82
|
1 |
|
other.address = this.address |
83
|
1 |
|
return other |
84
|
|
|
|
85
|
|
|
# Else, this is a new computer |
86
|
1 |
|
this.name = self.generate_name(this) |
87
|
1 |
|
assert this.name != 'localhost' |
88
|
1 |
|
log.debug("New computer: %s", this) |
89
|
1 |
|
self.append(this) |
|
|
|
|
90
|
1 |
|
return this |
91
|
|
|
|
92
|
1 |
|
def generate_name(self, computer): |
93
|
|
|
"""Generate a new label for a computer.""" |
94
|
1 |
|
name = computer.hostname.lower().split('.')[0] |
95
|
1 |
|
copy = 1 |
96
|
1 |
|
while name in self.names: |
97
|
1 |
|
copy += 1 |
98
|
1 |
|
name2 = "{}-{}".format(name, copy) |
99
|
1 |
|
if name2 not in self.names: |
100
|
1 |
|
name = name2 |
101
|
|
|
return name |
102
|
|
|
|
This can be caused by one of the following:
1. Missing Dependencies
This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.
2. Missing __init__.py files
This error could also result from missing
__init__.py
files in your module folders. Make sure that you place one file in each sub-folder.