Example #1
0
def makeResourceFromClass(component_class, params):
    """
    Create a new resource representation from the
    specified component class and parameter dictionary
    and store it on disk.
        
    The parameters need to look something like this:
    
            {
                "reource creation_params" : {
                        "suggested_name" : "my_twitter",
                        "desc"           : "Our Twitter stream"
                },
                "params" : {
                        "user"     : "AccountName",
                        "password" : "some password"
                },
                "positional_params" : [ "user" ]      # Optional
            }

    The method performs sanity checking on the supplied
    parameters and also fills in default values where
    available.
    
    @param component_class: A class (not instance) derived from BaseComponent.
    @type  component_class: BaseComponent or derived.
    
    @param params:          The resource parameters provided by the client.
                            Needs to contain at least a 'params' dictionary
                            or a 'resource_creation_dictionary'. Can contain
                            both.
    @type  params:          dict
    
    @return:                Success message in form of dictionary that contains
                            "status", "name" and "uri" fields.
    @rtype:                 dict
    
    @raise RestxException:  If the resource creation failed or there was a
                            problem with the provided parameters.

    """
    # We get the meta data (parameter definition) from the component
    component = component_class()
    component_params_def = component.getMetaData()
    component_params_def = languageStructToPython(component,
                                                  component_params_def)

    #
    # First we check whether there are any unknown parameters specified
    # on the top level.
    #
    if type(params) is not dict:
        raise RestxException(
            "Malformed resource parameter definition. Has to be JSON dictionary."
        )

    for k in params.keys():
        if k not in ['params', 'resource_creation_params']:
            raise RestxException(
                "Malformed resource parameter definition. Unknown key: %s" % k)
    #
    # Check whether there are unknown parameters in the 'param' or 'resource_creation_params' section.
    #
    provided_params = params.get('params')
    if not provided_params:
        # If no parameters were provided at all, we create them as
        # an empty dictionary. We need something here to be able
        # to merge some defaults into it later on.
        provided_params = dict()
        params['params'] = provided_params
    provided_resource_creation_params = params.get('resource_creation_params')
    paramSanityCheck(provided_params, component_params_def['params'], 'params')
    paramSanityCheck(provided_resource_creation_params,
                     component_params_def['resource_creation_params'],
                     'resource_creation_params')
    # Before storing the parameters, we make sure they are converted to the
    # types that have been specified
    convertTypes(component_params_def['params'], provided_params)

    # The parameters passed the sanity checks. We can now create the resource definition.
    suggested_name = provided_resource_creation_params['suggested_name']
    resource_uri = settings.PREFIX_RESOURCE + "/" + suggested_name
    resource_name = suggested_name  # TODO: Should check if the resource exists already...
    params['code_uri'] = component.getCodeUri(
    )  # Need a reference to the code that this applies to

    # Some parameters are optional. If they were not supplied,
    # we need to add their default values.
    fillDefaults(component_params_def['params'], provided_params)
    fillDefaults(component_params_def['resource_creation_params'],
                 provided_resource_creation_params)

    # Storage for a resource contains a private and public part. The public part is what
    # any user of the resource can see: URI, name and description. In the private part we
    # store whatever was provided here during resource creation. It contains the information
    # we need to instantiate a running resource.
    resource_def = {
        "private": params,
        "public": {
            "uri": resource_uri,
            "name": resource_name,
            "desc": provided_resource_creation_params['desc']
        }
    }

    # Storage to our 'database'.
    STORAGE_OBJECT.writeResourceToStorage(resource_name, resource_def)

    # Send a useful message back to the client.
    success_body = {
        "status": "created",
        "name":
        resource_name,  # Is returned, because server could have chosen different name
        "uri": resource_uri
    }

    return success_body
