update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwlaunchpad / plugins / rwpkgmgr / rift / tasklets / rwpkgmgr / downloader / copy.py
index c64a3f5..671501d 100644 (file)
 #   Author(s): Nandan Sinha
 #
 
+import enum
+import gi
+import json
 import os
-import uuid
 import shutil 
-import enum
+import uuid
 
-import gi
 gi.require_version('RwVnfdYang', '1.0')
 gi.require_version('RwNsdYang', '1.0')
 from gi.repository import (
@@ -34,6 +35,7 @@ from gi.repository import (
 )
 
 import rift.package.icon as icon 
+import rift.tasklets.rwlaunchpad.onboard as onboard 
 
 class PackageCopyError(Exception): 
     pass
@@ -69,12 +71,35 @@ class CopyMeta:
         return self.__dict__
 
     def to_yang(self):
-        job = RwPkgMgmtYang.CopyJob.from_dict({
+        job = RwPkgMgmtYang.YangData_RwProject_Project_CopyJobs_Job.from_dict({
             "transaction_id": self.transaction_id, 
             "status": CopyMeta.STATUS_MAP[self.state]
             })
         return job
 
+class CopyManifest: 
+    """ Utility class to hold manifest information."""
+    def __init__(self, project, log): 
+        self.tasklet_info = project.tasklet.tasklet_info
+        self.manifest = self.tasklet_info.get_pb_manifest() 
+        self.use_ssl = self.manifest.bootstrap_phase.rwsecurity.use_ssl
+        self.ssl_cert, self.ssl_key = None, None 
+        if self.use_ssl: 
+            self.ssl_cert = self.manifest.bootstrap_phase.rwsecurity.cert
+            self.ssl_key = self.manifest.bootstrap_phase.rwsecurity.key
+        self.onboarder = None
+        self.log = log
+
+    def ssl_manifest(self):
+        return (self.use_ssl, self.ssl_cert, self.ssl_key)
+
+    def get_onboarder(self, host="127.0.0.1", port="8008"): 
+        if not self.onboarder: 
+            self.onboarder = onboard.DescriptorOnboarder(self.log, 
+                host, port, *self.ssl_manifest())
+        return self.onboarder
+            
+        
 class PackageFileCopier:
     DESCRIPTOR_MAP = {
             "vnfd": (RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd, 'vnfd rw-vnfd'), 
@@ -82,11 +107,13 @@ class PackageFileCopier:
             }
 
     @classmethod
-    def from_rpc_input(cls, rpc_input, proxy, log=None): 
+    def from_rpc_input(cls, rpc_input, project, proxy, log=None): 
         return cls(
                 rpc_input.package_id,
                 rpc_input.package_type, 
                 rpc_input.package_name,
+                rpc_input.project_name,
+                project = project,
                 proxy = proxy,
                 log=log)
 
@@ -94,11 +121,15 @@ class PackageFileCopier:
             pkg_id, 
             pkg_type, 
             pkg_name, 
+            proj_name,
+            project,
             proxy, 
             log):
         self.src_package_id = pkg_id
         self.package_type = pkg_type.lower()
         self.dest_package_name = pkg_name
+        self.project_name = proj_name
+        self.manifest = CopyManifest(project, log)
         self.dest_package_id = str(uuid.uuid4())
         self.transaction_id = str(uuid.uuid4())
         self.proxy = proxy
@@ -107,17 +138,27 @@ class PackageFileCopier:
         self.src_package = None
         self.dest_desc_msg = None
 
+    @property
+    def onboarder(self): 
+        """ Onboarder object to invoke REST endpoint calls."""
+        return self.manifest.get_onboarder()
+
+    @property
+    def progress(self): 
+        """ Current status of operations."""
+        return self.meta.to_yang()
+
+    @property
+    def descriptor_msg(self): 
+        """ Descriptor message of the generated copied descriptor."""
+        return self.dest_desc_msg 
+
     # Start of delegate calls
     def call_delegate(self, event):
         if not self.delegate:
             return
         
-        # Send out the descriptor message to be posted on success
-        # Otherwise send out the CopyJob yang conversion from meta object.
-        if event == "on_download_succeeded":
-            getattr(self.delegate, event)(self.dest_desc_msg)
-        else:
-            getattr(self.delegate, event)(self.meta.to_yang())
+        getattr(self.delegate, event)(self) 
 
     def _copy_tree(self):
         """
@@ -127,12 +168,13 @@ class PackageFileCopier:
         """
         self.copy_progress()
 
-        store = self.proxy._get_store(self.package_type)
+        store = self.proxy._get_store(self.package_type, \
+                self.project_name if self.project_name else None)
         src_path = store._get_package_dir(self.src_package_id)
         self.src_package = store.get_package(self.src_package_id) 
 
         self.dest_copy_path = os.path.join(
-                store.DEFAULT_ROOT_DIR
+                store.root_dir
                 self.dest_package_id) 
         self.log.debug("Copying contents from {src} to {dest}".
                 format(src=src_path, dest=self.dest_copy_path))
@@ -154,29 +196,43 @@ class PackageFileCopier:
 
     def _create_descriptor_file(self):
         """ Update descriptor file for the newly copied descriptor catalog.
-        Use the existing descriptor file to create a descriptor proto gi object,
-        change some identifiers, and create a new descriptor yaml file from it.
-
+        Get descriptor contents from REST endpoint, change some identifiers
+        and create a new descriptor yaml file from it.
         """
-        src_desc_file = self.src_package.descriptor_file
-        src_desc_contents = self.src_package.descriptor_msg.as_dict()
-        src_desc_contents.update(
+        # API call for the updated descriptor contents
+        src_desc_contents = self.onboarder.get_updated_descriptor(self.src_package.descriptor_msg, self.project_name)
+
+        # To generate the pb object, extract subtree in dict from "project-nsd:nsd" and root it 
+        # under "nsd:nsd-catalog" (or vnfd)  
+        root_element = "{0}:{0}-catalog".format(self.package_type)
+        extract_sub_element = "project-{0}:{0}".format(self.package_type, self.package_type)
+        src_desc_contents[extract_sub_element].update(
                 id =self.dest_package_id, 
                 name = self.dest_package_name,
                 short_name = self.dest_package_name
                 )
+        D = {}
+        D[root_element] = {self.package_type : src_desc_contents[extract_sub_element]}
 
+        # Build the proto-buf gi object from generated JSON
+        json_desc_msg = json.dumps(D)
+        self.log.debug("*** JSON contents: {}".format(json_desc_msg))
         desc_cls, modules = PackageFileCopier.DESCRIPTOR_MAP[self.package_type]
-        self.dest_desc_msg = desc_cls.from_dict(src_desc_contents)
-        dest_desc_path = os.path.join(self.dest_copy_path, 
-                "{pkg_name}_{pkg_type}.yaml".format(pkg_name=self.dest_package_name, pkg_type=self.package_type))
-        model = RwYang.Model.create_libncx()
+
+        model = RwYang.Model.create_libyang()
         for module in modules.split():
             model.load_module(module) 
 
+        self.dest_desc_msg = desc_cls.from_json(model, json_desc_msg, strict=False)
+
+        # Write to yaml desc file 
+        dest_desc_path = os.path.join(self.dest_copy_path, 
+                "{pkg_name}_{pkg_type}.yaml".format(pkg_name=self.dest_package_name, pkg_type=self.package_type))
         with open(dest_desc_path, "w") as fh:
             fh.write(self.dest_desc_msg.to_yaml(model))
 
+        # Remove copied .yaml, if present 
+        src_desc_file = self.src_package.descriptor_file
         copied_desc_file = os.path.join(self.dest_copy_path, os.path.basename(src_desc_file))
         if os.path.exists(copied_desc_file):
             self.log.debug("Deleting copied yaml from old source %s" % (copied_desc_file))