def verify_base_size(base, size, base_size=0):
        """Check that the base image is not larger than size.
           Since images can't be generally shrunk, enforce this
           constraint taking account of virtual image size.
        """

        # Note(pbrady): The size and min_disk parameters of a glance
        #  image are checked against the instance size before the image
        #  is even downloaded from glance, but currently min_disk is
        #  adjustable and doesn't currently account for virtual disk size,
        #  so we need this extra check here.
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #  nova effectively ignore that size and use the size of the
        #  image is considered a feature at this time, not a bug.

        if size is None:
            return

        if size and not base_size:
            base_size = disk.get_disk_size(base)

        if size < base_size:
            msg = _('%(base)s virtual size %(base_size)s '
                    'larger than flavor root disk size %(size)s')
            LOG.error(msg % {
                'base': base,
                'base_size': base_size,
                'size': size
            })
            raise exception.FlavorDiskTooSmall()
예제 #2
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        if self.rbd is None:
            raise RuntimeError(_('rbd python libraries not found'))

        old_format = True
        features = 0
        if self._supports_layering():
            old_format = False
            features = self.rbd.RBD_FEATURE_LAYERING

        if not os.path.exists(base):
            prepare_template(target=base, max_size=size, *args, **kwargs)
        else:
            self.verify_base_size(base, size)

        # keep using the command line import instead of librbd since it
        # detects zeroes to preserve sparseness in the image
        args = ['--pool', self.pool, base, self.rbd_name]
        if self._supports_layering():
            args += ['--new-format']
        args += self._ceph_args()
        libvirt_utils.import_rbd_image(*args)

        base_size = disk.get_disk_size(base)

        if size and size > base_size:
            self._resize(self.rbd_name, size)
예제 #3
0
    def verify_base_size(base, size, base_size=0):
        """Check that the base image is not larger than size.
           Since images can't be generally shrunk, enforce this
           constraint taking account of virtual image size.
        """

        # Note(pbrady): The size and min_disk parameters of a glance
        #  image are checked against the instance size before the image
        #  is even downloaded from glance, but currently min_disk is
        #  adjustable and doesn't currently account for virtual disk size,
        #  so we need this extra check here.
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #  nova effectively ignore that size and use the size of the
        #  image is considered a feature at this time, not a bug.

        if size is None:
            return

        if size and not base_size:
            base_size = disk.get_disk_size(base)

        if size < base_size:
            msg = _LE('%(base)s virtual size %(base_size)s '
                      'larger than flavor root disk size %(size)s')
            LOG.error(msg % {'base': base,
                              'base_size': base_size,
                              'size': size})
            raise exception.FlavorDiskTooSmall()
예제 #4
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        if self.exists():
            self.connect_disk()
            return

        generating = 'image_id' not in kwargs
        # NOTE(ft): We assume that only root disk is recreated in rescue mode.
        # With this assumption the code becomes more simple and fast.
        if generating:
            sio_utils.verify_volume_size(size)
            self.sio_id = self.driver.create_volume(self.sio_name, size,
                                                    self.extra_specs)
            self.path = self.driver.map_volume(self.sio_id)
            prepare_template(target=self.path, is_block_dev=True,
                             *args, **kwargs)
        else:
            if not os.path.exists(base):
                prepare_template(target=base, *args, **kwargs)

            base_size = disk.get_disk_size(base)
            if (size is None and
                    sio_utils.is_sio_volume_rescuer(self.sio_name)):
                size = sio_utils.choose_volume_size(base_size)
                self.extra_specs = dict(self.extra_specs)
                self.extra_specs[sio_utils.PROVISIONING_TYPE_KEY] = 'thin'
            else:
                sio_utils.verify_volume_size(size)
                self.verify_base_size(base, size, base_size=base_size)

            self.sio_id = self.driver.create_volume(self.sio_name, size,
                                                    self.extra_specs)
            self.path = self.driver.map_volume(self.sio_id)
            self.driver.import_image(base, self.path)
예제 #5
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        if self.rbd is None:
            raise RuntimeError(_('rbd python libraries not found'))

        old_format = True
        features = 0
        if self._supports_layering():
            old_format = False
            features = self.rbd.RBD_FEATURE_LAYERING

        if not os.path.exists(base):
            prepare_template(target=base, max_size=size, *args, **kwargs)
        else:
            self.verify_base_size(base, size)

        # keep using the command line import instead of librbd since it
        # detects zeroes to preserve sparseness in the image
        args = ['--pool', self.pool, base, self.rbd_name]
        if self._supports_layering():
            args += ['--new-format']
        args += self._ceph_args()
        libvirt_utils.import_rbd_image(*args)

        base_size = disk.get_disk_size(base)

        if size and size > base_size:
            self._resize(self.rbd_name, size)
