switch to use the zvm cloud connector backend

Utilize the new zvm cloud connector utilities for the implement of
ceilometer-zvm driver APIs.

Change-Id: Ia24c4ca0c1e34f4a225ab1ddc58220e1d3e92774
This commit is contained in:
dongyan yang 2017-12-22 10:37:24 +08:00
parent ef127c85b2
commit e6e9b9efb0
8 changed files with 347 additions and 1226 deletions

View File

@ -0,0 +1,28 @@
# Copyright 2017 IBM Corp.
#
# 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.
from oslo_config import cfg
zvm_opts = [
cfg.URIOpt('zvm_cloud_connector_url',
help="""
URL to be used to communicate with z/VM Cloud Connector.
Example: https://10.10.10.1:8080.
"""),
]
CONF = cfg.CONF
CONF.register_opts(zvm_opts)

View File

@ -0,0 +1,22 @@
# Copyright 2017 IBM Corp.
#
# 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.
from ceilometer.compute.virt import inspector as virt_inspector
class ZVMConnectorRequestFailed(virt_inspector.InspectorException):
def __init__(self, msg, results):
self.results = results
super(ZVMConnectorRequestFailed, self).__init__(message=msg)

View File

@ -13,184 +13,94 @@
# under the License.
import six
from ceilometer.compute.virt import inspector as virt_inspector
from ceilometer.i18n import _
from oslo_config import cfg
from oslo_utils import timeutils
from oslo_utils import units
from ceilometer_zvm.compute.virt.zvm import exception
from ceilometer_zvm.compute.virt.zvm import utils as zvmutils
zvm_ops = [
cfg.StrOpt('zvm_xcat_server',
default=None,
help='Host name or IP address of xCAT management_node'),
cfg.StrOpt('zvm_xcat_username',
default=None,
help='xCAT username'),
cfg.StrOpt('zvm_xcat_password',
default=None,
secret=True,
help='Password of the xCAT user'),
cfg.IntOpt('zvm_xcat_connection_timeout',
default=600,
help="The number of seconds wait for xCAT MN response"),
cfg.StrOpt('xcat_zhcp_nodename',
default='zhcp',
help='xCat zHCP nodename in xCAT '),
cfg.StrOpt('zvm_host',
default=None,
help='z/VM host that managed by xCAT MN.'),
cfg.StrOpt('zvm_xcat_master',
default='xcat',
help='The xCAT MM node name'),
cfg.IntOpt('cache_update_interval',
default=600,
help="Cached data update interval"),
cfg.StrOpt('zvm_xcat_ca_file',
default=None,
help="CA file for https connection to xcat"),
]
CONF = cfg.CONF
CONF.register_opts(zvm_ops, group='zvm')
from oslo_utils import units
class ZVMInspector(virt_inspector.Inspector):
def __init__(self):
self.cache = zvmutils.CacheData()
self.cache_expiration = timeutils.utcnow_ts()
self.instances = {}
self.zhcp_info = {
'nodename': CONF.zvm.xcat_zhcp_nodename,
'hostname': zvmutils.get_node_hostname(
CONF.zvm.xcat_zhcp_nodename),
'userid': zvmutils.get_userid(CONF.zvm.xcat_zhcp_nodename)
}
def _update_inst_cpu_mem_stat(self, instances):
inst_pis = zvmutils.image_performance_query(
self.zhcp_info['nodename'], instances.values())
for inst_name, userid in instances.items():
if userid not in inst_pis.keys():
# Not performance data returned for this virtual machine
continue
with zvmutils.expect_invalid_xcat_resp_data():
guest_cpus = int(inst_pis[userid]['guest_cpus'])
used_cpu_time = inst_pis[userid]['used_cpu_time']
used_cpu_time = int(used_cpu_time.partition(' ')[0]) * units.k
used_memory = inst_pis[userid]['used_memory']
used_memory = int(used_memory.partition(' ')[0]) / units.Ki
inst_stat = {'nodename': inst_name,
'userid': userid,
'guest_cpus': guest_cpus,
'used_cpu_time': used_cpu_time,
'used_memory': used_memory}
self.cache.set('cpumem', inst_stat)
def _update_inst_nic_stat(self, instances):
vsw_dict = zvmutils.virutal_network_vswitch_query_iuo_stats(
self.zhcp_info['nodename'])
with zvmutils.expect_invalid_xcat_resp_data():
for vsw in vsw_dict['vswitches']:
for nic in vsw['nics']:
for inst_name, userid in instances.items():
if nic['userid'].upper() == userid.upper():
nic_entry = {
'vswitch_name': vsw['vswitch_name'],
'nic_vdev': nic['vdev'],
'nic_fr_rx': int(nic['nic_fr_rx']),
'nic_fr_tx': int(nic['nic_fr_tx']),
'nic_fr_rx_dsc': int(nic['nic_fr_rx_dsc']),
'nic_fr_tx_dsc': int(nic['nic_fr_tx_dsc']),
'nic_fr_rx_err': int(nic['nic_fr_rx_err']),
'nic_fr_tx_err': int(nic['nic_fr_tx_err']),
'nic_rx': int(nic['nic_rx']),
'nic_tx': int(nic['nic_tx'])}
inst_stat = self.cache.get('vnics', inst_name)
if inst_stat is None:
inst_stat = {
'nodename': inst_name,
'userid': userid,
'nics': [nic_entry]
}
else:
inst_stat['nics'].append(nic_entry)
self.cache.set('vnics', inst_stat)
def _update_cache(self, meter, instances={}):
if instances == {}:
self.cache.clear()
self.cache_expiration = (timeutils.utcnow_ts() +
CONF.zvm.cache_update_interval)
instances = self.instances = zvmutils.list_instances(
self.zhcp_info)
if meter == 'cpumem':
self._update_inst_cpu_mem_stat(instances)
if meter == 'vnics':
self._update_inst_nic_stat(instances)
def _check_expiration_and_update_cache(self, meter):
now = timeutils.utcnow_ts()
if now >= self.cache_expiration:
self._update_cache(meter)
def _get_inst_stat(self, meter, instance):
inst_name = zvmutils.get_inst_name(instance)
# zvm inspector can not get instance info in shutdown stat
if zvmutils.get_inst_power_state(instance) == 0x04:
msg = _("Can not get vm info in shutdown state "
"for %s") % inst_name
raise virt_inspector.InstanceShutOffException(msg)
self._check_expiration_and_update_cache(meter)
inst_stat = self.cache.get(meter, inst_name)
if inst_stat is None:
userid = (self.instances.get(inst_name) or
zvmutils.get_userid(inst_name))
self._update_cache(meter, {inst_name: userid})
inst_stat = self.cache.get(meter, inst_name)
if inst_stat is None:
msg = _("Can not get vm info for %s") % inst_name
raise virt_inspector.InstanceNotFoundException(msg)
else:
return inst_stat
def inspect_cpus(self, instance):
inst_stat = self._get_inst_stat('cpumem', instance)
return virt_inspector.CPUStats(number=inst_stat['guest_cpus'],
time=inst_stat['used_cpu_time'])
def inspect_memory_usage(self, instance, duration=None):
inst_stat = self._get_inst_stat('cpumem', instance)
return virt_inspector.MemoryUsageStats(usage=inst_stat['used_memory'])
self._reqh = zvmutils.zVMConnectorRequestHandler()
def inspect_vnics(self, instance):
inst_stat = self._get_inst_stat('vnics', instance)
for nic in inst_stat['nics']:
interface = virt_inspector.Interface(
name=nic['nic_vdev'],
mac=None,
fref=None,
parameters=None)
stats = virt_inspector.InterfaceStats(
rx_bytes=nic['nic_rx'],
rx_packets=nic['nic_fr_rx'],
tx_bytes=nic['nic_tx'],
tx_packets=nic['nic_fr_tx'],
rx_drop=nic['nic_fr_rx_dsc'],
tx_drop=nic['nic_fr_tx_dsc'],
rx_errors=nic['nic_fr_rx_err'],
tx_errors=nic['nic_fr_tx_err'])
yield (interface, stats)
nics_data = self._inspect_inst_data(instance, 'vnics')
# Construct the final result
for nic in nics_data:
yield virt_inspector.InterfaceStats(name=nic['nic_vdev'],
mac=None,
fref=None,
parameters=None,
rx_bytes=nic['nic_rx'],
rx_packets=nic['nic_fr_rx'],
rx_errors=None,
rx_drop=None,
tx_bytes=nic['nic_tx'],
tx_packets=nic['nic_fr_tx'],
tx_errors=None,
tx_drop=None
)
def inspect_instance(self, instance, duration):
inst_stats = self._inspect_inst_data(instance, 'stats')
cpu_number = inst_stats['guest_cpus']
used_cpu_time = (inst_stats['used_cpu_time_us'] * units.k)
used_mem_mb = inst_stats['used_mem_kb'] / units.Ki
# Construct the final result
return virt_inspector.InstanceStats(cpu_number=cpu_number,
cpu_time=used_cpu_time,
memory_usage=used_mem_mb
)
def _inspect_inst_data(self, instance, inspect_type):
inspect_data = {}
inst_name = zvmutils.get_inst_name(instance)
msg_shutdown = _("Can not get vm info in shutdown state "
"for %s") % inst_name
msg_notexist = _("Can not get vm info for %s, vm not exist"
) % inst_name
msg_nodata = _("Failed to get vm info for %s") % inst_name
# zvm inspector can not get instance info in shutdown stat
if zvmutils.get_inst_power_state(instance) == 0x04:
raise virt_inspector.InstanceShutOffException(msg_shutdown)
try:
if inspect_type == 'stats':
inspect_data = self._reqh.call('guest_inspect_stats',
inst_name)
elif inspect_type == 'vnics':
inspect_data = self._reqh.call('guest_inspect_vnics',
inst_name)
except Exception as err:
msg_nodata += (". Error: %s" % six.text_type(err))
raise virt_inspector.NoDataException(msg_nodata)
# Check the inst data is in the returned result
index_key = inst_name.upper()
if index_key not in inspect_data:
# Check the reason: shutdown or not exist or other error
power_stat = ''
try:
power_stat = self._reqh.call('guest_get_power_state',
inst_name)
except exception.ZVMConnectorRequestFailed as err:
if err.results['overallRC'] == 404:
# instance not exists
raise virt_inspector.InstanceNotFoundException(msg_notexist
)
else:
msg_nodata += (". Error: %s" % six.text_type(err))
raise virt_inspector.NoDataException(msg_nodata)
except Exception as err:
msg_nodata += (". Error: %s" % six.text_type(err))
raise virt_inspector.NoDataException(msg_nodata)
if power_stat == 'off':
raise virt_inspector.InstanceShutOffException(msg_shutdown)
else:
raise virt_inspector.NoDataException(msg_nodata)
else:
return inspect_data[index_key]

