Beispiel #1
0
 def _validate_required_keys(section):
     for required_key in ['host', 'backend']:
         if required_key not in call_parameters[section]:
             raise HttpNotAcceptableException(error_description='Invalid data passed: "{0}" misses information about {1}'.format(section, required_key),
                                              error='invalid_data')
     for sub_required_key in ['backend', 'metadata']:
         if sub_required_key not in call_parameters[section]['backend']:
             raise HttpNotAcceptableException(error_description='Invalid data passed: "{0}" missing information about {1}'.format(section, sub_required_key),
                                              error='invalid_data')
Beispiel #2
0
 def delete_vtemplate(self, vdisk):
     """
     Deletes a vDisk (template)
     :param vdisk: the vDisk (template) to delete
     :type vdisk: VDisk
     """
     if not vdisk.is_vtemplate:
         raise HttpNotAcceptableException(
             error_description='vDisk should be a vTemplate',
             error='impossible_request')
     if len(vdisk.child_vdisks) > 0:
         raise HttpNotAcceptableException(
             error_description='vTemplate has clones',
             error='impossible_request')
     return VDiskController.delete.delay(vdisk_guid=vdisk.guid)
Beispiel #3
0
    def devicename_exists(self, vpool, name=None, names=None):
        """
        Checks whether a given name can be created on the vpool
        :param vpool: vPool object
        :type vpool: VPool
        :param name: Candidate name
        :type name: str
        :param names: Candidate names
        :type names: list
        :return: Whether the devicename exists
        :rtype: bool
        """
        error_message = None
        if not (name is None) ^ (names is None):
            error_message = 'Either the name (string) or the names (list of strings) parameter must be passed'
        if name is not None and not isinstance(name, basestring):
            error_message = 'The name parameter must be a string'
        if names is not None and not isinstance(names, list):
            error_message = 'The names parameter must be a list of strings'
        if error_message is not None:
            raise HttpNotAcceptableException(error_description=error_message,
                                             error='impossible_request')

        if name is not None:
            devicename = VDiskController.clean_devicename(name)
            return VDiskList.get_by_devicename_and_vpool(devicename,
                                                         vpool) is not None
        for name in names:
            devicename = VDiskController.clean_devicename(name)
            if VDiskList.get_by_devicename_and_vpool(devicename,
                                                     vpool) is not None:
                return True
        return False
Beispiel #4
0
    def set_config_params(self, vdisk, new_config_params, version):
        """
        Sets configuration parameters to a given vdisk.
        :param vdisk: Guid of the virtual disk to configure
        :type vdisk: VDisk
        :param new_config_params: Configuration settings for the virtual disk
        :type new_config_params: dict
        :param version: Client version
        :type version: int
        """
        if version == 1 and 'dtl_target' in new_config_params:
            storage_router = StorageRouterList.get_by_ip(
                new_config_params['dtl_target'])
            if storage_router is None:
                raise HttpNotAcceptableException(
                    error_description=
                    'API version 1 requires a Storage Router IP',
                    error='invalid_version')
            new_config_params['dtl_target'] = [
                junction.domain_guid for junction in storage_router.domains
            ]

        new_config_params.pop('dedupe_mode', None)
        new_config_params.pop('cache_strategy', None)
        new_config_params.pop('readcache_limit', None)
        return VDiskController.set_config_params.delay(
            vdisk_guid=vdisk.guid, new_config_params=new_config_params)
