¡@

Home 

OpenStack Study: snapshotops.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2012 Cloudbase Solutions Srl

# 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.

"""

Management class for VM snapshot operations.

"""

import os

from oslo.config import cfg

from nova.compute import task_states

from nova.image import glance

from nova.openstack.common.gettextutils import _

from nova.openstack.common import log as logging

from nova.virt.hyperv import utilsfactory

CONF = cfg.CONF

LOG = logging.getLogger(__name__)

**** CubicPower OpenStack Study ****

class SnapshotOps(object):

**** CubicPower OpenStack Study ****

    def __init__(self):

        self._pathutils = utilsfactory.get_pathutils()

        self._vmutils = utilsfactory.get_vmutils()

        self._vhdutils = utilsfactory.get_vhdutils()

**** CubicPower OpenStack Study ****

    def _save_glance_image(self, context, name, image_vhd_path):

        (glance_image_service,

         image_id) = glance.get_remote_image_service(context, name)

        image_metadata = {"is_public": False,

                          "disk_format": "vhd",

                          "container_format": "bare",

                          "properties": {}}

        with self._pathutils.open(image_vhd_path, 'rb') as f:

            glance_image_service.update(context, image_id, image_metadata, f)

**** CubicPower OpenStack Study ****

    def snapshot(self, context, instance, name, update_task_state):

        """Create snapshot from a running VM instance."""

        instance_name = instance["name"]

        LOG.debug(_("Creating snapshot for instance %s"), instance_name)

        snapshot_path = self._vmutils.take_vm_snapshot(instance_name)

        update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD)

        export_dir = None

        try:

            src_vhd_path = self._pathutils.lookup_root_vhd_path(instance_name)

            LOG.debug(_("Getting info for VHD %s"), src_vhd_path)

            src_base_disk_path = self._vhdutils.get_vhd_parent_path(

                src_vhd_path)

            export_dir = self._pathutils.get_export_dir(instance_name)

            dest_vhd_path = os.path.join(export_dir, os.path.basename(

                src_vhd_path))

            LOG.debug(_('Copying VHD %(src_vhd_path)s to %(dest_vhd_path)s'),

                      {'src_vhd_path': src_vhd_path,

                       'dest_vhd_path': dest_vhd_path})

            self._pathutils.copyfile(src_vhd_path, dest_vhd_path)

            image_vhd_path = None

            if not src_base_disk_path:

                image_vhd_path = dest_vhd_path

            else:

                basename = os.path.basename(src_base_disk_path)

                dest_base_disk_path = os.path.join(export_dir, basename)

                LOG.debug(_('Copying base disk %(src_vhd_path)s to '

                            '%(dest_base_disk_path)s'),

                          {'src_vhd_path': src_vhd_path,

                           'dest_base_disk_path': dest_base_disk_path})

                self._pathutils.copyfile(src_base_disk_path,

                                         dest_base_disk_path)

                LOG.debug(_("Reconnecting copied base VHD "

                            "%(dest_base_disk_path)s and diff "

                            "VHD %(dest_vhd_path)s"),

                          {'dest_base_disk_path': dest_base_disk_path,

                           'dest_vhd_path': dest_vhd_path})

                self._vhdutils.reconnect_parent_vhd(dest_vhd_path,

                                                    dest_base_disk_path)

                LOG.debug(_("Merging base disk %(dest_base_disk_path)s and "

                            "diff disk %(dest_vhd_path)s"),

                          {'dest_base_disk_path': dest_base_disk_path,

                           'dest_vhd_path': dest_vhd_path})

                self._vhdutils.merge_vhd(dest_vhd_path, dest_base_disk_path)

                image_vhd_path = dest_base_disk_path

            LOG.debug(_("Updating Glance image %(name)s with content from "

                        "merged disk %(image_vhd_path)s"),

                      {'name': name, 'image_vhd_path': image_vhd_path})

            update_task_state(task_state=task_states.IMAGE_UPLOADING,

                              expected_state=task_states.IMAGE_PENDING_UPLOAD)

            self._save_glance_image(context, name, image_vhd_path)

            LOG.debug(_("Snapshot image %(name)s updated for VM "

                        "%(instance_name)s"),

                      {'name': name, 'instance_name': instance_name})

        finally:

            try:

                LOG.debug(_("Removing snapshot %s"), name)

                self._vmutils.remove_vm_snapshot(snapshot_path)

            except Exception as ex:

                LOG.exception(ex)

                LOG.warning(_('Failed to remove snapshot for VM %s')

                            % instance_name)

            if export_dir:

                LOG.debug(_('Removing directory: %s'), export_dir)

                self._pathutils.rmtree(export_dir)