nova-powervm/nova_powervm/virt/powervm/localdisk.py

145 lines
4.8 KiB
Python

# Copyright 2013 OpenStack Foundation
# Copyright 2015 IBM Corp.
#
# 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 abc
from oslo.config import cfg
import six
from nova import image
from nova.i18n import _LI, _LE
from nova.openstack.common import log as logging
from pypowervm.jobs import upload_lv
from pypowervm.wrappers import constants as pvm_consts
from pypowervm.wrappers import virtual_io_server as pvm_vios
from pypowervm.wrappers import volume_group as vol_grp
from nova_powervm.virt.powervm import blockdev
from nova_powervm.virt.powervm import vios
localdisk_opts = [
cfg.StrOpt('volume_group_name',
default='',
help='Volume Group to use for block device operations.')
]
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
CONF.register_opts(localdisk_opts)
IMAGE_API = image.API()
@six.add_metaclass(abc.ABCMeta)
class AbstractLocalStorageException(Exception):
def __init__(self, **kwds):
msg = self.msg_fmt % kwds
super(AbstractLocalStorageException, self).__init__(msg)
class VGNotFound(AbstractLocalStorageException):
msg_fmt = _LE('Unable to locate the volume group \'%(vg_name)s\''
' for this operation.')
class IterableToFileAdapter(object):
"""A degenerate file-like so that an iterable could be read like a file.
As Glance client returns an iterable, but PowerVM requires a file,
this is the adapter between the two.
Taken from xenapi/image/apis.py
"""
def __init__(self, iterable):
self.iterator = iterable.__iter__()
self.remaining_data = ''
def read(self, size):
chunk = self.remaining_data
try:
while not chunk:
chunk = self.iterator.next()
except StopIteration:
return ''
return_value = chunk[0:size]
self.remaining_data = chunk[size:]
return return_value
class LocalStorage(blockdev.StorageAdapter):
def __init__(self, connection):
super(LocalStorage, self).__init__(connection)
self.adapter = connection['adapter']
self.host_uuid = connection['host_uuid']
self.vios_name = connection['vios_name']
self.vios_uuid = connection['vios_uuid']
self.vg_name = CONF.volume_group_name
self.vg_uuid = self._get_vg_uuid(self.adapter, self.vios_uuid,
CONF.volume_group_name)
LOG.info(_LI('Local Storage driver initialized: '
'volume group: \'%s\'') % self.vg_name)
def delete_volume(self, context, volume_info):
# TODO(IBM):
pass
def create_volume_from_image(self, context, instance, image):
LOG.info(_LI('Create volume.'))
# Transfer the image
chunks = IMAGE_API.download(context, image['id'])
stream = IterableToFileAdapter(chunks)
vol_name = self._get_disk_name('boot', instance)
upload_lv.upload_new_vdisk(self.adapter, self.vios_uuid, self.vg_uuid,
stream, vol_name, image['size'])
return {'device_name': vol_name}
def connect_volume(self, context, instance, volume_info, lpar_uuid,
**kwds):
vol_name = volume_info['device_name']
# Create the mapping structure
scsi_map = pvm_vios.crt_scsi_map_to_vdisk(self.adapter, self.host_uuid,
lpar_uuid, vol_name)
# Add the mapping to the VIOS
vios.add_vscsi_mapping(self.adapter, self.vios_uuid, self.vios_name,
scsi_map)
def _get_disk_name(self, type_, instance):
return type_[:6] + '_' + instance.uuid[:8]
def _get_vg_uuid(self, adapter, vios_uuid, name):
try:
resp = adapter.read(pvm_consts.VIOS,
root_id=vios_uuid,
child_type=pvm_consts.VOL_GROUP)
except Exception as e:
LOG.exception(e)
raise e
# Search the feed for the volume group
for entry in resp.feed.entries:
wrapper = vol_grp.VolumeGroup(entry)
wrap_vg_name = wrapper.name
LOG.info(_LI('Volume group: %s') % wrap_vg_name)
if name == wrap_vg_name:
uuid = entry.properties['id']
return uuid
raise VGNotFound(vg_name=name)