diff options
author | Zach Marano <zmarano@google.com> | 2016-04-19 19:07:01 -0700 |
---|---|---|
committer | Zach Marano <zmarano@google.com> | 2016-04-19 19:07:01 -0700 |
commit | 827c16e068ecb768abd722d0946c39e4cadd7157 (patch) | |
tree | e7f8daf0a7c419bda4294a212c12b35ae1ea11a7 /legacy/gcimagebundle/gcimagebundlelib/fs_copy.py | |
parent | b7c2813b98fa723903ba9d63d32fcb4f8468f166 (diff) | |
parent | fd4d83b30609219fb42e5bc17dc21d576d477c7f (diff) | |
download | google-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.py | 180 |
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 |