¡@

Home 

OpenStack Study: windows.py

OpenStack Index

**** CubicPower OpenStack Study ****

# Copyright 2012 Pedro Navarro Perez

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

"""

Volume driver for Windows Server 2012

This driver requires ISCSI target role installed

"""

import os

from oslo.config import cfg

from cinder.image import image_utils

from cinder.openstack.common import log as logging

from cinder.volume import driver

from cinder.volume.drivers.windows import windows_utils

LOG = logging.getLogger(__name__)

windows_opts = [

cfg.StrOpt('windows_iscsi_lun_path',

default='C:\iSCSIVirtualDisks',

help='Path to store VHD backed volumes'),

]

CONF = cfg.CONF

CONF.register_opts(windows_opts)

**** CubicPower OpenStack Study ****

class WindowsDriver(driver.ISCSIDriver):

"""Executes volume driver commands on Windows Storage server."""

VERSION = '1.0.0'

**** CubicPower OpenStack Study ****

    def __init__(self, *args, **kwargs):

        super(WindowsDriver, self).__init__(*args, **kwargs)

        self.configuration = kwargs.get('configuration', None)

        if self.configuration:

            self.configuration.append_config_values(windows_opts)

**** CubicPower OpenStack Study ****

    def do_setup(self, context):

        """Setup the Windows Volume driver.

        Called one time by the manager after the driver is loaded.

        Validate the flags we care about

        """

        self.utils = windows_utils.WindowsUtils()

**** CubicPower OpenStack Study ****

    def check_for_setup_error(self):

        """Check that the driver is working and can communicate."""

        self.utils.check_for_setup_error()

**** CubicPower OpenStack Study ****

    def initialize_connection(self, volume, connector):

        """Driver entry point to attach a volume to an instance."""

        initiator_name = connector['initiator']

        target_name = volume['provider_location']

        self.utils.associate_initiator_with_iscsi_target(initiator_name,

                                                         target_name)

        properties = self.utils.get_host_information(volume, target_name)

        return {

            'driver_volume_type': 'iscsi',

            'data': properties,

        }

**** CubicPower OpenStack Study ****

    def terminate_connection(self, volume, connector, **kwargs):

        """Driver entry point to unattach a volume from an instance.

        Unmask the LUN on the storage system so the given initiator can no

        longer access it.

        """

        initiator_name = connector['initiator']

        target_name = volume['provider_location']

        self.utils.delete_iscsi_target(initiator_name, target_name)

**** CubicPower OpenStack Study ****

    def create_volume(self, volume):

        """Driver entry point for creating a new volume."""

        vhd_path = self.local_path(volume)

        vol_name = volume['name']

        vol_size = volume['size']

        self.utils.create_volume(vhd_path, vol_name, vol_size)

**** CubicPower OpenStack Study ****

    def local_path(self, volume):

        base_vhd_folder = self.configuration.windows_iscsi_lun_path

        if not os.path.exists(base_vhd_folder):

            LOG.debug(_('Creating folder %s '), base_vhd_folder)

            os.makedirs(base_vhd_folder)

        return os.path.join(base_vhd_folder, str(volume['name']) + ".vhd")

**** CubicPower OpenStack Study ****

    def delete_volume(self, volume):

        """Driver entry point for destroying existing volumes."""

        vol_name = volume['name']

        vhd_path = self.local_path(volume)

        self.utils.delete_volume(vol_name, vhd_path)

**** CubicPower OpenStack Study ****

    def create_snapshot(self, snapshot):

        """Driver entry point for creating a snapshot."""

        # Getting WT_Snapshot class

        vol_name = snapshot['volume_name']

        snapshot_name = snapshot['name']

        self.utils.create_snapshot(vol_name, snapshot_name)

**** CubicPower OpenStack Study ****

    def create_volume_from_snapshot(self, volume, snapshot):

        """Driver entry point for exporting snapshots as volumes."""

        snapshot_name = snapshot['name']

        vol_name = volume['name']

        self.utils.create_volume_from_snapshot(vol_name, snapshot_name)

