Cosmin Poieana 5b9dde9952 Enumerate VDS queries using a common function
Change-Id: I32a9844465656f77686a2e92822b180aa9f3a7fb
2015-09-14 04:49:58 +03:00

138 lines
5.1 KiB
Python

# Copyright 2013 Cloudbase Solutions Srl
#
# 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 ctypes
import re
from oslo_log import log as oslo_logging
from cloudbaseinit.utils.windows.storage import base
from cloudbaseinit.utils.windows import vds
LOG = oslo_logging.getLogger(__name__)
ole32 = ctypes.windll.ole32
ole32.CoTaskMemFree.restype = None
ole32.CoTaskMemFree.argtypes = [ctypes.c_void_p]
def _enumerate(query):
"""Enumerate VDS service queries."""
while True:
unk, avail = query.Next(1)
if not avail:
return
yield unk
class VDSStorageManager(base.BaseStorageManager):
def _extend_volumes(self, pack, volume_indexes):
for unk in _enumerate(pack.QueryVolumes()):
volume = unk.QueryInterface(vds.IVdsVolume)
volume_prop = volume.GetProperties()
try:
extend_volume = True
if volume_indexes:
volume_name = ctypes.wstring_at(volume_prop.pwszName)
volume_idx = self._get_volume_index(volume_name)
if volume_idx not in volume_indexes:
extend_volume = False
if extend_volume:
self._extend_volume(pack, volume, volume_prop)
finally:
ole32.CoTaskMemFree(volume_prop.pwszName)
def _get_volume_index(self, volume_name):
m = re.match(r"[^0-9]+([0-9]+)$", volume_name)
if m:
return int(m.group(1))
def _extend_volume(self, pack, volume, volume_prop):
volume_extents = self._get_volume_extents_to_resize(pack,
volume_prop.id)
input_disks = []
for (volume_extent, volume_extend_size) in volume_extents:
input_disk = vds.VDS_INPUT_DISK()
input_disks.append(input_disk)
input_disk.diskId = volume_extent.diskId
input_disk.memberIdx = volume_extent.memberIdx
input_disk.plexId = volume_extent.plexId
input_disk.ullSize = volume_extend_size
if input_disks:
extend_size = sum([i.ullSize for i in input_disks])
volume_name = ctypes.wstring_at(volume_prop.pwszName)
LOG.info('Extending volume "%s" with %s bytes' %
(volume_name, extend_size))
input_disks_ar = (vds.VDS_INPUT_DISK *
len(input_disks))(*input_disks)
async = volume.Extend(input_disks_ar, len(input_disks))
async.Wait()
def _get_volume_extents_to_resize(self, pack, volume_id):
volume_extents = []
for unk in _enumerate(pack.QueryDisks()):
disk = unk.QueryInterface(vds.IVdsDisk)
(extents_p, num_extents) = disk.QueryExtents()
try:
extents_array_type = vds.VDS_DISK_EXTENT * num_extents
extents_array = extents_array_type.from_address(
ctypes.addressof(extents_p.contents))
volume_extent_extend_size = None
for extent in extents_array:
if extent.volumeId == volume_id:
# Copy the extent in order to return it safely
# after the source is deallocated
extent_copy = vds.VDS_DISK_EXTENT()
ctypes.pointer(extent_copy)[0] = extent
volume_extent_extend_size = [extent_copy, 0]
volume_extents.append(volume_extent_extend_size)
elif (volume_extent_extend_size and
extent.type == vds.VDS_DET_FREE):
volume_extent_extend_size[1] += extent.ullSize
else:
volume_extent_extend_size = None
finally:
ole32.CoTaskMemFree(extents_p)
# Return only the extents that need to be resized
return [ve for ve in volume_extents if ve[1] > 0]
def _query_providers(self, svc):
return [unk.QueryInterface(vds.IVdsSwProvider)
for unk in _enumerate(
svc.QueryProviders(vds.VDS_QUERY_SOFTWARE_PROVIDERS))]
def _query_packs(self, provider):
return [unk.QueryInterface(vds.IVdsPack)
for unk in _enumerate(provider.QueryPacks())]
def extend_volumes(self, volume_indexes=None):
svc = vds.load_vds_service()
providers = self._query_providers(svc)
for provider in providers:
packs = self._query_packs(provider)
for pack in packs:
self._extend_volumes(pack, volume_indexes)