Merge branch 'master' into netslice 44/6844/1
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Fri, 2 Nov 2018 13:19:01 +0000 (14:19 +0100)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Fri, 2 Nov 2018 13:19:01 +0000 (14:19 +0100)
1  2 
osm_nbi/nbi.py

diff --combined osm_nbi/nbi.py
@@@ -32,7 -32,7 +32,7 @@@ auth_database_version = '1.0
  """
  North Bound Interface  (O: OSM specific; 5,X: SOL005 not implemented yet; O5: SOL005 implemented)
  URL: /osm                                                       GET     POST    PUT     DELETE  PATCH
 -        /nsd/v1                                                 O       O
 +        /nsd/v1
              /ns_descriptors_content                             O       O
                  /<nsdInfoId>                                    O       O       O       O
              /ns_descriptors                                     O5      O5
                  /<vnfInstanceId>                                O
              /subscriptions                                      5       5
                  /<subscriptionId>                               5                       X
 +
          /pdu/v1
              /pdu_descriptor                                     O       O
                  /<id>                                           O               O       O       O
 +
          /admin/v1
              /tokens                                             O       O
                  /<id>                                           O                       O
              /sdns                                               O       O
                  /<id>                                           O                       O       O
  
 +        /nst/v1                                                 O       O
 +            /netslice_templates_content                         O       O
 +                /<nstInfoId>                                    O       O       O       O
 +            /netslice_templates                                 O       O
 +                /<nstInfoId>                                    O                       O       O
 +                    /nst_content                                O               O
 +                    /nst                                        O
 +                    /artifacts[/<artifactPath>]                 O
 +            /subscriptions                                      X       X
 +                /<subscriptionId>                               X                       X
 +
 +        /nsilcm/v1
 +            /netslice_instances_content                         O       O
 +                /<SliceInstanceId>                              O                       O
 +            /netslice_instances                                 O       O
 +                /<SliceInstanceId>                              O                       O
 +                    instantiate                                         O
 +                    terminate                                           O
 +                    action                                              O
 +            /nsi_lcm_op_occs                                    O       O
 +                /<nsiLcmOpOccId>                                O                       O       O
 +            /subscriptions                                      X       X
 +                /<subscriptionId>                               X                       X
 +
  query string:
      Follows SOL005 section 4.3.2 It contains extra METHOD to override http method, FORCE to force.
      For filtering inside array, it must select the element of the array, or add ANYINDEX to apply the filtering over any
@@@ -273,40 -247,6 +273,40 @@@ class Server(object)
                                        },
                  }
              },
 +            "nst": {
 +                "v1": {
 +                    "netslice_templates_content": {"METHODS": ("GET", "POST"),
 +                                                   "<ID>": {"METHODS": ("GET", "PUT", "DELETE")}
 +                                                   },
 +                    "netslice_templates": {"METHODS": ("GET", "POST"),
 +                                           "<ID>": {"METHODS": ("GET", "DELETE"), "TODO": "PATCH",
 +                                                    "nst_content": {"METHODS": ("GET", "PUT")},
 +                                                    "nst": {"METHODS": "GET"},  # descriptor inside package
 +                                                    "artifacts": {"*": {"METHODS": "GET"}}
 +                                                    }
 +                                           },
 +                    "subscriptions": {"TODO": ("GET", "POST"),
 +                                      "<ID>": {"TODO": ("GET", "DELETE")}
 +                                      },
 +                }
 +            },
 +            "nsilcm": {
 +                "v1": {
 +                    "netslice_instances_content": {"METHODS": ("GET", "POST"),
 +                                                   "<ID>": {"METHODS": ("GET", "DELETE")}
 +                                                   },
 +                    "netslice_instances": {"METHODS": ("GET", "POST"),
 +                                           "<ID>": {"METHODS": ("GET", "DELETE"),
 +                                                    "terminate": {"METHODS": "POST"},
 +                                                    "instantiate": {"METHODS": "POST"},
 +                                                    "action": {"METHODS": "POST"},
 +                                                    }
 +                                           },
 +                    "nsi_lcm_op_occs": {"METHODS": "GET",
 +                                        "<ID>": {"METHODS": "GET"},
 +                                        },
 +                }
 +            },
          }
  
      def _format_in(self, kwargs):
                      if "application/json" in cherrypy.request.headers["Content-Type"]:
                          error_text = "Invalid json format "
                          indata = json.load(self.reader(cherrypy.request.body))
+                         cherrypy.request.headers.pop("Content-File-MD5", None)
                      elif "application/yaml" in cherrypy.request.headers["Content-Type"]:
                          error_text = "Invalid yaml format "
                          indata = yaml.load(cherrypy.request.body)
+                         cherrypy.request.headers.pop("Content-File-MD5", None)
                      elif "application/binary" in cherrypy.request.headers["Content-Type"] or \
                           "application/gzip" in cherrypy.request.headers["Content-Type"] or \
                           "application/zip" in cherrypy.request.headers["Content-Type"] or \
                          # 'application/yaml' for input format are available")
                          error_text = "Invalid yaml format "
                          indata = yaml.load(cherrypy.request.body)
+                         cherrypy.request.headers.pop("Content-File-MD5", None)
                  else:
                      error_text = "Invalid yaml format "
                      indata = yaml.load(cherrypy.request.body)
+                     cherrypy.request.headers.pop("Content-File-MD5", None)
              if not indata:
                  indata = {}
  
                      engine_topic = "nslcmops"
                  if topic == "vnfrs" or topic == "vnf_instances":
                      engine_topic = "vnfrs"
 +            elif main_topic == "nst":
 +                engine_topic = "nsts"
 +            elif main_topic == "nsilcm":
 +                engine_topic = "nsis"
 +                if topic == "nsi_lcm_op_occs":
 +                    engine_topic = "nsilcmops"
              elif main_topic == "pdu":
                  engine_topic = "pdus"
              if engine_topic == "vims":   # TODO this is for backward compatibility, it will remove in the future
                  engine_topic = "vim_accounts"
  
              if method == "GET":
 -                if item in ("nsd_content", "package_content", "artifacts", "vnfd", "nsd"):
 -                    if item in ("vnfd", "nsd"):
 +                if item in ("nsd_content", "package_content", "artifacts", "vnfd", "nsd", "nst", "nst_content"):
 +                    if item in ("vnfd", "nsd", "nst"):
                          path = "$DESCRIPTOR"
                      elif args:
                          path = args
                  else:
                      outdata = self.engine.get_item(session, engine_topic, _id)
              elif method == "POST":
 -                if topic in ("ns_descriptors_content", "vnf_packages_content"):
 +                if topic in ("ns_descriptors_content", "vnf_packages_content", "netslice_templates_content"):
                      _id = cherrypy.request.headers.get("Transaction-Id")
                      if not _id:
                          _id = self.engine.new_item(rollback, session, engine_topic, {}, None, cherrypy.request.headers,
                      self._set_location_header(main_topic, version, "ns_lcm_op_occs", _id)
                      outdata = {"id": _id}
                      cherrypy.response.status = HTTPStatus.ACCEPTED.value
 +                elif topic == "netslice_instances_content":
 +                    # creates NSI
 +                    _id = self.engine.new_item(rollback, session, engine_topic, indata, kwargs, force=force)
 +                    # creates nsilcmop
 +                    indata["lcmOperationType"] = "instantiate"
 +                    indata["nsiInstanceId"] = _id
 +                    self.engine.new_item(rollback, session, "nsilcmops", indata, None)
 +                    self._set_location_header(main_topic, version, topic, _id)
 +                    outdata = {"id": _id}
 +                elif topic == "netslice_instances" and item:
 +                    indata["lcmOperationType"] = item
 +                    indata["nsiInstanceId"] = _id
 +                    _id = self.engine.new_item(rollback, session, "nsilcmops", indata, kwargs)
 +                    self._set_location_header(main_topic, version, "nsi_lcm_op_occs", _id)
 +                    outdata = {"id": _id}
 +                    cherrypy.response.status = HTTPStatus.ACCEPTED.value
                  else:
                      _id = self.engine.new_item(rollback, session, engine_topic, indata, kwargs,
                                                 cherrypy.request.headers, force=force)
                          opp_id = self.engine.new_item(rollback, session, "nslcmops", nslcmop_desc, None)
                          outdata = {"_id": opp_id}
                          cherrypy.response.status = HTTPStatus.ACCEPTED.value
 +                    elif topic == "netslice_instances_content" and not force:
 +                        nsilcmop_desc = {
 +                            "lcmOperationType": "terminate",
 +                            "nsiInstanceId": _id,
 +                            "autoremove": True
 +                        }
 +                        opp_id = self.engine.new_item(rollback, session, "nsilcmops", nsilcmop_desc, None)
 +                        outdata = {"_id": opp_id}
 +                        cherrypy.response.status = HTTPStatus.ACCEPTED.value
                      else:
                          self.engine.del_item(session, engine_topic, _id, force)
                          cherrypy.response.status = HTTPStatus.NO_CONTENT.value
                  if not indata and not kwargs:
                      raise NbiException("Nothing to update. Provide payload and/or query string",
                                         HTTPStatus.BAD_REQUEST)
 -                if item in ("nsd_content", "package_content") and method == "PUT":
 +                if item in ("nsd_content", "package_content", "nst_content") and method == "PUT":
                      completed = self.engine.upload_content(session, engine_topic, _id, indata, kwargs,
                                                             cherrypy.request.headers, force=force)
                      if not completed:
              rollback.reverse()
              for rollback_item in rollback:
                  try:
-                     self.engine.del_item(**rollback_item, session=session, force=True)
+                     if rollback_item.get("operation") == "set":
+                         self.engine.db.set_one(rollback_item["topic"], {"_id": rollback_item["_id"]},
+                                                rollback_item["content"], fail_on_empty=False)
+                     else:
+                         self.engine.del_item(**rollback_item, session=session, force=True)
                  except Exception as e2:
                      rollback_error_text = "Rollback Exception {}: {}".format(rollback_item, e2)
                      cherrypy.log(rollback_error_text)
@@@ -949,11 -866,8 +957,8 @@@ def _start_service()
      # TODO add more entries, e.g.: storage
      cherrypy.tree.apps['/osm'].root.engine.start(engine_config)
      cherrypy.tree.apps['/osm'].root.authenticator.start(engine_config)
-     try:
-         cherrypy.tree.apps['/osm'].root.engine.init_db(target_version=database_version)
-         cherrypy.tree.apps['/osm'].root.authenticator.init_db(target_version=auth_database_version)
-     except (EngineException, AuthException):
-         pass
+     cherrypy.tree.apps['/osm'].root.engine.init_db(target_version=database_version)
+     cherrypy.tree.apps['/osm'].root.authenticator.init_db(target_version=auth_database_version)
      # getenv('OSMOPENMANO_TENANT', None)