--- /dev/null
+#
+# Copyright 2016 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): Varun Prasad
+# Creation Date: 09/25/2016
+#
+
+import asyncio
+import os
+
+import rift.package.store as store
+import rift.package.package
+
+from .base import AbstractPackageManagerProxy
+
+
+class UnknownPackageType(Exception):
+ pass
+
+
+class FileSystemProxy(AbstractPackageManagerProxy):
+ """Proxy for Filesystem based store.
+ """
+ PACKAGE_TYPE_MAP = {"vnfd": store.VnfdPackageFilesystemStore,
+ "nsd": store.NsdPackageFilesystemStore}
+
+ # Refer: https://confluence.riftio.com/display/ATG/Launchpad+package+formats
+ SCHEMA = {
+ "nsd": ["icons", "ns_config", "scripts", "vnf_config"],
+ "vnfd": ["charms", "cloud_init", "icons", "images", "scripts"]
+ }
+
+ SCHEMA_TO_PERMS = {'scripts': 0o777}
+
+ def __init__(self, loop, log):
+ self.loop = loop
+ self.log = log
+ self.store_cache = {}
+
+ def _get_store(self, package_type):
+ store_cls = self.PACKAGE_TYPE_MAP[package_type]
+ store = self.store_cache.setdefault(package_type, store_cls(self.log))
+
+ return store
+
+ @asyncio.coroutine
+ def endpoint(self, package_type, package_id):
+ package_type = package_type.lower()
+ if package_type not in self.PACKAGE_TYPE_MAP:
+ raise UnknownPackageType()
+
+ store = self._get_store(package_type)
+
+ package = store._get_package_dir(package_id)
+ rel_path = os.path.relpath(package, start=store.root_dir)
+
+ url = "https://127.0.0.1:4567/api/package/{}/{}".format(package_type, rel_path)
+
+ return url
+
+ @asyncio.coroutine
+ def schema(self, package_type):
+ package_type = package_type.lower()
+ if package_type not in self.PACKAGE_TYPE_MAP:
+ raise UnknownPackageType()
+
+ return self.SCHEMA[package_type]
+
+ def package_file_add(self, new_file, package_type, package_id, package_path):
+ # Get the schema from thr package path
+ # the first part will always be the vnfd/nsd name
+ mode = 0o664
+ components = package_path.split("/")
+ if len(components) > 2:
+ schema = components[1]
+ mode = self.SCHEMA_TO_PERMS.get(schema, mode)
+
+ # Fetch the package object
+ package_type = package_type.lower()
+ store = self._get_store(package_type)
+ package = store.get_package(package_id)
+
+ # Construct abs path of the destination obj
+ path = store._get_package_dir(package_id)
+ dest_file = os.path.join(path, package_path)
+
+ try:
+ package.insert_file(new_file, dest_file, package_path, mode=mode)
+ except rift.package.package.PackageAppendError as e:
+ self.log.exception(e)
+ return False
+
+ return True
+
+ def package_file_delete(self, package_type, package_id, package_path):
+ package_type = package_type.lower()
+ store = self._get_store(package_type)
+ package = store.get_package(package_id)
+
+ # package_path has to be relative, so strip off the starting slash if
+ # provided incorrectly.
+ if package_path[0] == "/":
+ package_path = package_path[1:]
+
+ # Construct abs path of the destination obj
+ path = store._get_package_dir(package_id)
+ dest_file = os.path.join(path, package_path)
+
+ try:
+ package.delete_file(dest_file, package_path)
+ except rift.package.package.PackageAppendError as e:
+ self.log.exception(e)
+ return False
+
+ return True
+