Beispiel #5
0
 def create(self, name, size, vpool_guid, storagerouter_guid, pagecache_ratio=1.0, cache_quota=None):
     """
     Create a new vdisk
     :param name: Name of the new vdisk
     :type name: str
     :param size: Size of  virtual disk in bytes
     :type size: int
     :param vpool_guid: Guid of vPool to create new vdisk on
     :type vpool_guid: str
     :param storagerouter_guid: Guid of the storagerouter to assign disk to
     :type storagerouter_guid: str
     :param pagecache_ratio: Ratio (0 < x <= 1) of the pagecache size related to the size
     :type pagecache_ratio: float
     :param cache_quota: Maximum caching space(s) the new volume can consume (in Bytes) per cache type.
     :type cache_quota: dict
     :return: Asynchronous result of a CeleryTask
     :rtype: celery.result.AsyncResult
     """
     storagerouter = StorageRouter(storagerouter_guid)
     for storagedriver in storagerouter.storagedrivers:
         if storagedriver.vpool_guid == vpool_guid:
             return VDiskController.create_new.delay(volume_name=name,
                                                     volume_size=size,
                                                     storagedriver_guid=storagedriver.guid,
                                                     pagecache_ratio=pagecache_ratio,
                                                     cache_quota=cache_quota)
     raise HttpNotAcceptableException(error_description='No storagedriver found for vPool: {0} and StorageRouter: {1}'.format(vpool_guid, storagerouter_guid),
                                      error='impossible_request')
Beispiel #6
0
 def delete(self, vdisk):
     """
     Delete a given vDisk
     :param vdisk: The vDisk to delete
     :type vdisk: VDisk
     """
     if len(vdisk.child_vdisks) > 0:
         raise HttpNotAcceptableException(
             error_description='vDisk has clones',
             error='impossible_request')
     return VDiskController.delete.delay(vdisk_guid=vdisk.guid)
Beispiel #7
0
 def set_as_template(self, vdisk):
     """
     Sets a vDisk as template
     :param vdisk: Guid of the virtual disk to set as template
     :type vdisk: VDisk
     """
     if len(vdisk.child_vdisks) > 0:
         raise HttpNotAcceptableException(
             error_description='vDisk has clones',
             error='impossible_request')
     return VDiskController.set_as_template.delay(vdisk_guid=vdisk.guid)
Beispiel #8
0
 def destroy(self, domain):
     """
     Deletes a Domain
     :param domain: The domain to return
     :type domain: Domain
     :return: None
     :rtype: None
     """
     if len(domain.storagerouters) > 0 or len(domain.backends) > 0 or len(domain.vdisks_dtl) > 0:
         raise HttpNotAcceptableException(error_description='The given Domain is still in use',
                                          error='in_use')
     domain.delete()
Beispiel #9
0
 def create(self, request):
     """
     Creates a Backend
     :param request: The raw request
     :type request: Request
     """
     serializer = FullSerializer(Backend, instance=Backend(), data=request.DATA)
     backend = serializer.deserialize()
     duplicate = BackendList.get_by_name(backend.name)
     if duplicate is None:
         backend.save()
         return backend
     raise HttpNotAcceptableException(error_description='Backend with this name already exists',
                                      error='duplicate')
Beispiel #10
0
 def can_be_deleted(self, storagedriver, version):
     """
     Checks whether a Storage Driver can be deleted
     :param storagedriver: StorageDriver to verify
     :type storagedriver: StorageDriver
     :param version: Client version
     :type version: int
     :return: Whether the StorageDriver can be deleted
     :rtype: bool
     """
     if version > 4:
         raise HttpNotAcceptableException(
             error_description='Only available in API versions 1 to 4',
             error='invalid_version')
     return not any(
         vdisk for vdisk in storagedriver.vpool.vdisks
         if vdisk.storagedriver_id == storagedriver.storagedriver_id)
Beispiel #11
0
 def create(self, request, contents=None):
     """
     Creates a new Domain
     :param request: The raw request:
     :type request: Request
     :param contents: Requested contents (serializer hint)
     :type contents: str
     """
     contents = None if contents is None else contents.split(',')
     serializer = FullSerializer(Domain, contents=contents, instance=Domain(), data=request.DATA)
     domain = serializer.deserialize()
     current_domains = DomainList.get_by_name(domain.name)
     if len(current_domains) > 0:
         raise HttpNotAcceptableException(error_description='A Domain with the given name already exists',
                                          error='duplicate')
     domain.save()
     return domain
