summaryrefslogtreecommitdiff
path: root/legacy/gcimagebundle/gcimagebundlelib/fs_copy.py
diff options
context:
space:
mode:
authorZach Marano <zmarano@google.com>2016-04-19 19:07:01 -0700
committerZach Marano <zmarano@google.com>2016-04-19 19:07:01 -0700
commit827c16e068ecb768abd722d0946c39e4cadd7157 (patch)
treee7f8daf0a7c419bda4294a212c12b35ae1ea11a7 /legacy/gcimagebundle/gcimagebundlelib/fs_copy.py
parentb7c2813b98fa723903ba9d63d32fcb4f8468f166 (diff)
parentfd4d83b30609219fb42e5bc17dc21d576d477c7f (diff)
downloadgoogle-compute-image-packages-827c16e068ecb768abd722d0946c39e4cadd7157.tar.gz
Merge pull request #215 from zmarano/master
Move gcimagebundle to legacy and update gce-disk-expand README.
Diffstat (limited to 'legacy/gcimagebundle/gcimagebundlelib/fs_copy.py')
-rw-r--r--legacy/gcimagebundle/gcimagebundlelib/fs_copy.py180
1 files changed, 180 insertions, 0 deletions
diff --git a/legacy/gcimagebundle/gcimagebundlelib/fs_copy.py b/legacy/gcimagebundle/gcimagebundlelib/fs_copy.py
new file mode 100644
index 0000000..e9adc91
--- /dev/null
+++ b/legacy/gcimagebundle/gcimagebundlelib/fs_copy.py
@@ -0,0 +1,180 @@
+# Copyright 2013 Google Inc. All Rights Reserved.
+#
+# 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.
+
+
+"""Creates a copy of specified directories\files."""
+
+
+
+import logging
+import os
+import re
+
+from gcimagebundlelib import manifest
+from gcimagebundlelib import utils
+
+
+class FsCopyError(Exception):
+ """Error occured in fs copy operation."""
+
+
+class InvalidFsCopyError(Exception):
+ """Error when verification fails before fs copying."""
+
+
+class FsCopy(object):
+ """Specifies which files/directories must be copied."""
+
+ def __init__(self):
+ # Populate the required parameters with None so we can verify.
+ self._output_tarfile = None
+ self._srcs = []
+ self._excludes = []
+ self._key = None
+ self._recursive = True
+ self._fs_size = 0
+ self._ignore_hard_links = False
+ self._platform = None
+ self._overwrite_list = []
+ self._scratch_dir = '/tmp'
+ self._disk = None
+ self._manifest = manifest.ImageManifest(is_gce_instance=utils.IsRunningOnGCE())
+
+ def SetTarfile(self, tar_file):
+ """Sets tar file which will contain file system copy.
+
+ Args:
+ tar_file: path to a tar file.
+ """
+ self._output_tarfile = tar_file
+
+ def AddDisk(self, disk):
+ """Adds the disk which should be bundled.
+
+ Args:
+ disk: The block disk that needs to be bundled.
+ """
+ self._disk = disk
+
+ def AddSource(self, src, arcname='', recursive=True):
+ """Adds a source to be copied to the tar file.
+
+ Args:
+ src: path to directory/file to be copied.
+ arcname: name of src in the tar archive. If arcname is empty, then instead
+ of copying src itself only its content is copied.
+ recursive: specifies if src directory should be copied recursively.
+
+ Raises:
+ ValueError: If src path doesn't exist.
+ """
+ if not os.path.exists(src):
+ raise ValueError('invalid path')
+ # Note that there is a fundamental asymmetry here as
+ # abspath('/') => '/' while abspath('/usr/') => '/usr'.
+ # This creates some subtleties elsewhere in the code.
+ self._srcs.append((os.path.abspath(src), arcname, recursive))
+
+ def AppendExcludes(self, excludes):
+ """Adds a file/directory to be excluded from file copy.
+
+ Args:
+ excludes: A list of ExcludeSpec objects.
+ """
+ self._excludes.extend(excludes)
+
+ def SetKey(self, key):
+ """Sets a key to use to sign the archive digest.
+
+ Args:
+ key: key to use to sign the archive digest.
+ """
+ # The key is ignored for now.
+ # TODO(user): sign the digest with the key
+ self._key = key
+
+ def SetPlatform(self, platform):
+ """Sets the OS platform which is used to create an image.
+
+ Args:
+ platform: OS platform specific settings.
+ """
+ self._platform = platform
+ logging.warning('overwrite list = %s',
+ ' '.join(platform.GetOverwriteList()))
+ self._overwrite_list = [re.sub('^/', '', x)
+ for x in platform.GetOverwriteList()]
+
+ def _SetManifest(self, image_manifest):
+ """For test only, allows to set a test manifest object."""
+ self._manifest = image_manifest
+
+ def SetScratchDirectory(self, directory):
+ """Sets a directory used for storing intermediate results.
+
+ Args:
+ directory: scratch directory path.
+ """
+ self._scratch_dir = directory
+
+ def IgnoreHardLinks(self):
+ """Requests that hard links should not be copied as hard links."""
+
+ # TODO(user): I don't see a reason for this option to exist. Currently
+ # there is a difference in how this option is interpreted between FsTarball
+ # and FsRawDisk. FsTarball only copies one hard link to an inode and ignores
+ # the rest of them. FsRawDisk copies the content of a file that hard link is
+ # pointing to instead of recreating a hard link. Either option seems useless
+ # for creating a copy of a file system.
+ self._ignore_hard_links = True
+
+ def Verify(self):
+ """Verify if we have all the components to build a tar."""
+ self._Verify()
+
+ def Bundleup(self):
+ """Creates the tar image based on set parameters.
+
+ Returns:
+ the SHA1 digest of the the tar archive.
+ """
+ return (0, None)
+
+ def _Verify(self):
+ """Verifies the tar attributes. Raises InvalidTarballError.
+
+ Raises:
+ InvalidFsCopyError: If not all required parameters are set.
+ FsCopyError: If source file does not exist.
+ """
+ if not self._output_tarfile or not self._srcs or not self._key:
+ raise InvalidFsCopyError('Incomplete copy spec')
+ for (src, _, _) in self._srcs:
+ if not os.path.exists(src):
+ raise FsCopyError('%s does not exists' % src)
+
+ def _ShouldExclude(self, filename):
+ """"Checks if a file/directory are excluded from a copy.
+
+ Args:
+ filename: a file/directory path.
+
+ Returns:
+ True if a file/directory shouldn't be copied, False otherwise.
+ """
+ for spec in self._excludes:
+ if spec.ShouldExclude(filename):
+ logging.info('tarfile: Excluded %s', filename)
+ return True
+ return False