def test_get_first_or_default(self): disk_a = {'id': 'disk-a', 'type': 'Single', 'size': 5} disk_b = {'id': 'disk-b', 'type': 'Single', 'size': 1} disk_c = {'id': 'disk-c', 'type': 'Mirrored', 'size': 5} disk_d = {'id': 'disk-d', 'type': 'Single', 'size': 10} test_source = [disk_a, disk_b, disk_c, disk_d] first = utils.get_first_or_default(lambda item: item['size'] == 1, test_source, None) self.assertEqual(disk_b, first) default = utils.get_first_or_default(lambda item: item['size'] == 15, test_source, None) self.assertIsNone(default)
def _get_target_domain(self, target, initiator): target_domains = self._api.get_target_domains() target_domain = datacore_utils.get_first_or_default( lambda domain: (domain.InitiatorHostId == initiator.HostId and domain.TargetHostId == target.HostId), target_domains, None) return target_domain
def _create_full_snapshot(self, description, name, pool_names, profile_id, src_virtual_disk): pools = self._get_available_disk_pools(pool_names) destination_pool = datacore_utils.get_first_or_default( lambda pool: (pool.ServerId == src_virtual_disk.FirstHostId or pool.ServerId == src_virtual_disk.SecondHostId), pools, None) if not destination_pool: msg = _("Suitable snapshot destination disk pool not found for " "virtual disk %s.") % src_virtual_disk.Id LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) server = datacore_utils.get_first( lambda srv: srv.Id == destination_pool.ServerId, self._api.get_servers()) if not server.SnapshotMapStorePoolId: self._api.designate_map_store(destination_pool.Id) snapshot = self._api.create_snapshot(src_virtual_disk.Id, name, description, destination_pool.Id, 'Full', False, profile_id) return snapshot
def _get_logical_unit(self, logical_disk, target_device): logical_units = self._api.get_logical_units() logical_unit = datacore_utils.get_first_or_default( lambda unit: (unit.LogicalDiskId == logical_disk.Id and unit. VirtualTargetDeviceId == target_device.Id), logical_units, None) return logical_unit
def _get_target_device(self, target_domain, target, initiator): target_devices = self._api.get_target_devices() target_device = datacore_utils.get_first_or_default( lambda device: (device.TargetDomainId == target_domain.Id and device.InitiatorPortId == initiator.Id and device. TargetPortId == target.Id), target_devices, None) return target_device
def test_get_first_or_default(self): disk_a = {'id': 'disk-a', 'type': 'Single', 'size': 5} disk_b = {'id': 'disk-b', 'type': 'Single', 'size': 1} disk_c = {'id': 'disk-c', 'type': 'Mirrored', 'size': 5} disk_d = {'id': 'disk-d', 'type': 'Single', 'size': 10} test_source = [disk_a, disk_b, disk_c, disk_d] first = utils.get_first_or_default(lambda item: item['size'] == 1, test_source, None) self.assertEqual(disk_b, first) default = utils.get_first_or_default(lambda item: item['size'] == 15, test_source, None) self.assertIsNone(default)
def _get_logical_unit(self, logical_disk, target_device): logical_units = self._api.get_logical_units() logical_unit = datacore_utils.get_first_or_default( lambda unit: (unit.LogicalDiskId == logical_disk.Id and unit.VirtualTargetDeviceId == target_device.Id), logical_units, None) return logical_unit
def _get_target_domain(self, target, initiator): target_domains = self._api.get_target_domains() target_domain = datacore_utils.get_first_or_default( lambda domain: (domain.InitiatorHostId == initiator.HostId and domain.TargetHostId == target.HostId), target_domains, None) return target_domain
def _get_target_device(self, target_domain, target, initiator): target_devices = self._api.get_target_devices() target_device = datacore_utils.get_first_or_default( lambda device: (device.TargetDomainId == target_domain.Id and device.InitiatorPortId == initiator.Id and device.TargetPortId == target.Id), target_devices, None) return target_device
def _get_storage_profile(self, profile_name, raise_not_found=False): profiles = self._api.get_storage_profiles() profile = datacore_utils.get_first_or_default( lambda p: p.Caption.lower() == profile_name.lower(), profiles, None) if not profile and raise_not_found: msg = (_("Specified storage profile %s not found.") % profile_name) LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) return profile
def _get_client(self, name, create_new=False): client_hosts = self._api.get_clients() client = datacore_utils.get_first_or_default( lambda host: host.HostName == name, client_hosts, None) if create_new: if not client: client = self._api.register_client(name, None, 'Other', 'PreferredServer', None) self._api.set_client_capabilities(client.Id, True, True) return client
def _get_client(self, name, create_new=False): client_hosts = self._api.get_clients() client = datacore_utils.get_first_or_default( lambda host: host.HostName == name, client_hosts, None) if create_new: if not client: client = self._api.register_client( name, None, 'Other', 'PreferredServer', None) self._api.set_client_capabilities(client.Id, True, True) return client
def _get_storage_profile(self, profile_name, raise_not_found=False): profiles = self._api.get_storage_profiles() profile = datacore_utils.get_first_or_default( lambda p: p.Caption.lower() == profile_name.lower(), profiles, None) if not profile and raise_not_found: msg = (_("Specified storage profile %s not found.") % profile_name) LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) return profile
def _get_initiator(self, host, iqn, available_ports): client = self._get_client(host, create_new=True) iscsi_initiator_ports = self._get_host_iscsi_initiator_ports( client, available_ports) iscsi_initiator = datacore_utils.get_first_or_default( lambda port: port.PortName == iqn, iscsi_initiator_ports, None) if not iscsi_initiator: scsi_port_data = self._api.build_scsi_port_data( client.Id, iqn, 'Initiator', 'iSCSI') iscsi_initiator = self._api.register_port(scsi_port_data) return iscsi_initiator
def _get_initiator(self, host, iqn, available_ports): client = self._get_client(host, create_new=True) iscsi_initiator_ports = self._get_host_iscsi_initiator_ports( client, available_ports) iscsi_initiator = datacore_utils.get_first_or_default( lambda port: port.PortName == iqn, iscsi_initiator_ports, None) if not iscsi_initiator: scsi_port_data = self._api.build_scsi_port_data( client.Id, iqn, 'Initiator', 'iSCSI') iscsi_initiator = self._api.register_port(scsi_port_data) return iscsi_initiator
def _get_virtual_disk_for(self, obj, raise_not_found=False): disk_id = obj.get('provider_location') virtual_disk = datacore_utils.get_first_or_default( lambda disk: disk.Id == disk_id, self._api.get_virtual_disks(), None) if not virtual_disk: msg = (_("Virtual disk not found for %(object)s %(object_id)s.") % {'object': obj.__class__.__name__.lower(), 'object_id': obj['id']}) if raise_not_found: LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) else: LOG.warning(msg) return virtual_disk
def _get_virtual_disk_for(self, obj, raise_not_found=False): disk_id = obj.get('provider_location') virtual_disk = datacore_utils.get_first_or_default( lambda disk: disk.Id == disk_id, self._api.get_virtual_disks(), None) if not virtual_disk: msg = (_("Virtual disk not found for %(object)s %(object_id)s.") % { 'object': obj.__class__.__name__.lower(), 'object_id': obj['id'] }) if raise_not_found: LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) else: LOG.warning(msg) return virtual_disk
def _check_iscsi_chap_configuration(self, iscsi_chap_enabled, targets): logical_units = self._api.get_logical_units() target_devices = self._api.get_target_devices() for logical_unit in logical_units: target_device_id = logical_unit.VirtualTargetDeviceId target_device = datacore_utils.get_first( lambda device, key=target_device_id: device.Id == key, target_devices) target_port_id = target_device.TargetPortId target = datacore_utils.get_first_or_default( lambda target_port, key=target_port_id: target_port.Id == key, targets, None) if (target and iscsi_chap_enabled == (target.ServerPortProperties.Authentication == 'None')): msg = _("iSCSI CHAP authentication can't be configured for " "target %s. Device exists that served through " "this target.") % target.PortName LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg)
def _create_full_snapshot(self, description, name, pool_names, profile_id, src_virtual_disk): pools = self._get_available_disk_pools(pool_names) destination_pool = datacore_utils.get_first_or_default( lambda pool: (pool.ServerId == src_virtual_disk.FirstHostId or pool .ServerId == src_virtual_disk.SecondHostId), pools, None) if not destination_pool: msg = _("Suitable snapshot destination disk pool not found for " "virtual disk %s.") % src_virtual_disk.Id LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) server = datacore_utils.get_first( lambda srv: srv.Id == destination_pool.ServerId, self._api.get_servers()) if not server.SnapshotMapStorePoolId: self._api.designate_map_store(destination_pool.Id) snapshot = self._api.create_snapshot(src_virtual_disk.Id, name, description, destination_pool.Id, 'Full', False, profile_id) return snapshot
def _setup_iscsi_chap_authentication(self, targets, initiator): iscsi_chap_enabled = self.configuration.datacore_iscsi_chap_enabled self._check_iscsi_chap_configuration(iscsi_chap_enabled, targets) server_group = self._get_our_server_group() update_access_token = False access_token = None chap_secret = None if iscsi_chap_enabled: authentication = 'CHAP' chap_secret = self._password_storage.get_password( server_group.Id, initiator.PortName) update_access_token = False if not chap_secret: chap_secret = volume_utils.generate_password(length=15) self._password_storage.set_password(server_group.Id, initiator.PortName, chap_secret) update_access_token = True access_token = self._api.build_access_token( initiator.PortName, None, None, False, initiator.PortName, chap_secret) else: authentication = 'None' if self._password_storage: self._password_storage.delete_password(server_group.Id, initiator.PortName) changed_targets = {} try: for target in targets: if iscsi_chap_enabled: target_iscsi_nodes = getattr(target.iSCSINodes, 'Node', []) iscsi_node = datacore_utils.get_first_or_default( lambda node: node.Name == initiator.PortName, target_iscsi_nodes, None) if (not iscsi_node or not iscsi_node.AccessToken.TargetUsername or update_access_token): self._api.set_access_token(target.Id, access_token) properties = target.ServerPortProperties if properties.Authentication != authentication: changed_targets[target] = properties.Authentication properties.Authentication = authentication self._api.set_server_port_properties(target.Id, properties) except Exception: with excutils.save_and_reraise_exception(): LOG.exception( "Configuring of iSCSI CHAP authentication for " "initiator %(initiator)s failed.", {'initiator': initiator.PortName}) try: for target in changed_targets: properties = target.ServerPortProperties properties.Authentication = changed_targets[target] self._api.set_server_port_properties( target.Id, properties) except datacore_exception.DataCoreException as e: LOG.warning( "An error occurred on a cleanup after failed " "configuration of iSCSI CHAP authentication " "on initiator %(initiator)s: %(error)s.", { 'initiator': initiator.PortName, 'error': e }) if iscsi_chap_enabled: return initiator.PortName, chap_secret
def _setup_iscsi_chap_authentication(self, targets, initiator): iscsi_chap_enabled = self.configuration.datacore_iscsi_chap_enabled self._check_iscsi_chap_configuration(iscsi_chap_enabled, targets) server_group = self._get_our_server_group() update_access_token = False access_token = None chap_secret = None if iscsi_chap_enabled: authentication = 'CHAP' chap_secret = self._password_storage.get_password( server_group.Id, initiator.PortName) update_access_token = False if not chap_secret: chap_secret = volume_utils.generate_password(length=15) self._password_storage.set_password( server_group.Id, initiator.PortName, chap_secret) update_access_token = True access_token = self._api.build_access_token( initiator.PortName, None, None, False, initiator.PortName, chap_secret) else: authentication = 'None' if self._password_storage: self._password_storage.delete_password(server_group.Id, initiator.PortName) changed_targets = {} try: for target in targets: if iscsi_chap_enabled: target_iscsi_nodes = getattr(target.iSCSINodes, 'Node', []) iscsi_node = datacore_utils.get_first_or_default( lambda node: node.Name == initiator.PortName, target_iscsi_nodes, None) if (not iscsi_node or not iscsi_node.AccessToken.TargetUsername or update_access_token): self._api.set_access_token(target.Id, access_token) properties = target.ServerPortProperties if properties.Authentication != authentication: changed_targets[target] = properties.Authentication properties.Authentication = authentication self._api.set_server_port_properties( target.Id, properties) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Configuring of iSCSI CHAP authentication for " "initiator %(initiator)s failed.", {'initiator': initiator.PortName}) try: for target in changed_targets: properties = target.ServerPortProperties properties.Authentication = changed_targets[target] self._api.set_server_port_properties( target.Id, properties) except datacore_exception.DataCoreException as e: LOG.warning("An error occurred on a cleanup after failed " "configuration of iSCSI CHAP authentication " "on initiator %(initiator)s: %(error)s.", {'initiator': initiator.PortName, 'error': e}) if iscsi_chap_enabled: return initiator.PortName, chap_secret
def _create_volume_from(self, volume, src_obj): src_virtual_disk = self._get_virtual_disk_for(src_obj, raise_not_found=True) if src_virtual_disk.DiskStatus != 'Online': LOG.warning( "Attempting to create a volume from virtual disk " "%(disk)s that is in %(state)s state.", { 'disk': src_virtual_disk.Id, 'state': src_virtual_disk.DiskStatus }) volume_options = self._get_volume_options(volume) profile_id = self._get_storage_profile_id( volume_options[self.DATACORE_STORAGE_PROFILE_KEY]) pool_names = volume_options[self.DATACORE_DISK_POOLS_KEY] volume_virtual_disk = self._create_virtual_disk_copy( src_virtual_disk, volume['id'], volume['display_name'], profile_id=profile_id, pool_names=pool_names) volume_logical_disk = datacore_utils.get_first( lambda disk: disk.VirtualDiskId == volume_virtual_disk.Id, self._api.get_logical_disks()) try: volume_virtual_disk = self._set_virtual_disk_size( volume_virtual_disk, self._get_size_in_bytes(volume['size'])) disk_type = volume_options[self.DATACORE_DISK_TYPE_KEY] if disk_type == self.DATACORE_MIRRORED_DISK: pools = self._get_available_disk_pools(pool_names) selected_pool = datacore_utils.get_first_or_default( lambda pool: (pool.ServerId != volume_logical_disk.ServerHostId and pool .Id != volume_logical_disk.PoolId), pools, None) if selected_pool: logical_disk = self._api.create_pool_logical_disk( selected_pool.Id, 'Striped', volume_virtual_disk.Size.Value) self._api.bind_logical_disk(volume_virtual_disk.Id, logical_disk.Id, 'Second', True, False, True) else: msg = _("Can not create mirrored virtual disk. " "Suitable disk pools not found.") LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) volume_virtual_disk = self._await_virtual_disk_online( volume_virtual_disk.Id) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Creation of volume %(volume)s failed.", {'volume': volume['id']}) try: self._api.delete_virtual_disk(volume_virtual_disk.Id, True) except datacore_exception.DataCoreException as e: LOG.warning( "An error occurred on a cleanup after failed " "creation of volume %(volume)s: %(error)s.", { 'volume': volume['id'], 'error': e }) return {'provider_location': volume_virtual_disk.Id}
def _create_volume_from(self, volume, src_obj): src_virtual_disk = self._get_virtual_disk_for(src_obj, raise_not_found=True) if src_virtual_disk.DiskStatus != 'Online': LOG.warning("Attempting to create a volume from virtual disk " "%(disk)s that is in %(state)s state.", {'disk': src_virtual_disk.Id, 'state': src_virtual_disk.DiskStatus}) volume_options = self._get_volume_options(volume) profile_id = self._get_storage_profile_id( volume_options[self.DATACORE_STORAGE_PROFILE_KEY]) pool_names = volume_options[self.DATACORE_DISK_POOLS_KEY] volume_virtual_disk = self._create_virtual_disk_copy( src_virtual_disk, volume['id'], volume['display_name'], profile_id=profile_id, pool_names=pool_names) volume_logical_disk = datacore_utils.get_first( lambda disk: disk.VirtualDiskId == volume_virtual_disk.Id, self._api.get_logical_disks()) try: volume_virtual_disk = self._set_virtual_disk_size( volume_virtual_disk, self._get_size_in_bytes(volume['size'])) disk_type = volume_options[self.DATACORE_DISK_TYPE_KEY] if disk_type == self.DATACORE_MIRRORED_DISK: pools = self._get_available_disk_pools(pool_names) selected_pool = datacore_utils.get_first_or_default( lambda pool: ( pool.ServerId != volume_logical_disk.ServerHostId and pool.Id != volume_logical_disk.PoolId), pools, None) if selected_pool: logical_disk = self._api.create_pool_logical_disk( selected_pool.Id, 'Striped', volume_virtual_disk.Size.Value) self._api.bind_logical_disk(volume_virtual_disk.Id, logical_disk.Id, 'Second', True, False, True) else: msg = _("Can not create mirrored virtual disk. " "Suitable disk pools not found.") LOG.error(msg) raise cinder_exception.VolumeDriverException(message=msg) volume_virtual_disk = self._await_virtual_disk_online( volume_virtual_disk.Id) except Exception: with excutils.save_and_reraise_exception(): LOG.exception("Creation of volume %(volume)s failed.", {'volume': volume['id']}) try: self._api.delete_virtual_disk(volume_virtual_disk.Id, True) except datacore_exception.DataCoreException as e: LOG.warning("An error occurred on a cleanup after failed " "creation of volume %(volume)s: %(error)s.", {'volume': volume['id'], 'error': e}) return {'provider_location': volume_virtual_disk.Id}