From 57160823d420c15d8ebe235cfdefcb5ab9f7e4a2 Mon Sep 17 00:00:00 2001 From: Mark Hamzy Date: Wed, 30 Nov 2016 14:18:56 -0600 Subject: [PATCH] Start testing the example usage for CI: test_hook_mi_ipmiblob.py test_hook_mi_ipmiblob.py is the provided sample for a CI team to use to allocate a MoltenIron instance before running tests. Change-Id: I217b8e3ba14cb3c4358d71be40ad9ca80aca32e1 --- README.rst | 22 +--- molteniron/tests/hardware_info.good | 1 + molteniron/tests/localrc.good | 5 + setup.py | 5 +- tox.ini | 6 + utils/test_hook_mi_ipmiblob.py | 164 ++++++++++++++++++++++++++++ utils/test_hook_mi_ipmiblob.sh | 23 ++++ 7 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 molteniron/tests/hardware_info.good create mode 100644 molteniron/tests/localrc.good create mode 100755 utils/test_hook_mi_ipmiblob.py create mode 100755 utils/test_hook_mi_ipmiblob.sh diff --git a/README.rst b/README.rst index 469f70a..c408be4 100644 --- a/README.rst +++ b/README.rst @@ -150,8 +150,6 @@ During the creation of a job, in the pre_test_hook.sh, add the following snippet REPO_DIR=/opt/stack/new/molteniron MI_CONF_DIR=/usr/local/etc/molteniron MI_IP=10.1.2.3 # @TODO - Replace with your IP addr here! - MI_SQLUSER=user # @TODO - Replace with your mysql user here! - MI_SQLPASS=passwd # @TODO - Replace with your mysql password here! # Grab molteniron and install it git clone https://git.openstack.org/openstack/molteniron ${REPO_DIR} || exit 1 @@ -173,21 +171,11 @@ During the creation of a job, in the pre_test_hook.sh, add the following snippet sudo sed -i "s/127.0.0.1/${MI_IP}/g" ${MI_CONF_DIR}/conf.yaml fi - if [ -n "${MI_SQLUSER}" ] - then - # Set the molteniron database user in the conf file - sudo sed -r -i -e 's,(^sqlUser: ")([a-zA-Z_]+)("$),\1'${MI_SQLUSER}'\3,' ${MI_CONF_DIR}/conf.yaml - fi - - if [ -n "${MI_SQLPASS}" ] - then - # Set the molteniron database password in the conf file - sudo sed -r -i -e 's,(^sqlPass: ")([a-zA-Z_]+)("$),\1'${MI_SQLPASS}'\3,' ${MI_CONF_DIR}/conf.yaml - fi - - export dsvm_uuid - # NOTE: dsvm_uuid used in the following script, hence the -E - sudo -E ${REPO_DIR}/utils/test_hook_configure_mi.sh + sudo ${REPO_DIR}/utils/test_hook_mi_ipmiblob.py \ + --hardware-info=/opt/stack/new/devstack/files/hardware_info \ + --localrc=/opt/stack/new/devstack/localrc \ + ${dsvm_uuid} \ + 1 ) || exit $? and change the MI_IP environment variable to be your MoltenIron server! diff --git a/molteniron/tests/hardware_info.good b/molteniron/tests/hardware_info.good new file mode 100644 index 0000000..c08a61d --- /dev/null +++ b/molteniron/tests/hardware_info.good @@ -0,0 +1 @@ +10.1.2.1 de:ad:be:ef:00:01 user password diff --git a/molteniron/tests/localrc.good b/molteniron/tests/localrc.good new file mode 100644 index 0000000..6c139de --- /dev/null +++ b/molteniron/tests/localrc.good @@ -0,0 +1,5 @@ +IRONIC_HW_ARCH=ppc64el +IRONIC_HW_NODE_CPU=8 +IRONIC_HW_NODE_RAM=2048 +IRONIC_HW_NODE_DISK=32 +ALLOCATION_POOL="start=10.1.2.3,end=10.1.2.3 --allocation-pool start=10.1.2.4,end=10.1.2.4" diff --git a/setup.py b/setup.py index 613737a..c970146 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,10 @@ setup(name="molteniron", description="Client/server database for Ironic Baremetal services", url="https://github.com/openstack/molteniron", py_modules=["molteniron/__init__", "molteniron/moltenirond"], - scripts=["molteniron/moltenirond-helper", "molteniron/molteniron"], + scripts=["molteniron/moltenirond-helper", + "molteniron/molteniron", + "utils/test_hook_mi_ipmiblob.py", + "utils/test_hook_mi_ipmiblob.sh"], data_files=[("etc/molteniron/", ["conf.yaml"])], setup_requires=['pbr'], pbr=True) diff --git a/tox.ini b/tox.ini index c944b00..026c736 100644 --- a/tox.ini +++ b/tox.ini @@ -12,8 +12,10 @@ setenv = deps = -r{toxinidir}/test-requirements.txt # Don't worry about installing bash commands in the virtual environment. whitelist_externals = mkdir + diff #commands = python setup.py test --slowest --testr-args='{posargs}' commands = mkdir -p testenv/var/run/ + mkdir -p testenv/tmp/ python setup.py \ install \ --install-data=testenv/ \ @@ -63,6 +65,10 @@ commands = mkdir -p testenv/var/run/ molteniron \ --conf-dir=testenv/etc/molteniron/ \ release hamzy + # Sadly needs a bash shell to run uuidgen + test_hook_mi_ipmiblob.sh + diff testenv/tmp/hardware_info molteniron/tests/hardware_info.good + diff testenv/tmp/localrc molteniron/tests/localrc.good python \ molteniron/tests/testAllocateBM.py \ --conf-dir=testenv/etc/molteniron/ diff --git a/utils/test_hook_mi_ipmiblob.py b/utils/test_hook_mi_ipmiblob.py new file mode 100755 index 0000000..5876ee0 --- /dev/null +++ b/utils/test_hook_mi_ipmiblob.py @@ -0,0 +1,164 @@ +#! /usr/bin/env python + +""" +This is the MoltenIron Command Line client that speaks to +a MoltenIron server. +""" + +# Copyright (c) 2016 IBM Corporation. +# +# 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. + +# pylint: disable-msg=C0103 +# pylint: disable=redefined-outer-name + +from __future__ import print_function + +import argparse +import json +from molteniron import molteniron +import os +import sys +import yaml + + +if __name__ == "__main__": + mi = molteniron.MoltenIron() + + parser = argparse.ArgumentParser(description="Molteniron test gate tool") + + parser.add_argument("-c", + "--conf-dir", + action="store", + type=str, + dest="conf_dir", + help="The directory where configuration is stored") + parser.add_argument("-i", # Stoopid -h for help + "--hardware-info", + action="store", + type=str, + dest="hardware_info", + required=True, + help="The hardware_info file") + parser.add_argument("-l", + "--localrc", + action="store", + type=str, + dest="localrc", + required=True, + help="The localrc file") + parser.add_argument("owner_name", + help="Name of the requester") + parser.add_argument("number_of_nodes", + type=int, + help="How many nodes to reserve") + + args = parser.parse_args() + + if args.conf_dir: + if not os.path.isdir(args.conf_dir): + msg = "Error: %s is not a valid directory" % (args.conf_dir, ) + print(msg, file=sys.stderr) + sys.exit(1) + + yaml_file = os.path.realpath("%s/conf.yaml" % (args.conf_dir, )) + else: + yaml_file = "/usr/local/etc/molteniron/conf.yaml" + + with open(yaml_file, "r") as f_obj: + conf = yaml.load(f_obj) + + mi.setup_conf(conf) + mi.setup_parser(parser) + + # For example: + # args_map = {"output": "json", + # "type": "human", + # "func": getattr(mi, "status"), + # "conf_dir": "testenv/etc/molteniron/"} + args_map = {"output": "json", + "owner_name": args.owner_name, + "number_of_nodes": args.number_of_nodes, + "func": getattr(mi, "allocate"), + "conf_dir": "testenv/etc/molteniron/"} + + # Call the function + mi.call_function(args_map) + + # Get the result + response_map = mi.get_response_map() + + try: + rc = response_map["status"] + except KeyError: + msg = ("Error: Server returned: %s and we expected a status " + + "somewhere") % (response_map, ) + print(msg, file=sys.stderr) + exit(444) + + if rc != 200: + msg = "Error: Status was not 200 %s" % (response_map["message"], ) + print(msg, file=sys.stderr) + exit(rc) + + assert response_map["status"] == 200 + assert "nodes" in response_map + + nodes = response_map["nodes"] + + assert len(nodes) == 1 + + # There can only be one! + node_key = list(nodes.keys())[0] + + # {u'status': u'dirty', + # u'provisioned': u'bb6141a2-3585-496a-bc02-1ef89c81e8fb', + # u'name': u'test2', + # u'timestamp': u'2016-11-30T15:50:03', + # u'ipmi_ip': u'10.1.2.2', + # u'blob': u'{"port_hwaddr": "\\"de:ad:be:ef:00:01\\"", + # "cpu_arch": "ppc64el", + # "ram_mb": "2048", + # "disk_gb": "32", + # "cpus": "8", + # "ipmi_user": "\\"user\\"", + # "ipmi_password": "\\"password\\""}', + # u'allocation_pool': u'10.1.2.5,10.1.2.6', + # u'id': 2} + node = nodes[node_key] + + assert "blob" in node + + json_blob = node["blob"] + blob = json.loads(json_blob) + + with open(args.hardware_info, "w") as hi_obj: + # Write one line + hi_obj.write(("%(ipmi_ip)s" % node) + + (" %(port_hwaddr)s" + + " %(ipmi_user)s" + + " %(ipmi_password)s\n") % blob) + + pool = node["allocation_pool"].split(",") + + pairs = ["start=%s,end=%s" % (x, x) for x in pool] + allocation_pool = " --allocation-pool ".join(pairs) + + with open(args.localrc, "a") as l_obj: + # Write multiple lines + l_obj.write(("IRONIC_HW_ARCH=%(cpu_arch)s\n" + + "IRONIC_HW_NODE_CPU=%(cpus)s\n" + + "IRONIC_HW_NODE_RAM=%(ram_mb)s\n" + + "IRONIC_HW_NODE_DISK=%(disk_gb)s\n") % blob + + "ALLOCATION_POOL=\"%s\"\n" % (allocation_pool, )) diff --git a/utils/test_hook_mi_ipmiblob.sh b/utils/test_hook_mi_ipmiblob.sh new file mode 100755 index 0000000..3383bd7 --- /dev/null +++ b/utils/test_hook_mi_ipmiblob.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Copyright (c) 2016 IBM Corporation. +# +# 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. + +test_hook_mi_ipmiblob.py \ + --conf-dir=testenv/etc/molteniron/ \ + --hardware-info=testenv/tmp/hardware_info \ + --localrc=testenv/tmp/localrc \ + $(uuidgen) \ + 1