Merge "Fixes cinder volume from snapshot on Windows"

This commit is contained in:
Jenkins
2014-06-30 08:41:31 +00:00
committed by Gerrit Code Review
3 changed files with 51 additions and 15 deletions

View File

@@ -146,7 +146,7 @@ class TestWindowsDriver(test.TestCase):
self.mox.StubOutWithMock(windows_utils.WindowsUtils,
'create_volume_from_snapshot')
windows_utils.WindowsUtils.\
create_volume_from_snapshot(volume['name'], snapshot['name'])
create_volume_from_snapshot(volume, snapshot['name'])
self.mox.ReplayAll()

View File

@@ -100,14 +100,7 @@ class WindowsDriver(driver.ISCSIDriver):
self.utils.create_volume(vhd_path, vol_name, vol_size)
def local_path(self, volume, format=None):
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)
if not format:
format = self.utils.get_supported_format()
return os.path.join(base_vhd_folder, str(volume['name']) + "." +
format)
return self.utils.local_path(volume, format)
def delete_volume(self, volume):
"""Driver entry point for destroying existing volumes."""
@@ -127,8 +120,7 @@ class WindowsDriver(driver.ISCSIDriver):
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)
self.utils.create_volume_from_snapshot(volume, snapshot_name)
def delete_snapshot(self, snapshot):
"""Driver entry point for deleting a snapshot."""

View File

@@ -16,9 +16,12 @@
Utility class for Windows Storage Server 2012 volume related operations.
"""
import ctypes
import os
import time
from oslo.config import cfg
from cinder import exception
from cinder.openstack.common import log as logging
from cinder.volume.drivers.windows import constants
@@ -27,6 +30,10 @@ from cinder.volume.drivers.windows import constants
if os.name == 'nt':
import wmi
from ctypes import wintypes
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
@@ -132,13 +139,17 @@ class WindowsUtils(object):
LOG.error(err_msg)
raise exception.VolumeBackendAPIException(data=err_msg)
def create_volume(self, vhd_path, vol_name, vol_size):
def create_volume(self, vhd_path, vol_name, vol_size=None):
"""Creates a volume."""
try:
cl = self._conn_wmi.__getattr__("WT_Disk")
if vol_size:
size_mb = vol_size * 1024
else:
size_mb = None
cl.NewWTDisk(DevicePath=vhd_path,
Description=vol_name,
SizeInMB=vol_size * 1024)
SizeInMB=size_mb)
except wmi.x_wmi as exc:
err_msg = (_(
'create_volume: error when creating the volume name: '
@@ -203,14 +214,24 @@ class WindowsUtils(object):
LOG.error(err_msg)
raise exception.VolumeBackendAPIException(data=err_msg)
def create_volume_from_snapshot(self, vol_name, snap_name):
def create_volume_from_snapshot(self, volume, snap_name):
"""Driver entry point for exporting snapshots as volumes."""
try:
vol_name = volume['name']
vol_path = self.local_path(volume)
wt_snapshot = self._conn_wmi.WT_Snapshot(Description=snap_name)[0]
disk_id = wt_snapshot.Export()[0]
# This export is read-only, so it needs to be copied
# to another disk.
wt_disk = self._conn_wmi.WT_Disk(WTD=disk_id)[0]
wt_disk.Description = vol_name
wt_disk.Description = '%s-temp' % vol_name
wt_disk.put()
src_path = wt_disk.DevicePath
self.copy(src_path, vol_path)
self.create_volume(vol_path, vol_name)
wt_disk.Delete_()
except wmi.x_wmi as exc:
err_msg = (_(
'create_volume_from_snapshot: error when creating the volume '
@@ -321,6 +342,16 @@ class WindowsUtils(object):
LOG.error(err_msg)
raise exception.VolumeBackendAPIException(data=err_msg)
def local_path(self, volume, format=None):
base_vhd_folder = CONF.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)
if not format:
format = self.get_supported_format()
return os.path.join(base_vhd_folder, str(volume['name']) + "." +
format)
def check_min_windows_version(self, major, minor, build=0):
version_str = self.get_windows_version()
return map(int, version_str.split('.')) >= [major, minor, build]
@@ -347,6 +378,19 @@ class WindowsUtils(object):
raise exception.VolumeBackendAPIException(
_('Operation failed with return value: %s') % ret_val)
def copy(self, src, dest):
# With large files this is 2x-3x faster than shutil.copy(src, dest),
# especially with UNC targets.
kernel32 = ctypes.windll.kernel32
kernel32.CopyFileW.restype = wintypes.BOOL
retcode = kernel32.CopyFileW(ctypes.c_wchar_p(src),
ctypes.c_wchar_p(dest),
wintypes.BOOL(True))
if not retcode:
raise IOError(_('The file copy from %(src)s to %(dest)s failed.')
% {'src': src, 'dest': dest})
def _wait_for_job(self, job_path):
"""Poll WMI job state and wait for completion."""
job = self._get_wmi_obj(job_path)