Merge lp:~mpontillo/maas/bug-1514486 into lp:maas/trunk

Proposed by Mike Pontillo on 2015-11-11
Status: Merged
Approved by: Mike Pontillo on 2015-11-11
Approved revision: 4486
Merged at revision: 4486
Proposed branch: lp:~mpontillo/maas/bug-1514486
Merge into: lp:maas/trunk
Diff against target: 127 lines (+50/-11)
2 files modified
src/maasserver/models/interface.py (+34/-11)
src/maasserver/models/tests/test_interface.py (+16/-0)
To merge this branch: bzr merge lp:~mpontillo/maas/bug-1514486
Reviewer Review Type Date Requested Status
Blake Rouse 2015-11-11 Approve on 2015-11-11
Review via email: mp+277207@code.launchpad.net

Commit message

If no discovered subnets are found when claiming a static IP address, fall back to the subnet on the attached cluster interface.

To post a comment you must log in.
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve
MAAS Lander (maas-lander) wrote :
Download full text (1021.2 KiB)

The attempt to merge lp:~mpontillo/maas/bug-1514486 into lp:maas failed. Below is the output from the failed tests.

Get:1 http://security.ubuntu.com trusty-security InRelease [64.4 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Get:2 http://nova.clouds.archive.ubuntu.com trusty-updates InRelease [64.4 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:3 http://security.ubuntu.com trusty-security/main Sources [99.2 kB]
Get:4 http://security.ubuntu.com trusty-security/universe Sources [31.5 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [244 kB]
Get:6 http://security.ubuntu.com trusty-security/main amd64 Packages [370 kB]
Get:7 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [143 kB]
Get:8 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [652 kB]
Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [119 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [326 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en [319 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en [172 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Fetched 2,604 kB in 4s (601 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 pyflakes python-apt python-bson python-bzrlib python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django 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-t...

Mike Pontillo (mpontillo) wrote :

Test failure looks unrelated: http://paste.ubuntu.com/13222946/

I'm going to try landing this again.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/models/interface.py'
2--- src/maasserver/models/interface.py 2015-11-10 17:50:31 +0000
3+++ src/maasserver/models/interface.py 2015-11-11 01:11:20 +0000
4@@ -1224,15 +1224,14 @@
5 if len(existing_statics) > 0:
6 return existing_statics
7
8+ parent = self._get_parent_node()
9 # Get the last subnets this interface DHCP'd from. This with be either
10 # one IPv4, one IPv6, or both IPv4 and IPv6.
11- if (self.node is not None and
12- not self.node.installable and
13- self.node.parent is not None):
14+ if parent is not None:
15 # If this interface is on a device then we need to look for
16 # discovered addresses on all the Node's interfaces.
17 discovered_ips = StaticIPAddress.objects.none()
18- for interface in self.node.parent.interface_set.all():
19+ for interface in parent.interface_set.all():
20 ip_addresses = interface.ip_addresses.filter(
21 alloc_type=IPADDRESS_TYPE.DISCOVERED)
22 ip_addresses = ip_addresses.order_by(
23@@ -1244,17 +1243,30 @@
24 discovered_ips = discovered_ips.order_by(
25 'id').select_related("subnet")
26
27+ discovered_subnets = [
28+ discovered_ip.subnet for discovered_ip in discovered_ips
29+ ]
30+
31+ if len(discovered_subnets) == 0:
32+ # Backward compatibility code. When databases are migrated from 1.8
33+ # and earlier, we may not have DISCOVERED addresses yet. So
34+ # try to find a subnet on an attached cluster interface.
35+ # (Note that get_cluster_interface() handles getting the parent
36+ # node, if needed.)
37+ for ngi in self.get_cluster_interfaces():
38+ if ngi is not None and ngi.subnet is not None:
39+ discovered_subnets.append(ngi.subnet)
40+
41 if requested_address is None:
42 # No requested address so claim a STATIC IP on all DISCOVERED
43 # subnets for this interface.
44 static_ips = []
45- for discovered_ip in discovered_ips:
46- subnet = discovered_ip.subnet
47- ngi = subnet.get_managed_cluster_interface()
48+ for discovered_subnet in discovered_subnets:
49+ ngi = discovered_subnet.get_managed_cluster_interface()
50 if ngi is not None:
51 static_ips.append(
52 self.link_subnet(
53- INTERFACE_LINK_TYPE.STATIC, subnet))
54+ INTERFACE_LINK_TYPE.STATIC, discovered_subnet))
55
56 # No valid subnets could be used to claim a STATIC IP address.
57 if not any(static_ips):
58@@ -1267,10 +1279,10 @@
59 else:
60 # Find the DISCOVERED subnet that the requested_address falls into.
61 found_subnet = None
62- for discovered_ip in discovered_ips:
63+ for discovered_subnet in discovered_subnets:
64 if (IPAddress(requested_address) in
65- discovered_ip.subnet.get_ipnetwork()):
66- found_subnet = discovered_ip.subnet
67+ discovered_subnet.get_ipnetwork()):
68+ found_subnet = discovered_subnet
69 break
70
71 if found_subnet:
72@@ -1284,6 +1296,17 @@
73 "requested_address '%s' is not in a managed subnet for "
74 "this interface '%s'" % (requested_address, self.name))
75
76+ def _get_parent_node(self):
77+ """Return the parent node for this interface, if it exists (and this
78+ interface belongs to a Device). Otherwise, return None.
79+ """
80+ if (self.node is not None and
81+ not self.node.installable and
82+ self.node.parent is not None):
83+ return self.node.parent
84+ else:
85+ return None
86+
87 def delete(self, remove_ip_address=True):
88 # We set the _skip_ip_address_removal so the signal can use it to
89 # skip removing the IP addresses. This is normally only done by the
90
91=== modified file 'src/maasserver/models/tests/test_interface.py'
92--- src/maasserver/models/tests/test_interface.py 2015-11-10 17:50:31 +0000
93+++ src/maasserver/models/tests/test_interface.py 2015-11-11 01:11:20 +0000
94@@ -26,6 +26,7 @@
95 INTERFACE_TYPE,
96 IPADDRESS_TYPE,
97 NODE_PERMISSION,
98+ NODE_STATUS,
99 NODEGROUP_STATUS,
100 NODEGROUPINTERFACE_MANAGEMENT,
101 )
102@@ -75,6 +76,7 @@
103 from testtools import ExpectedException
104 from testtools.matchers import (
105 Equals,
106+ HasLength,
107 MatchesDict,
108 MatchesListwise,
109 MatchesStructure,
110@@ -2594,3 +2596,17 @@
111 INTERFACE_LINK_TYPE.STATIC, subnet_v4,
112 ip_address=requested_ip))
113 self.assertEquals(sentinel.claimed_ip, claimed_ip)
114+
115+ def test__finds_device_subnet_via_parent_cluster_interface(self):
116+ node = factory.make_Node_with_Interface_on_Subnet(
117+ status=NODE_STATUS.DEPLOYED)
118+ # Create a situation that looks like a migration from MAAS 1.8
119+ # (no DISCOVERED IP addresses on this node, because it hasn't
120+ # recommissioned.)
121+ node.get_boot_interface().ip_addresses.filter(
122+ alloc_type=IPADDRESS_TYPE.DISCOVERED).delete()
123+ device = factory.make_Device(parent=node)
124+ iface = factory.make_Interface(node=device)
125+ self.patch_autospec(iface, "link_subnet")
126+ claimed_ips = iface.claim_static_ips()
127+ self.assertThat(claimed_ips, HasLength(1))