442 lines
19 KiB
Python
442 lines
19 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.
|
|
|
|
import json
|
|
import urlparse
|
|
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
from cinder import exception as cinder_exception
|
|
from cinder.i18n import _
|
|
from cinder.volume.drivers.huawei.fusioncompute.conf import FC_DRIVER_CONF
|
|
from cinder.volume.drivers.huawei.fusioncompute import exception as driver_exception
|
|
|
|
TASK_WAITING = 'waiting'
|
|
TASK_RUNNING = 'running'
|
|
TASK_SUCCESS = 'success'
|
|
TASK_FAILED = 'failed'
|
|
TASK_CANCELLING = 'cancelling'
|
|
TASK_UNKNOWN = 'unknown'
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class VRM_COMMANDS(object):
|
|
USER_AGENT = 'VRM-HTTP-Client for OpenStack'
|
|
RESOURCE_URI = 'uri'
|
|
TASK_URI = 'taskUri'
|
|
BASIC_URI = '/service'
|
|
glanceServer_host = ''
|
|
glanceServer_port = ''
|
|
version = CONF.vrm_version
|
|
site_uri = ''
|
|
|
|
def __init__(self):
|
|
self.site_urn = None
|
|
self.site_uri = None
|
|
|
|
glanceServer_Info = str(CONF.glance_api_servers).split(':')
|
|
LOG.info("glance_api_servers is [%s]", CONF.glance_api_servers)
|
|
LOG.info("sxmatch glanceServer_Info is %s", glanceServer_Info)
|
|
self.glanceServer_host =\
|
|
glanceServer_Info[0] + ":" + glanceServer_Info[1]
|
|
self.glanceServer_host = self.glanceServer_host.replace("['", '')
|
|
LOG.info("sxmatch glanceServer_host is %s", self.glanceServer_host)
|
|
self.glanceServer_port = glanceServer_Info[1].replace("']", '')
|
|
LOG.info("sxmatch glanceServer_port is %s", self.glanceServer_port)
|
|
|
|
"""Generate command to be sent to VRM."""
|
|
|
|
def _joined_params(self, params):
|
|
param_str = []
|
|
for k, v in params.items():
|
|
if (k is None) or (v is None) or len(k) == 0:
|
|
continue
|
|
if k == 'scope' and v == self.site_urn:
|
|
continue
|
|
param_str.append("%s=%s" % (k, str(v)))
|
|
return '&'.join(param_str)
|
|
|
|
def _joined_body(self, params):
|
|
param_str = []
|
|
for k, v in params.items():
|
|
if k is None or v is None or \
|
|
len(k) == 0:
|
|
continue
|
|
|
|
if type(v) in [int]:
|
|
param_str.append('"%s":%s' % (k, str(v)))
|
|
elif type(v) in [str, unicode]:
|
|
param_str.append('"%s":"%s"' % (k, str(v)))
|
|
elif type(v) in [bool]:
|
|
param_str.append('"%s":%s' % (k, str(v).lower()))
|
|
elif type(v) in [dict]:
|
|
param_str1 = json.dumps(v)
|
|
param_str.append('"%s":%s' % (k, param_str1))
|
|
else:
|
|
pass
|
|
|
|
if len(param_str) > 0:
|
|
return '{' + ','.join(param_str) + '}'
|
|
else:
|
|
return None
|
|
|
|
def _combine_vmConfig(self, **kwargs):
|
|
cpu_quantity = 1
|
|
mem_quantityMB = 1024
|
|
datastoreUrn = CONF.vrm_sm_datastoreurn
|
|
disk_quantityGB = 10
|
|
image_size = 10
|
|
|
|
if image_size > disk_quantityGB:
|
|
LOG.error(_("image is larger than sys-vol."))
|
|
raise cinder_exception.ImageTooLarge
|
|
|
|
cpu = {'quantity': cpu_quantity}
|
|
memory = {'quantityMB': mem_quantityMB}
|
|
disks = [
|
|
{
|
|
'datastoreUrn': datastoreUrn,
|
|
'quantityGB': disk_quantityGB,
|
|
'volType': 0,
|
|
'sequenceNum': 1,
|
|
}
|
|
]
|
|
properties = {
|
|
'isEnableHa': True,
|
|
'reoverByHost': False,
|
|
'isEnableFt': False
|
|
}
|
|
|
|
vmConfigBody = {
|
|
'cpu': cpu,
|
|
'memory': memory,
|
|
'disks': disks,
|
|
'properties': properties,
|
|
}
|
|
return vmConfigBody
|
|
|
|
def _combine_os_options(self, **kwargs):
|
|
osOptions = {
|
|
'osType': 'Windows',
|
|
'osVersion': 26
|
|
}
|
|
return osOptions
|
|
|
|
def init_site(self, uri, urn):
|
|
self.site_uri = uri
|
|
self.site_urn = urn
|
|
return
|
|
|
|
def _generate_url(self, path, query=None, frag=None):
|
|
LOG.info(_("[BRM-DRIVER] call _generate_url() "))
|
|
if CONF.vrm_ssl:
|
|
scheme = 'https'
|
|
else:
|
|
scheme = 'http'
|
|
fc_ip = FC_DRIVER_CONF.fc_ip
|
|
netloc = str(fc_ip) + ':' + str(CONF.vrm_port)
|
|
if path.startswith(self.BASIC_URI):
|
|
url = urlparse.urlunsplit((scheme, netloc, path, query, frag))
|
|
else:
|
|
url = urlparse.urlunsplit(
|
|
(scheme, netloc, self.BASIC_URI + str(path), query, frag))
|
|
|
|
return url
|
|
|
|
def generate_vrm_cmd(self, cmd, **kwargs):
|
|
COMMANDS = {
|
|
'v5.1': {
|
|
'list_tasks': ('GET',
|
|
('/tasks', kwargs.get(self.RESOURCE_URI), None,
|
|
None),
|
|
{},
|
|
{},
|
|
False),
|
|
'list_hosts': ('GET',
|
|
('/hosts', kwargs.get(self.RESOURCE_URI), None,
|
|
None),
|
|
{'limit': kwargs.get('limit'),
|
|
'offset': kwargs.get('offset'),
|
|
'scope': kwargs.get('scope')},
|
|
{},
|
|
False),
|
|
'list_datastores': ('GET',
|
|
('/datastores',
|
|
kwargs.get(self.RESOURCE_URI), None,
|
|
None),
|
|
{'limit': kwargs.get('limit'),
|
|
'offset': kwargs.get('offset'),
|
|
'scope': kwargs.get('scope')},
|
|
{},
|
|
False),
|
|
'list_volumes': ('GET',
|
|
('/volumes', kwargs.get(self.RESOURCE_URI),
|
|
None, kwargs.get('id')),
|
|
{'limit': kwargs.get('limit'),
|
|
'offset': kwargs.get('offset'),
|
|
'scope': kwargs.get('scope')},
|
|
{},
|
|
False),
|
|
'create_volume': ('POST',
|
|
('/volumes', None, None, None),
|
|
{},
|
|
{'name': kwargs.get('name'),
|
|
'quantityGB': kwargs.get('quantityGB'),
|
|
'datastoreUrn': kwargs.get('datastoreUrn'),
|
|
'uuid': kwargs.get('uuid'),
|
|
'isThin': kwargs.get('isThin'),
|
|
'type': kwargs.get('type'),
|
|
'indepDisk': kwargs.get('indepDisk'),
|
|
'persistentDisk': kwargs.get(
|
|
'persistentDisk'),
|
|
'volumeId': kwargs.get('volumeId')},
|
|
True),
|
|
'delete_volume': ('DELETE',
|
|
('/volumes', kwargs.get(self.RESOURCE_URI),
|
|
None, None),
|
|
{},
|
|
{},
|
|
True),
|
|
|
|
'list_volumesnapshot': ('GET',
|
|
('/volumesnapshots', None,
|
|
kwargs.get('uuid'), None),
|
|
{'limit': kwargs.get('limit'),
|
|
'offset': kwargs.get('offset'),
|
|
'scope': kwargs.get('scope')},
|
|
{},
|
|
False),
|
|
'create_volumesnapshot': ('POST',
|
|
('/volumesnapshots', None, None,
|
|
None),
|
|
{},
|
|
{'volumeUrn': kwargs.get('vol_urn'),
|
|
'snapshotUuid': kwargs.get('uuid')},
|
|
False),
|
|
'delete_volumesnapshot': ('DELETE',
|
|
('/volumesnapshots', None, None,
|
|
kwargs.get('id')),
|
|
{},
|
|
{
|
|
'snapshotUuid': kwargs.get(
|
|
'snapshotUuid')
|
|
},
|
|
True),
|
|
'createvolumefromsnapshot': ('POST',
|
|
('/volumesnapshots', None,
|
|
"createvol", None),
|
|
{},
|
|
{'snapshotUuid': kwargs.get(
|
|
'uuid'),
|
|
'volumeName':
|
|
kwargs.get('name')},
|
|
True),
|
|
'clone_volume': ('POST',
|
|
('/volumes', None, kwargs.get('src_name'),
|
|
'action/copyVol'),
|
|
{},
|
|
{'destinationVolumeID': kwargs.get(
|
|
'dest_name')},
|
|
True),
|
|
'copy_image_to_volume': ('POST',
|
|
('/volumes/imagetovolume', None, None,
|
|
None),
|
|
{},
|
|
{
|
|
'volumePara': {
|
|
'quantityGB': kwargs.get(
|
|
'volume_size'),
|
|
'urn': kwargs.get(
|
|
'volume_urn')
|
|
},
|
|
'imagePara': {
|
|
'id': kwargs.get('image_id'),
|
|
'url': kwargs.get(
|
|
'image_location')
|
|
},
|
|
'location': kwargs.get(
|
|
'host_urn'),
|
|
'needCreateVolume': False
|
|
},
|
|
True),
|
|
'copy_volume_to_image': ('POST',
|
|
('/volumes/volumetoimage', None, None,
|
|
None),
|
|
{},
|
|
{
|
|
'volumePara': {'urn': kwargs.get(
|
|
'volume_urn'),
|
|
'quantityGB': kwargs.get(
|
|
'volume_size')},
|
|
'imagePara': {
|
|
'id': kwargs.get('image_id'),
|
|
'url': kwargs.get(
|
|
'image_url')}
|
|
},
|
|
True),
|
|
'import_vm_from_image': ('POST',
|
|
('/vms/action/import', None, None,
|
|
None),
|
|
{},
|
|
dict({
|
|
'name': 'name',
|
|
'location': kwargs.get(
|
|
'host_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),
|
|
'detach_vol_from_vm': ('POST',
|
|
('/vms', None, kwargs.get('vm_id'),
|
|
'action/detachvol'),
|
|
{},
|
|
{'volUrn': kwargs.get('volUrn')},
|
|
True),
|
|
'stop_vm': ('POST',
|
|
('/vms', None, kwargs.get('vm_id'), 'action/stop'),
|
|
{},
|
|
{'mode': kwargs.get('mode')},
|
|
True),
|
|
'delete_vm': ('DELETE',
|
|
('/vms', None, kwargs.get('vm_id'), None),
|
|
{},
|
|
{},
|
|
True),
|
|
'query_vm': ('GET',
|
|
('/vms', None, kwargs.get('vm_id'), None),
|
|
{},
|
|
{},
|
|
False),
|
|
'list_templates': ('GET',
|
|
('/vms', None, None, None),
|
|
{'limit': kwargs.get('limit'),
|
|
'offset': kwargs.get('offset'),
|
|
'scope': kwargs.get('scope'),
|
|
'isTemplate': 'true'},
|
|
{},
|
|
False),
|
|
'clone_vm': ('POST',
|
|
('/vms', None, kwargs.get('template_id'),
|
|
'action/clone'),
|
|
{},
|
|
dict({
|
|
"name": "cinder-plugin-temp-vm",
|
|
"description": "cinder-plugin-temp-vm",
|
|
"isLinkClone": kwargs.get('linked_clone'),
|
|
'location': kwargs.get('host_urn'),
|
|
'autoBoot': 'false',
|
|
'vmConfig':
|
|
{
|
|
'cpu': {
|
|
'quantity': 2
|
|
},
|
|
'memory':
|
|
{
|
|
'quantityMB': 1024
|
|
},
|
|
'disks':
|
|
[{
|
|
'pciType': 'IDE',
|
|
'datastoreUrn': kwargs.get('ds_urn'),
|
|
'quantityGB': kwargs.get(
|
|
'volume_size'),
|
|
'volType': 0,
|
|
'sequenceNum': 1,
|
|
'isThin': kwargs.get('is_thin')
|
|
}]
|
|
},
|
|
}),
|
|
True),
|
|
},
|
|
|
|
'v2.0': {}
|
|
}
|
|
|
|
path = query = body = None
|
|
|
|
LOG.info("[BRM-DRIVER] version is [%s]", self.version)
|
|
if self.version not in COMMANDS.keys():
|
|
raise driver_exception.UnsupportedVersion()
|
|
else:
|
|
commands = COMMANDS[self.version]
|
|
|
|
if cmd not in commands.keys():
|
|
raise driver_exception.UnsupportedCommand()
|
|
else:
|
|
(method, pathparams, queryparams, bodyparams, hastask) = commands[
|
|
cmd]
|
|
|
|
resource, resource_uri, tag1, tag2 = pathparams
|
|
if resource_uri:
|
|
path = resource_uri
|
|
LOG.info(_("[VRM-CINDER] [%s]"), path)
|
|
else:
|
|
path = self.site_uri + resource
|
|
LOG.info(_("[VRM-CINDER] [%s]"), path)
|
|
if tag1:
|
|
path += ('/' + str(tag1))
|
|
LOG.info(_("[VRM-CINDER] [%s]"), path)
|
|
if tag2:
|
|
path += ('/' + str(tag2))
|
|
LOG.info(_("[VRM-CINDER] [%s]"), path)
|
|
|
|
if method == 'GET':
|
|
query = self._joined_params(queryparams)
|
|
elif method == 'DELETE':
|
|
query = self._joined_params(queryparams)
|
|
elif method == 'POST':
|
|
query = self._joined_params(queryparams)
|
|
LOG.info("[BRM-DRIVER] _generate_vrm_cmd bodyparams is [%s]",
|
|
bodyparams)
|
|
body = json.dumps(bodyparams)
|
|
LOG.info("[BRM-DRIVER] _generate_vrm_cmd body is [%s]", body)
|
|
else:
|
|
raise cinder_exception.UnknownCmd(cmd=method)
|
|
|
|
url = self._generate_url(path, query)
|
|
LOG.info("[BRM-DRIVER] _generate_vrm_cmd url is [%s]", url)
|
|
|
|
return (method, url, body, hastask)
|