d4aa455d53
Adapt "nova resize" code to support Virtuozzo ploop disks. As far as ploop disks are in fact directories we add '-r' argument to all utilities that deal with instance' disks such as cp, rsync and scp. Thus we copy disks universally whether they are folders or files. Also using "prl_disk_tool" instead of "qemu-img" is better for ploop images because it resizes guest filesystem as well. We can't resize disks from guest OS in containers, because they are not allowed to write directly to block device. ploop tool can resize partition table and internal filesystem, but only for container's disks. Such disks must have only one partition with ext filesystem. prl_disk_tool can resize disks with internal filesystems and doesn't require any special layout so it can resize disks for virtual machines. So it's better to use this tool instead of ploop. Also we make compute.filters more strict We call "ploop" only with "restore-descriptor" argument And we set disk size in megabytes for prl_disk_tool Co-Authored-By: Dmitry Guryanov <dguryanov@parallels.com> Depends-On: I04c4379459c2fc1fd4801ec2aad53d0f6053b6d6 Change-Id: I38dbf73beb01fe1939ddca63fbfedbec1dc3c826 Implements: blueprint virtuozzo-instance-resize-support
132 lines
3.5 KiB
Python
132 lines
3.5 KiB
Python
#
|
|
# Copyright (C) 2014 Red Hat, 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.
|
|
#
|
|
|
|
from oslo_utils import strutils
|
|
|
|
from nova import exception
|
|
|
|
FORMAT_RAW = "raw"
|
|
FORMAT_QCOW2 = "qcow2"
|
|
FORMAT_PLOOP = "ploop"
|
|
|
|
ALL_FORMATS = [
|
|
FORMAT_RAW,
|
|
FORMAT_QCOW2,
|
|
FORMAT_PLOOP,
|
|
]
|
|
|
|
|
|
class Image(object):
|
|
"""Base class for all image types.
|
|
|
|
All image types have a format, though for many of
|
|
them only a subset of formats will commonly be
|
|
used. For example, block devices are almost
|
|
always going to be FORMAT_RAW. Though it is in
|
|
fact possible from a technical POV to store a
|
|
qcow2 data inside a block device, Nova does not
|
|
(at this time) make use of such possibilities.
|
|
"""
|
|
|
|
def __init__(self, format):
|
|
"""Create a new abstract image
|
|
|
|
:param format: one of the format constants
|
|
"""
|
|
super(Image, self).__init__()
|
|
|
|
self.format = format
|
|
|
|
if format not in ALL_FORMATS:
|
|
raise exception.InvalidImageFormat(format=format)
|
|
|
|
def __repr__(self):
|
|
msg = "<" + self.__class__.__name__ + ":" + str(self.__dict__) + ">"
|
|
return strutils.mask_password(msg)
|
|
|
|
def __eq__(self, other):
|
|
return ((self.__class__ == other.__class__) and
|
|
(self.__dict__ == other.__dict__))
|
|
|
|
def __hash__(self):
|
|
return hash(str(self.__dict__))
|
|
|
|
|
|
class LocalImage(Image):
|
|
"""Class for images that are paths within the
|
|
local filesystem
|
|
"""
|
|
|
|
def __init__(self, path, format):
|
|
"""Create a new local image object
|
|
|
|
:param path: qualified filename of the image
|
|
:param format: one of the format constants
|
|
"""
|
|
super(LocalImage, self).__init__(format)
|
|
|
|
self.path = path
|
|
|
|
|
|
class LocalFileImage(LocalImage):
|
|
"""Class for images that are files on a locally
|
|
accessible filesystem
|
|
"""
|
|
|
|
def __init__(self, path, format):
|
|
"""Create a new local file object
|
|
|
|
:param path: qualified filename of the image
|
|
:param format: one of the format constants
|
|
"""
|
|
super(LocalFileImage, self).__init__(path, format)
|
|
|
|
|
|
class LocalBlockImage(LocalImage):
|
|
"""Class for images that are block devices on
|
|
the local host
|
|
"""
|
|
|
|
def __init__(self, path):
|
|
"""Create a new local file object
|
|
|
|
:param path: qualified filename of the image
|
|
"""
|
|
super(LocalBlockImage, self).__init__(path, FORMAT_RAW)
|
|
|
|
|
|
class RBDImage(Image):
|
|
"""Class for images that are volumes on a remote
|
|
RBD server
|
|
"""
|
|
|
|
def __init__(self, name, pool, user, password, servers):
|
|
"""Create a new RBD image object
|
|
|
|
:param name: name of the image relative to the pool
|
|
:param pool: name of the pool holding the image
|
|
:param user: username to authenticate as
|
|
:param password: credentials for authenticating with
|
|
:param servers: list of hostnames for the server
|
|
"""
|
|
super(RBDImage, self).__init__(FORMAT_RAW)
|
|
|
|
self.name = name
|
|
self.pool = pool
|
|
self.user = user
|
|
self.password = password
|
|
self.servers = servers
|