예제 #6
0
파일: imagebackend.py 프로젝트: sdague/nova
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     resize = size > base_size
     size = size if resize else base_size
     libvirt_utils.create_lvm_image(self.vg, self.lv, size, sparse=self.sparse)
     images.convert_image(base, self.path, "raw", run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #7
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     self.verify_base_size(base, size, base_size=base_size)
     resize = size > base_size
     size = size if resize else base_size
     lvm.create_volume(self.vg, self.lv, size, sparse=self.sparse)
     images.convert_image(base, self.path, 'raw', run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #8
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     resize = size > base_size
     size = size if resize else base_size
     libvirt_utils.create_lvm_image(self.vg, self.lv,
                                    size, sparse=self.sparse)
     cmd = ('dd', 'if=%s' % base, 'of=%s' % self.path, 'bs=4M')
     utils.execute(*cmd, run_as_root=True)
     if resize:
         disk.resize2fs(self.path)
예제 #9
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     resize = size > base_size
     size = size if resize else base_size
     libvirt_utils.create_lvm_image(self.vg, self.lv,
                                    size, sparse=self.sparse)
     cmd = ('dd', 'if=%s' % base, 'of=%s' % self.path, 'bs=4M')
     utils.execute(*cmd, run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #10
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     self.verify_base_size(base, size, base_size=base_size)
     resize = size > base_size
     size = size if resize else base_size
     lvm.create_volume(self.vg, self.lv,
                                  size, sparse=self.sparse)
     images.convert_image(base, self.path, 'raw', run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #11
0
파일: imagebackend.py 프로젝트: noorul/nova
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        @utils.synchronized(base, external=True, lock_path=self.lock_path)
        def copy_qcow2_image(base, target, size):
            # TODO(pbrady): Consider copying the cow image here
            # with preallocation=metadata set for performance reasons.
            # This would be keyed on a 'preallocate_images' setting.
            libvirt_utils.create_cow_image(base, target)
            if size:
                disk.extend(target, size)

        # Download the unmodified base image unless we already have a copy.
        if not os.path.exists(base):
            prepare_template(target=base, *args, **kwargs)

        legacy_backing_size = None
        legacy_base = base

        # Determine whether an existing qcow2 disk uses a legacy backing by
        # actually looking at the image itself and parsing the output of the
        # backing file it expects to be using.
        if os.path.exists(self.path):
            backing_path = libvirt_utils.get_disk_backing_file(self.path)
            if backing_path is not None:
                backing_file = os.path.basename(backing_path)
                backing_parts = backing_file.rpartition('_')
                if backing_file != backing_parts[-1] and \
                        backing_parts[-1].isdigit():
                    legacy_backing_size = int(backing_parts[-1])
                    legacy_base += '_%d' % legacy_backing_size
                    legacy_backing_size *= 1024 * 1024 * 1024

        # Create the legacy backing file if necessary.
        if legacy_backing_size:
            if not os.path.exists(legacy_base):
                with fileutils.remove_path_on_error(legacy_base):
                    libvirt_utils.copy_image(base, legacy_base)
                    disk.extend(legacy_base, legacy_backing_size)

        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #            nova effectively ignore that size and use the size of the
        #            image is considered a feature at this time, not a bug.
        disk_size = disk.get_disk_size(base)
        if size and size < disk_size:
            msg = _('%(base)s virtual size %(disk_size)s'
                    'larger than flavor root disk size %(size)s')
            LOG.error(msg % {
                'base': base,
                'disk_size': disk_size,
                'size': size
            })
            raise exception.InstanceTypeDiskTooSmall()
        if not os.path.exists(self.path):
            with fileutils.remove_path_on_error(self.path):
                copy_qcow2_image(base, self.path, size)
예제 #12
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     self.verify_base_size(base, size, base_size=base_size)
     resize = size > base_size
     size = size if resize else base_size
     lvm.create_volume(self.vg, self.lv, size, sparse=self.sparse)
     if self.ephemeral_key_uuid is not None:
         encrypt_lvm_image()
     images.convert_image(base, self.path, "raw", run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #13
0
    def test_get_disk_size(self, mock_execute, mock_exists):
        path = "/some/path"
        example_output = """image: 00000001
file format: raw
virtual size: 4.4M (4592640 bytes)
disk size: 4.4M
"""
        mock_execute.return_value = (example_output, "")
        self.assertEqual(4592640, disk.get_disk_size("/some/path"))
        mock_execute.assert_called_once_with("env", "LC_ALL=C", "LANG=C", "qemu-img", "info", path)
        mock_exists.assert_called_once_with(path)
예제 #14
0
    def test_get_disk_size(self, mock_execute, mock_exists):
        path = '/some/path'
        example_output = """image: 00000001
file format: raw
virtual size: 4.4M (4592640 bytes)
disk size: 4.4M
"""
        mock_execute.return_value = (example_output, '')
        self.assertEqual(4592640, disk.get_disk_size('/some/path'))
        mock_execute.assert_called_once_with('env', 'LC_ALL=C', 'LANG=C',
                                             'qemu-img', 'info', path)
        mock_exists.assert_called_once_with(path)
예제 #15
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        @utils.synchronized(base, external=True, lock_path=self.lock_path)
        def copy_qcow2_image(base, target, size):
            # TODO(pbrady): Consider copying the cow image here
            # with preallocation=metadata set for performance reasons.
            # This would be keyed on a 'preallocate_images' setting.
            libvirt_utils.create_cow_image(base, target)
            if size:
                disk.extend(target, size, use_cow=True)

        # Download the unmodified base image unless we already have a copy.
        if not os.path.exists(base):
            prepare_template(target=base, *args, **kwargs)

        legacy_backing_size = None
        legacy_base = base

        # Determine whether an existing qcow2 disk uses a legacy backing by
        # actually looking at the image itself and parsing the output of the
        # backing file it expects to be using.
        if os.path.exists(self.path):
            backing_path = libvirt_utils.get_disk_backing_file(self.path)
            if backing_path is not None:
                backing_file = os.path.basename(backing_path)
                backing_parts = backing_file.rpartition('_')
                if backing_file != backing_parts[-1] and \
                        backing_parts[-1].isdigit():
                    legacy_backing_size = int(backing_parts[-1])
                    legacy_base += '_%d' % legacy_backing_size
                    legacy_backing_size *= 1024 * 1024 * 1024

        # Create the legacy backing file if necessary.
        if legacy_backing_size:
            if not os.path.exists(legacy_base):
                with fileutils.remove_path_on_error(legacy_base):
                    libvirt_utils.copy_image(base, legacy_base)
                    disk.extend(legacy_base, legacy_backing_size, use_cow=True)

        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #            nova effectively ignore that size and use the size of the
        #            image is considered a feature at this time, not a bug.
        disk_size = disk.get_disk_size(base)
        if size and size < disk_size:
            msg = _('%(base)s virtual size %(disk_size)s'
                    'larger than flavor root disk size %(size)s')
            LOG.error(msg % {'base': base,
                              'disk_size': disk_size,
                              'size': size})
            raise exception.InstanceTypeDiskTooSmall()
        if not os.path.exists(self.path):
            with fileutils.remove_path_on_error(self.path):
                copy_qcow2_image(base, self.path, size)
예제 #16
0
파일: test_utils.py 프로젝트: yaochi/nova
    def test_get_disk_size(self):
        self.mox.StubOutWithMock(os.path, 'exists')
        self.mox.StubOutWithMock(utils, 'execute')
        os.path.exists('/some/path').AndReturn(True)
        utils.execute('env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
                      '/some/path').AndReturn(('''image: 00000001
file format: raw
virtual size: 4.4M (4592640 bytes)
disk size: 4.4M''', ''))

        # Start test
        self.mox.ReplayAll()
        self.assertEqual(disk.get_disk_size('/some/path'), 4592640)
예제 #17
0
    def test_get_disk_size(self):
        self.mox.StubOutWithMock(os.path, "exists")
        self.mox.StubOutWithMock(utils, "execute")
        os.path.exists("/some/path").AndReturn(True)
        utils.execute("env", "LC_ALL=C", "LANG=C", "qemu-img", "info", "/some/path").AndReturn(
            (
                """image: 00000001
file format: raw
virtual size: 4.4M (4592640 bytes)
disk size: 4.4M""",
                "",
            )
        )

        # Start test
        self.mox.ReplayAll()
        self.assertEqual(disk.get_disk_size("/some/path"), 4592640)
예제 #18
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     self.verify_base_size(base, size, base_size=base_size)
     resize = size > base_size
     size = size if resize else base_size
     lvm.create_volume(self.vg, self.lv, size, sparse=self.sparse)
     if self.ephemeral_key_uuid is not None:
         encrypt_lvm_image()
     # NOTE: by calling convert_image_unsafe here we're
     # telling qemu-img convert to do format detection on the input,
     # because we don't know what the format is. For example,
     # we might have downloaded a qcow2 image, or created an
     # ephemeral filesystem locally, we just don't know here. Having
     # audited this, all current sources have been sanity checked,
     # either because they're locally generated, or because they have
     # come from images.fetch_to_raw. However, this is major code smell.
     images.convert_image_unsafe(base, self.path, self.driver_format, run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #19
0
 def create_lvm_image(base, size):
     base_size = disk.get_disk_size(base)
     self.verify_base_size(base, size, base_size=base_size)
     resize = size > base_size if size else False
     size = size if resize else base_size
     lvm.create_volume(self.vg, self.lv,
                                  size, sparse=self.sparse)
     if self.ephemeral_key_uuid is not None:
         encrypt_lvm_image()
     # NOTE: by calling convert_image_unsafe here we're
     # telling qemu-img convert to do format detection on the input,
     # because we don't know what the format is. For example,
     # we might have downloaded a qcow2 image, or created an
     # ephemeral filesystem locally, we just don't know here. Having
     # audited this, all current sources have been sanity checked,
     # either because they're locally generated, or because they have
     # come from images.fetch_to_raw. However, this is major code smell.
     images.convert_image_unsafe(base, self.path, self.driver_format,
                                 run_as_root=True)
     if resize:
         disk.resize2fs(self.path, run_as_root=True)
예제 #20
0
파일: imagebackend.py 프로젝트: sdague/nova
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        @utils.synchronized(base, external=True, lock_path=self.lock_path)
        def copy_qcow2_image(base, target, size):
            # TODO(pbrady): Consider copying the cow image here
            # with preallocation=metadata set for performance reasons.
            # This would be keyed on a 'preallocate_images' setting.
            libvirt_utils.create_cow_image(base, target)
            if size:
                disk.extend(target, size)

        if not os.path.exists(base):
            prepare_template(target=base, *args, **kwargs)
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #            nova effectively ignore that size and use the size of the
        #            image is considered a feature at this time, not a bug.
        if size and size < disk.get_disk_size(base):
            LOG.error("%s virtual size larger than flavor root disk size %s" % (base, size))
            raise exception.InstanceTypeDiskTooSmall()
        if not os.path.exists(self.path):
            with utils.remove_path_on_error(self.path):
                copy_qcow2_image(base, self.path, size)
예제 #21
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        @utils.synchronized(base, external=True, lock_path=self.lock_path)
        def copy_qcow2_image(base, target, size):
            # TODO(pbrady): Consider copying the cow image here
            # with preallocation=metadata set for performance reasons.
            # This would be keyed on a 'preallocate_images' setting.
            libvirt_utils.create_cow_image(base, target)
            if size:
                disk.extend(target, size)

        if not os.path.exists(base):
            prepare_template(target=base, *args, **kwargs)
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #            nova effectively ignore that size and use the size of the
        #            image is considered a feature at this time, not a bug.
        if size and size < disk.get_disk_size(base):
            LOG.error('%s virtual size larger than flavor root disk size %s' %
                      (base, size))
            raise exception.InstanceTypeDiskTooSmall()
        if not os.path.exists(self.path):
            with utils.remove_path_on_error(self.path):
                copy_qcow2_image(base, self.path, size)
예제 #22
0
    def create_image(self, prepare_template, base, size, *args, **kwargs):
        @utils.synchronized(base, external=True, lock_path=self.lock_path)
        def copy_qcow2_image(base, target, size):
            qcow2_base = base
            if size:
                size_gb = size / (1024 * 1024 * 1024)
                qcow2_base += '_%d' % size_gb
                if not os.path.exists(qcow2_base):
                    with utils.remove_path_on_error(qcow2_base):
                        libvirt_utils.copy_image(base, qcow2_base)
                        disk.extend(qcow2_base, size)
            libvirt_utils.create_cow_image(qcow2_base, target)

        prepare_template(target=base, *args, **kwargs)
        # NOTE(cfb): Having a flavor that sets the root size to 0 and having
        #            nova effectively ignore that size and use the size of the
        #            image is considered a feature at this time, not a bug.
        if size and size < disk.get_disk_size(base):
            LOG.error('%s virtual size larger than flavor root disk size %s' %
                      (base, size))
            raise exception.ImageTooLarge()
        with utils.remove_path_on_error(self.path):
            copy_qcow2_image(base, self.path, size)
예제 #23
0
 def get_disk_size(self, name):
     disk.get_disk_size(name)
예제 #24
0
 def get_disk_size(self, name):
     return disk.get_disk_size(name)
예제 #25
0
 def get_disk_size(self, name):
     return disk.get_disk_size(name)
예제 #26
0
 def get_disk_size(self, name):
     disk.get_disk_size(name)