Example #2
0
def makeResourceFromComponentObject(component, params, specialized=None, partial_resource_name=None):
    """
    Create a new resource representation from the
    specified component class and parameter dictionary
    and store it on disk.
        
    The parameters need to look something like this:
    
            {
                "reource creation_params" : {
                        "suggested_name" : "my_twitter",
                        "desc"           : "Our Twitter stream",
                        "specialized"    : false
                },
                "params" : {
                        "user"     : "AccountName",
                        "password" : "some password"
                },
            }

    The method performs sanity checking on the supplied
    parameters and also fills in default values where
    available.
    
    @param component_class: A class (not instance) derived from BaseComponent.
    @type  component_class: BaseComponent or derived.
    
    @param params:          The resource parameters provided by the client.
                            Needs to contain at least a 'params' dictionary
                            or a 'resource_creation_dictionary'. Can contain
                            both.
    @type  params:          dict

    @param specialized:     If this resource should be based on a partial resource
                            definition (specialized code) then we are given the
                            resource definition dictionary of the partial resource
                            here. Otherwise, this is None. This is only permitted
                            if the resource-creation-parameters do NOT set the
                            'specialized' flag. That flag indicates that we want
                            to create a new specialized component resource, not a resource
                            based on a specialized component.
    @type specialized:      dict

    @param partial_resource_name: Name of the partial resource from which we have the
                                  specialized (partial resource) definition.
    @type partial_resource_name:  string
    
    @return:                Success message in form of dictionary that contains
                            "status", "name" and "uri" fields.
    @rtype:                 dict
    
    @raise RestxException:  If the resource creation failed or there was a
                            problem with the provided parameters.

    """    
    # We get the meta data (parameter definition) from the component
    component_params_def = component.getMetaData()
    component_params_def = languageStructToPython(component, component_params_def)
    if specialized:
        # Do an overwrite and merge with the specialized component (partial resource
        # data). This may modify the description and suggested name defaults.
        component_params_def = specializedOverwrite(component_params_def, specialized)

    #
    # First we check whether there are any unknown parameters specified
    # on the top level.
    #
    if type(params) is not dict:
        raise RestxException("Malformed resource parameter definition. Has to be JSON dictionary.")
        
    for k in params.keys():
        if k not in [ 'params', 'resource_creation_params' ]:
            raise RestxBadRequestException("Malformed resource parameter definition. Unknown key: %s" % k)

    # Check whether there are unknown parameters in the 'param' or 'resource_creation_params' section.
    provided_params = params.get('params')

    if not provided_params:
        # If no parameters were provided at all, we create them as
        # an empty dictionary. We need something here to be able
        # to merge some defaults into it later on.
        provided_params = dict()
        params['params'] = provided_params

    # Merge with any parameters provided by a partial resource we may use as base
    # If there are doubles (something was provided with the create request, which was
    # also already defined in the partial base resource) then we are simply ignoring
    # the provided value and overwrite them with what was defined in the partial
    # resource.
    specialized_params = None
    if specialized:
        try:
            specialized_params  = specialized['private']['params']
            provided_params.update(specialized_params)
        except:
            pass

    provided_resource_creation_params = params.get('resource_creation_params')
    # Note the difference between 'specialized' and the 'make_specialized_component' flag:
    # If a 'specialized' parameter is provided then we know that we want to create a new
    # usable resource, based on a specialized component resource. However, if the
    # resource-creation-parameters contain the 'specialized' flag, this means that we
    # just want to create the specialized component resource (the base resource). Those
    # two things are mutually exclusive.
    if provided_resource_creation_params:
        make_specialized_component = provided_resource_creation_params.get('specialized', False)
        if make_specialized_component and specialized:
            raise RestxException("Cannot create resource with specializec component resource as base AND set 'specialized' flag at the same time.")
    else:
        make_specialized_component = False
    paramSanityCheck(provided_params, component_params_def['params'], 'params', make_specialized_component)
    paramSanityCheck(provided_resource_creation_params,
                     component_params_def['resource_creation_params'],
                     'resource_creation_params')
    # Before storing the parameters, we make sure they are converted to the
    # types that have been specified
    convertTypes(component_params_def['params'], provided_params)

    # The parameters passed the sanity checks. We can now create the resource definition.
    suggested_name = provided_resource_creation_params['suggested_name']
    resource_uri   = (settings.PREFIX_RESOURCE if not make_specialized_component else settings.PREFIX_SPECIALIZED) + "/" + suggested_name
    resource_name  = suggested_name # TODO: Should check if the resource exists already...
    params['code_uri'] = component.getCodeUri()  # Need a reference to the code that this applies to
    
    # Some parameters are optional. If they were not supplied,
    # we need to add their default values. However, we only do this
    # when we create a normal resource. For specialized component
    # resources, we don't want to set those default values, since
    # otherwise they appear as 'set and unmodifiable' for those
    # who want to create an actual resource based on a specialized
    # component resource.
    if not make_specialized_component:
        fillDefaults(component_params_def['params'], provided_params)
    fillDefaults(component_params_def['resource_creation_params'], provided_resource_creation_params)

    # After all parameters have been dealt with, we now
    # should remove all the parameters that came from a partial resource
    # if we are creating a component based on that.
    private_params = params.get('params')
    if specialized_params  and  private_params:
        for key in specialized_params.keys():
            if key in private_params:
                del private_params[key]

    # Storage for a resource contains a private and public part. The public part is what
    # any user of the resource can see: URI, name and description. In the private part we
    # store whatever was provided here during resource creation. It contains the information
    # we need to instantiate a running resource.
    resource_def = {
        "private" : params,
        "public"  : {
                        "uri"  : resource_uri,
                        "name" : resource_name,
                        "desc" : provided_resource_creation_params['desc']
                    }
    }
    if specialized:
        resource_def['extends'] = partial_resource_name
        del resource_def['private']['code_uri']
    
    # Storage to our 'database'.
    STORAGE_OBJECT.writeResourceToStorage(resource_name, resource_def, make_specialized_component)

    # Send a useful message back to the client.
    success_body = {
        "status" : "created",
        "name"   : resource_name,   # Is returned, because server could have chosen different name
        "uri"    : resource_uri
    }

    return success_body
Example #3
0
def makeResourceFromClass(component_class, params):
    """
    Create a new resource representation from the
    specified component class and parameter dictionary
    and store it on disk.
        
    The parameters need to look something like this:
    
            {
                "reource creation_params" : {
                        "suggested_name" : "my_twitter",
                        "desc"           : "Our Twitter stream"
                },
                "params" : {
                        "user"     : "AccountName",
                        "password" : "some password"
                },
                "positional_params" : [ "user" ]      # Optional
            }

    The method performs sanity checking on the supplied
    parameters and also fills in default values where
    available.
    
    @param component_class: A class (not instance) derived from BaseComponent.
    @type  component_class: BaseComponent or derived.
    
    @param params:          The resource parameters provided by the client.
                            Needs to contain at least a 'params' dictionary
                            or a 'resource_creation_dictionary'. Can contain
                            both.
    @type  params:          dict
    
    @return:                Success message in form of dictionary that contains
                            "status", "name" and "uri" fields.
    @rtype:                 dict
    
    @raise RestxException:  If the resource creation failed or there was a
                            problem with the provided parameters.

    """    
    # We get the meta data (parameter definition) from the component
    component            = component_class()
    component_params_def = component.getMetaData()
    component_params_def = languageStructToPython(component, component_params_def)

    #
    # First we check whether there are any unknown parameters specified
    # on the top level.
    #
    if type(params) is not dict:
        raise RestxException("Malformed resource parameter definition. Has to be JSON dictionary.")
        
    for k in params.keys():
        if k not in [ 'params', 'resource_creation_params' ]:
            raise RestxException("Malformed resource parameter definition. Unknown key: %s" % k)
    #
    # Check whether there are unknown parameters in the 'param' or 'resource_creation_params' section.
    #
    provided_params = params.get('params')
    if not provided_params:
        # If no parameters were provided at all, we create them as
        # an empty dictionary. We need something here to be able
        # to merge some defaults into it later on.
        provided_params = dict()
        params['params'] = provided_params
    provided_resource_creation_params = params.get('resource_creation_params')
    paramSanityCheck(provided_params, component_params_def['params'], 'params')
    paramSanityCheck(provided_resource_creation_params,
                     component_params_def['resource_creation_params'],
                     'resource_creation_params')
    # Before storing the parameters, we make sure they are converted to the
    # types that have been specified
    convertTypes(component_params_def['params'], provided_params)


    # The parameters passed the sanity checks. We can now create the resource definition.
    suggested_name = provided_resource_creation_params['suggested_name']
    resource_uri   = settings.PREFIX_RESOURCE + "/" + suggested_name
    resource_name  = suggested_name # TODO: Should check if the resource exists already...
    params['code_uri'] = component.getCodeUri()  # Need a reference to the code that this applies to
    
    # Some parameters are optional. If they were not supplied,
    # we need to add their default values.
    fillDefaults(component_params_def['params'], provided_params)
    fillDefaults(component_params_def['resource_creation_params'], provided_resource_creation_params)

    # Storage for a resource contains a private and public part. The public part is what
    # any user of the resource can see: URI, name and description. In the private part we
    # store whatever was provided here during resource creation. It contains the information
    # we need to instantiate a running resource.
    resource_def = {
        "private" : params,
        "public"  : {
                        "uri"  : resource_uri,
                        "name" : resource_name,
                        "desc" : provided_resource_creation_params['desc']
                    }
    }
    
    # Storage to our 'database'.
    STORAGE_OBJECT.writeResourceToStorage(resource_name, resource_def)

    # Send a useful message back to the client.
    success_body = {
        "status" : "created",
        "name"   : resource_name,   # Is returned, because server could have chosen different name
        "uri"    : resource_uri
    }

    return success_body