X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=rwlaunchpad%2Fplugins%2Frwpkgmgr%2Frift%2Ftasklets%2Frwpkgmgr%2Fdownloader%2Fcopy.py;fp=rwlaunchpad%2Fplugins%2Frwpkgmgr%2Frift%2Ftasklets%2Frwpkgmgr%2Fdownloader%2Fcopy.py;h=fa3dd3e351326a5d76e399dcce1a2900e1901262;hb=ffd2636644e9e62b42ddcb1dbe2c4a6e77507a70;hp=0000000000000000000000000000000000000000;hpb=7295f64eb5dd9d75b1dd272567c99304b65a7d0a;p=osm%2FSO.git diff --git a/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/downloader/copy.py b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/downloader/copy.py new file mode 100644 index 00000000..fa3dd3e3 --- /dev/null +++ b/rwlaunchpad/plugins/rwpkgmgr/rift/tasklets/rwpkgmgr/downloader/copy.py @@ -0,0 +1,199 @@ +# +# Copyright 2017 RIFT.IO Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Author(s): Nandan Sinha +# + +import os +import uuid +import shutil +import enum + +import gi +gi.require_version('RwVnfdYang', '1.0') +gi.require_version('RwNsdYang', '1.0') +from gi.repository import ( + RwYang, + NsdYang, + VnfdYang, + RwVnfdYang, + RwNsdYang, + RwPkgMgmtYang +) + +class PackageCopyError(Exception): + pass + +class CopyStatus(enum.Enum): + UNINITIATED = 0 + STARTED = 1 + IN_PROGRESS = 2 + COMPLETED = 3 + FAILED = 4 + CANCELLED = 5 + +TaskStatus = RwPkgMgmtYang.TaskStatus + +class CopyMeta: + STATUS_MAP = { + CopyStatus.STARTED: TaskStatus.QUEUED.value_nick.upper(), + CopyStatus.UNINITIATED: TaskStatus.QUEUED.value_nick.upper(), + CopyStatus.IN_PROGRESS: TaskStatus.IN_PROGRESS.value_nick.upper(), + CopyStatus.COMPLETED: TaskStatus.COMPLETED.value_nick.upper(), + CopyStatus.FAILED: TaskStatus.FAILED.value_nick.upper(), + CopyStatus.CANCELLED: TaskStatus.CANCELLED.value_nick.upper() + } + + def __init__(self, transaction_id): + self.transaction_id = transaction_id + self.state = CopyStatus.UNINITIATED + + def set_state(self, state): + self.state = state + + def as_dict(self): + return self.__dict__ + + def to_yang(self): + job = RwPkgMgmtYang.CopyJob.from_dict({ + "transaction_id": self.transaction_id, + "status": CopyMeta.STATUS_MAP[self.state] + }) + return job + +class PackageFileCopier: + DESCRIPTOR_MAP = { + "vnfd": (RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd, 'vnfd rw-vnfd'), + "nsd" : (RwNsdYang.YangData_Nsd_NsdCatalog_Nsd, 'nsd rw-nsd') + } + + @classmethod + def from_rpc_input(cls, rpc_input, proxy, log=None): + return cls( + rpc_input.package_id, + rpc_input.package_type, + rpc_input.package_name, + proxy = proxy, + log=log) + + def __init__(self, + pkg_id, + pkg_type, + pkg_name, + proxy, + log): + self.src_package_id = pkg_id + self.package_type = pkg_type.lower() + self.dest_package_name = pkg_name + self.dest_package_id = str(uuid.uuid4()) + self.transaction_id = str(uuid.uuid4()) + self.proxy = proxy + self.log = log + self.meta = CopyMeta(self.transaction_id) + self.src_package = None + self.dest_desc_msg = None + + # 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()) + + def _copy_tree(self): + """ + Locate directory tree of the source descriptor folder. + Copy directory tree to destination descriptor folder. + + """ + store = self.proxy._get_store(self.package_type) + src_path = store._get_package_dir(self.src_package_id) + self.src_package = store.get_package(self.src_package_id) + src_desc_name = self.src_package.descriptor_name + src_copy_path = os.path.join(src_path, src_desc_name) + + self.dest_copy_path = os.path.join(store.DEFAULT_ROOT_DIR, + self.dest_package_id, + self.dest_package_name) + self.log.debug("Copying contents from {src} to {dest}". + format(src=src_copy_path, dest=self.dest_copy_path)) + + shutil.copytree(src_copy_path, self.dest_copy_path) + + 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. + + """ + src_desc_file = self.src_package.descriptor_file + src_desc_contents = self.src_package.descriptor_msg.as_dict() + src_desc_contents.update( + id =self.dest_package_id, + name = self.dest_package_name, + short_name = self.dest_package_name + ) + + 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() + for module in modules.split(): + model.load_module(module) + + with open(dest_desc_path, "w") as fh: + fh.write(self.dest_desc_msg.to_yaml(model)) + + 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)) + os.remove(copied_desc_file) + + def copy(self): + try: + if self.package_type not in PackageFileCopier.DESCRIPTOR_MAP: + raise PackageCopyError("Package type {} not currently supported for copy operations".format(self.package_type)) + + self._copy_tree() + self._create_descriptor_file() + self.copy_succeeded() + + except Exception as e: + self.log.exception(str(e)) + self.copy_failed() + + self.copy_finished() + + def copy_failed(self): + self.meta.set_state(CopyStatus.FAILED) + self.call_delegate("on_download_failed") + + def copy_progress(self): + self.meta.set_state(CopyStatus.IN_PROGRESS) + self.call_delegate("on_download_progress") + + def copy_succeeded(self): + self.meta.set_state(CopyStatus.COMPLETED) + self.call_delegate("on_download_succeeded") + + def copy_finished(self): + self.call_delegate("on_download_finished") +