Example #1
0
def deleteResourceFromStorage(uri, is_partial=False):
    """
    Delete a resource definition from storage.

    @param uri:   Uri of the resource
    @type  uri:   string

    """
    resource_name = uri[len(settings.PREFIX_SPECIALIZED if is_partial else settings.PREFIX_RESOURCE)+1:]
    STORAGE_OBJECT.deleteResourceFromStorage(resource_name, is_partial)
Example #2
0
def deleteResourceFromStorage(uri):
    """
    Delete a resource definition from storage.

    @param uri:   Uri of the resource
    @type  uri:   string

    """
    resource_name = uri[len(settings.PREFIX_RESOURCE) + 1:]
    STORAGE_OBJECT.deleteResourceFromStorage(resource_name)
Example #3
0
def deleteResourceFromStorage(uri):
    """
    Delete a resource definition from storage.

    @param uri:   Uri of the resource
    @type  uri:   string

    """
    resource_name = uri[len(settings.PREFIX_RESOURCE)+1:]
    STORAGE_OBJECT.deleteResourceFromStorage(resource_name)
Example #4
0
def listResources(partials=False):
    """
    Return list of all stored resources.
    
    Data is returned as dictionary keyed by resource name.
    For each resource the complete URI, the name and the description
    are returned.

    @param partials:     Indicate whether we want to list the partial resources
    @type partials:      boolean
    
    @return: Dictionary of available resources.
    @rtype:  dict
    
    """
    dir_list = STORAGE_OBJECT.listResourcesInStorage(partials)
    out = {}
    for resource_name in dir_list:
        rname = resource_name.lower()
        if rname not in EXCLUDED_NAMES  and  rname[0] not in EXCLUDE_PREFIXES:
            resource_dict = retrieveResourceFromStorage(getResourceUri(resource_name, partials), only_public=True, is_partial=partials)
            if resource_dict:
                out[resource_name] = dict(uri=Url(resource_dict['uri']), desc=resource_dict['desc'])
            else:
                out[resource_name] = "Not found"
    return out
Example #5
0
def listResources():
    """
    Return list of all stored resources.
    
    Data is returned as dictionary keyed by resource name.
    For each resource the complete URI, the name and the description
    are returned.
    
    @return: Dictionary of available resources.
    @rtype:  dict
    
    """
    dir_list = STORAGE_OBJECT.listResourcesInStorage()
    out = {}
    for resource_name in dir_list:
        rname = resource_name.lower()
        if rname not in EXCLUDED_NAMES and rname[0] not in EXCLUDE_PREFIXES:
            resource_dict = retrieveResourceFromStorage(
                getResourceUri(resource_name), only_public=True)
            if resource_dict:
                out[resource_name] = dict(uri=Url(resource_dict['uri']),
                                          desc=resource_dict['desc'])
            else:
                out[resource_name] = "Not found"
    return out
Example #6
0
def retrieveResourceFromStorage(uri, only_public=False, is_partial=False):
    """
    Return the details about a stored resource (partial or otherwise).
    
    The resource is identified via its URI.
    
    @param uri:         Identifies a resource via its URI.
    @type  uri:         string
    
    @param only_public: Flag indicating whether we only want to see the
                        public information about this resource.
    @type only_public:  boolean

    @param is_partial:  Indicate whether we are loading a partial resource.
    @type is_partial:   boolean
    
    @return:            Dictionary or None if not found.
    @rtype:             dict
    
    """
    # Need to take the resource URI prefix off to get the resource_name.
    if is_partial:
        resource_name = uri[len(settings.PREFIX_SPECIALIZED)+1:]
    else:
        resource_name = uri[len(settings.PREFIX_RESOURCE)+1:]
    obj = None
    try:
        obj = STORAGE_OBJECT.loadResourceFromStorage(resource_name, is_partial)
        if not obj:
            raise Exception("Unknown resource: " + resource_name)
        if type(obj) is not dict  or  'public' not in obj:
            obj = None
            raise Exception("Missing top-level element 'public' or malformed resource.")
        public_obj = obj['public']
        # Do some sanity checking on the resource. Needs to contain
        # a few key elements at least.
        for mandatory_key in [ 'uri', 'desc', 'name' ]:
            if mandatory_key not in public_obj:
                public_obj = None
                raise Exception("Mandatory key '%s' missing in stored resource '%s'" % \
                                (mandatory_key, resource_name))
        if only_public:
            obj = public_obj
            
    except Exception, e:
        log("Malformed storage for resource '%s': %s" % (resource_name, str(e)), facility=LOGF_RESOURCES)
Example #7
0
def retrieveResourceFromStorage(uri, only_public=False):
    """
    Return the details about a stored resource.
    
    The resource is identified via its URI.
    
    @param uri:         Identifies a resource via its URI.
    @type  uri:         string
    
    @param only_public: Flag indicating whether we only want to see the
                        public information about this resource.
    @type only_public:  boolean
    
    @return:            Dictionary or None if not found.
    @rtype:             dict
    
    """
    # Need to take the resource URI prefix off to get the resource_name.
    resource_name = uri[len(settings.PREFIX_RESOURCE) + 1:]
    obj = None
    try:
        obj = STORAGE_OBJECT.loadResourceFromStorage(resource_name)
        if not obj:
            raise Exception("Unknown resource: " + resource_name)
        if type(obj) is not dict or 'public' not in obj:
            obj = None
            raise Exception(
                "Missing top-level element 'public' or malformed resource.")
        public_obj = obj['public']
        # Do some sanity checking on the resource. Needs to contain
        # a few key elements at least.
        for mandatory_key in ['uri', 'desc', 'name']:
            if mandatory_key not in public_obj:
                public_obj = None
                raise Exception("Mandatory key '%s' missing in stored resource '%s'" % \
                                (mandatory_key, resource_name))
        if only_public:
            obj = public_obj

    except Exception, e:
        log("Malformed storage for resource '%s': %s" %
            (resource_name, str(e)),
            facility=LOGF_RESOURCES)
