def test_create_share__error_on_add_permission( self, add_permission_mock, delete_share): share = {'name': 'share', 'size': 1} add_permission_mock.side_effect = exception.NexentaException( 'An error occurred while adding permission') delete_share.side_effect = exception.NexentaException( 'An error occurred while deleting') self.assertRaises( exception.NexentaException, self.drv.create_share, self.ctx, share)
def test_create_share_from_snapshot__add_permission_error_error( self, add_permission_mock): share = {'name': 'share', 'size': 1} snapshot = {'share_name': 'share', 'name': 'share@first'} add_permission_mock.side_effect = exception.NexentaException( 'Some exception') self.drv.nef.delete.side_effect = exception.NexentaException( 'Some exception 2') self.assertRaises( exception.NexentaException, self.drv.create_share_from_snapshot, self.ctx, share, snapshot)
def test_create_share_from_snapshot__add_permission_error( self, add_permission_mock, delete_share): share = {'name': 'share', 'size': 1} snapshot = {'share_name': 'share', 'name': 'share@first'} delete_share.side_effect = exception.NexentaException( 'An error occurred while deleting') add_permission_mock.side_effect = exception.NexentaException( 'Some exception') self.assertRaises( exception.NexentaException, self.drv.create_share_from_snapshot, self.ctx, share, snapshot)
def test_delete_snapshot(self): self.mock_rpc.side_effect = exception.NexentaException('err', code='ENOENT') snapshot = {'share_name': 'share', 'name': 'share@first'} self.assertIsNone(self.drv.delete_snapshot(self.ctx, snapshot)) self.mock_rpc.side_effect = exception.NexentaException('err', code='somecode') self.assertRaises(exception.NexentaException, self.drv.delete_snapshot, self.ctx, snapshot)
def __init__(self, *args, **kwargs): """Do initialization.""" LOG.debug('Initializing Nexenta driver.') super(NexentaNasDriver, self).__init__((True, False), *args, **kwargs) self.configuration = kwargs.get('configuration') if self.configuration: self.configuration.append_config_values( options.nexenta_connection_opts) self.configuration.append_config_values(options.nexenta_nfs_opts) self.configuration.append_config_values( options.nexenta_dataset_opts) else: raise exception.BadConfigurationException( reason=_('Nexenta configuration missing.')) required_params = ['nas_host', 'user', 'password', 'pool', 'folder'] for param in required_params: if not getattr(self.configuration, 'nexenta_%s' % param): msg = 'Required parameter nexenta_%s is not provided.' % param raise exception.NexentaException(msg) self.nef = None self.verify_ssl = self.configuration.nexenta_ssl_cert_verify self.nef_host = self.configuration.nexenta_rest_address self.nas_host = self.configuration.nexenta_nas_host self.nef_port = self.configuration.nexenta_rest_port self.nef_user = self.configuration.nexenta_user self.nef_password = self.configuration.nexenta_password self.pool_name = self.configuration.nexenta_pool self.parent_fs = self.configuration.nexenta_folder self.nfs_mount_point_base = self.configuration.nexenta_mount_point_base self.dataset_compression = ( self.configuration.nexenta_dataset_compression) self.provisioned_capacity = 0
def storage_protocol(self): protocol = '' if self.configuration.nexenta_nfs: protocol = 'NFS' else: msg = _('At least 1 storage protocol must be enabled.') raise exception.NexentaException(msg) return protocol
def test_delete_share__exists_error(self, post): share = { 'name': 'share', 'size': 1, 'share_proto': self.cfg.enabled_share_protocols } post.return_value = FakeResponse() post.side_effect = exception.NexentaException('does not exist') self.drv.delete_share(self.ctx, share)
def check_error(self, response): code = response.status_code if code not in (200, 201, 202): reason = response.reason content = json.loads( response.content) if response.content else None response.close() if content and 'code' in content: message = content.get( 'message', 'Message is not specified by Nexenta REST') raise exception.NexentaException(reason=message, code=content['code']) raise exception.NexentaException( reason=_('Got bad response: %(code)s %(reason)s %(content)s') % { 'code': code, 'reason': reason, 'content': content })
def manage_existing(self, share, driver_options): """Brings an existing share under Manila management. If the provided share is not valid, then raise a ManageInvalidShare exception, specifying a reason for the failure. If the provided share is not in a state that can be managed, such as being replicated on the backend, the driver *MUST* raise ManageInvalidShare exception with an appropriate message. The share has a share_type, and the driver can inspect that and compare against the properties of the referenced backend share. If they are incompatible, raise a ManageExistingShareTypeMismatch, specifying a reason for the failure. :param share: Share model :param driver_options: Driver-specific options provided by admin. :return: share_update dictionary with required key 'size', which should contain size of the share. """ LOG.debug('Manage share %s.', self._get_share_name(share)) export_path = share['export_locations'][0]['path'] # check that filesystem with provided export exists. fs_path = export_path.split(':/')[1] fs_list = self.nef.filesystems.get(fs_path) if not fs_list: # wrong export path, raise exception. msg = _('Share %s does not exist on Nexenta Store appliance, ' 'cannot manage.') % export_path raise exception.NexentaException(msg) # get dataset properties. fs_data = self.nef.filesystems.get(fs_path) if fs_data['referencedQuotaSize']: size = (fs_data['referencedQuotaSize'] / units.Gi) + 1 else: size = fs_data['bytesReferenced'] / units.Gi + 1 # rename filesystem on appliance to correlate with manila ID. new_path = '%s/%s' % (self.root_path, self._get_share_name(share)) self.nef.filesystems.rename(fs_path, {'newPath': new_path}) # make sure quotas and reservations are correct. if not self.configuration.nexenta_thin_provisioning: self._set_reservation(share, size) self._set_quota(share, size) return { 'size': size, 'export_locations': [{ 'path': '%s:/%s' % (self.nas_host, new_path) }] }
def check_for_setup_error(self): if not self.nms.volume.object_exists(self.volume): raise exception.NexentaException(reason=_( "Volume %s does not exist in NexentaStor appliance.") % self.volume) folder = '%s/%s' % (self.volume, self.share) create_folder_props = { 'recordsize': '4K', 'quota': 'none', 'compression': self.dataset_compression, } if not self.nms.folder.object_exists(folder): self.nms.folder.create_with_props( self.volume, self.share, create_folder_props)
def __call__(self, *args): data = jsonutils.dumps({ 'object': self.obj, 'method': self.method, 'params': args, }) auth = (self.user, self.password) headers = { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' } LOG.debug('Sending JSON data: %s', data) r = requests.post(self.url, data=data, headers=headers, auth=auth) response = json.loads(r.content) if r.content else None LOG.debug('Got response: %s', response) if response.get('error') is not None: message = response['error'].get('message', '') raise exception.NexentaException(reason=message) return response.get('result')
def __call__(self, *args): data = jsonutils.dumps({ 'object': self.obj, 'method': self.method, 'params': args, }) auth = base64.b64encode( ('%s:%s' % (self.user, self.password)).encode('utf-8')) headers = { 'Content-Type': 'application/json', 'Authorization': 'Basic %s' % auth, } LOG.debug('Sending JSON data: %s', data) r = requests.post(self.url, data=data, headers=headers) response = json.loads(r.content) if r.content else None LOG.debug('Got response: %s', response) if response.get('error') is not None: message = response['error'].get('message', '') raise exception.NexentaException(reason=message) return response.get('result')
def test_delete_snapshot__nexenta_error_2(self, post): snapshot = {'share_name': 'share', 'name': 'share@first'} post.return_value = FakeResponse() post.side_effect = exception.NexentaException('has dependent clones') self.drv.delete_snapshot(self.ctx, snapshot)