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)
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)
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)
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
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
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)
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)
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")
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
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