← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~allenap/maas/pserv-cobbler-reconcile into lp:maas

 

Gavin Panella has proposed merging lp:~allenap/maas/pserv-cobbler-reconcile into lp:maas.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~allenap/maas/pserv-cobbler-reconcile/+merge/98702

Provides a couple of tools (one of which uses the other) to get started with an existing Cobbler installation (i.e. vdenv) and Juju. These tools will not end up in the package that users install; they're strictly dev & qa only.
-- 
https://code.launchpad.net/~allenap/maas/pserv-cobbler-reconcile/+merge/98702
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/maas/pserv-cobbler-reconcile into lp:maas.
=== added directory 'qa/scripts'
=== added file 'qa/scripts/prepare-for-juju-with-vdenv'
--- qa/scripts/prepare-for-juju-with-vdenv	1970-01-01 00:00:00 +0000
+++ qa/scripts/prepare-for-juju-with-vdenv	2012-03-21 18:20:29 +0000
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+# Exit immediately if a command exits with a non-zero status.
+set -o errexit
+# Treat unset variables as an error when substituting.
+set -o nounset
+
+wait_for_next() {
+    local key=
+    until [ "${key}" == "n" ]; do
+        read -s -p 'Press `n` to continue. ' -n 1 key
+        echo
+    done
+    echo
+}
+
+cat <<'EOF'
+
+This script assumes that `vdenv` has been started, and that `zimmer` is
+running. It will then *destroy* your development/demo database, rebuild
+everything, and reconcile with Cobbler.
+
+EOF
+wait_for_next
+
+# After setting up vdenv, do the following:
+
+export DJANGO_SETTINGS_MODULE="maas.demo"
+
+make distclean
+make syncdb
+make pserv-start
+make txlongpoll-start
+bin/maas createadmin \
+    --username "${LOGNAME}" --password test \
+    --email "${LOGNAME}@example.com"
+bin/maas reconcile
+utilities/maasdb shell db <<'EOF'
+UPDATE maasserver_node
+   SET owner_id = NULL, status = 4
+ WHERE hostname LIKE 'odev-node%';
+EOF
+
+cat <<'EOF'
+
+Next the MAAS server will be started, at which point you can Juju.
+
+However, once MAAS is running, Juju needs to be pointed at it, and given
+credentials with which to manipulate it:
+
+  1. Copy an OAuth token from <http://localhost:5240/account/prefs/>.
+
+  2. Interpolate it into the following:
+
+     {{{
+     juju: environments
+     environments:
+       maas:
+         type: maas
+         maas-server: 'http://localhost:5240'
+         maas-oauth: '${OAUTH_TOKEN_FROM_STEP_1}
+         admin-secret: 'nothing'
+         juju-origin: lp:maas
+     }}}
+
+  3. Customize `juju-origin` as desired.
+
+  4. Put it into `~/.juju/environments.yaml`.
+
+Some tips for productive Juju fun:
+
+  - Check VNC output (via virsh). Go to vt7 for the boot log.
+
+  - Check netboot enabled/disabled (in Cobbler).
+
+Good luck. You'll need it ;)
+
+EOF
+wait_for_next
+
+make run

=== modified file 'setup.py'
--- setup.py	2012-03-16 21:04:55 +0000
+++ setup.py	2012-03-21 18:20:29 +0000
@@ -50,9 +50,10 @@
     packages=find_packages(
         where=b'src',
         exclude=[
+            b"*.testing",
+            b"*.tests",
             b"maastesting",
-            b"maastesting.*",
-            ]
+            ],
         ),
     package_dir={'': b'src'},
     include_package_data=True,

=== modified file 'src/maas/development.py'
--- src/maas/development.py	2012-03-21 05:38:18 +0000
+++ src/maas/development.py	2012-03-21 18:20:29 +0000
@@ -1,4 +1,3 @@
-
 # Copyright 2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 

=== modified file 'src/maasserver/management/commands/createadmin.py'
--- src/maasserver/management/commands/createadmin.py	2012-03-21 14:25:09 +0000
+++ src/maasserver/management/commands/createadmin.py	2012-03-21 18:20:29 +0000
@@ -1,4 +1,3 @@
-
 # Copyright 2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 

=== added directory 'src/maastesting/management'
=== added file 'src/maastesting/management/__init__.py'
=== added directory 'src/maastesting/management/commands'
=== added file 'src/maastesting/management/commands/__init__.py'
=== added file 'src/maastesting/management/commands/reconcile.py'
--- src/maastesting/management/commands/reconcile.py	1970-01-01 00:00:00 +0000
+++ src/maastesting/management/commands/reconcile.py	2012-03-21 18:20:29 +0000
@@ -0,0 +1,84 @@
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Reconcile MAAS's view of the world with the Provisioning Server's.
+
+The Provisioning Server is currently stateless, so this actually implies
+reconciling with Cobbler.
+
+************************************************************************
+**                DO NOT USE ON A PRODUCTION SYSTEM                   **
+**            This is intended for use as a QA tool only              **
+************************************************************************
+"""
+
+from __future__ import (
+    print_function,
+    unicode_literals,
+    )
+
+__metaclass__ = type
+__all__ = [
+    "Command",
+    ]
+
+from django.core.management.base import NoArgsCommand
+from maasserver import (
+    models,
+    provisioning,
+    )
+
+
+def reconcile():
+    papi = provisioning.get_provisioning_api_proxy()
+    nodes_local = {node.system_id: node for node in models.Node.objects.all()}
+    nodes_remote = papi.get_nodes()
+
+    missing_local = set(nodes_remote).difference(nodes_local)
+    for name in missing_local:
+        print("remote:", name)
+        remote_node = nodes_remote[name]
+        local_node = models.Node(
+            system_id=remote_node["name"],
+            # TODO: Figure out the correct architecture.
+            architecture=models.ARCHITECTURE.amd64,
+            power_type=remote_node["power_type"],
+            hostname=remote_node["name"])
+        local_node.save()
+        for mac_address in remote_node["mac_addresses"]:
+            local_node.add_mac_address(mac_address)
+
+    missing_remote = set(nodes_local).difference(nodes_remote)
+    for name in missing_remote:
+        print("local:", name)
+        local_node = nodes_local[name]
+        provisioning.provision_post_save_Node(
+            sender=None, instance=local_node, created=False)
+
+    present_in_both = set(nodes_local).intersection(nodes_remote)
+    for name in present_in_both:
+        print("common:", name)
+        node_local = nodes_local[name]
+        node_remote = nodes_remote[name]
+        # Check that MACs are the same.
+        macs_local = {
+            mac.mac_address
+            for mac in node_local.macaddress_set.all()
+            }
+        print("- local macs:", " ".join(sorted(macs_local)))
+        macs_remote = {
+            mac for mac in node_remote["mac_addresses"]
+            }
+        print("- remote macs:", " ".join(sorted(macs_remote)))
+        for mac in macs_remote - macs_local:
+            node_local.add_mac_address(mac)
+        if len(macs_local - macs_remote) != 0:
+            provisioning.set_node_mac_addresses(node_local)
+
+
+class Command(NoArgsCommand):
+
+    help = __doc__
+
+    def handle_noargs(self, **options):
+        reconcile()


Follow ups