Beispiel #12
0
 def shrink_vpool(self, vpool, storagerouter_guid):
     """
     Remove the storagedriver linking the specified vPool and storagerouter_guid
     :param vpool: vPool to shrink (or delete if its the last storagerouter linked to it)
     :type vpool: VPool
     :param storagerouter_guid: Guid of the Storage Router
     :type storagerouter_guid: str
     """
     sr = StorageRouter(storagerouter_guid)
     intersection = set(vpool.storagedrivers_guids).intersection(
         set(sr.storagedrivers_guids))
     if not intersection:
         raise HttpNotAcceptableException(
             error_description=
             'Storage Router {0} is not a member of vPool {1}'.format(
                 sr.name, vpool.name),
             error='impossible_request')
     return StorageRouterController.remove_storagedriver.delay(
         list(intersection)[0])
Beispiel #13
0
 def scrub_multiple_vdisks(self, vpool, vdisk_guids=None):
     """
     Scrubs the specified vDisks or all vDisks of the vPool is no guids are passed in
     :param vpool: The vPool to which the vDisks belong to scrub
     :type vpool: ovs.dal.hybrids.vpool.VPool
     :param vdisk_guids: The guids of the vDisks to scrub
     :type vdisk_guids: list
     :return: Asynchronous result of a CeleryTask
     :rtype: celery.result.AsyncResult
     """
     if vdisk_guids is None:
         vdisk_guids = []
     if set(vdisk_guids).difference(set(vpool.vdisks_guids)):
         raise HttpNotAcceptableException(
             error_description=
             'Some of the vDisks specified do not belong to this vPool',
             error='invalid_data')
     return GenericController.execute_scrub.delay(
         vdisk_guids=vdisk_guids or vpool.vdisks_guids)
Beispiel #14
0
 def create(self, request, role_guids=None):
     """
     Creates a Client
     :param request: Raw request
     :type request: Request
     :param role_guids: The GUIDs of the roles where the client should get access to
     :type role_guids: str
     """
     if 'role_guids' in request.DATA:
         del request.DATA['role_guids']
     serializer = FullSerializer(Client,
                                 instance=Client(),
                                 data=request.DATA)
     client = serializer.deserialize()
     if client.user is not None:
         if client.user_guid == request.client.user_guid or Toolbox.is_client_in_roles(
                 request.client, ['manage']):
             client.grant_type = 'CLIENT_CREDENTIALS'
             client.client_secret = OAuth2Toolbox.create_hash(64)
             client.save()
             if not role_guids:
                 roles = [
                     junction.role for junction in client.user.group.roles
                 ]
             else:
                 possible_role_guids = [
                     junction.role_guid
                     for junction in client.user.group.roles
                 ]
                 roles = [
                     Role(guid) for guid in role_guids
                     if guid in possible_role_guids
                 ]
             for role in roles:
                 roleclient = RoleClient()
                 roleclient.client = client
                 roleclient.role = role
                 roleclient.save()
             return client
     raise HttpNotAcceptableException(
         error_description='A client must have a user',
         error='invalid_data')
Beispiel #15
0
 def shrink_vpool(self, vpool, storagerouter_guid):
     """
     Remove the storagedriver linking the specified vPool and storagerouter_guid
     :param vpool: vPool to shrink (or delete if its the last storagerouter linked to it)
     :type vpool: VPool
     :param storagerouter_guid: Guid of the Storage Router
     :type storagerouter_guid: str
     """
     sr = StorageRouter(storagerouter_guid)
     sd_guid = None
     sd_guids = [
         storagedriver.guid for storagedriver in vpool.storagedrivers
     ]
     for storagedriver in sr.storagedrivers:
         if storagedriver.guid in sd_guids:
             sd_guid = storagedriver.guid
             break
     if sd_guid is None:
         raise HttpNotAcceptableException(
             error_description=
             'Storage Router {0} is not a member of vPool {1}'.format(
                 sr.name, vpool.name),
             error='impossible_request')
     return StorageRouterController.remove_storagedriver.delay(sd_guid)