Example #8
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
    def form(self, method, input, component_name, message="", specialized=False):
        """
        Display a resource creation form for a specified component.
        
        @param method:          The HTTP request method.
        @type method:           string
        
        @param input:           Any data that came in the body of the request.
        @type input:            string

        @param component_name:  Name of the component for which to create the resource.
        @type component_name:   string

        @param message:         An error message to be displayed above the form.
        @type message:          string

        @return:                The output data of this service.
        @rtype:                 Result

        """
        input_params = dict()
        input_rctp   = dict()
        if input  and  HttpMethod.POST:
            flag, msg, input = self.__create(input, component_name, specialized)
            if not flag:
                message = msg
            else:
                return Result.created(msg['uri'], msg)

        if input:
            if type(input) is dict:
                # We receive a dict of values if the 'create' method discovered an
                # error. In that case, the values should be used to pre-populate
                # the fields when the form is re-displayed (with the error messsage
                # on top).
                input_rctp   = input.get('resource_creation_params', dict())   # Resource creation time parameters
                input_params = input.get('params', dict())                     # Other parameters

        if specialized:
            # Need to read the definition of the partial resource and get the
            # component name from there.
            specialized_code_name = component_name
            specialized_def       = STORAGE_OBJECT.loadResourceFromStorage(specialized_code_name, True)
            component_uri         = specialized_def['private']['code_uri']
            elems                 = component_uri.split("/")
            component_name        = elems[len(elems)-1]

        # Take the parameter map from the component
        comp = restx.components.make_component(component_name)
        if not comp:
            return Result.notFound("Cannot find component '%s'" % component_name)
        header = settings.HTML_HEADER

        # Assemble the form elements for the parameters
        params = dict()
        params.update(comp.getParams())  # In case this is a Java component, we get a Python dict this way

        if specialized:
            fname = specialized_def['public']['name']
            fdesc = specialized_def['public']['desc']
            # Remove all parameters that have been specified in the specialized component resource
            # definition already
            spec_params = specialized_def['private'].get('params')
            if spec_params:
                for name in spec_params:
                    if name in params:
                        del params[name]
        else:
            fname = comp.getName()
            fdesc = comp.getDesc()

        param_fields_html = ""
        if params:
            param_field_names = params.keys()
            param_field_names.sort()
            for pname in param_field_names:
                pdef = params[pname]
                if not pdef.required:
                    opt_str = "<br>optional, default: %s" % pdef.getDefaultVal()
                else:
                    opt_str = ""
                values = input_params.get(pname)
                if type(values) is not list  and  pdef.isList():
                    if values is None:
                        values = []
                    else:
                        values = [ values ]
                param_fields_html += \
"""<tr>
    <td valign=top id="%s_name">%s<br><small>(%s%s)</small></td>
    <td valign=top>%s</td>
</tr>""" % (pname, pname, pdef.desc, opt_str, pdef.html_type("params__"+pname, values))

        if message:
            msg = "<b><i><font color=red>%s</font></i></b><br><p>" % message
        else:
            msg = ""

        body = """
<h3>Resource creation form for: %s</h3>
<p><i>"%s"</i></p>

<hr>
Please enter the resource configuration...<br><p>
%s
<form id="resource_form" name="input" action="%s" method="POST">
    <table>""" % (fname, fdesc, msg, "%s%s/form/%s%s" % (settings.DOCUMENT_ROOT, self.getMyResourceUri(),
                                                           component_name if not specialized else specialized_code_name, "?specialized=y" if specialized else ""))
        # Gather any initial values of the resource creation time form fields
        suggested_name_value = input_rctp.get("suggested_name", "")
        if suggested_name_value:
            suggested_name_value = 'value="%s" ' % suggested_name_value
        desc_value           = input_rctp.get("desc", "")
        if desc_value:
            desc_value = 'value="%s" ' % desc_value
        specialized_value    = "checked " if input_rctp.get("specialized") in [ "on", "ON" ] else " "
        if not specialized:
            body += """
        <tr>
            <td id="Make_this_a_specialized_component_name">Make this a specialized component:</td>
            <td><input type="checkbox" %s id="resource_creation_params__specialized" name="resource_creation_params__specialized" /><label for=resource_creation_params__specialized><small>Can only be used as basis for other resources</small></label></td>
        </tr>
            """ % specialized_value
        body += """
        <tr>
            <td id="Resource_name_name">Resource name:</td>
            <td><input type="text" %sname="resource_creation_params__suggested_name" id="resource_creation_params__suggested_name" /></td>
        </tr>
        <tr>
            <td id="Description_name">Description:<br><small>(optional)</small></td>
            <td><input type="text" %sname="resource_creation_params__desc" id="resource_creation_params__desc" /></td>
        </tr>
        %s
        <tr><td colspan=2 align=center><input id="submit_button" type="submit" value="Submit" /></tr>
    </table>
</form>""" % (suggested_name_value, desc_value, param_fields_html)

        footer = settings.HTML_FOOTER

        return Result.ok(header + body + footer).addHeader("Content-type", "text/html; charset=UTF-8")
Example #10
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 #11
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