Merge lp:~rvb/maas/net-name-bug-1400909 into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 3419
Proposed branch: lp:~rvb/maas/net-name-bug-1400909
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 167 lines (+94/-8)
4 files modified
src/maasserver/forms.py (+1/-3)
src/maasserver/migrations/0099_convert_cluster_interfaces_to_networks.py (+21/-3)
src/maasserver/tests/test_forms_network.py (+71/-1)
src/maasserver/tests/test_forms_nodegroupinterface.py (+1/-1)
To merge this branch: bzr merge lp:~rvb/maas/net-name-bug-1400909
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+244415@code.launchpad.net

Commit message

Fix call to get_name_and_vlan_from_cluster_interface in create_Network_from_NodeGroupInterface. It was using the interface's name in lieu of the cluster's name.

Description of the change

I also added the tests for create_Network_from_NodeGroupInterface, it was completely untested.

Drive-by fix: copy the get_name_and_vlan_from_cluster_interface utility in the migration which uses it. It's generally a bad idea to use utilities from migrations: the code might have to be changed but the version used by the migration needs to work with the old code.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Nice catch with the migration.

Looks good.

review: Approve
Revision history for this message
Raphaël Badin (rvb) wrote :

Thanks for the review!

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

The attempt to merge lp:~rvb/maas/net-name-bug-1400909 into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://security.ubuntu.com trusty-security Release
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Hit http://nova.clouds.archive.ubuntu.com trusty-updates Release
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
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
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb curl daemontools debhelper dh-apport distro-info dnsutils firefox freeipmi-tools gjs ipython isc-dhcp-common libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make pep8 postgresql pyflakes python-amqplib python-bzrlib python-celery python-convoy 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-lockfile python-lxml python-mimeparse python-mock python-netaddr python-netifaces python-nose python-oauth python-oops python-oops-amqp python-oops-datedir-repo python-oops-twisted python-oops-wsgi python-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-seamicroclient python-simplejson python-simplestreams python-sphinx py...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/forms.py'
2--- src/maasserver/forms.py 2014-12-10 21:16:37 +0000
3+++ src/maasserver/forms.py 2014-12-11 15:14:43 +0000
4@@ -1421,14 +1421,12 @@
5
6 def create_Network_from_NodeGroupInterface(interface):
7 """Given a `NodeGroupInterface`, create its Network counterpart."""
8- # This method cannot use non-orm model properties because it needs
9- # to be used in a data migration, where they won't work.
10 if not interface.subnet_mask:
11 # Can be None or empty string, do nothing if so.
12 return
13
14 name, vlan_tag = get_name_and_vlan_from_cluster_interface(
15- interface.name, interface.interface)
16+ interface.nodegroup.name, interface.interface)
17 ipnetwork = make_network(interface.ip, interface.subnet_mask)
18 network = Network(
19 name=name,
20
21=== modified file 'src/maasserver/migrations/0099_convert_cluster_interfaces_to_networks.py'
22--- src/maasserver/migrations/0099_convert_cluster_interfaces_to_networks.py 2014-11-13 19:43:11 +0000
23+++ src/maasserver/migrations/0099_convert_cluster_interfaces_to_networks.py 2014-12-11 15:14:43 +0000
24@@ -5,14 +5,32 @@
25 transaction,
26 )
27 from django.db.utils import IntegrityError
28-from maasserver.utils.interfaces import (
29- get_name_and_vlan_from_cluster_interface,
30- )
31 from netaddr import IPNetwork
32 from south.db import db
33 from south.utils import datetime_utils as datetime
34 from south.v2 import DataMigration
35
36+# "Frozen" method from maasserver.utils.interfaces.
37+def get_name_and_vlan_from_cluster_interface(cluster_name, interface):
38+ """Return a name suitable for a `Network` managed by a cluster interface.
39+
40+ :param interface: Network interface name, e.g. `eth0:1`.
41+ :param cluster_name: Name of the cluster.
42+ :return: a tuple of the new name and the interface's VLAN tag. The VLAN
43+ tag may be None.
44+ """
45+ name = interface
46+ vlan_tag = None
47+ if '.' in name:
48+ _, vlan_tag = name.split('.', 1)
49+ if ':' in vlan_tag:
50+ # Nasty: there's an alias after the VLAN tag.
51+ vlan_tag, _ = vlan_tag.split(':', 1)
52+ name = name.replace('.', '-')
53+ name = name.replace(':', '-')
54+ network_name = "-".join((cluster_name, name))
55+ return network_name, vlan_tag
56+
57
58 class Migration(DataMigration):
59
60
61=== modified file 'src/maasserver/tests/test_forms_network.py'
62--- src/maasserver/tests/test_forms_network.py 2014-11-25 14:24:38 +0000
63+++ src/maasserver/tests/test_forms_network.py 2014-12-11 15:14:43 +0000
64@@ -14,8 +14,13 @@
65 __metaclass__ = type
66 __all__ = []
67
68+from maasserver import forms as forms_module
69 from maasserver.dns import config as dns_config_module
70-from maasserver.forms import NetworkForm
71+from maasserver.enum import NODEGROUPINTERFACE_MANAGEMENT
72+from maasserver.forms import (
73+ create_Network_from_NodeGroupInterface,
74+ NetworkForm,
75+ )
76 from maasserver.models import (
77 MACAddress,
78 Network,
79@@ -25,6 +30,7 @@
80 from maasserver.testing.testcase import MAASServerTestCase
81 from maastesting.matchers import MockCalledOnceWith
82 from netaddr import IPNetwork
83+from testtools.matchers import Contains
84
85
86 class TestNetworkForm(MAASServerTestCase):
87@@ -196,3 +202,67 @@
88 dns_config_module, "write_full_dns_config")
89 network.delete()
90 self.assertThat(write_full_dns_config, MockCalledOnceWith())
91+
92+
93+class TestCreateNetworkFromNodeGroupInterface(MAASServerTestCase):
94+
95+ def test_skips_creation_if_netmask_undefined(self):
96+ nodegroup = factory.make_NodeGroup()
97+ interface = factory.make_NodeGroupInterface(
98+ nodegroup, management=NODEGROUPINTERFACE_MANAGEMENT.UNMANAGED)
99+ interface.subnet_mask = None
100+ network = create_Network_from_NodeGroupInterface(interface)
101+ self.assertIsNone(network)
102+ self.assertItemsEqual([], Network.objects.all())
103+
104+ def test_creates_network_without_vlan(self):
105+ nodegroup = factory.make_NodeGroup()
106+ interface = factory.make_NodeGroupInterface(nodegroup)
107+ network = create_Network_from_NodeGroupInterface(interface)
108+ definition = {
109+ 'name': "%s-%s" % (
110+ interface.nodegroup.name, interface.interface),
111+ 'description': (
112+ "Auto created when creating interface %s on cluster %s" % (
113+ interface.name, interface.nodegroup.name)),
114+ 'ip': "%s" % interface.network.ip,
115+ 'netmask': "%s" % interface.network.netmask,
116+ 'vlan_tag': None,
117+ }
118+ network_obj = Network.objects.get(id=network.id)
119+ self.assertAttributes(network_obj, definition)
120+
121+ def test_creates_network_with_vlan(self):
122+ nodegroup = factory.make_NodeGroup()
123+ intf = 'eth0'
124+ vlan = 1
125+ interface = factory.make_NodeGroupInterface(
126+ nodegroup, interface="%s.%d" % (intf, vlan))
127+ network = create_Network_from_NodeGroupInterface(interface)
128+ net_name = "%s-%s" % (interface.nodegroup.name, interface.interface)
129+ net_name = net_name.replace('.', '-')
130+ definition = {
131+ 'name': net_name,
132+ 'description': (
133+ "Auto created when creating interface %s on cluster %s" % (
134+ interface.name, interface.nodegroup.name)),
135+ 'ip': "%s" % interface.network.ip,
136+ 'netmask': "%s" % interface.network.netmask,
137+ 'vlan_tag': vlan,
138+ }
139+ network_obj = Network.objects.get(id=network.id)
140+ self.assertAttributes(network_obj, definition)
141+
142+ def test_skips_creation_if_network_already_exists(self):
143+ nodegroup = factory.make_NodeGroup()
144+ interface = factory.make_NodeGroupInterface(nodegroup)
145+ create_Network_from_NodeGroupInterface(interface)
146+ maaslog = self.patch(forms_module, 'maaslog')
147+
148+ self.assertIsNone(create_Network_from_NodeGroupInterface(interface))
149+ self.assertEqual(
150+ 1, maaslog.warning.call_count,
151+ "maaslog.warning hasn't been called")
152+ self.assertThat(
153+ maaslog.warning.call_args[0][0],
154+ Contains("Failed to create Network"))
155
156=== modified file 'src/maasserver/tests/test_forms_nodegroupinterface.py'
157--- src/maasserver/tests/test_forms_nodegroupinterface.py 2014-11-13 19:43:11 +0000
158+++ src/maasserver/tests/test_forms_nodegroupinterface.py 2014-12-11 15:14:43 +0000
159@@ -372,7 +372,7 @@
160 form.save()
161 [network] = Network.objects.all()
162 expected, _ = get_name_and_vlan_from_cluster_interface(
163- interface.name, interface.interface)
164+ interface.nodegroup.name, interface.interface)
165 self.assertEqual(expected, network.name)
166
167 def test_sets_vlan_tag(self):