Beispiel #16
0
 def create(self, name, size, vpool_guid, storagerouter_guid):
     """
     Create a new vdisk
     :param name: Name of the new vdisk
     :type name: str
     :param size: Size of  virtual disk in bytes
     :type size: int
     :param vpool_guid: Guid of vPool to create new vdisk on
     :type vpool_guid: str
     :param storagerouter_guid: Guid of the storagerouter to assign disk to
     :type storagerouter_guid: str
     """
     storagerouter = StorageRouter(storagerouter_guid)
     for storagedriver in storagerouter.storagedrivers:
         if storagedriver.vpool_guid == vpool_guid:
             return VDiskController.create_new.delay(
                 volume_name=name,
                 volume_size=size,
                 storagedriver_guid=storagedriver.guid)
     raise HttpNotAcceptableException(
         error_description=
         'No storagedriver found for vPool: {0} and StorageRouter: {1}'.
         format(vpool_guid, storagerouter_guid),
         error='impossible_request')
Beispiel #17
0
 def create(self, request):
     """
     Creates a User
     :param request: The raw request
     :type request: Request
     """
     serializer = FullSerializer(User,
                                 instance=User(),
                                 data=request.DATA,
                                 allow_passwords=True)
     user = serializer.deserialize()
     if UserList.get_user_by_username(user.username) is not None:
         raise HttpNotAcceptableException(
             error_description='User with this username already exists',
             error='duplicate')
     user.save()
     pw_client = Client()
     pw_client.ovs_type = 'INTERNAL'
     pw_client.grant_type = 'PASSWORD'
     pw_client.user = user
     pw_client.save()
     cc_client = Client()
     cc_client.ovs_type = 'INTERNAL'
     cc_client.grant_type = 'CLIENT_CREDENTIALS'
     cc_client.client_secret = ''.join(
         random.choice(string.ascii_letters + string.digits +
                       '|_=+*#@!/-[]{}<>.?,\'";:~') for _ in range(128))
     cc_client.user = user
     cc_client.save()
     for junction in user.group.roles:
         for client in [cc_client, pw_client]:
             roleclient = RoleClient()
             roleclient.client = client
             roleclient.role = junction.role
             roleclient.save()
     return user
