cinder-fusioncompute/cinder/volume/drivers/huawei/fusioncompute/vm_proxy.py

1169 lines
41 KiB
Python

# Copyright 2016 Huawei Technologies Co.,LTD.
# 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.
"""
[VRM DRIVER] VRM CLIENT.
"""
import json
import threading
from oslo_config import cfg
from oslo_log import log as logging
from cinder import exception
from cinder.i18n import _
from cinder.volume.drivers.huawei.vrm.base_proxy import BaseProxy
from cinder.volume.drivers.huawei.vrm.conf import FC_DRIVER_CONF
from cinder.volume.drivers.huawei.vrm.task_proxy import TaskProxy
try:
from eventlet import sleep
except ImportError:
from time import sleep
TASK_WAITING = 'waiting'
TASK_RUNNING = 'running'
TASK_SUCCESS = 'success'
TASK_FAILED = 'failed'
TASK_CANCELLING = 'cancelling'
TASK_UNKNOWN = 'unknown'
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
vrm_template_lock = threading.Lock()
class VmProxy(BaseProxy):
'''VmProxy
VmProxy
'''
def __init__(self, *args, **kwargs):
super(VmProxy, self).__init__()
self.task_proxy = TaskProxy()
def query_vm(self, **kwargs):
'''Query VM
'query_vm': ('GET',
('/vms', None, kwargs.get('vm_id'), None),
{},
{},
False)
'''
LOG.info(_("[VRM-CINDER] start query_vm()"))
uri = '/vms'
method = 'GET'
path = self.site_uri + uri + '/' + kwargs.get('vm_id')
new_url = self._generate_url(path)
resp, body = self.vrmhttpclient.request(new_url, method)
LOG.info(_("[VRM-CINDER] end ()"))
return body
def query_vm_by_uri(self, **kwargs):
'''Query VM by Uri
'query_vm': ('GET',
('/vms', None, kwargs.get('vm_id'), None),
{},
{},
False)
'''
LOG.info(_("[VRM-CINDER] start query_vm()"))
method = 'GET'
path = kwargs.get('vm_uri')
new_url = self._generate_url(path)
resp, body = self.vrmhttpclient.request(new_url, method)
LOG.info(_("[VRM-CINDER] end ()"))
return body
def delete_vm(self, **kwargs):
'''Delete VM
'delete_vm': ('DELETE',
('/vms', None, kwargs.get('vm_id'), None),
{},
{},
True),
'''
LOG.info(_("[VRM-CINDER] start delete_vm()"))
uri = '/vms'
method = 'DELETE'
path = self.site_uri + uri + '/' + kwargs.get('vm_id')
if kwargs.get('isReserveDisks') is not None and kwargs.get(
'isReserveDisks') == 1:
path = path + '?isReserveDisks=1'
new_url = self._generate_url(path)
resp, body = self.vrmhttpclient.request(new_url, method)
task_uri = body.get('taskUri')
if kwargs.get('isReserveDisks') is not None and kwargs.get(
'isReserveDisks') == 1:
self.task_proxy.wait_task(task_uri=task_uri, isShortQuery=1)
else:
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end ()"))
def detach_vol_from_vm(self, **kwargs):
'''detach_vol_from_vm
'detach_vol_from_vm': ('POST',
('/vms', None, kwargs.get('vm_id'),
'action/detachvol'),
{},
{'volUrn': kwargs.get('volUrn')},
True),
'''
LOG.info(_("[VRM-CINDER] start detach_vol_from_vm()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/detachvol'
new_url = self._generate_url(path)
body = {'volUrn': kwargs.get('volume_urn')}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end ()"))
def attach_vol_to_vm(self, **kwargs):
'''attach_vol_to_vm
'attach_vol_to_vm': ('POST',
('/vms', None, kwargs.get('vm_id'),
'action/attachvol'),
{},
{'volUrn': kwargs.get('volUrn')},
True),
'''
LOG.info(_("[VRM-CINDER] start attach_vol_to_vm()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/attachvol'
new_url = self._generate_url(path)
body = {'volUrn': kwargs.get('volume_urn')}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end attach_vol_to_vm()"))
def stop_vm(self, **kwargs):
'''stop_vm
'stop_vm': ('POST',
('/vms', None, kwargs.get('vm_id'), 'action/stop'),
{},
{'mode': kwargs.get('mode')},
True),
'''
LOG.info(_("[VRM-CINDER] start stop_vm()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get('vm_id') + '/action/stop'
new_url = self._generate_url(path)
body = {'mode': kwargs.get('mode')}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end ()"))
def _combine_empty_vmConfig(self, **kwargs):
'''_combine_empty_vmConfig
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start _combine_empty_vmConfig ()"))
cpu_quantity = 2
mem_quantityMB = 1024
cpu = {'quantity': cpu_quantity}
memory = {'quantityMB': mem_quantityMB}
disks = []
vmConfigBody = {
'cpu': cpu,
'memory': memory,
'disks': disks,
}
LOG.info(_("[VRM-CINDER] _combine_empty_vmConfig end ()"))
return vmConfigBody
def _combine_vmConfig_4_import(self, **kwargs):
'''_combine_vmConfig_4_import
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start _combine_vmConfig ()"))
cpu_quantity = 2
mem_quantityMB = 1024
datastoreUrn = kwargs.get('ds_urn')
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
link = kwargs.get('linkClone')
disk_quantityGB = kwargs.get('volume_size')
if link:
uuid = ""
if kwargs.get('quick_start') is True:
disk_quantityGB = kwargs.get('image_size')
else:
uuid = kwargs.get("volume_id")
thin = kwargs.get('is_thin')
volumeUrn = kwargs.get('volume_urn')
cpu = {'quantity': cpu_quantity}
memory = {'quantityMB': mem_quantityMB}
disks = [
{
'volumeUrn': volumeUrn,
'datastoreUrn': datastoreUrn,
'quantityGB': disk_quantityGB,
'volType': 0,
'sequenceNum': kwargs.get('volume_sequence_num'),
'pciType': 'IDE',
'volumeUuid': uuid,
'isThin': thin,
'isCoverData': True
}
]
vmConfigBody = {
'cpu': cpu,
'memory': memory,
'disks': disks,
}
LOG.info(_("[VRM-CINDER] end ()"))
return vmConfigBody
def _combine_vmConfig_4_clone(self, **kwargs):
'''_combine_vmConfig_4_clone
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start _combine_vmConfig ()"))
cpu_quantity = 2
mem_quantityMB = 1024
datastoreUrn = kwargs.get('ds_urn')
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
disk_quantityGB = kwargs.get('volume_size')
link = kwargs.get('linkClone')
if link:
uuid = ""
else:
uuid = kwargs.get("volume_id")
thin = kwargs.get('is_thin')
cpu = {'quantity': cpu_quantity}
memory = {'quantityMB': mem_quantityMB}
disks = [
{
'datastoreUrn': datastoreUrn,
'quantityGB': disk_quantityGB,
'volType': 0,
'sequenceNum': 1,
'pciType': 'IDE',
'volumeUuid': uuid,
'isThin': thin
}
]
vmConfigBody = {
'cpu': cpu,
'memory': memory,
'disks': disks,
}
LOG.info(_("[VRM-CINDER] end ()"))
return vmConfigBody
def _combine_vmConfig_4_export(self, **kwargs):
'''_combine_vmConfig_4_export
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start _combine_vmConfig ()"))
cpu_quantity = 2
mem_quantityMB = 1024
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
cpu = {'quantity': cpu_quantity}
memory = {'quantityMB': mem_quantityMB}
disks = [
{
'sequenceNum': kwargs.get('volume_sequence_num'),
}
]
vmConfigBody = {
'cpu': cpu,
'memory': memory,
'disks': disks,
}
LOG.info(_("[VRM-CINDER] end ()"))
return vmConfigBody
def _combine_os_options(self, **kwargs):
'''_combine_os_options
:param kwargs:
:return:
'''
osOptions = {
'osType': 'Windows',
'osVersion': 26
}
LOG.info(_("[VRM-CINDER] end ()"))
return osOptions
def clone_vm(self, **kwargs):
'''clone_vm
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start clone_vm()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'template_id') + '/action/clone'
new_url = self._generate_url(path)
linked_clone = kwargs.get('linked_clone')
if linked_clone is None:
linked_clone = False
LOG.info(_("[VRM-CINDER] start clone_vm()"))
body = {
'name': 'cinder-vm-' + kwargs.get('volume_id'),
'group': 'FSP',
'description': 'cinder-driver-temp-vm',
'autoBoot': 'false',
'isLinkClone': linked_clone,
'vmConfig': self._combine_vmConfig_4_clone(**kwargs),
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri, isShortQuery=1)
LOG.info(_("[VRM-CINDER] end clone_vm()"))
return body.get('urn')
def import_vm_from_glance(self, **kwargs):
'''import_vm_from_glance
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start import_vm_from_glance()"))
uri = self.site_uri + '/vms/action/import'
method = 'POST'
new_url = self._generate_url(uri)
link_nfs = kwargs.get('linkClone')
if link_nfs:
name = kwargs.get('image_id')
else:
name = kwargs.get('volume_id')
is_template = kwargs.get("is_template")
if is_template is None or is_template:
template = 'true'
else:
template = 'false'
if CONF.glance_host is None or str(CONF.glance_port) is None \
or FC_DRIVER_CONF.glance_server_ip is None:
raise exception.ParameterNotFound(param='glance_host or '
'glance_port or glance_ip')
endpoint = CONF.glance_host + ":" + str(CONF.glance_port)
token = kwargs.get('auth_token')
serviceIp = FC_DRIVER_CONF.glance_server_ip
body = {
'name': 'cinder-vm-' + name,
'group': 'FSP',
'description': 'cinder-glance-vm',
'autoBoot': 'false',
'location': kwargs.get("cluster_urn"),
'osOptions': self._combine_os_options(**kwargs),
'protocol': "glance",
'vmConfig': self._combine_vmConfig_4_import(**kwargs),
'isTemplate': template,
'glanceConfig': {
'imageID': kwargs.get('image_id'),
'endPoint': endpoint,
'serverIp': serviceIp,
'token': token}
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end import_vm_from_glance()"))
return body.get('urn')
def import_vm_from_uds(self, **kwargs):
'''import_vm_from_uds
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start import_vm_from_uds()"))
uri = self.site_uri + '/vms/action/import'
method = 'POST'
new_url = self._generate_url(uri)
link_nfs = kwargs.get('linkClone')
if link_nfs:
name = kwargs.get('image_id')
else:
name = kwargs.get('volume_id')
is_template = kwargs.get("is_template")
if is_template is None or is_template:
template = 'true'
else:
template = 'false'
if FC_DRIVER_CONF.s3_store_access_key_for_cinder is None or \
FC_DRIVER_CONF.s3_store_secret_key_for_cinder is None:
LOG.error(_("[VRM-CINDER] some params is None, please check: "
"s3_store_access_key_for_cinder, "
"s3_store_secret_key_for_cinder"))
raise exception.ParameterNotFound(
param='s3_store_access_key_for_cinder or '
's3_store_secret_key_for_cinder')
uds_name = FC_DRIVER_CONF.s3_store_access_key_for_cinder
uds_password = FC_DRIVER_CONF.s3_store_secret_key_for_cinder
location = kwargs.get('image_location')
location = location.split(":")
if len(location) != 4:
msg = _('image_location is invalid')
LOG.error(msg)
raise exception.ImageUnacceptable(image_id=kwargs.get('image_id'),
reason=msg)
serverIp = location[0].strip()
port = location[1].strip()
bucketName = location[2].strip()
key = location[3].strip()
body = {
'name': 'cinder-vm-' + name,
'group': 'FSP',
'description': 'cinder-uds-vm',
'autoBoot': 'false',
'location': kwargs.get("cluster_urn"),
'osOptions': self._combine_os_options(**kwargs),
'protocol': "uds",
'vmConfig': self._combine_vmConfig_4_import(**kwargs),
'isTemplate': template,
's3Config': {
'serverIp': serverIp,
'port': port,
'accessKey': uds_name,
'secretKey': uds_password,
'bucketName': bucketName,
'key': key
}
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end import_vm_from_uds()"))
return body.get('urn')
def import_vm_from_nfs(self, **kwargs):
'''import_vm_from_nfs
'import_vm_from_image': ('POST',
('/vms/action/import', None, None, None),
{},
dict({
'name': 'name',
'location': kwargs.get('cluster_urn'),
'autoBoot': 'false',
'url': kwargs.get('url'),
'protocol': 'nfs',
'vmConfig': {
'cpu': {
'quantity': 1
},
'memory': {
'quantityMB': 1024
},
'disks': [
{
'pciType': 'IDE',
'datastoreUrn': kwargs.get('ds_urn'),
'quantityGB': kwargs.get('vol_size'),
'volType': 0,
'sequenceNum': 1,
},
],
},
'osOptions': {
'osType': 'Windows',
'osVersion': 32
}
}),
True),
'''
LOG.info(_("[VRM-CINDER] start import_vm_from_nfs()"))
uri = self.site_uri + '/vms/action/import'
method = 'POST'
new_url = self._generate_url(uri)
link_nfs = kwargs.get('linkClone')
if link_nfs:
name = kwargs.get('image_id')
else:
name = kwargs.get('volume_id')
is_template = kwargs.get("is_template")
if is_template is None or is_template:
template = 'true'
else:
template = 'false'
body = \
{
'name': 'cinder-vm-' + name,
'group': 'FSP',
'description': 'cinder-nfs-vm',
'autoBoot': 'false',
'location': kwargs.get("cluster_urn"),
'osOptions': self._combine_os_options(**kwargs),
'protocol': "nfs",
'vmConfig': self._combine_vmConfig_4_import(**kwargs),
'url': kwargs.get('image_location'),
'isTemplate': template
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end import_vm_from_nfs()"))
return body.get('urn')
def create_volume_from_extend(self, **kwargs):
'''create_volume_from_extend
create_linkclone_volume
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start create_volume_from_extend()"))
image_type = kwargs.get('image_type')
if image_type == "nfs":
LOG.info(_("[VRM-CINDER] start create_volume_from_nfs"))
vm_urn = self.import_vm_from_nfs(**kwargs)
elif image_type == 'uds':
LOG.info(_("[VRM-CINDER] start create_volume_from_uds"))
vm_urn = self.import_vm_from_uds(**kwargs)
else:
LOG.info(_("[VRM-CINDER] start create_volume_from_glance"))
vm_urn = self.import_vm_from_glance(**kwargs)
vm_id = vm_urn[-10:]
vm = self.query_vm(vm_id=vm_id)
vm_config = vm['vmConfig']
disks = vm_config['disks']
volume_urn = None
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
for disk in disks:
if int(disk['sequenceNum']) == int(kwargs['volume_sequence_num']):
volume_urn = disk['volumeUrn']
break
if volume_urn is None:
msg = (_("[VRM-CINDER] no available disk"))
LOG.error(msg)
self.delete_vm(vm_id=vm_id)
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
try:
self.detach_vol_from_vm(vm_id=vm_id, volume_urn=volume_urn)
except Exception as ex:
LOG.error(_('detach volume is failed'))
self.delete_vm(vm_id=vm_id)
raise ex
self.delete_vm(vm_id=vm_id)
LOG.info(_("[VRM-CINDER] end ()"))
return volume_urn
def check_template_status(self, vm_id):
LOG.info(_("[VRM-CINDER] start check template status()"))
uri = self.site_uri + '/vms/' + vm_id + '/competition'
method = 'GET'
new_url = self._generate_url(uri)
resp, body = self.vrmhttpclient.request(new_url, method)
LOG.info(_("[VRM-CINDER] template info %s") % body)
body.get('status')
def check_template(self, **kwargs):
'''check_template
:param kwargs:
:return:
'''
template_id = kwargs.get('template_id')
vm_name = kwargs.get('vm_name')
templates = self.get_templates()
id = None
for template in templates:
if template_id is not None:
urn = template.get('urn')
id = urn[-10:]
if id == template_id:
LOG.info(_("[VRM-CINDER] template exists [%s]"),
template_id)
return id
if vm_name is not None:
name = template.get('name')
if name == vm_name:
urn = template.get('urn')
id = urn[-10:]
LOG.info(_("[VRM-CINDER] vm is exists [%s]"), vm_name)
return id
return id
def create_volume_from_template(self, **kwargs):
'''create_volume_from_template
create_linkclone_volume
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start create_volume_from_template()"))
template = kwargs['image_location']
kwargs['template_id'] = template[-10:]
is_exist = self.check_template(**kwargs)
if is_exist is None:
msg = (_("[VRM-CINDER] no such template %s "),
kwargs.get('template_id'))
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
while True:
template_vm = self.query_vm(vm_id=kwargs['template_id'])
LOG.info(_("[VRM-CINDER] template_vm status is %s"),
template_vm.get('status'))
if 'creating' == template_vm.get('status'):
sleep(10)
elif 'stopped' == template_vm.get('status'):
break
else:
msg = (_("[VRM-CINDER] template isn't available %s "),
kwargs.get('template_id'))
LOG.error(msg)
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
vm_config = template_vm['vmConfig']
template_disks = vm_config['disks']
if len(template_disks) != 1:
msg = _("template must have one disk")
LOG.error(msg)
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
vm_urn = self.clone_vm(**kwargs)
vm_id = vm_urn[-10:]
vm = self.query_vm(vm_id=vm_id)
vm_config = vm['vmConfig']
disks = vm_config['disks']
volume_urn = None
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
for disk in disks:
if int(disk['sequenceNum']) == int(kwargs['volume_sequence_num']):
volume_urn = disk['volumeUrn']
break
if volume_urn is None:
msg = (_("[VRM-CINDER] no available disk"))
LOG.error(msg)
self.delete_vm(vm_id=vm_id)
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
try:
self.delete_vm(vm_id=vm_id, isReserveDisks=1)
except Exception as ex:
LOG.error(_("delete vm(reserveDisk) is failed "))
self.delete_vm(vm_id=vm_id)
raise ex
LOG.info(_("[VRM-CINDER] end ()"))
return volume_urn
def create_linkclone_from_template(self, **kwargs):
'''create_linkclone_from_template
create_linkclone_volume
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start create_linkclone_from_template()"))
kwargs['linked_clone'] = True
return self.create_volume_from_template(**kwargs)
def create_linkClone_from_extend(self, **kwargs):
'''create_linkClone_from_extend
:param kwargs:
:return:
'''
LOG.debug(_("[VRM-CINDER] start create_linkClone_volume()"))
vrm_template_lock.acquire()
try:
kwargs['linkClone'] = True
vm_name = 'cinder-vm-' + kwargs.get('image_id')
LOG.info(_("[VRM-CINDER] vm_name is %s"), vm_name)
kwargs['vm_name'] = vm_name
vm_id = self.check_template(**kwargs)
kwargs.pop('vm_name')
LOG.info(_("[VRM-CINDER] vm_id is %s"), vm_id)
image_type = kwargs.get('image_type')
if kwargs.get('volume_sequence_num') is None:
kwargs['volume_sequence_num'] = 1
if 1 < int(kwargs['volume_sequence_num']):
msg = (_("[VRM-CINDER] volume_sequence_num is %s "),
kwargs['volume_sequence_num'])
LOG.error(msg)
raise exception.ImageUnacceptable(image_id=kwargs['image_id'],
reason=msg)
if vm_id is None:
kwargs["is_template"] = True
if image_type == 'nfs':
vm_urn = self.import_vm_from_nfs(**kwargs)
kwargs.pop('linkClone')
LOG.info(_("[VRM-CINDER] import_vm_from_nfs vm_urn is %s"),
vm_urn)
vm_id = vm_urn[-10:]
kwargs['image_location'] = vm_id
elif image_type == 'uds':
vm_urn = self.import_vm_from_uds(**kwargs)
kwargs.pop('linkClone')
LOG.info(_("[VRM-CINDER] import_vm_from_uds vm_urn is %s"),
vm_urn)
vm_id = vm_urn[-10:]
kwargs['image_location'] = vm_id
else:
vm_urn = self.import_vm_from_glance(**kwargs)
kwargs.pop('linkClone')
LOG.info(
_("[VRM-CINDER] import_vm_from_glance vm_urn is %s"),
vm_urn)
vm_id = vm_urn[-10:]
kwargs['image_location'] = vm_id
else:
kwargs.pop('linkClone')
kwargs['image_location'] = vm_id
except Exception as ex:
vrm_template_lock.release()
raise ex
vrm_template_lock.release()
return self.create_linkclone_from_template(**kwargs)
def get_templates(self, **kwargs):
'''get_templates
'list_templates': ('GET',
('/vms', None, None, None),
{'limit': kwargs.get('limit'),
'offset': kwargs.get('offset'),
'scope': kwargs.get('scope'),
'isTemplate': 'true'
},
{},
False),
'''
LOG.info(_("[VRM-CINDER] start _get_templates()"))
uri = '/vms'
method = 'GET'
path = self.site_uri + uri
offset = 0
templates = []
while True:
parames = {
'limit': self.limit,
'offset': offset,
'scope': kwargs.get('scope'),
'isTemplate': 'true'
}
appendix = self._joined_params(parames)
new_url = self._generate_url(path, appendix)
resp, body = self.vrmhttpclient.request(new_url, method)
total = int(body.get('total') or 0)
if total > 0:
res = body.get('vms')
templates += res
offset += len(res)
if offset >= total or len(templates) >= total or len(
res) < self.limit:
break
else:
break
LOG.info(_("[VRM-CINDER] end ()"))
return templates
def create_vm(self, **kwargs):
'''Create Vm
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start create_vm()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri
new_url = self._generate_url(path)
body = {
'name': 'cinder-driver-temp-' + kwargs.get('volume_id'),
'group': 'FSP',
'description': 'cinder-driver-temp-vm',
'autoBoot': 'false',
'location': kwargs.get("cluster_urn"),
'vmConfig': self._combine_empty_vmConfig(**kwargs),
'osOptions': self._combine_os_options(**kwargs)
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end create_vm()"))
return body
def export_vm_to_glance(self, **kwargs):
'''export_vm_to_glance
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start export_vm_to_glance"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/export'
new_url = self._generate_url(path)
if CONF.glance_host is None or str(CONF.glance_port) is None \
or FC_DRIVER_CONF.glance_server_ip is None:
raise exception.ParameterNotFound(param='glance_host or '
'glance_port or glance_ip')
endpoint = CONF.glance_host + ":" + str(CONF.glance_port)
token = kwargs.get('auth_token')
serviceIp = FC_DRIVER_CONF.glance_server_ip
format = 'xml' if FC_DRIVER_CONF.export_version == 'v1.2' else 'ovf'
body = {
'name': kwargs.get('image_id'),
'format': format,
'protocol': 'glance',
'isOverwrite': 'false',
'vmConfig': self._combine_vmConfig_4_export(**kwargs),
'glanceConfig': {
'imageID': kwargs.get('image_id'),
'endPoint': endpoint,
'serverIp': serviceIp,
'token': token}
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end export_vm_to_glance"))
return body.get('urn')
def export_vm_to_uds(self, **kwargs):
'''export_vm_to_uds
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start export_vm_to_uds"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/export'
new_url = self._generate_url(path)
if FC_DRIVER_CONF.s3_store_access_key_for_cinder is None \
or FC_DRIVER_CONF.s3_store_secret_key_for_cinder is None \
or FC_DRIVER_CONF.uds_port is None or FC_DRIVER_CONF.uds_ip \
is None \
or FC_DRIVER_CONF.uds_bucket_name is None:
LOG.error(_("[VRM-CINDER] some params is None, please check: "
"s3_store_access_key_for_cinder, "
"s3_store_secret_key_for_cinder, uds_port, uds_ip, "
"uds_bucket_name"))
raise exception.ParameterNotFound(
param='s3_store_access_key_for_cinder '
'or s3_store_secret_key_for_cinder or'
'uds_port or uds_serverIp or uds_bucket_name')
uds_name = FC_DRIVER_CONF.s3_store_access_key_for_cinder
uds_password = FC_DRIVER_CONF.s3_store_secret_key_for_cinder
port = FC_DRIVER_CONF.uds_port
serverIp = FC_DRIVER_CONF.uds_ip
bucketName = FC_DRIVER_CONF.uds_bucket_name
key = kwargs.get('image_id')
bucket_type = FC_DRIVER_CONF.uds_bucket_type
if bucket_type is not None:
if str(bucket_type) == 'wildcard':
if kwargs.get('project_id') is None:
LOG.error(_("project_id is none "))
raise exception.ParameterNotFound(
param='project_id is none')
else:
bucketName += kwargs.get('project_id')
LOG.info(_("[VRM-CINDER] bucketName is %s"), bucketName)
format = 'xml' if FC_DRIVER_CONF.export_version == 'v1.2' else 'ovf'
body = {
'name': kwargs.get('image_id'),
'format': format,
'protocol': 'uds',
'isOverwrite': 'false',
'vmConfig': self._combine_vmConfig_4_export(**kwargs),
's3Config': {
'serverIp': serverIp,
'port': port,
'accessKey': uds_name,
'secretKey': uds_password,
'bucketName': bucketName,
'key': key}
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end export_vm_to_uds"))
return body.get('urn')
def export_vm_to_nfs(self, **kwargs):
'''export_vm_to_nfs
Post <vm_uri>/<id>/action/export HTTP/1.1
Host: https://<ip>:<port>
Content-Type: application/json; charset=UTF-8
Accept: application/json;version=<version>; charset=UTF-8
X-Auth-Token: <Authen_TOKEN>
{
"name":string,
"url:string,
"username":administrator
"password":string
}
'''
LOG.info(_("[VRM-CINDER] start export_vm_to_nfs()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/export'
new_url = self._generate_url(path)
format = 'xml' if FC_DRIVER_CONF.export_version == 'v1.2' else 'ovf'
body = {
'name': kwargs.get('image_id'),
'url': kwargs.get('image_url') + '/' + kwargs.get('image_id'),
'vmConfig': self._combine_vmConfig_4_export(**kwargs),
'format': format,
'protocol': 'nfs',
'isOverwrite': 'false'
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end export_vm_to_nfs()"))
return body.get('urn')
def get_volume_sequence_num(self, vm_body, volume_urn):
volume_sequence_num = 1
if vm_body is not None:
vm_uri = vm_body.get('uri')
volume_body = self.query_vm(vm_id=vm_uri[-10:])
if volume_body is not None:
for item in volume_body.get('vmConfig').get('disks'):
if item.get('volumeUrn') == volume_urn:
volume_sequence_num = item.get("sequenceNum")
else:
LOG.info(_("[VRM-CINDER] vm_body is null)"))
return volume_sequence_num
def export_volume_to_image(self, **kwargs):
'''export_volume_to_image
:param kwargs:
:return:
'''
LOG.info(_("[VRM-CINDER] start export_volume_to_image()"))
vm_body = self.query_vm_volume(**kwargs)
if vm_body is not None:
kwargs['volume_sequence_num'] = self.get_volume_sequence_num(
vm_body,
kwargs.get('volume_urn'))
vm_uri = vm_body.get('uri')
kwargs['vm_id'] = vm_uri[-10:]
LOG.info(_("[VRM-CINDER] volume is already attached"))
self.export_attached_volume_to_image(**kwargs)
LOG.info(_("[VRM-CINDER] volume_sequence_num %s"),
kwargs['volume_sequence_num'])
return kwargs['volume_sequence_num']
vm_body = self.create_vm(**kwargs)
vm_uri = vm_body.get('uri')
kwargs['vm_id'] = vm_uri[-10:]
if kwargs.get('shareable') == 'share':
kwargs['volume_sequence_num'] = 2
else:
kwargs['volume_sequence_num'] = 1
try:
self.attach_vol_to_vm(**kwargs)
except Exception as ex:
LOG.error(_("[VRM-CINDER] attach volume is error "))
self.delete_vm(**kwargs)
raise ex
try:
self.export_attached_volume_to_image(**kwargs)
except Exception as ex:
LOG.error(_("[VRM-CINDER] export vm is error "))
self.detach_vol_from_vm(**kwargs)
self.delete_vm(**kwargs)
raise ex
self.detach_vol_from_vm(**kwargs)
self.delete_vm(**kwargs)
LOG.info(_("[VRM-CINDER] end export_volume_to_nfs()"))
LOG.info(_("[VRM-CINDER] volume_sequence_num %s"),
kwargs['volume_sequence_num'])
return kwargs['volume_sequence_num']
def export_attached_volume_to_image(self, **kwargs):
image_type = kwargs.get('image_type')
if image_type == 'nfs':
LOG.info(_('[VRM-CINDER] export_vm_to_nfs'))
self.export_vm_to_nfs(**kwargs)
elif image_type == 'uds':
LOG.info(_('VRM-CINDER] export_vm_to_uds'))
self.export_vm_to_uds(**kwargs)
else:
LOG.info(_('VRM-CINDER] export_vm_to_glance'))
self.export_vm_to_glance(**kwargs)
LOG.info(_("[VRM-CINDER] end export_attached_volume_to_image()"))
def query_vm_volume(self, **kwargs):
'''query_vm_volume
URL:https://192.168.106.111:8443/OmsPortal/service/sites/4286080F/vms
?scope=urn%3Asites%3A4286080F%3Avolumes%3A137
&detail=2
'''
LOG.info(_("[VRM-CINDER] start query_vm_volume()"))
uri = '/vms'
method = 'GET'
path = self.site_uri + uri
parames = {
'scope': kwargs.get('volume_urn'),
'detail': 0
}
appendix = self._joined_params(parames)
new_url = self._generate_url(path, appendix)
resp, body = self.vrmhttpclient.request(new_url, method)
total = int(body.get('total') or 0)
vm = None
if total >= 1:
vms = body.get('vms')
vm = vms[0]
else:
LOG.info(_("[VRM-CINDER] find no vms()"))
LOG.info(_("[VRM-CINDER] end query_vm_volume()"))
return vm
def migrate_vm_volume(self, **kwargs):
'''migrate_vm_volume
Post /<vm_uri>/<vm_id>/action/migratevol HTTP/1.1
Host: https://<ip>:<port>
Content-Type: application/json; charset=UTF-8
Accept: application/json;version=<version>; charset=UTF-8
X-Auth-Token: <Authen_TOKEN>
{
"disks":[
{
"volumeUrn":string
"datastoreUrn":string //urn:sites:1:datastores:1
}
],
"speed": integer
}
'''
LOG.info(_("[VRM-CINDER] start migrate_vm_volume()"))
uri = '/vms'
method = 'POST'
path = self.site_uri + uri + '/' + kwargs.get(
'vm_id') + '/action/migratevol'
new_url = self._generate_url(path)
body = {
"disks": [
{
"volumeUrn": kwargs.get('volume_urn'),
"datastoreUrn": kwargs.get('dest_ds_urn'),
'migrateType': kwargs.get('migrate_type')
}
],
"speed": kwargs.get('speed')
}
resp, body = self.vrmhttpclient.request(new_url, method,
body=json.dumps(body))
task_uri = body.get('taskUri')
self.task_proxy.wait_task(task_uri=task_uri)
LOG.info(_("[VRM-CINDER] end migrate_vm_volume()"))
return body.get('urn')