View File

@ -13,416 +13,17 @@
# under the License.
import contextlib
import functools
import os
from six.moves import http_client as httplib
import socket
import ssl
import six.moves.urllib.parse as urlparse
from ceilometer.compute.virt import inspector
from ceilometer.i18n import _
from ceilometer.i18n import _LW
from oslo_config import cfg
from ceilometer_zvm.compute.virt.zvm import conf
from ceilometer_zvm.compute.virt.zvm import exception
from oslo_log import log as logging
from oslo_serialization import jsonutils
from zvmconnector import connector
CONF = cfg.CONF
CONF = conf.CONF
LOG = logging.getLogger(__name__)
class ZVMException(inspector.InspectorException):
pass
class CacheData(object):
"""Virtual machine stat cache."""
_CTYPES = ('cpumem', 'vnics')
def __init__(self):
self._reset()
def _reset(self):
self.cache = dict((tp, {}) for tp in self._CTYPES)
def set(self, ctype, inst_stat):
"""Set or update cache content.
@ctype: cache type.
@inst_stat: cache data.
"""
self.cache[ctype][inst_stat['nodename']] = inst_stat
def get(self, ctype, inst_name):
return self.cache[ctype].get(inst_name, None)
def delete(self, ctype, inst_name):
if inst_name in self.cache[ctype]:
del self.cache[ctype][inst_name]
def clear(self, ctype='all'):
if ctype == 'all':
self._reset()
else:
self.cache[ctype] = {}
class XCATUrl(object):
"""To return xCAT url for invoking xCAT REST API."""
def __init__(self):
self.PREFIX = '/xcatws'
self.SUFFIX = ''.join(('?userName=', CONF.zvm.zvm_xcat_username,
'&password=', CONF.zvm.zvm_xcat_password,
'&format=json'))
# xcat objects
self.NODES = '/nodes'
self.TABLES = '/tables'
# xcat actions
self.XDSH = '/dsh'
def _append_addp(self, rurl, addp=None):
if addp is not None:
return ''.join((rurl, addp))
else:
return rurl
def xdsh(self, arg=''):
"""Run shell command."""
return ''.join((self.PREFIX, self.NODES, arg, self.XDSH, self.SUFFIX))
def gettab(self, arg='', addp=None):
rurl = ''.join((self.PREFIX, self.TABLES, arg, self.SUFFIX))
return self._append_addp(rurl, addp)
def tabdump(self, arg='', addp=None):
return self.gettab(arg, addp)
def lsdef_node(self, arg='', addp=None):
rurl = ''.join((self.PREFIX, self.NODES, arg, self.SUFFIX))
return self._append_addp(rurl, addp)
class HTTPSClientAuthConnection(httplib.HTTPSConnection):
"""For https://wiki.openstack.org/wiki/OSSN/OSSN-0033."""
def __init__(self, host, port, ca_file, timeout=None, key_file=None,
cert_file=None):
httplib.HTTPSConnection.__init__(self, host, port,
key_file=key_file,
cert_file=cert_file)
self.key_file = key_file
self.cert_file = cert_file
self.ca_file = ca_file
self.timeout = timeout
self.use_ca = True
if self.ca_file is None:
LOG.debug("no xCAT CA file specified, this is considered "
"not secure")
self.use_ca = False
def connect(self):
sock = socket.create_connection((self.host, self.port), self.timeout)
if self._tunnel_host:
self.sock = sock
self._tunnel()
if (self.ca_file is not None and
not os.path.exists(self.ca_file)):
LOG.warning(_LW("the CA file %(ca_file) does not exist!"),
{'ca_file': self.ca_file})
self.use_ca = False
if not self.use_ca:
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
cert_reqs=ssl.CERT_NONE)
else:
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
ca_certs=self.ca_file,
cert_reqs=ssl.CERT_REQUIRED)
class XCATConnection(object):
"""Https requests to xCAT web service."""
def __init__(self):
"""Initialize https connection to xCAT service."""
self.host = CONF.zvm.zvm_xcat_server
self.port = 443
self.conn = HTTPSClientAuthConnection(self.host, self.port,
CONF.zvm.zvm_xcat_ca_file,
timeout=CONF.zvm.zvm_xcat_connection_timeout)
def request(self, method, url, body=None, headers={}):
"""Send https request to xCAT server.
Will return a python dictionary including:
{'status': http return code,
'reason': http reason,
'message': response message}
"""
if body is not None:
body = jsonutils.dumps(body)
headers = {'content-type': 'text/plain',
'content-length': len(body)}
_rep_ptn = ''.join(('&password=', CONF.zvm.zvm_xcat_password))
LOG.debug("Sending request to xCAT. xCAT-Server:%(xcat_server)s "
"Request-method:%(method)s "
"URL:%(url)s "
"Headers:%(headers)s "
"Body:%(body)s" %
{'xcat_server': CONF.zvm.zvm_xcat_server,
'method': method,
'url': url.replace(_rep_ptn, ''), # hide password in log
'headers': str(headers),
'body': body})
try:
self.conn.request(method, url, body, headers)
except socket.gaierror as err:
msg = (_("Failed to connect xCAT server %(srv)s: %(err)s") %
{'srv': self.host, 'err': err})
raise ZVMException(msg)
except (socket.error, socket.timeout) as err:
msg = (_("Communicate with xCAT server %(srv)s error: %(err)s") %
{'srv': self.host, 'err': err})
raise ZVMException(msg)
try:
res = self.conn.getresponse()
except Exception as err:
msg = (_("Failed to get response from xCAT server %(srv)s: "
"%(err)s") % {'srv': self.host, 'err': err})
raise ZVMException(msg)
msg = res.read()
resp = {
'status': res.status,
'reason': res.reason,
'message': msg}
LOG.debug("xCAT response: %s" % str(resp))
# Only "200" or "201" returned from xCAT can be considered
# as good status
err = None
if method == "POST":
if res.status != 201:
err = str(resp)
else:
if res.status != 200:
err = str(resp)
if err is not None:
msg = (_('Request to xCAT server %(srv)s failed: %(err)s') %
{'srv': self.host, 'err': err})
raise ZVMException(msg)
return resp
def xcat_request(method, url, body=None, headers={}):
conn = XCATConnection()
resp = conn.request(method, url, body, headers)
return load_xcat_resp(resp['message'])
def jsonloads(jsonstr):
try:
return jsonutils.loads(jsonstr)
except ValueError:
errmsg = _("xCAT response data is not in JSON format")
LOG.error(errmsg)
raise ZVMException(errmsg)
@contextlib.contextmanager
def expect_invalid_xcat_resp_data():
"""Catch exceptions when using xCAT response data."""
try:
yield
except (ValueError, TypeError, IndexError, AttributeError,
KeyError) as err:
msg = _("Invalid xCAT response data: %s") % str(err)
raise ZVMException(msg)
def wrap_invalid_xcat_resp_data_error(function):
"""Catch exceptions when using xCAT response data."""
@functools.wraps(function)
def decorated_function(*arg, **kwargs):
try:
return function(*arg, **kwargs)
except (ValueError, TypeError, IndexError, AttributeError,
KeyError) as err:
msg = _("Invalid xCAT response data: %s") % str(err)
raise ZVMException(msg)
return decorated_function
@wrap_invalid_xcat_resp_data_error
def translate_xcat_resp(rawdata, dirt):
"""Translate xCAT response JSON stream to a python dictionary."""
data_list = rawdata.split("\n")
data = {}
for ls in data_list:
for k in dirt.keys():
if ls.__contains__(dirt[k]):
data[k] = ls[(ls.find(dirt[k]) + len(dirt[k])):].strip(' "')
break
return data
@wrap_invalid_xcat_resp_data_error
def load_xcat_resp(message):
"""Abstract information from xCAT REST response body."""
resp_list = jsonloads(message)['data']
keys = ('info', 'data', 'node', 'errorcode', 'error')
resp = {}
for k in keys:
resp[k] = []
for d in resp_list:
for k in keys:
if d.get(k) is not None:
resp[k].append(d.get(k))
err = resp.get('error')
if err != []:
for e in err:
if _is_warning(str(e)):
# ignore known warnings or errors:
continue
else:
raise ZVMException(message)
_log_warnings(resp)
return resp
def _log_warnings(resp):
for msg in (resp['info'], resp['node'], resp['data']):
msgstr = str(msg)
if 'warn' in msgstr.lower():
LOG.warning(_("Warning from xCAT: %s") % msgstr)
def _is_warning(err_str):
ignore_list = (
'Warning: the RSA host key for',
'Warning: Permanently added',
'WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED',
)
for im in ignore_list:
if im in err_str:
return True
return False
def get_userid(node_name):
"""Returns z/VM userid for the xCAT node."""
url = XCATUrl().lsdef_node(''.join(['/', node_name]))
info = xcat_request('GET', url)['info']
with expect_invalid_xcat_resp_data():
for s in info[0]:
if s.__contains__('userid='):
return s.strip().rpartition('=')[2]
def xdsh(node, commands):
""""Run command on xCAT node."""
LOG.debug('Run command %(cmd)s on xCAT node %(node)s' %
{'cmd': commands, 'node': node})
def xdsh_execute(node, commands):
"""Invoke xCAT REST API to execute command on node."""
xdsh_commands = 'command=%s' % commands
# Add -q (quiet) option to ignore ssh warnings and banner msg
opt = 'options=-q'
body = [xdsh_commands, opt]
url = XCATUrl().xdsh('/' + node)
return xcat_request("PUT", url, body)
res_dict = xdsh_execute(node, commands)
return res_dict
def get_node_hostname(node_name):
addp = '&col=node&value=%s&attribute=hostnames' % node_name
url = XCATUrl().gettab("/hosts", addp)
with expect_invalid_xcat_resp_data():
return xcat_request("GET", url)['data'][0][0]
def list_instances(hcp_info):
zvm_host = CONF.zvm.zvm_host
url = XCATUrl().tabdump("/zvm")
res_dict = xcat_request("GET", url)
instances = {}
with expect_invalid_xcat_resp_data():
data_entries = res_dict['data'][0][1:]
for data in data_entries:
l = data.split(",")
node = l[0].strip("\"")
hcp = l[1].strip("\"")
userid = l[2].strip("\"")
# zvm host and zhcp are not included in the list
if (hcp.upper() == hcp_info['hostname'].upper() and
node.upper() not in (zvm_host.upper(),
hcp_info['nodename'].upper(),
CONF.zvm.zvm_xcat_master.upper())):
instances[node] = userid.upper()
return instances
def image_performance_query(zhcp_node, inst_list):
cmd = ('smcli Image_Performance_Query -T "%(inst_list)s" -c %(num)s' %
{'inst_list': " ".join(inst_list), 'num': len(inst_list)})
with expect_invalid_xcat_resp_data():
resp = xdsh(zhcp_node, cmd)
raw_data = resp["data"][0][0]
ipq_kws = {
'userid': "Guest name:",
'guest_cpus': "Guest CPUs:",
'used_cpu_time': "Used CPU time:",
'used_memory': "Used memory:",
}
pi_dict = {}
with expect_invalid_xcat_resp_data():
rpi_list = raw_data.split("".join((zhcp_node, ": \n")))
for rpi in rpi_list:
pi = translate_xcat_resp(rpi, ipq_kws)
if pi.get('userid') is not None:
pi_dict[pi['userid']] = pi
return pi_dict
def get_inst_name(instance):
return getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', None)
@ -431,79 +32,20 @@ def get_inst_power_state(instance):
return getattr(instance, 'OS-EXT-STS:power_state', None)
def virutal_network_vswitch_query_iuo_stats(zhcp_node):
cmd = ('smcli Virtual_Network_Vswitch_Query_IUO_Stats -T "%s" '
'-k "switch_name=*"' % zhcp_node)
class zVMConnectorRequestHandler(object):
with expect_invalid_xcat_resp_data():
resp = xdsh(zhcp_node, cmd)
raw_data_list = resp["data"][0]
def __init__(self):
_url = urlparse.urlparse(CONF.zvm_cloud_connector_url)
self._conn = connector.ZVMConnector(_url.hostname, _url.port)
while raw_data_list.__contains__(None):
raw_data_list.remove(None)
raw_data = '\n'.join(raw_data_list)
rd_list = raw_data.split('\n')
def _parse_value(data_list, idx, keyword, offset):
return idx + offset, data_list[idx].rpartition(keyword)[2].strip()
vsw_dict = {}
with expect_invalid_xcat_resp_data():
# vswitch count
idx = 0
idx, vsw_count = _parse_value(rd_list, idx, 'vswitch count:', 2)
vsw_dict['vswitch_count'] = int(vsw_count)
# deal with each vswitch data
vsw_dict['vswitches'] = []
for i in range(vsw_dict['vswitch_count']):
vsw_data = {}
# skip vswitch number
idx += 1
# vswitch name
idx, vsw_name = _parse_value(rd_list, idx, 'vswitch name:', 1)
vsw_data['vswitch_name'] = vsw_name
# uplink count
idx, up_count = _parse_value(rd_list, idx, 'uplink count:', 1)
# skip uplink data
idx += int(up_count) * 9
# skip bridge data
idx += 8
# nic count
vsw_data['nics'] = []
idx, nic_count = _parse_value(rd_list, idx, 'nic count:', 1)
nic_count = int(nic_count)
for j in range(nic_count):
nic_data = {}
idx, nic_id = _parse_value(rd_list, idx, 'nic_id:', 1)
userid, toss, vdev = nic_id.partition(' ')
nic_data['userid'] = userid
nic_data['vdev'] = vdev
idx, nic_data['nic_fr_rx'] = _parse_value(rd_list, idx,
'nic_fr_rx:', 1)
idx, nic_data['nic_fr_rx_dsc'] = _parse_value(rd_list, idx,
'nic_fr_rx_dsc:', 1)
idx, nic_data['nic_fr_rx_err'] = _parse_value(rd_list, idx,
'nic_fr_rx_err:', 1)
idx, nic_data['nic_fr_tx'] = _parse_value(rd_list, idx,
'nic_fr_tx:', 1)
idx, nic_data['nic_fr_tx_dsc'] = _parse_value(rd_list, idx,
'nic_fr_tx_dsc:', 1)
idx, nic_data['nic_fr_tx_err'] = _parse_value(rd_list, idx,
'nic_fr_tx_err:', 1)
idx, nic_data['nic_rx'] = _parse_value(rd_list, idx,
'nic_rx:', 1)
idx, nic_data['nic_tx'] = _parse_value(rd_list, idx,
'nic_tx:', 1)
vsw_data['nics'].append(nic_data)
# vlan count
idx, vlan_count = _parse_value(rd_list, idx, 'vlan count:', 1)
# skip vlan data
idx += int(vlan_count) * 3
# skip the blank line
idx += 1
vsw_dict['vswitches'].append(vsw_data)
return vsw_dict
def call(self, func_name, *args, **kwargs):
results = self._conn.send_request(func_name, *args, **kwargs)
if results['overallRC'] == 0:
return results['output']
else:
msg = ("z/VM Cloud Connector request %(api)s failed with "
"parameters: %(args)s %(kwargs)s . Results: %(results)s" %
{'api': func_name, 'args': str(args), 'kwargs': str(kwargs),
'results': str(results)})
LOG.debug(msg)
raise exception.ZVMConnectorRequestFailed(msg=msg, results=results)

