¡@

Home 

OpenStack Study: vdi_through_dev.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2013 OpenStack Foundation

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

import contextlib

import eventlet

from eventlet import greenio

import os

import tarfile

from nova.image import glance

from nova import utils

from nova.virt.xenapi import vm_utils

**** CubicPower OpenStack Study ****

class VdiThroughDevStore(object):

"""Deal with virtual disks by attaching them to the OS domU.

At the moment it supports upload to Glance, and the upload format is a raw

disk inside a tgz.

"""

**** CubicPower OpenStack Study ****

    def upload_image(self, context, session, instance, vdi_uuids, image_id):

        command = UploadToGlanceAsRawTgz(

            context, session, instance, vdi_uuids, image_id)

        return command.upload_image()

**** CubicPower OpenStack Study ****

    def download_image(self, context, session, instance, image_id):

        # TODO(matelakat) Move through-dev image download functionality to this

        # method.

        raise NotImplementedError()

**** CubicPower OpenStack Study ****

class UploadToGlanceAsRawTgz(object):

**** CubicPower OpenStack Study ****

    def __init__(self, context, session, instance, vdi_uuids, image_id):

        self.context = context

        self.image_id = image_id

        self.session = session

        self.vdi_uuids = vdi_uuids

**** CubicPower OpenStack Study ****

    def _get_virtual_size(self):

        return self.session.call_xenapi(

            'VDI.get_virtual_size', self._get_vdi_ref())

**** CubicPower OpenStack Study ****

    def _get_vdi_ref(self):

        return self.session.call_xenapi('VDI.get_by_uuid', self.vdi_uuids[0])

**** CubicPower OpenStack Study ****

    def _perform_upload(self, devpath):

        readfile, writefile = self._create_pipe()

        size = self._get_virtual_size()

        producer = TarGzProducer(devpath, writefile, size, 'disk.raw')

        consumer = glance.UpdateGlanceImage(

            self.context, self.image_id, producer.get_metadata(), readfile)

        pool = eventlet.GreenPool()

        pool.spawn(producer.start)

        pool.spawn(consumer.start)

        pool.waitall()

**** CubicPower OpenStack Study ****

    def _create_pipe(self):

        rpipe, wpipe = os.pipe()

        rfile = greenio.GreenPipe(rpipe, 'rb', 0)

        wfile = greenio.GreenPipe(wpipe, 'wb', 0)

        return rfile, wfile

**** CubicPower OpenStack Study ****

    def upload_image(self):

        vdi_ref = self._get_vdi_ref()

        with vm_utils.vdi_attached_here(self.session, vdi_ref,

                                        read_only=True) as dev:

            devpath = utils.make_dev_path(dev)

            with utils.temporary_chown(devpath):

                self._perform_upload(devpath)

**** CubicPower OpenStack Study ****

class TarGzProducer(object):

**** CubicPower OpenStack Study ****

    def __init__(self, devpath, writefile, size, fname):

        self.fpath = devpath

        self.output = writefile

        self.size = size

        self.fname = fname

**** CubicPower OpenStack Study ****

    def get_metadata(self):

        return {

            'disk_format': 'raw',

            'container_format': 'tgz'

        }

**** CubicPower OpenStack Study ****

    def start(self):

        with contextlib.closing(self.output):

            tinfo = tarfile.TarInfo(name=self.fname)

            tinfo.size = int(self.size)

            with tarfile.open(fileobj=self.output, mode='w|gz') as tfile:

                with self._open_file(self.fpath, 'rb') as input_file:

                    tfile.addfile(tinfo, fileobj=input_file)

**** CubicPower OpenStack Study ****

    def _open_file(self, *args):

        return open(*args)