def __init__(self, *args, **kwargs): """ Initializes an AlbaNode, setting up its additional helpers """ DataObject.__init__(self, *args, **kwargs) self._frozen = False self.client = ASDManagerClient(self) self._frozen = True
class AlbaNode(DataObject): """ The AlbaNode contains information about nodes (containing OSDs) """ __properties = [Property('ip', str, doc='IP Address'), Property('port', int, doc='Port'), Property('node_id', str, doc='Alba node_id identifier'), Property('username', str, doc='Username of the AlbaNode'), Property('password', str, doc='Password of the AlbaNode'), Property('type', ['ASD', 'SUPERMICRO'], default='ASD', doc='The type of the AlbaNode')] __relations = [Relation('storagerouter', StorageRouter, 'alba_nodes', mandatory=False, doc='StorageRouter hosting the AlbaNode')] __dynamics = [Dynamic('ips', list, 3600), Dynamic('all_disks', list, 5)] def __init__(self, *args, **kwargs): """ Initializes an AlbaNode, setting up its additional helpers """ DataObject.__init__(self, *args, **kwargs) self._frozen = False self.client = ASDManagerClient(self) self._frozen = True def _ips(self): """ Returns the IPs of the node """ return EtcdConfiguration.get('/ovs/alba/asdnodes/{0}/config/network|ips'.format(self.node_id)) def _all_disks(self): """ Returns a live list of all disks on this node """ try: disks = self.client.get_disks(reraise=True) except (requests.ConnectionError, requests.Timeout): from ovs.dal.lists.albabackendlist import AlbaBackendList disks = [] asd_ids = [] for backend in AlbaBackendList.get_albabackends(): # All backends of this node config = 'etcd://127.0.0.1:2379/ovs/arakoon/{0}-abm/config'.format(backend.name) osds = AlbaCLI.run('list-all-osds', config=config, as_json=True) for osd in osds: node_id = osd.get('node_id') asd_id = osd.get('long_id') decommissioned = osd.get('decommissioned') if node_id == self.node_id and asd_id not in asd_ids and decommissioned is False: asd_ids.append(asd_id) disks.append({'asd_id': asd_id, 'node_id': osd.get('node_id'), 'port': osd.get('port'), 'ips': osd.get('ips'), 'available': False, 'state': {'state': 'error', 'detail': 'nodedown'}, 'log_level': 'info', 'device': asd_id, 'home': asd_id, 'mountpoint': asd_id, 'name': asd_id, 'usage': {'available': 0, 'size': 0, 'used': 0}}) return disks
class AlbaNode(DataObject): """ The AlbaNode contains information about nodes (containing OSDs) """ __properties = [Property('ip', str, unique=True, doc='IP Address'), Property('port', int, doc='Port'), Property('node_id', str, unique=True, doc='Alba node_id identifier'), Property('username', str, doc='Username of the AlbaNode'), Property('password', str, doc='Password of the AlbaNode'), Property('type', ['ASD'], default='ASD', doc='The type of the AlbaNode'), Property('package_information', dict, mandatory=False, default={}, doc='Information about installed packages and potential available new versions')] __relations = [Relation('storagerouter', StorageRouter, 'alba_node', onetoone=True, mandatory=False, doc='StorageRouter hosting the AlbaNode')] __dynamics = [Dynamic('storage_stack', dict, 5), Dynamic('ips', list, 3600)] def __init__(self, *args, **kwargs): """ Initializes an AlbaNode, setting up its additional helpers """ DataObject.__init__(self, *args, **kwargs) self._frozen = False self.client = ASDManagerClient(self) self._frozen = True def _storage_stack(self): """ Returns a live list of all disks known to this AlbaNode """ storage_stack = {'status': 'ok', 'stack': {}} stack = storage_stack['stack'] try: disk_data = self.client.get_disks() except (requests.ConnectionError, requests.Timeout, InvalidCredentialsError): storage_stack['status'] = 'nodedown' disk_data = {} partition_device_map = {} for disk_id, disk_info in disk_data.iteritems(): entry = {'name': disk_id, 'asds': {}} entry.update(disk_info) if disk_info['state'] == 'ok': entry['status'] = 'uninitialized' if disk_info['available'] is True else 'initialized' entry['status_detail'] = '' else: entry['status'] = disk_info['state'] entry['status_detail'] = disk_info.get('state_detail', '') stack[disk_id] = entry if 'partition_aliases' in disk_info: for partition_alias in disk_info['partition_aliases']: partition_device_map[partition_alias] = disk_id else: partition_device_map[disk_id] = disk_id # Model Disk information for disk in self.disks: found = False for disk_id, disk_info in stack.iteritems(): if any(alias in disk.aliases for alias in disk_info['aliases']): found = True if found is False and len(disk.aliases) > 0: disk_id = disk.aliases[0].split('/')[-1] stack[disk_id] = {'available': False, 'name': disk_id, 'asds': {}, 'status': 'error', 'status_detail': 'missing', 'aliases': disk.aliases, 'device': disk.aliases[0], 'partition_aliases': [], 'node_id': self.node_id} # Live ASD information try: asd_data = self.client.get_asds() except (requests.ConnectionError, requests.Timeout, InvalidCredentialsError): storage_stack['status'] = 'nodedown' asd_data = {} for partition_id, asds in asd_data.iteritems(): if partition_id not in partition_device_map: continue disk_id = partition_device_map.get(partition_id) if disk_id is not None and disk_id in stack: for asd_id, asd_info in asds.iteritems(): stack[disk_id]['asds'][asd_id] = {'asd_id': asd_id, 'status': 'error' if asd_info['state'] == 'error' else 'initialized', 'status_detail': asd_info.get('state_detail', ''), 'state': asd_info['state'], 'state_detail': asd_info.get('state_detail', '')} return storage_stack def _ips(self): """ Returns the IPs of the node """ return Configuration.get('/ovs/alba/asdnodes/{0}/config/network|ips'.format(self.node_id))
def test_asd_statistics(self): """ Validates whether the ASD statistics work as expected. * Add keys that were not passed in * Collapse certain keys * Calculate correct per-second, average, total, min and max values """ expected_0 = {'statistics': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'range': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'range_entries': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'multi_get': {'max': 10, 'n_ps': 0, 'min': 1, 'avg': 13, 'n': 5}, 'apply': {'max': 5, 'n_ps': 0, 'min': 5, 'avg': 5, 'n': 1}, 'timestamp': None} expected_1 = {'statistics': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'range': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'range_entries': {'max': 0, 'n_ps': 0, 'min': 0, 'avg': 0, 'n': 0}, 'multi_get': {'max': 10, 'n_ps': 1, 'min': 1, 'avg': 12.5, 'n': 10}, 'apply': {'max': 5, 'n_ps': 0, 'min': 5, 'avg': 5, 'n': 1}, 'timestamp': None} base_time = time.time() backend_type = BackendType() backend_type.code = 'alba' backend_type.name = 'ALBA' backend_type.save() backend = Backend() backend.name = 'foobar' backend.backend_type = backend_type backend.save() alba_backend = AlbaBackend() alba_backend.backend = backend alba_backend.save() alba_node = AlbaNode() alba_node.ip = '127.0.0.1' alba_node.port = 8500 alba_node.username = '******' alba_node.password = '******' alba_node.node_id = 'foobar' alba_node.save() alba_disk = AlbaDisk() alba_disk.name = 'foo' alba_disk.alba_node = alba_node alba_disk.save() asd = AlbaASD() asd.asd_id = 'foo' asd.alba_backend = alba_backend asd.alba_disk = alba_disk asd.save() service_type = ServiceType() service_type.name = 'AlbaManager' service_type.save() service = Service() service.name = 'foobar' service.type = service_type service.ports = [] service.save() abm_service = ABMService() abm_service.service = service abm_service.alba_backend = alba_backend abm_service.save() asdmanager_client = ASDManagerClient('') asdmanager_client._results['get_disks'] = [] AlbaCLI._run_results['asd-multistatistics'] = {'foo': {'success': True, 'result': {'Apply': {'n': 1, 'avg': 5, 'min': 5, 'max': 5}, 'MultiGet': {'n': 2, 'avg': 10, 'min': 5, 'max': 10}, 'MultiGet2': {'n': 3, 'avg': 15, 'min': 1, 'max': 5}}}} statistics = asd._statistics(AlbaASD._dynamics[0]) expected_0['timestamp'] = base_time self.assertDictEqual(statistics, expected_0, 'The first statistics should be as expected: {0} vs {1}'.format(statistics, expected_0)) time.sleep(5) asdmanager_client._results['get_disks'] = [] AlbaCLI._run_results['asd-multistatistics'] = {'foo': {'success': True, 'result': {'Apply': {'n': 1, 'avg': 5, 'min': 5, 'max': 5}, 'MultiGet': {'n': 5, 'avg': 10, 'min': 5, 'max': 10}, 'MultiGet2': {'n': 5, 'avg': 15, 'min': 1, 'max': 5}}}} statistics = asd._statistics(AlbaASD._dynamics[0]) expected_1['timestamp'] = base_time + 5 self.assertDictEqual(statistics, expected_1, 'The second statistics should be as expected: {0} vs {1}'.format(statistics, expected_1))