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
Exemple #3
0
    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)
Exemple #7
0
 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
Exemple #8
0
 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
Exemple #9
0
 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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    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
Exemple #13
0
    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
Exemple #15
0
    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
Exemple #16
0
    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
Exemple #17
0
    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
Exemple #18
0
    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)
Exemple #19
0
    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
Exemple #21
0
    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
Exemple #22
0
    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}
Exemple #23
0
    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}