← Back to team overview

launchpad-reviewers team mailing list archive

[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