X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fbase_topic.py;h=95724092a4c1a53033c15153606584159632c66f;hp=130d4fca8d0ba66baba8c5bd7b20288ddce2810f;hb=cddb07d092fdcf72ce2c87cd801b93732e64d3a9;hpb=ac55f06ddd44914cd40ee757cc6f2ac9186a1c46 diff --git a/osm_nbi/base_topic.py b/osm_nbi/base_topic.py index 130d4fc..9572409 100644 --- a/osm_nbi/base_topic.py +++ b/osm_nbi/base_topic.py @@ -65,6 +65,26 @@ def versiontuple(v): return tuple(filled) +def increment_ip_mac(ip_mac, vm_index=1): + if not isinstance(ip_mac, str): + return ip_mac + try: + # try with ipv4 look for last dot + i = ip_mac.rfind(".") + if i > 0: + i += 1 + return "{}{}".format(ip_mac[:i], int(ip_mac[i:]) + vm_index) + # try with ipv6 or mac look for last colon. Operate in hex + i = ip_mac.rfind(":") + if i > 0: + i += 1 + # format in hex, len can be 2 for mac or 4 for ipv6 + return ("{}{:0" + str(len(ip_mac) - i) + "x}").format(ip_mac[:i], int(ip_mac[i:], 16) + vm_index) + except Exception: + pass + return None + + class BaseTopic: # static variables for all instance classes topic = None # to_override @@ -140,7 +160,7 @@ class BaseTopic: validate_input(input, self.schema_new) return input - def _validate_input_edit(self, input, force=False): + def _validate_input_edit(self, input, content, force=False): """ Validates input user content for an edition. It uses jsonschema. Some overrides will use pyangbind :param input: user input content for the new topic @@ -354,11 +374,16 @@ class BaseTopic: except YAMLError: raise EngineException("Invalid query string '{}' yaml format".format(k)) - def show(self, session, _id): + def sol005_projection(self, data): + # Projection was moved to child classes + return data + + def show(self, session, _id, api_req=False): """ Get complete information on an topic :param session: contains "username", "admin", "force", "public", "project_id", "set_project" :param _id: server internal id + :param api_req: True if this call is serving an external API request. False if serving internal request. :return: dictionary, raise exception if not found. """ if not self.multiproject: @@ -367,7 +392,14 @@ class BaseTopic: filter_db = self._get_project_filter(session) # To allow project&user addressing by name AS WELL AS _id filter_db[BaseTopic.id_field(self.topic, _id)] = _id - return self.db.get_one(self.topic, filter_db) + data = self.db.get_one(self.topic, filter_db) + + # Only perform SOL005 projection if we are serving an external request + if api_req: + self.sol005_projection(data) + + return data + # TODO transform data for SOL005 URL requests # TODO remove _admin if not admin @@ -382,11 +414,12 @@ class BaseTopic: """ raise EngineException("Method get_file not valid for this topic", HTTPStatus.INTERNAL_SERVER_ERROR) - def list(self, session, filter_q=None): + def list(self, session, filter_q=None, api_req=False): """ Get a list of the topic that matches a filter :param session: contains the used login username and working project :param filter_q: filter of data to be applied + :param api_req: True if this call is serving an external API request. False if serving internal request. :return: The list, it can be empty if no one match the filter. """ if not filter_q: @@ -396,7 +429,13 @@ class BaseTopic: # TODO transform data for SOL005 URL requests. Transform filtering # TODO implement "field-type" query string SOL005 - return self.db.get_list(self.topic, filter_q) + data = self.db.get_list(self.topic, filter_q) + + # Only perform SOL005 projection if we are serving an external request + if api_req: + data = [self.sol005_projection(inst) for inst in data] + + return data def new(self, rollback, session, indata=None, kwargs=None, headers=None): """ @@ -497,14 +536,14 @@ class BaseTopic: # remove reference from project_read if there are more projects referencing it. If it last one, # do not remove reference, but delete other_projects_referencing = next((p for p in item_content["_admin"]["projects_read"] - if p not in session["project_id"]), None) + if p not in session["project_id"] and p != "ANY"), None) # check if there are projects referencing it (apart from ANY, that means, public).... if other_projects_referencing: # remove references but not delete - update_dict_pull = {"_admin.projects_read.{}".format(p): None for p in session["project_id"]} - update_dict_pull.update({"_admin.projects_write.{}".format(p): None for p in session["project_id"]}) - self.db.set_one(self.topic, filter_q, update_dict=None, pull=update_dict_pull) + update_dict_pull = {"_admin.projects_read": session["project_id"], + "_admin.projects_write": session["project_id"]} + self.db.set_one(self.topic, filter_q, update_dict=None, pull_list=update_dict_pull) return None else: can_write = next((p for p in item_content["_admin"]["projects_write"] if p == "ANY" or @@ -538,11 +577,13 @@ class BaseTopic: if indata and session.get("set_project"): raise EngineException("Cannot edit content and set to project (query string SET_PROJECT) at same time", HTTPStatus.UNPROCESSABLE_ENTITY) - indata = self._validate_input_edit(indata, force=session["force"]) - + # TODO self._check_edition(session, indata, _id, force) if not content: content = self.show(session, _id) + + indata = self._validate_input_edit(indata, content, force=session["force"]) + deep_update_rfc7396(content, indata) # To allow project addressing by name AS WELL AS _id. Get the _id, just in case the provided one is a name