Modified agent in order to make it more failure tolerant
This commit is contained in:
committed by
default
parent
6ca35fa0c7
commit
8ea9c0c2a0
92
bin/agent
92
bin/agent
@@ -143,51 +143,56 @@ class NodeAgent
|
||||
|
||||
def _detailed
|
||||
detailed_meta = {
|
||||
:System => {
|
||||
:Manufacturer => _manufacturer,
|
||||
:Serial => _serial,
|
||||
:Product => _product_name,
|
||||
:Family => (@os[:dmi][:system][:family] or "Unknown"),
|
||||
:Version => (@os[:dmi][:system][:version] or "Unknown"),
|
||||
:system => {
|
||||
:manufacturer => _manufacturer,
|
||||
:serial => _serial,
|
||||
:product => _product_name,
|
||||
:family => (@os[:dmi][:system][:family] rescue nil),
|
||||
:version => (@os[:dmi][:system][:version] rescue nil),
|
||||
},
|
||||
:Interfaces => [],
|
||||
:Cpu => {
|
||||
:Total => @os[:cpu][:total],
|
||||
:Real => @os[:cpu][:real],
|
||||
:Spec => [],
|
||||
:interfaces => [],
|
||||
:cpu => {
|
||||
:total => (@os[:cpu][:total] rescue nil),
|
||||
:real => (@os[:cpu][:real] rescue nil),
|
||||
:spec => [],
|
||||
},
|
||||
:Disks => [],
|
||||
:Memory => _real_memory,
|
||||
:disks => [],
|
||||
:memory => _real_memory,
|
||||
}
|
||||
@os[:network][:interfaces].each do |int, intinfo|
|
||||
intinfo[:addresses].each do |addr, addrinfo|
|
||||
if addrinfo[:family] =~ /lladdr/
|
||||
detailed_meta[:Interfaces] << {
|
||||
:Name => int,
|
||||
:Mac => addr
|
||||
|
||||
(@os[:network][:interfaces] or {} rescue {}).each do |int, intinfo|
|
||||
(intinfo[:addresses] or {} rescue {}).each do |addr, addrinfo|
|
||||
if (addrinfo[:family] rescue nil) =~ /lladdr/
|
||||
detailed_meta[:interfaces] << {
|
||||
:name => int,
|
||||
:mac => addr
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@os[:cpu].each do |cpu, cpuinfo|
|
||||
if cpu =~ /^[\d]+/
|
||||
detailed_meta[:Cpu][:Spec] << {
|
||||
:Mhz => cpuinfo[:mhz].to_i.to_s,
|
||||
:Model => cpuinfo[:model_name].gsub(/ +/, " ")
|
||||
|
||||
(@os[:cpu] or {} rescue {}).each do |cpu, cpuinfo|
|
||||
if cpu =~ /^[\d]+/ and cpuinfo
|
||||
detailed_meta[:cpu][:spec] << {
|
||||
# .to_i.to_s is applied in order to round to integer
|
||||
:mhz => (cpuinfo[:mhz].to_i.to_s rescue nil),
|
||||
:model => (cpuinfo[:model_name].gsub(/ +/, " ") rescue nil)
|
||||
}
|
||||
end
|
||||
end
|
||||
@os[:block_device].each do |bname, binfo|
|
||||
if bname =~ /^(sd|hd|vd)./
|
||||
block_size = `cat /sys/block/#{bname}/queue/logical_block_size`
|
||||
detailed_meta[:Disks] << {
|
||||
:Name => bname,
|
||||
:Model => binfo[:model],
|
||||
# 512 bytes is the size of one sector by default
|
||||
# 1000000000 bytes is 1 Gb
|
||||
:Size => (binfo[:size].to_i * block_size.to_i).to_s,
|
||||
|
||||
(@os[:block_device] or {} rescue {}).each do |bname, binfo|
|
||||
if bname =~ /^(sd|hd|vd)./ and binfo
|
||||
# 512 bytes is the size of one sector by default
|
||||
block_size = 512
|
||||
block_size = `cat /sys/block/#{bname}/queue/logical_block_size`.to_i if $?.to_i == 0
|
||||
detailed_meta[:disks] << {
|
||||
:name => bname,
|
||||
:model => binfo[:model],
|
||||
:size => (binfo[:size].to_i * block_size).to_s,
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
detailed_meta
|
||||
end
|
||||
@@ -202,38 +207,39 @@ class NodeAgent
|
||||
else
|
||||
# Check in other place for VBox: ohai doesn't show it's virtual with VBox 4.2.4
|
||||
return "VBOX" if @os["dmi"]["system"]["product_name"] == "VirtualBox" rescue nil
|
||||
return @os[:dmi][:system][:manufacturer] rescue "Unknown"
|
||||
return @os[:dmi][:system][:manufacturer] rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
def _product_name
|
||||
if _is_virtual
|
||||
@os["virtualization"]["role"] rescue "Unknown"
|
||||
@os["virtualization"]["role"] rescue nil
|
||||
else
|
||||
@os[:dmi][:system][:product_name] rescue "Unknown"
|
||||
@os[:dmi][:system][:product_name] rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
def _serial
|
||||
@os[:dmi][:system][:serial_number] rescue "Unknown"
|
||||
@os[:dmi][:system][:serial_number] rescue nil
|
||||
end
|
||||
|
||||
def _real_memory
|
||||
dmi = `dmidecode`
|
||||
return nil if $?.to_i != 0
|
||||
mem_mapped = false
|
||||
dmi.each do |line|
|
||||
mem_mapped = true if /^Memory Array Mapped Address$/.match(line)
|
||||
if /^\s*Range Size:\s+(\d+)\s+(mb|gb|kb)/i.match(line) and mem_mapped
|
||||
size, unit = $1, $2
|
||||
size, unit = $1.to_i, $2
|
||||
case unit
|
||||
when /^kb$/i
|
||||
return (size.to_i * 1024).to_s
|
||||
return (size * 1024).to_s
|
||||
when /^mb$/i
|
||||
return (size.to_i * 1048576).to_s
|
||||
return (size * 1048576).to_s
|
||||
when /^gb$/i
|
||||
return (size.to_i * 1073741824).to_s
|
||||
return (size * 1073741824).to_s
|
||||
end
|
||||
mem_mapped = false
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -299,6 +305,8 @@ rescue Exception => e
|
||||
end
|
||||
|
||||
agent = NodeAgent.new(logger, url)
|
||||
puts JSON.pretty_generate agent._detailed
|
||||
exit 0
|
||||
agent.update_state
|
||||
|
||||
post_res = agent.post
|
||||
|
||||
@@ -12,7 +12,7 @@ from nailgun.api.handlers.base import JSONHandler
|
||||
|
||||
|
||||
class NodeHandler(JSONHandler):
|
||||
fields = ('id', 'name', 'info', 'network_data', 'role', 'progress',
|
||||
fields = ('id', 'name', 'meta', 'network_data', 'role', 'progress',
|
||||
'status', 'mac', 'fqdn', 'ip', 'manufacturer', 'platform_name',
|
||||
'pending_addition', 'pending_deletion', 'os_platform',
|
||||
'error_type')
|
||||
@@ -85,13 +85,14 @@ class NodeCollectionHandler(JSONHandler):
|
||||
node.name = "Untitled (%s)" % data['mac'][-5:]
|
||||
orm().add(node)
|
||||
orm().commit()
|
||||
ram = "Unknown"
|
||||
if 'Memory' in node.info and node.info['Memory']:
|
||||
ram = round(int(node.info['Memory']) / 1073741824, 1)
|
||||
cores = node.info.get('Cpu', {}).get('Total', "Unknown")
|
||||
try:
|
||||
ram = round(int(node.meta['memory']) / 1073741824, 1)
|
||||
except (KeyError, TypeError):
|
||||
ram = "unknown"
|
||||
cores = node.meta.get('cpu', {}).get('total', "unknown")
|
||||
notifier.notify("discover",
|
||||
"New node with %s CPU core(s) "
|
||||
"and %s memory is discovered" %
|
||||
"and %s GB memory is discovered" %
|
||||
(cores, ram), node_id=node.id)
|
||||
raise web.webapi.created(json.dumps(
|
||||
NodeHandler.render(node),
|
||||
|
||||
@@ -174,7 +174,7 @@ class Node(Base, BasicValidator):
|
||||
cluster_id = Column(Integer, ForeignKey('clusters.id'))
|
||||
name = Column(Unicode(100))
|
||||
status = Column(Enum(*NODE_STATUSES), nullable=False, default='discover')
|
||||
meta = Column(JSON)
|
||||
meta = Column(JSON, default={})
|
||||
mac = Column(String(17), nullable=False, unique=True)
|
||||
ip = Column(String(15))
|
||||
fqdn = Column(String(255))
|
||||
@@ -211,10 +211,6 @@ class Node(Base, BasicValidator):
|
||||
def needs_redeletion(self):
|
||||
return self.status == 'error' and self.error_type == 'deletion'
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
return self.meta or {}
|
||||
|
||||
@classmethod
|
||||
def validate(cls, data):
|
||||
d = cls.validate_json(data)
|
||||
|
||||
@@ -12,45 +12,45 @@
|
||||
"mac": "C0:8D:DF:52:76:F1",
|
||||
"ip": "10.0.12.45",
|
||||
"meta": {
|
||||
"Interfaces": [
|
||||
{
|
||||
"Mac": "C0:8D:DF:52:76:F1",
|
||||
"Name": "eth0"
|
||||
},
|
||||
{
|
||||
"Mac": "C0:8D:DF:52:76:F2",
|
||||
"Name": "eth1"
|
||||
}
|
||||
],
|
||||
"Cpu": {
|
||||
"Real": 1,
|
||||
"Spec": [
|
||||
{
|
||||
"Mhz": "1200",
|
||||
"Model": "Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz"
|
||||
},
|
||||
{
|
||||
"Mhz": "2101",
|
||||
"Model": "Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz"
|
||||
}
|
||||
],
|
||||
"Total": 2
|
||||
},
|
||||
"Disks": [
|
||||
{
|
||||
"Size": "320072933376",
|
||||
"Model": "TOSHIBA MK3259GS",
|
||||
"Name": "sda"
|
||||
}
|
||||
],
|
||||
"Memory": "8589934592",
|
||||
"System": {
|
||||
"Product": "QWERTY",
|
||||
"Family": "Not Specified",
|
||||
"Manufacturer": "Dell",
|
||||
"Serial": "123456",
|
||||
"Version": "Not Specified"
|
||||
"disks": [
|
||||
{
|
||||
"size": "320072933376",
|
||||
"model": "TOSHIBA MK3259GS",
|
||||
"name": "sda"
|
||||
}
|
||||
],
|
||||
"interfaces": [
|
||||
{
|
||||
"mac": "52:54:00:96:81:6E",
|
||||
"name": "eth0"
|
||||
},
|
||||
{
|
||||
"mac": "C8:0A:A9:A6:FF:28",
|
||||
"name": "eth1"
|
||||
}
|
||||
],
|
||||
"cpu": {
|
||||
"total": 2,
|
||||
"real": 1,
|
||||
"spec": [
|
||||
{
|
||||
"mhz": "1200",
|
||||
"model": "Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz"
|
||||
},
|
||||
{
|
||||
"mhz": "1200",
|
||||
"model": "Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz"
|
||||
}
|
||||
]
|
||||
},
|
||||
"memory": 8589934592,
|
||||
"system": {
|
||||
"version": "Power Edge 2970",
|
||||
"manufacturer": "Dell",
|
||||
"product": "QWERTY",
|
||||
"serial": "123456",
|
||||
"family": "Power Edge"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -159,8 +159,8 @@ class FakeDeletionThread(FakeThread):
|
||||
for node in nodes_to_restore:
|
||||
orm.add(node)
|
||||
orm.commit()
|
||||
ram = round(node.info.get('ram') or 0, 1)
|
||||
cores = node.info.get('cores') or 'unknown'
|
||||
ram = round(node.meta.get('ram') or 0, 1)
|
||||
cores = node.meta.get('cores') or 'unknown'
|
||||
notifier.notify("discover",
|
||||
"New node with %s CPU core(s) "
|
||||
"and %s GB memory is discovered" %
|
||||
|
||||
@@ -48,60 +48,56 @@ class BaseHandlers(TestCase):
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
flush()
|
||||
for fxtr in self.fixtures:
|
||||
self.upload_fixtures(self.fixtures)
|
||||
|
||||
def fxtr_paths_by_names(self, fxtr_names):
|
||||
for fxtr in fxtr_names:
|
||||
fxtr_path = os.path.join(
|
||||
self.fixture_dir,
|
||||
"%s.json" % fxtr
|
||||
)
|
||||
|
||||
if not os.path.exists(fxtr_path):
|
||||
logging.warning(
|
||||
"Fixture file not found: %s",
|
||||
"Fixture file was not found: %s",
|
||||
fxtr_path
|
||||
)
|
||||
break
|
||||
else:
|
||||
logging.info(
|
||||
"Uploading fixture from file: %s",
|
||||
logging.debug(
|
||||
"Fixture file is found, yielding path: %s",
|
||||
fxtr_path
|
||||
)
|
||||
with open(fxtr_path, "r") as fixture:
|
||||
upload_fixture(fixture)
|
||||
yield fxtr_path
|
||||
|
||||
def upload_fixtures(self, fxtr_names):
|
||||
for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
|
||||
with open(fxtr_path, "r") as fxtr_file:
|
||||
upload_fixture(fxtr_file)
|
||||
|
||||
def read_fixtures(self, fxtr_names):
|
||||
data = []
|
||||
for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
|
||||
with open(fxtr_path, "r") as fxtr_file:
|
||||
try:
|
||||
data.extend(json.load(fxtr_file))
|
||||
except:
|
||||
logging.error(
|
||||
"Error occured while loading "
|
||||
"fixture %s" % fxtr_path
|
||||
)
|
||||
return data
|
||||
|
||||
def find_item_by_pk_model(self, data, pk, model):
|
||||
for item in data:
|
||||
if item.get('pk') == pk and item.get('model') == model:
|
||||
return item
|
||||
|
||||
def default_metadata(self):
|
||||
metadata = {
|
||||
"Interfaces": [
|
||||
{
|
||||
"Mac": "C0:8D:DF:52:76:F1",
|
||||
"Name": "eth0"
|
||||
}
|
||||
],
|
||||
"Cpu": {
|
||||
"Real": 1,
|
||||
"Spec": [
|
||||
{
|
||||
"Mhz": "1200",
|
||||
"Model": "Intel(R) Core(TM)2 Duo CPU T6570 @ 2.10GHz"
|
||||
}
|
||||
],
|
||||
"Total": 1
|
||||
},
|
||||
"Disks": [
|
||||
{
|
||||
"Size": "320072933376",
|
||||
"Model": "TOSHIBA MK3259GS",
|
||||
"Name": "sda"
|
||||
}
|
||||
],
|
||||
"Memory": "8589934592",
|
||||
"System": {
|
||||
"Product": "QWERTY",
|
||||
"Family": "Not Specified",
|
||||
"Manufacturer": "Dell",
|
||||
"Serial": "123456",
|
||||
"Version": "Not Specified"
|
||||
}
|
||||
}
|
||||
return metadata
|
||||
item = self.find_item_by_pk_model(
|
||||
self.read_fixtures(("sample_environment",)),
|
||||
1, 'nailgun.node')
|
||||
return item.get('fields').get('meta')
|
||||
|
||||
def _generate_random_mac(self):
|
||||
mac = [randint(0x00, 0x7f) for _ in xrange(6)]
|
||||
|
||||
@@ -27,11 +27,11 @@ class TestHandlers(BaseHandlers):
|
||||
node.pending_deletion, response['pending_deletion'])
|
||||
self.assertEquals(node.status, response['status'])
|
||||
self.assertEquals(
|
||||
node.info['Cpu']['Total'],
|
||||
response['info']['Cpu']['Total']
|
||||
node.meta['cpu']['total'],
|
||||
response['meta']['cpu']['total']
|
||||
)
|
||||
self.assertEquals(node.info['Disks'], response['info']['Disks'])
|
||||
self.assertEquals(node.info['Memory'], response['info']['Memory'])
|
||||
self.assertEquals(node.meta['disks'], response['meta']['disks'])
|
||||
self.assertEquals(node.meta['memory'], response['meta']['memory'])
|
||||
|
||||
def test_node_creation_with_id(self):
|
||||
node_id = '080000000003'
|
||||
|
||||
Reference in New Issue
Block a user