**** CubicPower OpenStack Study ****

    def delete_snapshot(self, snapshot):

        """Driver entry point for deleting a snapshot."""

        snapshot_name = snapshot['name']

        self.utils.delete_snapshot(snapshot_name)

**** CubicPower OpenStack Study ****

    def _do_export(self, _ctx, volume, ensure=False):

        """Do all steps to get disk exported as LUN 0 at separate target.

        :param volume: reference of volume to be exported

        :param ensure: if True, ignore errors caused by already existing

            resources

        :return: iscsiadm-formatted provider location string

        """

        target_name = "%s%s" % (self.configuration.iscsi_target_prefix,

                                volume['name'])

        self.utils.create_iscsi_target(target_name, ensure)

        # Get the disk to add

        vol_name = volume['name']

        self.utils.add_disk_to_target(vol_name, target_name)

        return target_name

**** CubicPower OpenStack Study ****

    def ensure_export(self, context, volume):

        """Driver entry point to get the export info for an existing volume."""

        self._do_export(context, volume, ensure=True)

**** CubicPower OpenStack Study ****

    def create_export(self, context, volume):

        """Driver entry point to get the export info for a new volume."""

        loc = self._do_export(context, volume, ensure=False)

        return {'provider_location': loc}

**** CubicPower OpenStack Study ****

    def remove_export(self, context, volume):

        """Driver entry point to remove an export for a volume.

        """

        target_name = "%s%s" % (self.configuration.iscsi_target_prefix,

                                volume['name'])

        self.utils.remove_iscsi_target(target_name)

**** CubicPower OpenStack Study ****

    def copy_image_to_volume(self, context, volume, image_service, image_id):

        """Fetch the image from image_service and write it to the volume."""

        # Convert to VHD and file back to VHD

        image_utils.fetch_to_vhd(context, image_service, image_id,

                                 self.local_path(volume),

                                 self.configuration.volume_dd_blocksize)

**** CubicPower OpenStack Study ****

    def copy_volume_to_image(self, context, volume, image_service, image_meta):

        """Copy the volume to the specified image."""

        # Copy the volume to the image conversion dir

        temp_vhd_path = os.path.join(self.configuration.image_conversion_dir,

                                     str(image_meta['id']) + ".vhd")

        self.utils.copy_vhd_disk(self.local_path(volume), temp_vhd_path)

        image_utils.upload_volume(context, image_service, image_meta,

                                  temp_vhd_path, 'vpc')

**** CubicPower OpenStack Study ****

    def create_cloned_volume(self, volume, src_vref):

        """Creates a clone of the specified volume."""

        # Create a new volume

        # Copy VHD file of the volume to clone to the created volume

        self.create_volume(volume)

        self.utils.copy_vhd_disk(self.local_path(src_vref),

                                 self.local_path(volume))

**** CubicPower OpenStack Study ****

    def get_volume_stats(self, refresh=False):

        """Get volume stats.

        If 'refresh' is True, run update the stats first.

        """

        if refresh:

            self._update_volume_stats()

        return self._stats

**** CubicPower OpenStack Study ****

    def _update_volume_stats(self):

        """Retrieve stats info for Windows device."""

        LOG.debug(_("Updating volume stats"))

        data = {}

        backend_name = self.__class__.__name__

        if self.configuration:

            backend_name = self.configuration.safe_get('volume_backend_name')

        data["volume_backend_name"] = backend_name or self.__class__.__name__

        data["vendor_name"] = 'Microsoft'

        data["driver_version"] = self.VERSION

        data["storage_protocol"] = 'iSCSI'

        data['total_capacity_gb'] = 'infinite'

        data['free_capacity_gb'] = 'infinite'

        data['reserved_percentage'] = 100

        data['QoS_support'] = False

        self._stats = data

**** CubicPower OpenStack Study ****

    def extend_volume(self, volume, new_size):

        """Extend an Existing Volume."""

        old_size = volume['size']

        LOG.debug(_("Extend volume from %(old_size)s GB to %(new_size)s GB."),

                  {'old_size': old_size, 'new_size': new_size})

        additional_size = (new_size - old_size) * 1024

        self.utils.extend(volume['name'], additional_size)