Beispiel #18
0
    def add_vpool(self, storagerouter, call_parameters, version, local_storagerouter, request):
        """
        Adds a vPool to a given Storage Router
        :param storagerouter: StorageRouter to add the vPool to
        :type storagerouter: StorageRouter
        :param call_parameters: A complex (JSON encoded) dictionary containing all various parameters to create the vPool
        :type call_parameters: dict
        :param version: Client version
        :type version: int
        :param local_storagerouter: StorageRouter on which the call is executed
        :type local_storagerouter: StorageRouter
        :param request: The raw request
        :type request: Request
        """
        def _validate_required_keys(section):
            for required_key in ['host', 'backend']:
                if required_key not in call_parameters[section]:
                    raise HttpNotAcceptableException(error_description='Invalid data passed: "{0}" misses information about {1}'.format(section, required_key),
                                                     error='invalid_data')
            for sub_required_key in ['backend', 'metadata']:
                if sub_required_key not in call_parameters[section]['backend']:
                    raise HttpNotAcceptableException(error_description='Invalid data passed: "{0}" missing information about {1}'.format(section, sub_required_key),
                                                     error='invalid_data')

        # API backwards compatibility
        if version <= 2:
            call_parameters['storagerouter_ip'] = storagerouter.ip
            call_parameters['fragment_cache_on_read'] = True
            call_parameters['fragment_cache_on_write'] = False
            call_parameters['backend_connection_info'] = {'host': call_parameters.pop('connection_host'),
                                                          'port': call_parameters.pop('connection_port'),
                                                          'username': call_parameters.pop('connection_username'),
                                                          'password': call_parameters.pop('connection_password')}
            if 'connection_backend' in call_parameters:
                connection_backend = call_parameters.pop('connection_backend')
                call_parameters['backend_connection_info']['backend'] = {'backend': connection_backend.pop('backend') if 'backend' in connection_backend else None,
                                                                         'metadata': connection_backend.pop('metadata') if 'metadata' in connection_backend else None}
        if version < 6:
            if 'backend_connection_info' not in call_parameters:
                raise HttpNotAcceptableException(error_description='Invalid data passed: "backend_connection_info" should be passed',
                                                 error='invalid_data')
            _validate_required_keys(section='backend_connection_info')
            if 'backend_info' not in call_parameters:
                call_parameters['backend_info'] = {}
            if 'connection_info' not in call_parameters:
                call_parameters['connection_info'] = {}
            call_parameters['backend_info']['preset'] = call_parameters['backend_connection_info']['backend']['metadata']
            call_parameters['backend_info']['alba_backend_guid'] = call_parameters['backend_connection_info']['backend']['backend']
            call_parameters['connection_info']['host'] = call_parameters['backend_connection_info']['host']
            call_parameters['connection_info']['port'] = call_parameters['backend_connection_info'].get('port', '')
            call_parameters['connection_info']['client_id'] = call_parameters['backend_connection_info'].get('username', '')
            call_parameters['connection_info']['client_secret'] = call_parameters['backend_connection_info'].get('password', '')
            call_parameters.pop('backend_connection_info')

            if 'backend_connection_info_aa' in call_parameters:
                if 'backend_info_aa' not in call_parameters:
                    call_parameters['backend_info_aa'] = {}
                if 'connection_info_aa' not in call_parameters:
                    call_parameters['connection_info_aa'] = {}
                _validate_required_keys(section='backend_connection_info_aa')
                call_parameters['backend_info_aa']['preset'] = call_parameters['backend_connection_info_aa']['backend']['metadata']
                call_parameters['backend_info_aa']['alba_backend_guid'] = call_parameters['backend_connection_info_aa']['backend']['backend']
                call_parameters['connection_info_aa']['host'] = call_parameters['backend_connection_info_aa']['host']
                call_parameters['connection_info_aa']['port'] = call_parameters['backend_connection_info_aa'].get('port', '')
                call_parameters['connection_info_aa']['client_id'] = call_parameters['backend_connection_info_aa'].get('username', '')
                call_parameters['connection_info_aa']['client_secret'] = call_parameters['backend_connection_info_aa'].get('password', '')
                call_parameters.pop('backend_connection_info_aa')

        if version >= 6 and 'backend_connection_info' in call_parameters:
            raise HttpNotAcceptableException(error_description='Invalid data passed: "backend_connection_info" is deprecated',
                                             error='invalid_data')

        # API client translation (cover "local backend" selection in GUI)
        if 'backend_info' not in call_parameters or 'connection_info' not in call_parameters or 'config_params' not in call_parameters:
            raise HttpNotAcceptableException(error_description='Invalid call_parameters passed',
                                             error='invalid_data')
        connection_info = call_parameters['connection_info']
        connection_info_aa = call_parameters.get('connection_info_aa')
        if connection_info['host'] == '' or (connection_info_aa is not None and connection_info_aa['host'] == ''):
            client = None
            for _client in request.client.user.clients:
                if _client.ovs_type == 'INTERNAL' and _client.grant_type == 'CLIENT_CREDENTIALS':
                    client = _client
            if client is None:
                raise HttpNotAcceptableException(error_description='Invalid call_parameters passed',
                                                 error='invalid_data')
            if connection_info['host'] == '':
                connection_info['client_id'] = client.client_id
                connection_info['client_secret'] = client.client_secret
                connection_info['host'] = local_storagerouter.ip
                connection_info['port'] = 443
                connection_info['local'] = True
            if connection_info_aa is not None and connection_info_aa['host'] == '':
                connection_info_aa['client_id'] = client.client_id
                connection_info_aa['client_secret'] = client.client_secret
                connection_info_aa['host'] = local_storagerouter.ip
                connection_info_aa['port'] = 443
                connection_info_aa['local'] = True

        call_parameters.pop('type', None)
        call_parameters.pop('readcache_size', None)
        call_parameters['config_params'].pop('dedupe_mode', None)
        call_parameters['config_params'].pop('cache_strategy', None)

        # Finally, launching the add_vpool task
        return StorageRouterController.add_vpool.delay(call_parameters)
