Skip to content

Commit

Permalink
Merge pull request #915 from andrzej-jankowski/shares_detection_fix
Browse files Browse the repository at this point in the history
Scan - shares detection
  • Loading branch information
xor-xor committed Jun 9, 2014
2 parents bd521c2 + 64e17a5 commit f48aea4
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 30 deletions.
31 changes: 24 additions & 7 deletions src/ralph/discovery/hardware.py
Expand Up @@ -217,7 +217,7 @@ def handle_smbios(dev, smbios, is_virtual=False, priority=0):
cpu.save(priority=priority)


def get_disk_shares(ssh):
def get_disk_shares(ssh, include_logical_volumes=False):
stdin, stdout, stderr = ssh.exec_command("multipath -l")
pvs = {}
for line in stdout.readlines():
Expand All @@ -238,27 +238,44 @@ def get_disk_shares(ssh):
if '(' not in wwn:
wwn, pv, model = line.strip().split(None, 2)
path = None
wwn = normalize_wwn(wwn.strip('()'))
wwn = wwn.strip('()')
if not path:
path = wwn
wwn = normalize_wwn(wwn)
pvs['/dev/%s' % pv] = wwn
if path:
pvs['/dev/mapper/%s' % path] = wwn
stdin, stdout, stderr = ssh.exec_command(
"pvs --noheadings --units M --separator '|'")
"pvs --noheadings --units M --separator '|'"
)
vgs = {}
for line in stdout.readlines():
pv, vg, rest = line.split('|', 2)
pv, vg, fmt, attr, size, rest = line.split('|', 5)
pv = pv.strip()
vg = vg.strip()
mount_size = int(float(size.strip('M')))
if not vg:
continue
vgs[vg] = pv
stdin, stdout, stderr = ssh.exec_command("lvs --noheadings --units M")
try:
wwn = pvs[pv]
except KeyError:
continue
vgs[vg] = {
'wwn': wwn,
'mount_size': mount_size,
'pv': pv,
}
storage = {}
if not include_logical_volumes:
for vg, mount_data in vgs.iteritems():
storage[vg] = (mount_data['wwn'], mount_data['mount_size'])
return storage
stdin, stdout, stderr = ssh.exec_command("lvs --noheadings --units M")
for line in stdout.readlines():
lv, vg, attr, size, rest = (line + ' x').strip().split(None, 4)
size = int(float(size.strip('M')))
try:
wwn = pvs[vgs[vg]]
wwn = pvs[vgs[vg]['pv']]
except KeyError:
continue
storage[lv] = (wwn, size)
Expand Down
3 changes: 1 addition & 2 deletions src/ralph/discovery/tests/plugins/test_ssh_linux.py
Expand Up @@ -154,6 +154,5 @@ def test_os_disk_share(self):
LogVol01 VolGroup00 -wi-ao 2080.37M"""), ])
storage = hardware.get_disk_shares(ssh)
self.assertEqual(storage, {
'LogVol01': (u'50002AC000660910', 2080),
'LogVol00': (u'50002AC000660910', 144552)
'VolGroup00': (u'50002AC000660910', 146632)
})
2 changes: 1 addition & 1 deletion src/ralph/discovery/tests/plugins/test_xen.py
Expand Up @@ -215,7 +215,7 @@ def test_xen_shares(self):
060d5424-b9f1-ad56-629b-10c0c4e2cfa5 XSLocalEXT-060d5424-b9f1-ad56-629b-10c0c4e2cfa5 -wi-ao 128.68M
"""),
])
shares = hardware.get_disk_shares(ssh)
shares = hardware.get_disk_shares(ssh, include_logical_volumes=True)
self.maxDiff = None
self.assertEqual(shares, {
'MGT': ('600144F008BF8A000000500CFFF20003', 4),
Expand Down
39 changes: 30 additions & 9 deletions src/ralph/scan/data.py
Expand Up @@ -47,7 +47,7 @@
'fibrechannel_cards': [('physical_id', 'device')],
'parts': [('serial_number',)],
'disk_exports': [('serial_number',)],
'disk_shares': [('device', 'share')],
'disk_shares': [('device', 'serial_number')],
'installed_software': [('device', 'path')],
}
SAVE_PRIORITY = 215
Expand Down Expand Up @@ -410,7 +410,7 @@ def get_device_data(device):
return data


def set_device_data(device, data, save_priority=SAVE_PRIORITY):
def set_device_data(device, data, save_priority=SAVE_PRIORITY, warnings=[]):
"""
Go through the submitted data, and update the Device object
in accordance with the meaning of the particular fields.
Expand Down Expand Up @@ -612,6 +612,7 @@ def set_device_data(device, data, save_priority=SAVE_PRIORITY):
save_priority=save_priority,
)
if 'disk_shares' in data:
shares = []
for share in data['disk_shares']:
if share.get('server'):
servers = find_devices({
Expand All @@ -628,16 +629,31 @@ def set_device_data(device, data, save_priority=SAVE_PRIORITY):
share['server'] = servers[0]
else:
share['server'] = None
share['share'] = DiskShare.objects.get(wwn=share['serial_number'])
if share.get('address'):
share['address'] = IPAddress.objects.get(
address=share['address'],
try:
share['share'] = DiskShare.objects.get(
wwn=share['serial_number']
)
except DiskShare.DoesNotExist:
warnings.append(
'No share found for share mount: %r' % share
)
continue
if share.get('address'):
try:
share['address'] = IPAddress.objects.get(
address=share['address'],
)
except IPAddress.DoesNotExist:
warnings.append(
'No IP address found for share mount: %r' % share
)
continue
elif 'address' in share:
del share['address']
shares.append(share)
_update_component_data(
device,
data['disk_shares'],
shares,
DiskShareMount,
{
'share': 'share',
Expand Down Expand Up @@ -705,6 +721,7 @@ def set_device_data(device, data, save_priority=SAVE_PRIORITY):
subdevice = device_from_data(
subdevice_data,
save_priority=save_priority,
warnings=warnings
)
if (
device.model and
Expand All @@ -731,7 +748,9 @@ def set_device_data(device, data, save_priority=SAVE_PRIORITY):
assign_asset(device.id, asset_id)


def device_from_data(data, save_priority=SAVE_PRIORITY, user=None):
def device_from_data(
data, save_priority=SAVE_PRIORITY, user=None, warnings=[]
):
"""
Create or find a device based on the provided scan data.
"""
Expand All @@ -749,7 +768,9 @@ def device_from_data(data, save_priority=SAVE_PRIORITY, user=None):
model_name=model_name,
model_type=model_type,
)
set_device_data(device, data, save_priority=save_priority)
set_device_data(
device, data, save_priority=save_priority, warnings=warnings
)
device.save(priority=save_priority, user=user)
return device

Expand Down
2 changes: 1 addition & 1 deletion src/ralph/scan/plugins/ssh_proxmox.py
Expand Up @@ -218,7 +218,7 @@ def _get_virtual_machine_info(

def _get_virtual_machines(ssh, master_ip_address, hypervisor_ip_address):
detected_machines = []
storages = get_disk_shares(ssh)
storages = get_disk_shares(ssh, include_logical_volumes=True)
stdin, stdout, stderr = ssh.exec_command("qm list")
for line in stdout:
line = line.strip()
Expand Down
4 changes: 2 additions & 2 deletions src/ralph/scan/plugins/ssh_xen.py
Expand Up @@ -190,7 +190,7 @@ def _ssh_xen(ssh, ip_address):
vms = _get_running_vms(ssh, uuid, sudo_mode)
macs = _get_macs(ssh, sudo_mode)
disks = _get_disks(ssh, sudo_mode)
shares = get_disk_shares(ssh)
shares = get_disk_shares(ssh, include_logical_volumes=True)
device_info = {
'subdevices': [],
'type': DeviceType.unknown.raw,
Expand Down Expand Up @@ -224,7 +224,7 @@ def _ssh_xen(ssh, ip_address):
]
vm_disks = disks.get(vm_name, [])
for uuid, sr_uuid, size, device in vm_disks:
wwn, mount_size = shares.get('VHD-%s' % sr_uuid, (None, None))
wwn, mount_size = shares.get('VHD-%s' % uuid, (None, None))
if wwn:
share = {
'serial_number': wwn,
Expand Down
9 changes: 2 additions & 7 deletions src/ralph/scan/tests/plugins/test_ssh_linux.py
Expand Up @@ -197,13 +197,8 @@ def test_get_disk_shares(self):
[
{
'serial_number': '50002AC000660910',
'size': 2080,
'volume': 'LogVol01',
},
{
'serial_number': '50002AC000660910',
'size': 144552,
'volume': 'LogVol00',
'size': 146632,
'volume': 'VolGroup00',
},
],
)
9 changes: 8 additions & 1 deletion src/ralph/ui/views/common.py
Expand Up @@ -1731,14 +1731,16 @@ def post(self, *args, **kwargs):
field_name: form.get_value(field_name)
for field_name in form.result
}
warnings = []
try:
if device is None:
device = device_from_data(
data=data,
user=self.request.user,
warnings=warnings
)
else:
set_device_data(device, data)
set_device_data(device, data, warnings=warnings)
device.save(
priority=SAVE_PRIORITY,
user=self.request.user,
Expand All @@ -1751,6 +1753,11 @@ def post(self, *args, **kwargs):
self.request,
"Device %s saved." % device,
)
for warning in warnings:
messages.warning(
self.request,
warning
)
return HttpResponseRedirect(self.request.path)
else:
messages.error(self.request, "Errors in the form.")
Expand Down
2 changes: 2 additions & 0 deletions src/ralph/util/pricing.py
Expand Up @@ -487,6 +487,8 @@ def details_disk(dev, purchase_only=False):
mount.share.label, total, mount.share.size)
else:
name = '%s (%d MiB)' % (mount.share.label, mount.share.size)
if mount.is_virtual:
name = '[Virtual Mount] %s' % name
yield {
'label': name,
'model': mount.share.model,
Expand Down

0 comments on commit f48aea4

Please sign in to comment.