View File

@ -14,304 +14,202 @@
import mock
import unittest
from ceilometer.compute.virt import inspector as virt_inspertor
from oslo_config import fixture as fixture_config
from oslo_utils import timeutils
from oslotest import base
from ceilometer_zvm.compute.virt.zvm import inspector as zvm_inspector
from ceilometer.compute.virt import inspector as virt_inspector
from ceilometer_zvm.compute.virt.zvm import conf
from ceilometer_zvm.compute.virt.zvm import exception as zvmexception
from ceilometer_zvm.compute.virt.zvm import inspector as zvminspector
from ceilometer_zvm.compute.virt.zvm import utils as zvmutils
class TestZVMInspector(base.BaseTestCase):
CONF = conf.CONF
class TestZVMInspector(unittest.TestCase):
def setUp(self):
self.CONF = self.useFixture(
fixture_config.Config(zvm_inspector.CONF)).conf
self.CONF.set_override('xcat_zhcp_nodename', 'zhcp', 'zvm')
super(TestZVMInspector, self).setUp()
unittest.TestCase.setUp(self)
CONF.zvm_cloud_connector_url = 'https://1.1.1.1:1111'
self._inspector = zvminspector.ZVMInspector()
self._inst = mock.MagicMock()
self._stats_dict = {'guest_cpus': 1,
'used_cpu_time_us': 7185838,
'elapsed_cpu_time_us': 35232895,
'min_cpu_count': 2,
'max_cpu_limit': 10000,
'samples_cpu_in_use': 0,
'samples_cpu_delay': 0,
'used_mem_kb': 390232,
'max_mem_kb': 3097152,
'min_mem_kb': 0,
'shared_mem_kb': 5222192
}
self._vnics_list = [{'vswitch_name': 'vsw1',
'nic_vdev': '0600',
'nic_fr_rx': 99999,
'nic_fr_tx': 99999,
'nic_rx': 9999999,
'nic_tx': 9999999,
'nic_fr_rx_dsc': 0,
'nic_fr_tx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx_err': 0},
{'vswitch_name': 'vsw2',
'nic_vdev': '0700',
'nic_fr_rx': 88888,
'nic_fr_tx': 88888,
'nic_rx': 8888888,
'nic_tx': 8888888,
'nic_fr_rx_dsc': 0,
'nic_fr_tx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx_err': 0}]
get_nhn = mock.MagicMock(return_value='zhcp.com')
get_uid = mock.MagicMock(return_value='zhcp')
with mock.patch.multiple(zvmutils, get_node_hostname=get_nhn,
get_userid=get_uid):
self.inspector = zvm_inspector.ZVMInspector()
def test_init(self):
self.assertEqual('zhcp', self.inspector.zhcp_info['nodename'])
self.assertEqual('zhcp.com', self.inspector.zhcp_info['hostname'])
self.assertEqual('zhcp', self.inspector.zhcp_info['userid'])
@mock.patch.object(zvmutils, 'image_performance_query')
def test_update_inst_cpu_mem_stat(self, ipq):
ipq.return_value = {'INST1': {'userid': 'INST1',
'guest_cpus': '2',
'used_cpu_time': '1710205201 uS',
'used_memory': '4189268 KB'},
'INST2': {'userid': 'INST2',
'guest_cpus': '4',
'used_cpu_time': '1710205201 uS',
'used_memory': '4189268 KB'}}
inst_list = {'inst1': 'INST1', 'inst2': 'INST2'}
self.inspector._update_inst_cpu_mem_stat(inst_list)
exp1 = {'guest_cpus': 2,
'nodename': 'inst1',
'used_cpu_time': 1710205201000,
'used_memory': 4091,
'userid': 'INST1'}
self.assertEqual(exp1, self.inspector.cache.get('cpumem', 'inst1'))
self.assertEqual(4,
self.inspector.cache.get('cpumem', 'inst2')['guest_cpus'])
@mock.patch.object(zvmutils, 'image_performance_query')
def test_update_inst_cpu_mem_stat_invalid_data(self, ipq):
ipq.return_value = {'INST1': {'userid': 'INST1', 'guest_cpus': 's'}}
self.assertRaises(zvmutils.ZVMException,
self.inspector._update_inst_cpu_mem_stat,
{'inst1': 'INST1'})
@mock.patch.object(zvminspector.ZVMInspector, "_inspect_inst_data")
def test_inspect_instance(self, inspect_inst):
inspect_inst.return_value = self._stats_dict
rdata = self._inspector.inspect_instance(self._inst, 0)
inspect_inst.assert_called_once_with(self._inst, 'stats')
self.assertIsInstance(rdata, virt_inspector.InstanceStats)
self.assertEqual(rdata.cpu_number, 1)
self.assertEqual(rdata.cpu_time, 7185838000)
self.assertEqual(rdata.memory_usage, 381)
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_inst_cpu_mem_stat")
@mock.patch.object(zvmutils, 'list_instances')
def test_update_cache_all(self, list_inst, upd):
inst_list = {'inst1': 'INST1', 'inst2': 'INST2'}
list_inst.return_value = inst_list
self.inspector._update_cache("cpumem", {})
list_inst.assert_called_with(self.inspector.zhcp_info)
upd.assert_called_with(inst_list)
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_inst_cpu_mem_stat")
def test_update_cache_one_inst(self, upd):
inst = {'inst1': 'INST1'}
self.inspector._update_cache('cpumem', inst)
upd.assert_called_with(inst)
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_cache")
def test_check_expiration_and_update_cache(self, udc):
self.inspector._check_expiration_and_update_cache('cpus')
udc.assert_called_once_with('cpus')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_cache")
def test_check_expiration_and_update_cache_no_update(self, udc):
self.inspector.cache_expiration = timeutils.utcnow_ts() + 100
self.inspector._check_expiration_and_update_cache('cpus')
udc.assert_not_called()
"_inspect_inst_data")
@mock.patch.object(zvmutils, 'get_inst_name')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_check_expiration_and_update_cache")
def test_get_inst_stat(self, check_update, get_name):
get_name.return_value = 'inst1'
self.inspector.cache.set('cpumem',
{'guest_cpus': 2, 'nodename': 'inst1'})
inst_stat = self.inspector._get_inst_stat('cpumem', {'inst1': 'INST1'})
self.assertEqual(2, inst_stat['guest_cpus'])
check_update.assert_called_once_with('cpumem')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_cache")
@mock.patch.object(zvmutils, 'get_userid')
@mock.patch.object(zvmutils, 'get_inst_name')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_check_expiration_and_update_cache")
def test_get_inst_stat_not_found(self, check_update, get_name,
get_uid, update):
get_name.return_value = 'inst1'
get_uid.return_value = 'INST1'
self.assertRaises(virt_inspertor.InstanceNotFoundException,
self.inspector._get_inst_stat, 'cpumem',
{'inst1': 'INST1'})
check_update.assert_called_once_with('cpumem')
update.assert_called_once_with('cpumem', {'inst1': 'INST1'})
def test_inspect_vnics(self, get_inst_name, inspect_data):
get_inst_name.return_value = 'INST1'
inspect_data.return_value = self._vnics_list
interface = list(self._inspector.inspect_vnics({'inst1': 'INST1'}))[0]
if interface.name == '0600':
self.assertEqual(99999, interface.rx_packets)
else:
self.assertEqual(8888888, interface.rx_bytes)
inspect_data.assert_called_once_with({'inst1': 'INST1'}, 'vnics')
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_get_inst_stat_shutoff(self, get_name, get_power_stat):
get_name.return_value = 'inst1'
get_power_stat.return_value = 0x04
self.inspector.instances = {'inst1': 'INST1'}
def test_private_inspect_inst_type_stats(self, inst_name, inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.return_value = {'FAKEINST': self._stats_dict}
rdata = self._inspector._inspect_inst_data(self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
sdkclient_call.assert_called_once_with('guest_inspect_stats',
'FAKEINST')
self.assertDictEqual(rdata, self._stats_dict)
self.assertRaises(virt_inspertor.InstanceShutOffException,
self.inspector._get_inst_stat, 'cpumem',
{'inst1': 'INST1'})
get_name.assert_called_once_with({'inst1': 'INST1'})
get_power_stat.assert_called_once_with({'inst1': 'INST1'})
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_update_cache")
@mock.patch.object(zvmutils, 'get_userid')
@mock.patch("ceilometer_zvm.compute.virt.zvm.utils.CacheData.get")
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_check_expiration_and_update_cache")
def test_get_inst_stat_update_cache(self, check_update, get_name,
cache_get, get_uid, update):
get_name.return_value = 'inst1'
cache_get.side_effect = [None, {'guest_cpus': 2, 'nodename': 'inst1'}]
get_uid.return_value = 'INST1'
inst_stat = self.inspector._get_inst_stat('cpus', {'inst1': 'INST1'})
self.assertEqual(2, inst_stat['guest_cpus'])
check_update.assert_called_once_with('cpus')
update.assert_called_once_with('cpus', {'inst1': 'INST1'})
def test_private_inspect_inst_type_vnics(self, inst_name, inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.return_value = {'FAKEINST': self._vnics_list}
rdata = self._inspector._inspect_inst_data(self._inst, 'vnics')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
sdkclient_call.assert_called_once_with('guest_inspect_vnics',
'FAKEINST')
self.assertListEqual(rdata, self._vnics_list)
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_check_expiration_and_update_cache")
def test_get_inst_stat_nics(self, check_update, get_name):
get_name.return_value = 'inst1'
self.inspector.cache.set(
'vnics',
{'nodename': 'inst1',
'userid': 'INST1',
'nics': [{'vswitch_name': 'vsw1',
'nic_vdev': '0600',
'nic_fr_rx': 99999,
'nic_fr_tx': 99999,
'nic_rx': 9999999,
'nic_tx': 9999999},
{'vswitch_name': 'vsw2',
'nic_vdev': '0700',
'nic_fr_rx': 88888,
'nic_fr_tx': 88888,
'nic_rx': 8888888,
'nic_tx': 8888888}]}
)
inst_stat = self.inspector._get_inst_stat('vnics', {'inst1': 'INST1'})
self.assertEqual(2, len(inst_stat['nics']))
check_update.assert_called_once_with('vnics')
def test_private_inspect_inst_power_off(self, inst_name,
inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x04
self.assertRaises(virt_inspector.InstanceShutOffException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
sdkclient_call.assert_not_called()
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_get_inst_stat")
def test_inspect_cpus(self, get_stat):
get_stat.return_value = {'guest_cpus': 2, 'used_cpu_time': 99999999}
cpu_stat = self.inspector.inspect_cpus(None)
self.assertEqual(2, cpu_stat.number)
self.assertEqual(99999999, cpu_stat.time)
get_stat.assert_called_once_with('cpumem', None)
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_private_inspect_inst_not_exist(self, inst_name,
inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.side_effect = [{},
zvmexception.ZVMConnectorRequestFailed(
msg='SDK Request Failed',
results={'overallRC': 404,
'output': ''})
]
self.assertRaises(virt_inspector.InstanceNotFoundException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_get_inst_stat")
def test_inspect_memory_usage(self, get_stat):
get_stat.return_value = {'used_memory': 1998}
mem_usage = self.inspector.inspect_memory_usage(None)
self.assertEqual(1998, mem_usage.usage)
get_stat.assert_called_once_with('cpumem', None)
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_private_inspect_inst_other_exception(self, inst_name,
inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.side_effect = Exception()
self.assertRaises(virt_inspector.NoDataException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
sdkclient_call.assert_called_with('guest_inspect_stats', 'FAKEINST')
@mock.patch.object(zvmutils, 'virutal_network_vswitch_query_iuo_stats')
def test_update_inst_nic_stat(self, vswq):
vsw_dist = {'vswitches': [
{'vswitch_name': 'XCATVSW1',
'nics': [
{'nic_fr_rx_dsc': '0',
'nic_fr_rx_err': '0',
'nic_fr_tx_err': '4',
'userid': 'INST1',
'nic_rx': '103024058',
'nic_fr_rx': '573952',
'nic_fr_tx': '548780',
'vdev': '0600',
'nic_fr_tx_dsc': '0',
'nic_tx': '102030890'},
{'nic_fr_rx_dsc': '0',
'nic_fr_rx_err': '0',
'nic_fr_tx_err': '4',
'userid': 'INST2',
'nic_rx': '3111714',
'nic_fr_rx': '17493',
'nic_fr_tx': '16886',
'vdev': '0600',
'nic_fr_tx_dsc': '0',
'nic_tx': '3172646'}]},
{'vswitch_name': 'XCATVSW2',
'nics': [
{'nic_fr_rx_dsc': '0',
'nic_fr_rx_err': '0',
'nic_fr_tx_err': '0',
'userid': 'INST1',
'nic_rx': '4684435',
'nic_fr_rx': '34958',
'nic_fr_tx': '16211',
'vdev': '1000',
'nic_fr_tx_dsc': '0',
'nic_tx': '3316601'},
{'nic_fr_rx_dsc': '0',
'nic_fr_rx_err': '0',
'nic_fr_tx_err': '0',
'userid': 'INST2',
'nic_rx': '3577163',
'nic_fr_rx': '27211',
'nic_fr_tx': '12344',
'vdev': '1000',
'nic_fr_tx_dsc': '0',
'nic_tx': '2515045'}]}],
'vswitch_count': 2}
vswq.return_value = vsw_dist
instances = {'inst1': 'INST1', 'inst2': 'INST2'}
self.inspector._update_inst_nic_stat(instances)
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_private_inspect_inst_null_data_shutdown(self, inst_name,
inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.side_effect = [{}, 'off']
self.assertRaises(virt_inspector.InstanceShutOffException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
exp_inst1_nics_data = [
{'nic_fr_rx': 573952,
'nic_fr_rx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx': 548780,
'nic_fr_tx_dsc': 0,
'nic_fr_tx_err': 4,
'nic_rx': 103024058,
'nic_tx': 102030890,
'nic_vdev': '0600',
'vswitch_name': 'XCATVSW1'},
{'nic_fr_rx': 34958,
'nic_fr_rx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx': 16211,
'nic_fr_tx_dsc': 0,
'nic_fr_tx_err': 0,
'nic_rx': 4684435,
'nic_tx': 3316601,
'nic_vdev': '1000',
'vswitch_name': 'XCATVSW2'}
]
self.assertEqual(exp_inst1_nics_data,
self.inspector.cache.get('vnics', 'inst1')['nics'])
vswq.assert_called_once_with('zhcp')
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_private_inspect_inst_null_data_active(self, inst_name,
inst_power_state,
sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.side_effect = [{}, 'on']
self.assertRaises(virt_inspector.NoDataException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)
@mock.patch("ceilometer_zvm.compute.virt.zvm.inspector.ZVMInspector."
"_get_inst_stat")
def test_inspect_nics(self, get_stat):
get_stat.return_value = {'nodename': 'inst1',
'userid': 'INST1',
'nics': [
{'vswitch_name': 'vsw1',
'nic_vdev': '0600',
'nic_fr_rx': 99999,
'nic_fr_tx': 99999,
'nic_rx': 9999999,
'nic_tx': 9999999,
'nic_fr_rx_dsc': 0,
'nic_fr_tx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx_err': 0},
{'vswitch_name': 'vsw2',
'nic_vdev': '0700',
'nic_fr_rx': 88888,
'nic_fr_tx': 88888,
'nic_rx': 8888888,
'nic_tx': 8888888,
'nic_fr_rx_dsc': 0,
'nic_fr_tx_dsc': 0,
'nic_fr_rx_err': 0,
'nic_fr_tx_err': 0}]}
nic, stat = list(self.inspector.inspect_vnics({'inst1': 'INST1'}))[0]
if nic.name == '0600':
self.assertEqual(99999, stat.rx_packets)
else:
self.assertEqual(8888888, stat.rx_bytes)
get_stat.assert_called_once_with('vnics', {'inst1': 'INST1'})
@mock.patch.object(zvmutils.zVMConnectorRequestHandler, 'call')
@mock.patch.object(zvmutils, 'get_inst_power_state')
@mock.patch.object(zvmutils, 'get_inst_name')
def test_private_inspect_inst_null_data_unknown_exception(self,
inst_name, inst_power_state, sdkclient_call):
inst_name.return_value = 'FAKEINST'
inst_power_state.return_value = 0x01
sdkclient_call.side_effect = [{}, Exception()]
self.assertRaises(virt_inspector.NoDataException,
self._inspector._inspect_inst_data,
self._inst, 'stats')
inst_name.assert_called_once_with(self._inst)
inst_power_state.assert_called_once_with(self._inst)

View File

@ -14,309 +14,25 @@
import mock
import unittest
from oslo_config import fixture as fixture_config
from oslo_serialization import jsonutils
from oslotest import base
from ceilometer_zvm.compute.virt.zvm import inspector as zvm_inspector
from ceilometer_zvm.compute.virt.zvm import utils as zvmutils
class TestXCATUrl(base.BaseTestCase):
class TestZVMUtils(unittest.TestCase):
def setUp(self):
self.CONF = self.useFixture(
fixture_config.Config(zvm_inspector.CONF)).conf
self.CONF.set_override('zvm_xcat_username', 'user', 'zvm')
self.CONF.set_override('zvm_xcat_password', 'pwd', 'zvm')
super(TestXCATUrl, self).setUp()
self.xcaturl = zvmutils.XCATUrl()
def test_xdsh(self):
url = ("/xcatws/nodes/fakenode/dsh"
"?userName=user&password=pwd&format=json")
self.assertEqual(self.xcaturl.xdsh("/fakenode"), url)
def test_gettab(self):
url = ("/xcatws/tables/table"
"?userName=user&password=pwd&format=json&addp")
self.assertEqual(self.xcaturl.gettab('/table', '&addp'), url)
def test_lsdef_node(self):
url = ("/xcatws/nodes/fakenode"
"?userName=user&password=pwd&format=json")
self.assertEqual(self.xcaturl.lsdef_node("/fakenode"), url)
def test_tabdump(self):
url = ("/xcatws/tables/table"
"?userName=user&password=pwd&format=json&addp")
self.assertEqual(self.xcaturl.tabdump('/table', '&addp'), url)
class TestXCATConnection(base.BaseTestCase):
def setUp(self):
self.CONF = self.useFixture(
fixture_config.Config(zvm_inspector.CONF)).conf
self.CONF.set_override('zvm_xcat_server', '1.1.1.1', 'zvm')
self.CONF.set_override('zvm_xcat_username', 'user', 'zvm')
self.CONF.set_override('zvm_xcat_password', 'pwd', 'zvm')
super(TestXCATConnection, self).setUp()
self.conn = zvmutils.XCATConnection()
def test_request(self):
with mock.patch.object(self.conn, 'conn') as fake_conn:
fake_res = mock.Mock()
fake_res.status = 200
fake_res.reason = 'OK'
fake_res.read.return_value = 'data'
fake_conn.getresponse.return_value = fake_res
exp_data = {'status': 200,
'reason': 'OK',
'message': 'data'}
res_data = self.conn.request("GET", 'url')
self.assertEqual(exp_data, res_data)
def test_request_failed(self):
with mock.patch.object(self.conn, 'conn') as fake_conn:
fake_res = mock.Mock()
fake_res.status = 500
fake_res.reason = 'INVALID'
fake_res.read.return_value = 'err data'
fake_conn.getresponse.return_value = fake_res
self.assertRaises(zvmutils.ZVMException,
self.conn.request, 'GET', 'url')
class TestZVMUtils(base.BaseTestCase):
def setUp(self):
self.CONF = self.useFixture(
fixture_config.Config(zvm_inspector.CONF)).conf
self.CONF.set_override('zvm_xcat_server', '1.1.1.1', 'zvm')
self.CONF.set_override('zvm_xcat_username', 'user', 'zvm')
self.CONF.set_override('zvm_xcat_password', 'pwd', 'zvm')
self.CONF.set_override('zvm_host', 'zvmhost1', 'zvm')
super(TestZVMUtils, self).setUp()
self._inst = mock.MagicMock()
setattr(self._inst, 'OS-EXT-SRV-ATTR:instance_name',
'fakeinst')
setattr(self._inst, 'OS-EXT-STS:power_state',
0x01)
@mock.patch('ceilometer_zvm.compute.virt.zvm.utils.XCATConnection.request')
def test_xcat_request(self, xcat_req):
xcat_req.return_value = {'message': jsonutils.dumps(
{'data': [{'data': ['data']}]})}
self.assertEqual([['data']],
zvmutils.xcat_request("GET", 'url')['data'])
def test_get_instance_name(self):
inst = zvmutils.get_inst_name(self._inst)
self.assertEqual('fakeinst', inst)
@mock.patch('ceilometer_zvm.compute.virt.zvm.utils.xcat_request')
def test_get_userid(self, xcat_req):
xcat_req.return_value = {'info': [['userid=fakeuser']]}
self.assertEqual('fakeuser', zvmutils.get_userid('fakenode'))
@mock.patch('ceilometer_zvm.compute.virt.zvm.utils.xcat_request')
def test_xdsh(self, xcat_req):
zvmutils.xdsh('node', 'cmds')
xcat_req.assert_any_call('PUT',
'/xcatws/nodes/node/dsh?userName=user&password=pwd&format=json',
['command=cmds', 'options=-q'])
@mock.patch('ceilometer_zvm.compute.virt.zvm.utils.xcat_request')
def test_get_node_hostname(self, xcat_req):
xcat_req.return_value = {'data': [['hostname']]}
self.assertEqual('hostname', zvmutils.get_node_hostname('nodename'))
@mock.patch.object(zvmutils, 'xcat_request')
def test_list_instances(self, xcat_req):
resp_list = [
'toss',
'"xcat","zhcp.com","xcat"',
'"zhcp","zhcp.com","zhcp"',
'"zvmhost1","zhcp.com",""',
'"node1","zhcp.com","node1"',
'"node2","zhcp.com","node2"',
'"node3","zhcp2.com","node3"',
]
xcat_req.return_value = {'data': [resp_list]}
exp_list = {'node1': 'NODE1', 'node2': 'NODE2'}
hcp_info = {'nodename': 'zhcp',
'hostname': 'zhcp.com',
'userid': 'zhcp'}
self.assertEqual(exp_list, zvmutils.list_instances(hcp_info))
@mock.patch.object(zvmutils, 'xcat_request')
def test_list_instances_invalid_data(self, xcat_req):
resp_list = [
'toss',
'"xcat","zhcp.com","xcat"',
'"zhcp","zhcp.com","zhcp"',
'"zvmhost1","zhcp.com",""',
'"node1","zhcp.com"',
]
hcp_info = {'nodename': 'zhcp',
'hostname': 'zhcp.com',
'userid': 'zhcp'}
xcat_req.return_value = {'data': [resp_list]}
self.assertRaises(zvmutils.ZVMException, zvmutils.list_instances,
hcp_info)
@mock.patch.object(zvmutils, 'xdsh')
def test_image_performance_query(self, dsh):
res_data = ["zhcp: Number of virtual server IDs: 2 \n"
"zhcp: Guest name: INST1\n"
"zhcp: Used CPU time: \"1710205201 uS\"\n"
"zhcp: Elapsed time: \"6659572798 uS\"\n"
"zhcp: Used memory: \"4189268 KB\"\n"
"zhcp: Guest CPUs: \"2\"\n"
"zhcp: \n"
"zhcp: Guest name: INST2\n"
"zhcp: Used CPU time: \"1710205201 uS\"\n"
"zhcp: Elapsed time: \"6659572798 uS\"\n"
"zhcp: Used memory: \"4189268 KB\"\n"
"zhcp: Guest CPUs: \"4\"\n"]
dsh.return_value = {'data': [res_data]}
inst_list = {'inst1': 'INST1', 'inst2': 'INST2'}
exp_data = {'INST1': {'userid': 'INST1',
'guest_cpus': '2',
'used_cpu_time': '1710205201 uS',
'used_memory': '4189268 KB'},
'INST2': {'userid': 'INST2',
'guest_cpus': '4',
'used_cpu_time': '1710205201 uS',
'used_memory': '4189268 KB'}}
self.assertEqual(exp_data,
zvmutils.image_performance_query('zhcp', inst_list))
@mock.patch.object(zvmutils, 'xdsh')
def test_virutal_network_vswitch_query_iuo_stats(self, dsh):
vsw_data = ['zhcp11: vswitch count: 2\n'
'zhcp11: \n'
'zhcp11: vswitch number: 1\n'
'zhcp11: vswitch name: XCATVSW1\n'
'zhcp11: uplink count: 1\n'
'zhcp11: uplink_conn: 6240\n'
'zhcp11: uplink_fr_rx: 3658251\n'
'zhcp11: uplink_fr_rx_dsc: 0\n'
'zhcp11: uplink_fr_rx_err: 0\n'
'zhcp11: uplink_fr_tx: 4209828\n'
'zhcp11: uplink_fr_tx_dsc: 0\n'
'zhcp11: uplink_fr_tx_err: 0\n'
'zhcp11: uplink_rx: 498914052\n'
'zhcp11: uplink_tx: 2615220898\n'
'zhcp11: bridge_fr_rx: 0\n'
'zhcp11: bridge_fr_rx_dsc: 0\n'
'zhcp11: bridge_fr_rx_err: 0\n'
'zhcp11: bridge_fr_tx: 0\n'
'zhcp11: bridge_fr_tx_dsc: 0\n'
'zhcp11: bridge_fr_tx_err: 0\n'
'zhcp11: bridge_rx: 0\n'
'zhcp11: bridge_tx: 0\n'
'zhcp11: nic count: 2\n'
'zhcp11: nic_id: INST1 0600\n'
'zhcp11: nic_fr_rx: 573952\n'
'zhcp11: nic_fr_rx_dsc: 0\n'
'zhcp11: nic_fr_rx_err: 0\n'
'zhcp11: nic_fr_tx: 548780\n'
'zhcp11: nic_fr_tx_dsc: 0\n'
'zhcp11: nic_fr_tx_err: 4\n'
'zhcp11: nic_rx: 103024058\n'
'zhcp11: nic_tx: 102030890\n'
'zhcp11: nic_id: INST2 0600\n'
'zhcp11: nic_fr_rx: 17493\n'
'zhcp11: nic_fr_rx_dsc: 0\n'
'zhcp11: nic_fr_rx_err: 0\n'
'zhcp11: nic_fr_tx: 16886\n'
'zhcp11: nic_fr_tx_dsc: 0\n'
'zhcp11: nic_fr_tx_err: 4\n'
'zhcp11: nic_rx: 3111714\n'
'zhcp11: nic_tx: 3172646\n'
'zhcp11: vlan count: 0\n'
'zhcp11: \n'
'zhcp11: vswitch number: 2\n'
'zhcp11: vswitch name: XCATVSW2\n'
'zhcp11: uplink count: 1\n'
'zhcp11: uplink_conn: 6200\n'
'zhcp11: uplink_fr_rx: 1608681\n'
'zhcp11: uplink_fr_rx_dsc: 0\n'
'zhcp11: uplink_fr_rx_err: 0\n'
'zhcp11: uplink_fr_tx: 2120075\n'
'zhcp11: uplink_fr_tx_dsc: 0\n'
'zhcp11: uplink_fr_tx_err: 0\n'
'zhcp11: uplink_rx: 314326223',
'zhcp11: uplink_tx: 1503721533\n'
'zhcp11: bridge_fr_rx: 0\n'
'zhcp11: bridge_fr_rx_dsc: 0\n'
'zhcp11: bridge_fr_rx_err: 0\n'
'zhcp11: bridge_fr_tx: 0\n'
'zhcp11: bridge_fr_tx_dsc: 0\n'
'zhcp11: bridge_fr_tx_err: 0\n'
'zhcp11: bridge_rx: 0\n'
'zhcp11: bridge_tx: 0\n'
'zhcp11: nic count: 2\n'
'zhcp11: nic_id: INST1 1000\n'
'zhcp11: nic_fr_rx: 34958\n'
'zhcp11: nic_fr_rx_dsc: 0\n'
'zhcp11: nic_fr_rx_err: 0\n'
'zhcp11: nic_fr_tx: 16211\n'
'zhcp11: nic_fr_tx_dsc: 0\n'
'zhcp11: nic_fr_tx_err: 0\n'
'zhcp11: nic_rx: 4684435\n'
'zhcp11: nic_tx: 3316601\n'
'zhcp11: nic_id: INST2 1000\n'
'zhcp11: nic_fr_rx: 27211\n'
'zhcp11: nic_fr_rx_dsc: 0\n'
'zhcp11: nic_fr_rx_err: 0\n'
'zhcp11: nic_fr_tx: 12344\n'
'zhcp11: nic_fr_tx_dsc: 0\n'
'zhcp11: nic_fr_tx_err: 0\n'
'zhcp11: nic_rx: 3577163\n'
'zhcp11: nic_tx: 2515045\n'
'zhcp11: vlan count: 0',
None]
dsh.return_value = {'data': [vsw_data]}
vsw_dict = zvmutils.virutal_network_vswitch_query_iuo_stats('zhcp11')
self.assertEqual(2, len(vsw_dict['vswitches']))
self.assertEqual('INST1',
vsw_dict['vswitches'][0]['nics'][0]['userid'])
@mock.patch.object(zvmutils, 'xdsh')
def test_virutal_network_vswitch_query_iuo_stats_invalid_data(self, dsh):
dsh.return_value = ['invalid', 'data']
self.assertRaises(zvmutils.ZVMException,
zvmutils.virutal_network_vswitch_query_iuo_stats,
'zhcp')
class TestCacheData(base.BaseTestCase):
def setUp(self):
super(TestCacheData, self).setUp()
self.cache_data = zvmutils.CacheData()
def tearDown(self):
self.cache_data.clear()
super(TestCacheData, self).tearDown()
def test_set(self):
self.cache_data.set('cpumem', {'nodename': 'node'})
self.assertEqual({'nodename': 'node'},
self.cache_data.cache['cpumem']['node'])
def test_get(self):
self.cache_data.set('vnics', {'nodename': 'node'})
self.assertEqual({'nodename': 'node'},
self.cache_data.get('vnics', 'node'))
def test_delete(self):
self.cache_data.set('cpumem', {'nodename': 'node'})
self.cache_data.delete('cpumem', 'node')
self.assertIsNone(self.cache_data.get('cpumem', 'node'))
def test_clear(self):
self.cache_data.set('cpumem', {'nodename': 'node1'})
self.cache_data.set('vnics', {'nodename': 'node2'})
self.cache_data.clear()
self.assertEqual({'cpumem': {}, 'vnics': {}},
self.cache_data.cache)
def test_get_inst_power_state(self):
pst = zvmutils.get_inst_power_state(self._inst)
self.assertEqual(0x01, pst)

View File

@ -5,3 +5,5 @@ oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.8.0 # Apache-2.0
oslo.service>=0.6.0 # Apache-2.0
pbr<2.0,>=1.4
six>=1.9.0
zVMCloudConnector>=0.3.2 # Apache 2.0 License

View File

@ -10,15 +10,18 @@ setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
-egit+https://github.com/openstack/ceilometer#egg=ceilometer
-egit+https://github.com/openstack/ceilometer@master#egg=ceilometer
-egit+https://github.com/mfcloud/python-zvm-sdk@master#egg=zvmsdk
commands = python setup.py testr --slowest --testr-args='{posargs}'
[testenv:pep8]
commands = flake8
[testenv:py27]
whitelist_externals = git
commands = /bin/cp -r {toxinidir}/ceilometer_zvm/compute/virt/zvm \
{toxinidir}/.tox/py27/src/ceilometer/ceilometer/compute/virt/
git --git-dir={toxinidir}/.tox/py27/src/zvmsdk/.git --work-tree={toxinidir}/.tox/py27/src/zvmsdk pull
python setup.py testr --slowest --testr-args='{posargs}'
[testenv:venv]