Merge lp:~blake-rouse/maas/fix-1516722 into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4507
Proposed branch: lp:~blake-rouse/maas/fix-1516722
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 98 lines (+67/-13)
1 file modified
src/maasserver/migrations/0182_initial_networking_layout.py (+67/-13)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-1516722
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+277877@code.launchpad.net

Commit message

Modify the initial networking migration to use the orm only from the migration, instead of using the current node model from source.

Description of the change

I have tested this on upgrade from 1.8 to 1.9. This fixes the issue as previous the upgrade broke.

This does not have unit tests because they would have to be skipped anyway because the model is now different.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

So when this lands we need to test in real deployments

upgrade from 1.7 to 1.9
upgrade from 1.8 to 1.9
upgrade from 1.9 to 1.9

I'll prepare rc2 and test some of this later today.

Thanks.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (983.4 KiB)

The attempt to merge lp:~blake-rouse/maas/fix-1516722 into lp:maas failed. Below is the output from the failed tests.

Hit http://security.ubuntu.com xenial-security InRelease
Get:1 http://nova.clouds.archive.ubuntu.com xenial InRelease [218 kB]
Hit http://nova.clouds.archive.ubuntu.com xenial-updates InRelease
Hit http://security.ubuntu.com xenial-security/main Sources
Hit http://security.ubuntu.com xenial-security/universe Sources
Hit http://security.ubuntu.com xenial-security/main amd64 Packages
Hit http://security.ubuntu.com xenial-security/universe amd64 Packages
Hit http://security.ubuntu.com xenial-security/main Translation-en
Hit http://security.ubuntu.com xenial-security/universe Translation-en
Get:2 http://nova.clouds.archive.ubuntu.com xenial/main Sources [1,117 kB]
Get:3 http://nova.clouds.archive.ubuntu.com xenial/universe Sources [7,464 kB]
Get:4 http://nova.clouds.archive.ubuntu.com xenial/main amd64 Packages [1,441 kB]
Get:5 http://nova.clouds.archive.ubuntu.com xenial/universe amd64 Packages [6,955 kB]
Get:6 http://nova.clouds.archive.ubuntu.com xenial/main Translation-en [841 kB]
Get:7 http://nova.clouds.archive.ubuntu.com xenial/universe Translation-en [4,707 kB]
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Translation-en
Fetched 22.7 MB in 14s (1,620 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm pep8 phantomjs postgresql pxelinux pyflakes python-apt python-bson python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django16 python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lxml python-mock python-netaddr python-netifaces python-nose python-oauth python-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-pyparsing python-seamicroclient python-simplejson python-simplestreams python-sphinx python-subunit python-tempita python-testresources python-testscenarios python-testtools python-twisted python-txtftp python-tz python-unittest2 python-virtualenv python-yaml python-zope.interface socat syslinux-common tgt ubuntu-cloudimage-keyring virtualenv wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is ...

Revision history for this message
MAAS Lander (maas-lander) wrote :

The attempt to merge lp:~blake-rouse/maas/fix-1516722 into lp:maas failed. Below is the output from the failed tests.

Hit http://security.ubuntu.com xenial-security InRelease
Get:1 http://nova.clouds.archive.ubuntu.com xenial InRelease [218 kB]
Hit http://security.ubuntu.com xenial-security/main Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates InRelease
Hit http://security.ubuntu.com xenial-security/universe Sources
Hit http://security.ubuntu.com xenial-security/main amd64 Packages
Hit http://security.ubuntu.com xenial-security/universe amd64 Packages
Hit http://security.ubuntu.com xenial-security/main Translation-en
Hit http://security.ubuntu.com xenial-security/universe Translation-en
Get:2 http://nova.clouds.archive.ubuntu.com xenial/main Sources [1,117 kB]
Get:3 http://nova.clouds.archive.ubuntu.com xenial/universe Sources [7,466 kB]
Get:4 http://nova.clouds.archive.ubuntu.com xenial/main amd64 Packages [1,441 kB]
Get:5 http://nova.clouds.archive.ubuntu.com xenial/universe amd64 Packages [6,956 kB]
Get:6 http://nova.clouds.archive.ubuntu.com xenial/main Translation-en [841 kB]
Get:7 http://nova.clouds.archive.ubuntu.com xenial/universe Translation-en [4,709 kB]
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Translation-en
Fetched 22.7 MB in 14s (1,532 kB/s)

W: Failed to fetch http://nova.clouds.archive.ubuntu.com/ubuntu/dists/xenial/universe/i18n/Translation-en Hash Sum mismatch

E: Some index files failed to download. They have been ignored, or old ones used instead.

Revision history for this message
Mike Pontillo (mpontillo) wrote :

I was hoping to review this before it landed; looks good, but the one change I would have considered is to (rather than choose all READY nodes) choose all nodes *except* deployed and new.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/migrations/0182_initial_networking_layout.py'
2--- src/maasserver/migrations/0182_initial_networking_layout.py 2015-09-30 07:29:27 +0000
3+++ src/maasserver/migrations/0182_initial_networking_layout.py 2015-11-18 16:51:19 +0000
4@@ -1,27 +1,81 @@
5 from django.db import models
6-from maasserver.enum import NODE_STATUS
7+from maasserver.enum import (
8+ IPADDRESS_TYPE,
9+ NODE_STATUS,
10+ NODEGROUP_STATUS,
11+ NODEGROUPINTERFACE_MANAGEMENT,
12+)
13 from maasserver.models.node import Node
14 from south.db import db
15 from south.utils import datetime_utils as datetime
16 from south.v2 import DataMigration
17
18
19+def get_managed_ngi_for_subnet(subnet):
20+ """Return the cluster interface that manages this subnet."""
21+ interfaces = subnet.nodegroupinterface_set.filter(
22+ nodegroup__status=NODEGROUP_STATUS.ENABLED)
23+ interfaces = interfaces.exclude(
24+ management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
25+ return interfaces.first()
26+
27+
28+def get_managed_subnet_for_interface(interface):
29+ """Return the `Subnet` that manages the `VLAN` for this `interface`."""
30+ for subnet in interface.vlan.subnet_set.all():
31+ ngi = get_managed_ngi_for_subnet(subnet)
32+ if ngi is not None:
33+ return subnet
34+ return None
35+
36+
37 class Migration(DataMigration):
38
39 def forwards(self, orm):
40- # We don't use orm here because we want the current Node model to
41- # include all of the networking methods we require. This will break
42- # if the node these methods get removed from the Node, so we assert
43- # that they at least exists.
44- assert hasattr(Node, "_clear_networking_configuration")
45- assert hasattr(Node, "set_initial_networking_configuration")
46- for node in Node.objects.filter(
47+ now = datetime.datetime.now()
48+
49+ # Loop through all ready nodes and fix their interface configuration.
50+ # Deploying and deployed nodes will already have an AUTO or STICKY IP
51+ # address and on release MAAS will do the correct thing.
52+ for node in orm['maasserver.Node'].objects.filter(
53 installable=True, status=NODE_STATUS.READY):
54- # The node has to be ready and we set the default networking
55- # configuration. Deploying or deployed nodes will already have a
56- # configuration with an AUTO IP or STATIC IP.
57- node._clear_networking_configuration()
58- node.set_initial_networking_configuration()
59+
60+ # Check if any IP addresses already exists for this node.
61+ has_ip = False
62+ for interface in node.interface_set.all():
63+ has_ip = interface.ip_addresses.exclude(
64+ alloc_type=IPADDRESS_TYPE.DISCOVERED).exists()
65+ if has_ip:
66+ break
67+
68+ # If already has an IP address then nothing needs to be done. If
69+ # not then an AUTO IP address needs to be created on the boot
70+ # interface or fallback to DHCP if the boot interface is not on
71+ # a managed subnet.
72+ if not has_ip:
73+ # Get the boot interface for the node.
74+ boot_interface = node.boot_interface
75+ if boot_interface is None:
76+ boot_interface = node.interface_set.order_by('id').first()
77+ if boot_interface is None:
78+ continue
79+
80+ # Get the subnet that manages the VLAN this interface is
81+ # connected to.
82+ subnet = get_managed_subnet_for_interface(boot_interface)
83+ if subnet is not None:
84+ # Create an AUTO IP address for this subnet.
85+ sip = orm['maasserver.StaticIPAddress'].objects.create(
86+ alloc_type=IPADDRESS_TYPE.AUTO, user=None,
87+ ip=None, subnet=subnet, created=now, updated=now)
88+ else:
89+ # No subnet managing the VLAN this interface is connected
90+ # to, so set the boot interface to just DHCP.
91+ sip = orm['maasserver.StaticIPAddress'].objects.create(
92+ alloc_type=IPADDRESS_TYPE.DHCP, user=None,
93+ ip=None, subnet=None, created=now, updated=now)
94+ boot_interface.ip_addresses.add(sip)
95+ boot_interface.save()
96
97 def backwards(self, orm):
98 # No need to go backward.