launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #13347
[Merge] lp:~matsubara/maas/quantal-tests into lp:~maas-maintainers/maas/packaging
Diogo Matsubara has proposed merging lp:~matsubara/maas/quantal-tests into lp:~maas-maintainers/maas/packaging.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~matsubara/maas/quantal-tests/+merge/129319
This adds integration tests to run autopkgtests in the QA lab.
--
https://code.launchpad.net/~matsubara/maas/quantal-tests/+merge/129319
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~matsubara/maas/quantal-tests into lp:~maas-maintainers/maas/packaging.
=== modified file 'debian/tests/maas-integration.py'
--- debian/tests/maas-integration.py 2012-09-20 02:22:33 +0000
+++ debian/tests/maas-integration.py 2012-10-11 21:37:29 +0000
@@ -1,72 +1,208 @@
-# TODO
-# - send ipmi commands to turn on/off nodes
-# - run import pxe files
-# - check node states once they're on/off
-# - check node state changes (declared -> commissionig -> ready)
import os
-from subprocess import check_output
+from simplejson import loads
import sys
+from subprocess import Popen, PIPE
+from time import sleep
from unittest import TestCase
-from pyvirtualdisplay import Display
-from sst.actions import (
- assert_url, assert_text_contains, assert_title_contains, click_button,
- get_element, go_to, write_textfield)
-
-
sys.path.insert(0, "/usr/share/maas")
os.environ['DJANGO_SETTINGS_MODULE'] = 'maas.settings'
-from maasserver.models import User
-
-MAAS_URL = "http://10.98.0.13/MAAS"
+from django.core.management import call_command
+from django.contrib.auth.models import User
+
+from maasserver.models.user import get_creds_tuple
+from apiclient.creds import convert_tuple_to_string
+
+
+MAAS_URL = "http://10.98.0.90/MAAS"
ADMIN_USER = "admin"
PASSWORD = "test"
+POWER_USER = "root"
+POWER_PASS = "ubuntu"
+
+LAB_MAC_ADDRESSES = [
+ ("lenovo-RD230-03", "00:E0:81:DD:D5:99"),
+ ("lenovo-RD230-04", "00:E0:81:DD:D1:0B"),
+ ("lenovo-RD230-05", "00:E0:81:DD:D4:11"),
+ ("lenovo-RD230-06", "00:E0:81:D1:B1:47"),
+ ("lenovo-RD230-07", "00:E0:81:DD:D1:1B"),
+ ("lenovo-RD230-08", "00:E0:81:DD:D1:2B"),
+ ("lenovo-RD230-09", "00:E0:81:DD:D1:A3"),
+ ("lenovo-RD230-10", "00:E0:81:DC:38:6D"),
+ ("lenovo-RD230-11", "00:E0:81:DD:D0:FF"),
+ ("lenovo-RD230-12", "00:E0:81:DD:D4:F9")
+ ]
+
+LENOVO_LAB = {}
+ipmi_address_template = "192.168.22.%d"
+for number, (hostname, mac) in enumerate(LAB_MAC_ADDRESSES, 33):
+ LENOVO_LAB[mac] = (hostname, ipmi_address_template % number)
+
+LAB_DNS_CONFIG = """
+options {
+ directory "/var/cache/bind";
+ forwarders {
+ 10.98.0.1;
+ };
+ dnssec-validation auto;
+ auth-nxdomain no; # conform to RFC1035
+};
+"""
class TestMAASIntegration(TestCase):
- def setUp(self):
- self.display = Display(visible=0, size=(1280, 1024))
- self.display.start()
-
- def tearDown(self):
- self.display.stop()
-
- def createadmin(self):
- """Run sudo maas createsuperuser."""
- cmd_output = check_output(
- ["sudo", "maas", "createsuperuser", "--username=%s" % ADMIN_USER,
- "--email=example@xxxxxxxxxxxxx", "--noinput"])
- ## Set password for admin user.
- try:
- admin = User.objects.get(username=ADMIN_USER)
- except User.DoesNotExist:
- admin = User(username=ADMIN_USER)
- admin.set_password(PASSWORD)
- admin.save()
- return cmd_output
-
- def installation(self):
- # Check the installation worked.
- go_to(MAAS_URL)
- assert_text_contains(
- get_element(tag="body"), "No admin user has been created yet")
-
- def createadmin_and_login(self):
- ## Creates the admin user.
- output = self.createadmin()
- self.assertEqual(output, 'Superuser created successfully.')
- ## Login with the newly created admin user
- go_to(MAAS_URL)
- assert_text_contains(
- get_element(tag="body"), "Login to lenovo-RD230-01 MAAS")
- write_textfield("id_username", ADMIN_USER)
- write_textfield("id_password", PASSWORD)
- click_button("Login")
- assert_url("MAAS/")
- assert_title_contains("Dashboard")
+ def _run_command(self, args):
+ process = Popen(args, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = process.communicate()
+ return stdout, stderr
+
+ def _run_maas_cli(self, args):
+ return self._run_command(["maas-cli", "maas"] + args)
+
+ def create_admin(self):
+ """Run maas createsuperuser."""
+ cmd_output = call_command(
+ "createadmin", username=ADMIN_USER, password=PASSWORD,
+ email="example@xxxxxxxxxxxxx", noinput=True)
+ # No output, means admin user was created successfully.
+ self.assertEqual(cmd_output, None)
+
+ def login_api(self):
+ admin = User.objects.get(username=ADMIN_USER)
+ token = admin.tokens.all()[0]
+ token_str = convert_tuple_to_string(get_creds_tuple(token))
+ api_url = MAAS_URL + "/api/1.0/"
+ self._run_command(
+ ["maas-cli", "login", "maas", api_url, token_str])
+
+ def update_pxe_config(self):
+ pxe_fd = open("/etc/maas/import_pxe_files", "r+")
+ pxe_file = pxe_fd.read()
+ pxe_file = pxe_file.replace(
+ 'RELEASES="precise"', 'RELEASES="precise quantal"')
+ pxe_fd.seek(0)
+ pxe_fd.write(pxe_file)
+ pxe_fd.close()
+ ephemerals_fd = open("/etc/maas/import_ephemerals", "r+")
+ ephemerals = ephemerals_fd.read()
+ ephemerals = ephemerals.replace(
+ '#REMOTE_IMAGES_MIRROR="https://cloud-images.ubuntu.com"',
+ 'REMOTE_IMAGES_MIRROR="http://10.98.0.13/mirrors/maas-ephemeral"')
+ ephemerals += '\nSTREAM=daily\n'
+ ephemerals_fd.seek(0)
+ ephemerals_fd.write(ephemerals)
+ ephemerals_fd.close()
+
+ def import_pxe_files(self):
+ self._run_command(["maas-import-pxe-files"])
+
+ def update_preseed_arm(self):
+ #XXX: matsubara add workaround to boot arm nodes.
+ userdata_fd = open("/usr/share/maas/preseeds/enlist_userdata", "r+")
+ userdata = userdata_fd.read()
+ userdata += '\napt_sources:\n - source: "deb http://ports.ubuntu.com/ubuntu-ports precise-proposed main"'
+ userdata_fd.seek(0)
+ userdata_fd.write(userdata)
+ userdata_fd.close()
+
+ def set_up_dhcp(self):
+ self._run_maas_cli([
+ "node-group-interfaces", "new", "master",
+ "ip=192.168.21.5", "interface=eth1", "management=2",
+ "subnet_mask=255.255.255.0",
+ "broadcast_ip=192.168.21.255",
+ "router_ip=192.168.21.1",
+ "ip_range_low=192.168.21.10",
+ "ip_range_high=192.168.21.30"])
+ while os.path.exists("/etc/maas/dhcpd.conf") is False:
+ sleep(2)
+ dhcp_fd = open("/etc/maas/dhcpd.conf", "r+")
+ dhcp = dhcp_fd.read()
+ dhcp += open("/home/ubuntu/mac-ip-mapping").read()
+ dhcp_fd.seek(0)
+ dhcp_fd.write(dhcp)
+ dhcp_fd.close()
+ self._run_command(["service", "maas-dhcp-server", "restart"])
+
+ def power_on(self, ip, user, password):
+ self._run_command(
+ ["ipmipower", "-h", ip, "-u", user, "-p", password, "--on"])
+
+ def power_off(self, ip, user, password):
+ self._run_command(
+ ["ipmipower", "-h", ip, "-u", user, "-p", password, "--off"])
+
+ def boot_nodes(self):
+ # Run ipmipower to boot up nodes.
+ lenovo_ipmi = [
+ ipmi for hostname, ipmi in LENOVO_LAB.values() if
+ hostname[-2:] in ["03", "04", "06", "09"]]
+ for ipmi_address in lenovo_ipmi:
+ self.power_off(ipmi_address, POWER_USER, POWER_PASS)
+ self.power_on(ipmi_address, POWER_USER, POWER_PASS)
+ arm_ipmi = ["192.168.21.50", "192.168.21.52", "192.168.21.53"]
+ for ipmi_address in arm_ipmi:
+ self.power_off(ipmi_address, 'admin', 'admin')
+ self.power_on(ipmi_address, 'admin', 'admin')
+
+ def _wait_nodes(self, status):
+ output, err = self._run_maas_cli(
+ ["nodes", "list", "status=%d" % status])
+ node_list = loads(output)
+ while not len(node_list) == 7:
+ sleep(5)
+ output, err = self._run_maas_cli(
+ ["nodes", "list", "status=%d" % status ])
+ node_list = loads(output)
+
+ def check_nodes_declared(self):
+ # XXX: matsubara This needs a timeout. If nodes don't show up as
+ # declared in say 5 mins consider test failure.
+ self._wait_nodes(0)
+
+ def check_nodes_ready(self):
+ # XXX: matsubara This needs a timeout. If nodes don't show up as
+ # ready in say 5 mins consider test failure.
+ self._wait_nodes(4)
+
+ def set_nodes_ipmi_config(self):
+ """Set IPMI configuration for each node."""
+ for mac in LENOVO_LAB.keys():
+ # run maas-cli command to search node by mac and return system_id
+ out, err = self._run_maas_cli(
+ ["nodes", "list", "mac_address=%s" % mac])
+ node_list = loads(out)
+ for node in node_list:
+ ignored = self._run_maas_cli(
+ ["node", "update", node['system_id'], "power_type=ipmi",
+ "power_parameters_power_address=%s " % LENOVO_LAB[mac][1],
+ "power_parameters_power_user=%s" % POWER_USER,
+ "power_parameters_power_pass=%s" % POWER_PASS])
+
+ def update_dns_config(self):
+ #XXX: matsubara Could be asked by maas-dns package and configurable
+ # through debconf seed file.
+ dns_config = open("/etc/bind/named.conf.options", 'w')
+ dns_config.write(LAB_DNS_CONFIG)
+ dns_config.close()
+ self._run_command(["service", "bind9", "restart"])
+
+ def commission_nodes(self):
+ # Use maas-cli to accept all nodes.
+ self._run_maas_cli(["nodes","accept-all"])
def test_integration(self):
# Run the integration tests in order.
- self.installation()
- self.createadmin_and_login()
+ self.create_admin()
+ self.update_pxe_config()
+ self.import_pxe_files()
+ self.update_preseed_arm()
+ self.login_api()
+ self.set_up_dhcp()
+ self.update_dns_config()
+ self.boot_nodes()
+ self.check_nodes_declared()
+ self.set_nodes_ipmi_config()
+ self.commission_nodes()
+ self.check_nodes_ready()
=== modified file 'debian/tests/maas-package-test'
--- debian/tests/maas-package-test 2012-09-20 02:22:33 +0000
+++ debian/tests/maas-package-test 2012-10-11 21:37:29 +0000
@@ -1,5 +1,4 @@
#!/bin/sh
set -e -u
exec 2>&1
-pip install sst
nosetests debian/tests/maas-integration.py