Added file digest computation

Support to compute file digest and save it to manifest file. Also extend
the manifest file module to be able to write content into temporary
file.

Change-Id: If1f3f42799eb527bdeac418d1a40aa203641f628
Issue-ID: VNFSDK-174
Signed-off-by: Lianhao Lu <lianhao.lu@intel.com>
diff --git a/vnfsdk_pkgtools/cli/__main__.py b/vnfsdk_pkgtools/cli/__main__.py
index 005a1ac..88776de 100644
--- a/vnfsdk_pkgtools/cli/__main__.py
+++ b/vnfsdk_pkgtools/cli/__main__.py
@@ -87,6 +87,10 @@
     csar_create.add_argument(
         '--licenses',
         help='Directory containing license information, relative to service template directory')
+    csar_create.add_argument(
+        '--digest',
+        choices=['SHA256', 'SHA512'],
+        help='If present, means to check the file deigest in manifest;  compute the digest using the specified hash algorithm of all files in the csar package to be put into the manifest file')
 
 
     csar_open = subparsers.add_parser('csar-open')
diff --git a/vnfsdk_pkgtools/packager/csar.py b/vnfsdk_pkgtools/packager/csar.py
index b4bee29..31fba8b 100644
--- a/vnfsdk_pkgtools/packager/csar.py
+++ b/vnfsdk_pkgtools/packager/csar.py
@@ -21,6 +21,7 @@
 import requests
 from ruamel import yaml # @UnresolvedImport
 
+from vnfsdk_pkgtools.packager import manifest
 
 META_FILE = 'TOSCA-Metadata/TOSCA.meta'
 META_FILE_VERSION_KEY = 'TOSCA-Meta-File-Version'
@@ -90,6 +91,12 @@
                        msg='Please specify a valid manifest file.',
                        check_dir=False)
         metadata[META_ENTRY_MANIFEST_FILE_KEY] = args.manifest
+        manifest_file = manifest.Manifest(source, args.manifest) 
+        manifest_file_full_path = os.path.join(source, args.manifest)
+    else:
+        manifest_file = None
+        manifest_file_full_path = None
+
 
     if(args.history):
         check_file_dir(root=source,
@@ -117,9 +124,14 @@
         for root, dirs, files in os.walk(source):
             for file in files:
                 file_full_path = os.path.join(root, file)
-                file_relative_path = os.path.relpath(file_full_path, source)
-                logger.debug('Writing to archive: {0}'.format(file_relative_path))
-                f.write(file_full_path, file_relative_path)
+                # skip manifest file here in case we need to generate digest
+                if file_full_path!=manifest_file_full_path:
+                    file_relative_path = os.path.relpath(file_full_path, source)
+                    logger.debug('Writing to archive: {0}'.format(file_relative_path))
+                    f.write(file_full_path, file_relative_path)
+                    if manifest_file and args.digest:
+                        logger.debug('Update file digest: {0}'.format(file_relative_path))
+                        manifest_file.add_file(file_relative_path, args.digest)
             # add empty dir
             for dir in dirs:
                 dir_full_path = os.path.join(root, dir)
@@ -128,6 +140,13 @@
                     logger.debug('Writing to archive: {0}'.format(dir_relative_path))
                     f.write(dir_full_path + os.sep, dir_relative_path)
 
+        if manifest_file:
+            if args.digest:
+                logger.debug('Update manifest file to temporary file')
+                manifest_file_full_path = manifest_file.update_to_file(True)
+            logger.debug('Writing to archive: {0}'.format(args.manifest))
+            f.write(manifest_file_full_path, args.manifest)
+
         logger.debug('Writing new metadata file to {0}'.format(META_FILE))
         f.writestr(META_FILE, yaml.dump(metadata, default_flow_style=False))
 
@@ -149,6 +168,7 @@
         self.source = os.path.expanduser(source)
         self.destination = os.path.expanduser(destination)
         self.metadata = {}
+        self.manifest = None
         try:
             if not os.path.exists(self.source):
                 raise ValueError('{0} does not exists. Please specify a valid CSAR path.'
@@ -247,6 +267,9 @@
                             'The manifest file {0} referenced by the metadata '
                             'file does not exist.'.format(self.entry_manifest_file),
                             check_dir=False)
+             self.manifest = manifest.Manifest(self.destination,
+                                               self.entry_manifest_file)
+
 
         if(self.entry_history_file):
              check_file_dir(self.destination,
diff --git a/vnfsdk_pkgtools/packager/manifest.py b/vnfsdk_pkgtools/packager/manifest.py
index a2d9d70..d819a70 100644
--- a/vnfsdk_pkgtools/packager/manifest.py
+++ b/vnfsdk_pkgtools/packager/manifest.py
@@ -15,6 +15,7 @@
 
 from collections import namedtuple
 import os
+import tempfile
 
 import udatetime
 
@@ -158,7 +159,13 @@
             ret += "Hash: %s\n" % digest[1]
         return ret
 
-    def update_to_file(self):
+    def update_to_file(self, temporary=False):
         content = self.return_as_string()
-        with open(os.path.join(self.root, self.path), 'w') as fp:
+        if temporary:
+            abs_path = tempfile.mktemp()
+        else:
+            abs_path = os.path.abspath(os.path.join(self.root, self.path))
+
+        with open(abs_path, 'w') as fp:
             fp.write(content)
+        return abs_path