def test_get_share_type_extra_specs(self): share_type = self.fake_type_w_extra["test_with_extra"] self.mock_object(db, "share_type_get", mock.Mock(return_value=share_type)) id = share_type["id"] extra_spec = share_types.get_share_type_extra_specs(id, key="gold") self.assertEqual(share_type["extra_specs"]["gold"], extra_spec) extra_spec = share_types.get_share_type_extra_specs(id) self.assertEqual(share_type["extra_specs"], extra_spec)
def test_get_share_type_extra_specs(self): share_type = self.fake_type_w_extra['test_with_extra'] self.mock_object(db, 'share_type_get', mock.Mock(return_value=share_type)) id = share_type['id'] extra_spec = share_types.get_share_type_extra_specs(id, key='gold') self.assertEqual(share_type['extra_specs']['gold'], extra_spec) extra_spec = share_types.get_share_type_extra_specs(id) self.assertEqual(share_type['extra_specs'], extra_spec)
def get_share_extra_specs_params(type_id): """Return the parameters for creating the share.""" opts = None if type_id is not None: specs = share_types.get_share_type_extra_specs(type_id) opts = _get_opts_from_specs(specs) LOG.debug('Get share type extra specs: %s', opts) return opts
def manage_existing(self, share, driver_options): """Manage existing share.""" driver_mode = share_types.get_share_type_extra_specs( share['share_type_id'], common_constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS) if strutils.bool_from_string(driver_mode): msg = _("%(mode)s != False") % { 'mode': common_constants.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS } raise exception.ManageExistingShareTypeMismatch(reason=msg) share_proto = share['share_proto'] share_name = share['name'] old_export_location = share['export_locations'][0]['path'] pool_name = share_utils.extract_host(share['host'], level='pool') share_url_type = self.helper._get_share_url_type(share_proto) old_share_name = self.helper._get_share_name_by_export_location( old_export_location, share_proto) share = self.helper._get_share_by_name(old_share_name, share_url_type) if not share: err_msg = (_("Can not get share ID by share %s.") % old_export_location) LOG.error(err_msg) raise exception.InvalidShare(reason=err_msg) fs_id = share['FSID'] fs = self.helper._get_fs_info_by_id(fs_id) if not self.check_fs_status(fs['HEALTHSTATUS'], fs['RUNNINGSTATUS']): raise exception.InvalidShare( reason=(_('Invalid status of filesystem: %(health)s ' '%(running)s.') % {'health': fs['HEALTHSTATUS'], 'running': fs['RUNNINGSTATUS']})) if pool_name and pool_name != fs['POOLNAME']: raise exception.InvalidHost( reason=(_('The current pool(%(fs_pool)s) of filesystem ' 'does not match the input pool(%(host_pool)s).') % {'fs_pool': fs['POOLNAME'], 'host_pool': pool_name})) self.helper._change_fs_name(fs_id, share_name) share_size = int(fs['CAPACITY']) / units.Mi / 2 location = self._get_location_path(share_name, share_proto) return (share_size, [location])
def get_share_extra_specs_params(type_id): specs = {} if type_id: specs = share_types.get_share_type_extra_specs(type_id) opts = _get_opts_from_specs(specs) _get_smartprovisioning_opts(opts) _check_smartcache_opts(opts) _check_smartpartition_opts(opts) _get_qos_opts(opts) LOG.info('Get share type extra specs: %s', opts) return opts
def get_share_privilege(type_id): specs = {} if type_id: specs = share_types.get_share_type_extra_specs(type_id) share_privilege = { 'huawei_share_privilege:sync': _get_string_param, 'huawei_share_privilege:allsquash': _get_string_param, 'huawei_share_privilege:rootsquash': _get_string_param, 'huawei_share_privilege:secure': _get_string_param, } opts = {} for spec_key in specs: key = spec_key.lower() if share_privilege.get(key): opt_key = _get_opt_key(key) opts[opt_key.upper()] = share_privilege[key](key, specs[spec_key]) return opts
def manage_existing(self, share, driver_options): """Manage existing share to manila. Generic driver accepts only one driver_option 'volume_id'. If an administrator provides this option, then appropriate Cinder volume will be managed by Manila as well. :param share: share data :param driver_options: Empty dict or dict with 'volume_id' option. :return: dict with share size, example: {'size': 1} """ if self.driver_handles_share_servers: msg = _('Operation "manage" for shares is supported only when ' 'driver does not handle share servers.') raise exception.InvalidDriverMode(msg) helper = self._get_helper(share) driver_mode = share_types.get_share_type_extra_specs( share['share_type_id'], const.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS) if strutils.bool_from_string(driver_mode): msg = _("%(mode)s != False") % { 'mode': const.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS } raise exception.ManageExistingShareTypeMismatch(reason=msg) share_server = self.service_instance_manager.get_common_server() server_details = share_server['backend_details'] old_export_location = share['export_locations'][0]['path'] mount_path = helper.get_share_path_by_export_location( share_server['backend_details'], old_export_location) LOG.debug("Manage: mount path = %s", mount_path) mounted = self._is_device_mounted(mount_path, server_details) LOG.debug("Manage: is share mounted = %s", mounted) if not mounted: msg = _("Provided share %s is not mounted.") % share['id'] raise exception.ManageInvalidShare(reason=msg) def get_volume(): if 'volume_id' in driver_options: try: return self.volume_api.get( self.admin_context, driver_options['volume_id']) except exception.VolumeNotFound as e: raise exception.ManageInvalidShare(reason=six.text_type(e)) # NOTE(vponomaryov): Manila can only combine volume name by itself, # nowhere to get volume ID from. Return None since Cinder volume # names are not unique or fixed, hence, they can not be used for # sure. return None share_volume = get_volume() if share_volume: instance_volumes = self.compute_api.instance_volumes_list( self.admin_context, server_details['instance_id']) attached_volumes = [vol.id for vol in instance_volumes] LOG.debug('Manage: attached volumes = %s', six.text_type(attached_volumes)) if share_volume['id'] not in attached_volumes: msg = _("Provided volume %s is not attached " "to service instance.") % share_volume['id'] raise exception.ManageInvalidShare(reason=msg) linked_volume_name = self._get_volume_name(share['id']) if share_volume['name'] != linked_volume_name: LOG.debug('Manage: volume_id = %s' % share_volume['id']) self.volume_api.update(self.admin_context, share_volume['id'], {'name': linked_volume_name}) self.private_storage.update( share['id'], {'volume_id': share_volume['id']}) share_size = share_volume['size'] else: share_size = self._get_mounted_share_size( mount_path, share_server['backend_details']) export_locations = helper.get_exports_for_share( server_details, old_export_location) return {'size': share_size, 'export_locations': export_locations}
def manage_existing(self, share, driver_options): """Manage existing share.""" share_proto = share['share_proto'] share_name = share['name'] old_export_location = share['export_locations'][0]['path'] pool_name = share_utils.extract_host(share['host'], level='pool') share_url_type = self.helper._get_share_url_type(share_proto) old_share_name = self.helper._get_share_name_by_export_location( old_export_location, share_proto) share_storage = self.helper._get_share_by_name(old_share_name, share_url_type) if not share_storage: err_msg = (_("Can not get share ID by share %s.") % old_export_location) LOG.error(err_msg) raise exception.InvalidShare(reason=err_msg) fs_id = share_storage['FSID'] fs = self.helper._get_fs_info_by_id(fs_id) if not self.check_fs_status(fs['HEALTHSTATUS'], fs['RUNNINGSTATUS']): raise exception.InvalidShare( reason=(_('Invalid status of filesystem: %(health)s ' '%(running)s.') % {'health': fs['HEALTHSTATUS'], 'running': fs['RUNNINGSTATUS']})) if pool_name and pool_name != fs['POOLNAME']: raise exception.InvalidHost( reason=(_('The current pool(%(fs_pool)s) of filesystem ' 'does not match the input pool(%(host_pool)s).') % {'fs_pool': fs['POOLNAME'], 'host_pool': pool_name})) result = self.helper._find_all_pool_info() poolinfo = self.helper._find_pool_info(pool_name, result) opts = huawei_utils.get_share_extra_specs_params( share['share_type_id']) specs = share_types.get_share_type_extra_specs(share['share_type_id']) if ('capabilities:thin_provisioning' not in specs.keys() and 'thin_provisioning' not in specs.keys()): if fs['ALLOCTYPE'] == constants.ALLOC_TYPE_THIN_FLAG: opts['thin_provisioning'] = constants.THIN_PROVISIONING else: opts['thin_provisioning'] = constants.THICK_PROVISIONING change_opts = self.check_retype_change_opts(opts, poolinfo, fs) LOG.info(_LI('Retyping share (%(share)s), changed options are : ' '(%(change_opts)s).'), {'share': old_share_name, 'change_opts': change_opts}) try: self.retype_share(change_opts, fs_id) except Exception as err: message = (_("Retype share error. Share: %(share)s. " "Reason: %(reason)s.") % {'share': old_share_name, 'reason': err}) raise exception.InvalidShare(reason=message) share_size = int(fs['CAPACITY']) / units.Mi / 2 self.helper._change_fs_name(fs_id, share_name) location = self._get_location_path(share_name, share_proto) return (share_size, [location])
def manage_existing(self, share, driver_options): """Manage existing share to manila. Generic driver accepts only one driver_option 'volume_id'. If an administrator provides this option, then appropriate Cinder volume will be managed by Manila as well. :param share: share data :param driver_options: Empty dict or dict with 'volume_id' option. :return: dict with share size, example: {'size': 1} """ if self.driver_handles_share_servers: msg = _('Operation "manage" for shares is supported only when ' 'driver does not handle share servers.') raise exception.InvalidDriverMode(msg) helper = self._get_helper(share) driver_mode = share_types.get_share_type_extra_specs( share['share_type_id'], const.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS) if strutils.bool_from_string(driver_mode): msg = _("%(mode)s != False") % { 'mode': const.ExtraSpecs.DRIVER_HANDLES_SHARE_SERVERS } raise exception.ManageExistingShareTypeMismatch(reason=msg) share_server = self.service_instance_manager.get_common_server() server_details = share_server['backend_details'] old_export_location = share['export_locations'][0]['path'] mount_path = helper.get_share_path_by_export_location( share_server['backend_details'], old_export_location) LOG.debug("Manage: mount path = %s", mount_path) mounted = self._is_device_mounted(mount_path, server_details) LOG.debug("Manage: is share mounted = %s", mounted) if not mounted: msg = _("Provided share %s is not mounted.") % share['id'] raise exception.ManageInvalidShare(reason=msg) def get_volume(): if 'volume_id' in driver_options: try: return self.volume_api.get(self.admin_context, driver_options['volume_id']) except exception.VolumeNotFound as e: raise exception.ManageInvalidShare(reason=six.text_type(e)) # NOTE(vponomaryov): Manila can only combine volume name by itself, # nowhere to get volume ID from. Return None since Cinder volume # names are not unique or fixed, hence, they can not be used for # sure. return None share_volume = get_volume() if share_volume: instance_volumes = self.compute_api.instance_volumes_list( self.admin_context, server_details['instance_id']) attached_volumes = [vol.id for vol in instance_volumes] LOG.debug('Manage: attached volumes = %s', six.text_type(attached_volumes)) if share_volume['id'] not in attached_volumes: msg = _("Provided volume %s is not attached " "to service instance.") % share_volume['id'] raise exception.ManageInvalidShare(reason=msg) linked_volume_name = self._get_volume_name(share['id']) if share_volume['name'] != linked_volume_name: LOG.debug('Manage: volume_id = %s' % share_volume['id']) self.volume_api.update(self.admin_context, share_volume['id'], {'name': linked_volume_name}) share_size = share_volume['size'] else: share_size = self._get_mounted_share_size( mount_path, share_server['backend_details']) export_locations = helper.get_exports_for_share( server_details, old_export_location) return {'size': share_size, 'export_locations': export_locations}