Beispiel #19
0
 def new_function(*args, **kwargs):
     """
     Wrapped function
     """
     request = _find_request(args)
     new_kwargs = {}
     validation_new_kwargs = {}
     # Find out the arguments of the decorated function
     if validator is not None:
         f_info = inspect.getargspec(validator)
         if f_info.defaults is None:
             validation_mandatory_vars = f_info.args[1:]
             validation_optional_vars = []
         else:
             validation_mandatory_vars = f_info.args[1:-len(f_info.
                                                            defaults)]
             validation_optional_vars = f_info.args[
                 len(validation_mandatory_vars) + 1:]
     else:
         validation_mandatory_vars = []
         validation_optional_vars = []
     # Check versioning
     version_match = regex.match(request.META['HTTP_ACCEPT'])
     if version_match is not None:
         version = version_match.groupdict()['version']
     else:
         version = settings.VERSION[-1]
     raw_version = version
     versions = (max(min_version, settings.VERSION[0]),
                 min(max_version, settings.VERSION[-1]))
     if version == '*':  # If accepting all versions, it defaults to the highest one
         version = versions[1]
     version = int(version)
     if version < versions[0] or version > versions[1]:
         raise HttpNotAcceptableException(
             error_description=
             'API version requirements: {0} <= <version> <= {1}. Got {2}'
             .format(versions[0], versions[1], version),
             error='invalid_version')
     # Load some information
     instance = None
     if 'pk' in kwargs and object_type is not None:
         try:
             instance = object_type(kwargs['pk'])
         except ObjectNotFoundException:
             raise HttpNotFoundException(
                 error_description=
                 'The requested object could not be found',
                 error='object_not_found')
     # Build new kwargs
     for _mandatory_vars, _optional_vars, _new_kwargs in [
         (f.ovs_metadata['load']['mandatory'][:],
          f.ovs_metadata['load']['optional'][:], new_kwargs),
         (validation_mandatory_vars, validation_optional_vars,
          validation_new_kwargs)
     ]:
         if 'version' in _mandatory_vars:
             _new_kwargs['version'] = version
             _mandatory_vars.remove('version')
         if 'raw_version' in _mandatory_vars:
             _new_kwargs['raw_version'] = raw_version
             _mandatory_vars.remove('raw_version')
         if 'request' in _mandatory_vars:
             _new_kwargs['request'] = request
             _mandatory_vars.remove('request')
         if instance is not None:
             typename = object_type.__name__.lower()
             if typename in _mandatory_vars:
                 _new_kwargs[typename] = instance
                 _mandatory_vars.remove(typename)
         if 'local_storagerouter' in _mandatory_vars:
             storagerouter = StorageRouterList.get_by_machine_id(
                 settings.UNIQUE_ID)
             _new_kwargs['local_storagerouter'] = storagerouter
             _mandatory_vars.remove('local_storagerouter')
         # The rest of the mandatory parameters
         post_data = request.DATA if hasattr(request,
                                             'DATA') else request.POST
         get_data = request.QUERY_PARAMS if hasattr(
             request, 'QUERY_PARAMS') else request.GET
         for name in _mandatory_vars:
             if name in kwargs:
                 _new_kwargs[name] = kwargs[name]
             else:
                 if name not in post_data:
                     if name not in get_data:
                         raise HttpNotAcceptableException(
                             error_description=
                             'Invalid data passed: {0} is missing'.
                             format(name),
                             error='invalid_data')
                     _new_kwargs[name] = _try_parse(get_data[name])
                 else:
                     _new_kwargs[name] = _try_parse(post_data[name])
         # Try to fill optional parameters
         for name in _optional_vars:
             if name in kwargs:
                 _new_kwargs[name] = kwargs[name]
             else:
                 if name in post_data:
                     _new_kwargs[name] = _try_parse(post_data[name])
                 elif name in get_data:
                     _new_kwargs[name] = _try_parse(get_data[name])
     # Execute validator
     if validator is not None:
         validator(args[0], **validation_new_kwargs)
     # Call the function
     return f(args[0], **new_kwargs)