Merge lp:~rvb/maas/bug-1104215-1.2 into lp:maas/1.2

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 1351
Proposed branch: lp:~rvb/maas/bug-1104215-1.2
Merge into: lp:maas/1.2
Diff against target: 219 lines (+103/-3)
5 files modified
src/maas/settings.py (+5/-0)
src/maasserver/api.py (+16/-2)
src/maasserver/tests/test_api.py (+32/-1)
src/maasserver/utils/__init__.py (+23/-0)
src/maasserver/utils/tests/test_utils.py (+27/-0)
To merge this branch: bzr merge lp:~rvb/maas/bug-1104215-1.2
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+145641@code.launchpad.net

Commit message

Backport revision 1426.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maas/settings.py'
2--- src/maas/settings.py 2012-12-03 05:42:24 +0000
3+++ src/maas/settings.py 2013-01-30 16:03:23 +0000
4@@ -85,6 +85,11 @@
5 # maasserver.middleware.APIErrorsMiddleware)
6 PISTON_DISPLAY_ERRORS = False
7
8+# Location of the local cluster config file (installed by
9+# the package maas-cluster-controller). Use to distinguish the local cluster
10+# from the others.
11+LOCAL_CLUSTER_CONFIG = "/etc/maas/maas_cluster.conf"
12+
13 TEMPLATE_DEBUG = DEBUG
14
15 # Set this to where RaphaelJS files can be found.
16
17=== modified file 'src/maasserver/api.py'
18--- src/maasserver/api.py 2013-01-16 11:12:48 +0000
19+++ src/maasserver/api.py 2013-01-30 16:03:23 +0000
20@@ -168,6 +168,7 @@
21 absolute_reverse,
22 build_absolute_uri,
23 find_nodegroup,
24+ is_local_cluster_UUID,
25 map_enum,
26 strip_domain,
27 )
28@@ -1156,17 +1157,30 @@
29 "eth0"}]'
30 """
31 uuid = get_mandatory_param(request.data, 'uuid')
32+ is_local_cluster = is_local_cluster_UUID(uuid)
33 existing_nodegroup = get_one(NodeGroup.objects.filter(uuid=uuid))
34 if existing_nodegroup is None:
35 master = NodeGroup.objects.ensure_master()
36 # Does master.uuid look like it's a proper uuid?
37 if master.uuid in ('master', ''):
38 # Master nodegroup not yet configured, configure it.
39+ if is_local_cluster:
40+ # Connecting from localhost, accept the cluster
41+ # controller.
42+ status = NODEGROUP_STATUS.ACCEPTED
43+ else:
44+ # Connecting remotely, mark the cluster as pending.
45+ status = NODEGROUP_STATUS.PENDING
46 form = NodeGroupWithInterfacesForm(
47- data=request.data, instance=master)
48+ data=request.data, status=status, instance=master)
49 if form.is_valid():
50 form.save()
51- return get_celery_credentials()
52+ if status == NODEGROUP_STATUS.ACCEPTED:
53+ return get_celery_credentials()
54+ else:
55+ return HttpResponse(
56+ "Cluster registered. Awaiting admin approval.",
57+ status=httplib.ACCEPTED)
58 else:
59 raise ValidationError(form.errors)
60 else:
61
62=== modified file 'src/maasserver/tests/test_api.py'
63--- src/maasserver/tests/test_api.py 2013-01-16 11:12:48 +0000
64+++ src/maasserver/tests/test_api.py 2013-01-30 16:03:23 +0000
65@@ -32,6 +32,7 @@
66 import random
67 import shutil
68 import sys
69+from textwrap import dedent
70 from urlparse import urlparse
71
72 from apiclient.maas_client import MAASClient
73@@ -3718,9 +3719,20 @@
74 # validated by an admin.
75 self.assertEqual(httplib.ACCEPTED, response.status_code)
76
77- def test_register_nodegroup_returns_credentials_if_master(self):
78+ def setup_local_cluster_config(self, uuid):
79+ # Helper to get settings.LOCAL_CLUSTER_CONFIG to point to a valid
80+ # cluster config file with CLUSTER_UUID set to the given uuid.
81+ contents = dedent("""
82+ MAAS_URL=http://localhost/MAAS
83+ CLUSTER_UUID="%s"
84+ """ % uuid)
85+ file_name = self.make_file(contents=contents)
86+ self.patch(settings, 'LOCAL_CLUSTER_CONFIG', file_name)
87+
88+ def test_register_nodegroup_returns_credentials_if_local_cluster(self):
89 name = factory.make_name('name')
90 uuid = factory.getRandomUUID()
91+ self.setup_local_cluster_config(uuid)
92 fake_broker_url = factory.make_name('fake-broker_url')
93 celery_conf = app_or_default().conf
94 self.patch(celery_conf, 'BROKER_URL', fake_broker_url)
95@@ -3737,9 +3749,27 @@
96 ({'BROKER_URL': fake_broker_url}, uuid),
97 (parsed_result, NodeGroup.objects.ensure_master().uuid))
98
99+ def test_register_nodegroup_gets_accepted_if_not_local_cluster(self):
100+ name = factory.make_name('name')
101+ uuid = factory.getRandomUUID()
102+ fake_broker_url = factory.make_name('fake-broker_url')
103+ celery_conf = app_or_default().conf
104+ self.patch(celery_conf, 'BROKER_URL', fake_broker_url)
105+ response = self.client.post(
106+ reverse('nodegroups_handler'),
107+ {
108+ 'op': 'register',
109+ 'name': name,
110+ 'uuid': uuid,
111+ })
112+ self.assertEqual(httplib.ACCEPTED, response.status_code, response)
113+ self.assertEqual(
114+ response.content, "Cluster registered. Awaiting admin approval.")
115+
116 def test_register_nodegroup_configures_master_if_unconfigured(self):
117 name = factory.make_name('nodegroup')
118 uuid = factory.getRandomUUID()
119+ self.setup_local_cluster_config(uuid)
120 interface = make_interface_settings()
121 self.client.post(
122 reverse('nodegroups_handler'),
123@@ -3758,6 +3788,7 @@
124
125 def test_register_nodegroup_uses_default_zone_name(self):
126 uuid = factory.getRandomUUID()
127+ self.setup_local_cluster_config(uuid)
128 self.client.post(
129 reverse('nodegroups_handler'),
130 {
131
132=== modified file 'src/maasserver/utils/__init__.py'
133--- src/maasserver/utils/__init__.py 2012-12-04 16:23:12 +0000
134+++ src/maasserver/utils/__init__.py 2013-01-30 16:03:23 +0000
135@@ -16,10 +16,13 @@
136 'find_nodegroup',
137 'get_db_state',
138 'ignore_unused',
139+ 'is_local_cluster_UUID',
140 'map_enum',
141 'strip_domain',
142 ]
143
144+import errno
145+import re
146 from urllib import urlencode
147 from urlparse import urljoin
148
149@@ -110,6 +113,26 @@
150 return hostname.split('.', 1)[0]
151
152
153+def is_local_cluster_UUID(uuid):
154+ """Return whether the given UUID is the UUID of the local cluster."""
155+ try:
156+ cluster_config = open(settings.LOCAL_CLUSTER_CONFIG).read()
157+ match = re.search(
158+ "CLUSTER_UUID=(?P<quote>[\"']?)([^\"']+)(?P=quote)",
159+ cluster_config)
160+ if match is not None:
161+ return uuid == match.groups()[1]
162+ else:
163+ return False
164+ except IOError as error:
165+ if error.errno == errno.ENOENT:
166+ # Cluster config file is not present.
167+ return False
168+ else:
169+ # Anything else is an error.
170+ raise
171+
172+
173 def find_nodegroup(request):
174 """Find the nodegroup whose subnet contains the IP Address of the
175 originating host of the request..
176
177=== modified file 'src/maasserver/utils/tests/test_utils.py'
178--- src/maasserver/utils/tests/test_utils.py 2012-12-04 16:23:12 +0000
179+++ src/maasserver/utils/tests/test_utils.py 2013-01-30 16:03:23 +0000
180@@ -34,6 +34,7 @@
181 build_absolute_uri,
182 find_nodegroup,
183 get_db_state,
184+ is_local_cluster_UUID,
185 map_enum,
186 strip_domain,
187 )
188@@ -194,6 +195,32 @@
189 self.assertEqual(results, map(strip_domain, inputs))
190
191
192+class TestIsLocalClusterUUID(TestCase):
193+
194+ def test_is_local_cluster_UUID_returns_false_if_no_config_file(self):
195+ bogus_file_name = '/tmp/bogus/%s' % factory.make_name('name')
196+ self.patch(settings, 'LOCAL_CLUSTER_CONFIG', bogus_file_name)
197+ self.assertFalse(is_local_cluster_UUID(factory.getRandomUUID()))
198+
199+ def test_is_local_cluster_UUID_returns_false_if_parsing_fails(self):
200+ file_name = self.make_file(contents="wrong content")
201+ self.patch(settings, 'LOCAL_CLUSTER_CONFIG', file_name)
202+ self.assertFalse(is_local_cluster_UUID(factory.getRandomUUID()))
203+
204+ def test_is_local_cluster_UUID_returns_false_if_wrong_UUID(self):
205+ uuid = factory.getRandomUUID()
206+ other_uuid = factory.getRandomUUID()
207+ file_name = self.make_file(contents='CLUSTER_UUID="%s"' % other_uuid)
208+ self.patch(settings, 'LOCAL_CLUSTER_CONFIG', file_name)
209+ self.assertFalse(is_local_cluster_UUID(uuid))
210+
211+ def test_is_local_cluster_UUID_returns_true_if_local_UUID(self):
212+ uuid = factory.getRandomUUID()
213+ file_name = self.make_file(contents='CLUSTER_UUID="%s"' % uuid)
214+ self.patch(settings, 'LOCAL_CLUSTER_CONFIG', file_name)
215+ self.assertTrue(is_local_cluster_UUID(uuid))
216+
217+
218 def get_request(origin_ip):
219 return RequestFactory().post('/', REMOTE_ADDR=origin_ip)
220

Subscribers

People subscribed via source and target branches

to status/vote changes: