Merge lp:~jtv/maas/bug-1086239 into lp:~maas-committers/maas/trunk

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 1397
Proposed branch: lp:~jtv/maas/bug-1086239
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 393 lines (+111/-68)
14 files modified
etc/democeleryconfig_cluster.py (+0/-4)
services/cluster-worker/run (+5/-0)
services/pserv/run (+5/-0)
src/provisioningserver/auth.py (+0/-8)
src/provisioningserver/boot_images.py (+5/-5)
src/provisioningserver/cluster_config.py (+44/-0)
src/provisioningserver/dhcp/leases.py (+2/-2)
src/provisioningserver/dhcp/tests/test_leases.py (+0/-9)
src/provisioningserver/start_cluster_controller.py (+1/-8)
src/provisioningserver/tags.py (+2/-6)
src/provisioningserver/tests/test_auth.py (+0/-12)
src/provisioningserver/tests/test_boot_images.py (+0/-10)
src/provisioningserver/tests/test_cluster_config.py (+46/-0)
src/provisioningserver/tftp.py (+1/-4)
To merge this branch: bzr merge lp:~jtv/maas/bug-1086239
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+139172@code.launchpad.net

Commit message

Take cluster-uuid setting from environment, not celery config.

Description of the change

This builds on a multi-step change agreed with Julian. The relevant part is:
 1 Duplicate the CLUSTER_UUID setting, from Celery config to maas_cluster.conf.
 2 Make pserv's upstart job source maas_cluster.conf.
 3 Have get_cluster_uuid read the setting from the environment instead of from celery.
 4 Clean up the duplicated setting.

What you see here is step 3. It also puts get_cluster_uuid in a saner place. That function was "borrowed" from a place where nobody should be importing it from. Not so bad for a provisional fix, but this is the cleanup.

Finally, the cluster uuid is no longer one of the "worker secrets" that the region controller sends to the clusters. So this also removes some of the remnants of that old situation. In particular, "I don't know my cluster uuid yet" is no longer a valid reason for cluster controllers to be unable to perform tasks. Now, if the uuid is not set, either installation failed in some unusual way or we're running something that needs the information without sourcing maas_cluster.conf. There may be some nooks and crannies where this may still need doing, so I tried to make the failure a helpful one.

All of this work is to be backported to the 1.2 branch.

Jeroen

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) :
review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/maas-merger-trunk/129/console reported an error when processing this lp:~jtv/maas/bug-1086239 branch.
Not merging it.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Weird Jenkins failure. I'll try again. I also snuck in a small change for the part I forgot to cover: running a demo cluster controller in a source branch.

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

The Jenkins job https://jenkins.qa.ubuntu.com/job/maas-merger-trunk/130/console reported an error when processing this lp:~jtv/maas/bug-1086239 branch.
Not merging it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'etc/democeleryconfig_cluster.py'
--- etc/democeleryconfig_cluster.py 2012-10-23 12:48:31 +0000
+++ etc/democeleryconfig_cluster.py 2012-12-11 13:35:25 +0000
@@ -26,10 +26,6 @@
2626
27import_settings(democeleryconfig_common)27import_settings(democeleryconfig_common)
2828
29# Set a fixed CLUSTER_UUID. In production, this is taken from
30# maas_local_celeryconfig.
31CLUSTER_UUID = "adfd3977-f251-4f2c-8d61-745dbd690bfc"
32
33CELERYD_LOG_FILE = os.path.join(29CELERYD_LOG_FILE = os.path.join(
34 DEV_ROOT_DIRECTORY, 'logs/cluster-worker/current')30 DEV_ROOT_DIRECTORY, 'logs/cluster-worker/current')
3531
3632
=== modified file 'services/cluster-worker/run'
--- services/cluster-worker/run 2012-10-03 11:39:37 +0000
+++ services/cluster-worker/run 2012-12-11 13:35:25 +0000
@@ -16,6 +16,11 @@
1616
17export PYTHONPATH=etc/:src/17export PYTHONPATH=etc/:src/
18export CELERY_CONFIG_MODULE=democeleryconfig_cluster18export CELERY_CONFIG_MODULE=democeleryconfig_cluster
19
20# Set a fixed cluster UUID. This is identical for all cluster services
21# running in the demo setup: they're all the same cluster.
22export CLUSTER_UUID="adfd3977-f251-4f2c-8d61-745dbd690bfc"
23
19script="$(readlink -f bin/maas-provision)"24script="$(readlink -f bin/maas-provision)"
20exec fghack "${script}" start-cluster-controller \25exec fghack "${script}" start-cluster-controller \
21 http://0.0.0.0:5240/ -u "$(id -un)" -g "$(id -gn)"26 http://0.0.0.0:5240/ -u "$(id -un)" -g "$(id -gn)"
2227
=== modified file 'services/pserv/run'
--- services/pserv/run 2012-09-26 14:16:33 +0000
+++ services/pserv/run 2012-12-11 13:35:25 +0000
@@ -17,5 +17,10 @@
17# Exec the Provisioning Server.17# Exec the Provisioning Server.
18script="$(readlink -f bin/twistd.pserv)"18script="$(readlink -f bin/twistd.pserv)"
19config="$(readlink -f etc/pserv.yaml)"19config="$(readlink -f etc/pserv.yaml)"
20
21# Set a fixed cluster UUID. This is identical for all cluster services
22# running in the demo setup: they're all the same cluster.
23export CLUSTER_UUID="adfd3977-f251-4f2c-8d61-745dbd690bfc"
24
20exec $(command -v authbind && echo --deep) \25exec $(command -v authbind && echo --deep) \
21 "${script}" --nodaemon --pidfile="" maas-pserv --config-file "${config}"26 "${script}" --nodaemon --pidfile="" maas-pserv --config-file "${config}"
2227
=== modified file 'src/provisioningserver/auth.py'
--- src/provisioningserver/auth.py 2012-11-23 01:42:03 +0000
+++ src/provisioningserver/auth.py 2012-12-11 13:35:25 +0000
@@ -13,13 +13,10 @@
13__all__ = [13__all__ = [
14 'get_recorded_api_credentials',14 'get_recorded_api_credentials',
15 'get_recorded_nodegroup_uuid',15 'get_recorded_nodegroup_uuid',
16 'get_recorded_maas_url',
17 'record_api_credentials',16 'record_api_credentials',
18 'record_nodegroup_uuid',17 'record_nodegroup_uuid',
19 ]18 ]
2019
21import os
22
23from apiclient.creds import convert_string_to_tuple20from apiclient.creds import convert_string_to_tuple
24from provisioningserver import cache21from provisioningserver import cache
2522
@@ -30,11 +27,6 @@
30NODEGROUP_UUID_CACHE_KEY = 'nodegroup_uuid'27NODEGROUP_UUID_CACHE_KEY = 'nodegroup_uuid'
3128
3229
33def get_recorded_maas_url():
34 """Return the base URL for the MAAS server."""
35 return os.environ.get("MAAS_URL")
36
37
38def record_api_credentials(api_credentials):30def record_api_credentials(api_credentials):
39 """Update the recorded API credentials.31 """Update the recorded API credentials.
4032
4133
=== modified file 'src/provisioningserver/boot_images.py'
--- src/provisioningserver/boot_images.py 2012-11-16 11:25:07 +0000
+++ src/provisioningserver/boot_images.py 2012-12-11 13:35:25 +0000
@@ -26,13 +26,13 @@
26 MAASDispatcher,26 MAASDispatcher,
27 MAASOAuth,27 MAASOAuth,
28 )28 )
29from provisioningserver.auth import (29from provisioningserver.auth import get_recorded_api_credentials
30 get_recorded_api_credentials,30from provisioningserver.cluster_config import (
31 get_recorded_maas_url,31 get_cluster_uuid,
32 get_maas_url,
32 )33 )
33from provisioningserver.config import Config34from provisioningserver.config import Config
34from provisioningserver.pxe import tftppath35from provisioningserver.pxe import tftppath
35from provisioningserver.start_cluster_controller import get_cluster_uuid
3636
3737
38logger = getLogger(__name__)38logger = getLogger(__name__)
@@ -44,7 +44,7 @@
44 :return: Tuple of cached items: (maas_url, api_credentials). Either may44 :return: Tuple of cached items: (maas_url, api_credentials). Either may
45 be None if the information has not been received from the server yet.45 be None if the information has not been received from the server yet.
46 """46 """
47 maas_url = get_recorded_maas_url()47 maas_url = get_maas_url()
48 if maas_url is None:48 if maas_url is None:
49 logger.debug("Not reporting boot images: don't have API URL yet.")49 logger.debug("Not reporting boot images: don't have API URL yet.")
50 api_credentials = get_recorded_api_credentials()50 api_credentials = get_recorded_api_credentials()
5151
=== added file 'src/provisioningserver/cluster_config.py'
--- src/provisioningserver/cluster_config.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/cluster_config.py 2012-12-11 13:35:25 +0000
@@ -0,0 +1,44 @@
1# Copyright 2012 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Accessors for cluster configuration as set in `maas_cluster.conf`."""
5
6from __future__ import (
7 absolute_import,
8 print_function,
9 unicode_literals,
10 )
11
12__metaclass__ = type
13__all__ = [
14 'get_cluster_uuid',
15 'get_maas_url',
16 ]
17
18from os import environ
19
20
21def get_cluster_variable(var):
22 """Obtain the given environment variable from maas_cluster.conf.
23
24 If the variable is not set, it probably means that whatever script
25 started the current process neglected to run maas_cluster.conf.
26 In that case, fail helpfully but utterly.
27 """
28 value = environ.get(var)
29 if value is None:
30 raise AssertionError(
31 "%s is not set. This probably means that the script which "
32 "started this program failed to source maas_cluster.conf."
33 % var)
34 return value
35
36
37def get_cluster_uuid():
38 """Return the `CLUSTER_UUID` setting."""
39 return get_cluster_variable('CLUSTER_UUID')
40
41
42def get_maas_url():
43 """Return the `MAAS_URL` setting."""
44 return get_cluster_variable('MAAS_URL')
045
=== modified file 'src/provisioningserver/dhcp/leases.py'
--- src/provisioningserver/dhcp/leases.py 2012-11-16 11:25:07 +0000
+++ src/provisioningserver/dhcp/leases.py 2012-12-11 13:35:25 +0000
@@ -49,9 +49,9 @@
49from provisioningserver import cache49from provisioningserver import cache
50from provisioningserver.auth import (50from provisioningserver.auth import (
51 get_recorded_api_credentials,51 get_recorded_api_credentials,
52 get_recorded_maas_url,
53 get_recorded_nodegroup_uuid,52 get_recorded_nodegroup_uuid,
54 )53 )
54from provisioningserver.cluster_config import get_maas_url
55from provisioningserver.dhcp.leases_parser import parse_leases55from provisioningserver.dhcp.leases_parser import parse_leases
5656
5757
@@ -150,7 +150,7 @@
150 """Send lease updates to the server API."""150 """Send lease updates to the server API."""
151 # Items that the server must have sent us before we can do this.151 # Items that the server must have sent us before we can do this.
152 knowledge = {152 knowledge = {
153 'maas_url': get_recorded_maas_url(),153 'maas_url': get_maas_url(),
154 'api_credentials': get_recorded_api_credentials(),154 'api_credentials': get_recorded_api_credentials(),
155 'nodegroup_uuid': get_recorded_nodegroup_uuid(),155 'nodegroup_uuid': get_recorded_nodegroup_uuid(),
156 }156 }
157157
=== modified file 'src/provisioningserver/dhcp/tests/test_leases.py'
--- src/provisioningserver/dhcp/tests/test_leases.py 2012-11-26 02:24:46 +0000
+++ src/provisioningserver/dhcp/tests/test_leases.py 2012-12-11 13:35:25 +0000
@@ -328,15 +328,6 @@
328 (get_write_time(leases_file), {params['ip']: params['mac']}),328 (get_write_time(leases_file), {params['ip']: params['mac']}),
329 parse_leases_file())329 parse_leases_file())
330330
331 def test_send_leases_does_nothing_without_maas_url(self):
332 self.patch(MAASClient, 'post', FakeMethod())
333 self.set_lease_state()
334 self.set_items_needed_for_lease_update()
335 self.clear_maas_url()
336 leases = factory.make_random_leases()
337 send_leases(leases)
338 self.assertEqual([], MAASClient.post.calls)
339
340 def test_send_leases_does_nothing_without_credentials(self):331 def test_send_leases_does_nothing_without_credentials(self):
341 self.patch(MAASClient, 'post', FakeMethod())332 self.patch(MAASClient, 'post', FakeMethod())
342 self.set_items_needed_for_lease_update()333 self.set_items_needed_for_lease_update()
343334
=== modified file 'src/provisioningserver/start_cluster_controller.py'
--- src/provisioningserver/start_cluster_controller.py 2012-11-23 01:42:03 +0000
+++ src/provisioningserver/start_cluster_controller.py 2012-12-11 13:35:25 +0000
@@ -32,6 +32,7 @@
32 MAASDispatcher,32 MAASDispatcher,
33 NoAuth,33 NoAuth,
34 )34 )
35from provisioningserver.cluster_config import get_cluster_uuid
35from provisioningserver.network import discover_networks36from provisioningserver.network import discover_networks
3637
3738
@@ -65,14 +66,6 @@
65 return MAASClient(NoAuth(), MAASDispatcher(), server_url)66 return MAASClient(NoAuth(), MAASDispatcher(), server_url)
6667
6768
68def get_cluster_uuid():
69 """Read this cluster's UUID from the config."""
70 # Import this lazily. It reads config as a side effect, which can
71 # produce warnings.
72 from celery.app import app_or_default
73 return app_or_default().conf.CLUSTER_UUID
74
75
76def register(server_url):69def register(server_url):
77 """Request Rabbit connection details from the domain controller.70 """Request Rabbit connection details from the domain controller.
7871
7972
=== modified file 'src/provisioningserver/tags.py'
--- src/provisioningserver/tags.py 2012-11-16 11:25:07 +0000
+++ src/provisioningserver/tags.py 2012-12-11 13:35:25 +0000
@@ -30,9 +30,9 @@
30from lxml import etree30from lxml import etree
31from provisioningserver.auth import (31from provisioningserver.auth import (
32 get_recorded_api_credentials,32 get_recorded_api_credentials,
33 get_recorded_maas_url,
34 get_recorded_nodegroup_uuid,33 get_recorded_nodegroup_uuid,
35 )34 )
35from provisioningserver.cluster_config import get_maas_url
36import simplejson as json36import simplejson as json
3737
3838
@@ -51,10 +51,6 @@
5151
52 :return: (client, nodegroup_uuid)52 :return: (client, nodegroup_uuid)
53 """53 """
54 maas_url = get_recorded_maas_url()
55 if maas_url is None:
56 logger.error("Not updating tags: don't have API URL yet.")
57 return None, None
58 api_credentials = get_recorded_api_credentials()54 api_credentials = get_recorded_api_credentials()
59 if api_credentials is None:55 if api_credentials is None:
60 logger.error("Not updating tags: don't have API key yet.")56 logger.error("Not updating tags: don't have API key yet.")
@@ -64,7 +60,7 @@
64 logger.error("Not updating tags: don't have UUID yet.")60 logger.error("Not updating tags: don't have UUID yet.")
65 return None, None61 return None, None
66 client = MAASClient(MAASOAuth(*api_credentials), MAASDispatcher(),62 client = MAASClient(MAASOAuth(*api_credentials), MAASDispatcher(),
67 maas_url)63 get_maas_url())
68 return client, nodegroup_uuid64 return client, nodegroup_uuid
6965
7066
7167
=== modified file 'src/provisioningserver/tests/test_auth.py'
--- src/provisioningserver/tests/test_auth.py 2012-11-26 14:41:53 +0000
+++ src/provisioningserver/tests/test_auth.py 2012-12-11 13:35:25 +0000
@@ -14,8 +14,6 @@
1414
15from apiclient.creds import convert_tuple_to_string15from apiclient.creds import convert_tuple_to_string
16from apiclient.testing.credentials import make_api_credentials16from apiclient.testing.credentials import make_api_credentials
17from fixtures import EnvironmentVariableFixture
18from maastesting.factory import factory
19from provisioningserver import (17from provisioningserver import (
20 auth,18 auth,
21 cache,19 cache,
@@ -38,13 +36,3 @@
3836
39 def test_get_recorded_api_credentials_returns_None_without_creds(self):37 def test_get_recorded_api_credentials_returns_None_without_creds(self):
40 self.assertIsNone(auth.get_recorded_api_credentials())38 self.assertIsNone(auth.get_recorded_api_credentials())
41
42 def test_get_recorded_nodegroup_uuid_vs_record_nodegroup_uuid(self):
43 nodegroup_uuid = factory.make_name('nodegroupuuid')
44 auth.record_nodegroup_uuid(nodegroup_uuid)
45 self.assertEqual(nodegroup_uuid, auth.get_recorded_nodegroup_uuid())
46
47 def test_get_recorded_maas_url_uses_environment_override(self):
48 required_url = factory.make_name("MAAS_URL")
49 self.useFixture(EnvironmentVariableFixture("MAAS_URL", required_url))
50 self.assertEqual(required_url, auth.get_recorded_maas_url())
5139
=== modified file 'src/provisioningserver/tests/test_boot_images.py'
--- src/provisioningserver/tests/test_boot_images.py 2012-11-26 02:24:46 +0000
+++ src/provisioningserver/tests/test_boot_images.py 2012-12-11 13:35:25 +0000
@@ -12,7 +12,6 @@
12__metaclass__ = type12__metaclass__ = type
13__all__ = []13__all__ = []
1414
15import os
16import json15import json
1716
18from apiclient.maas_client import MAASClient17from apiclient.maas_client import MAASClient
@@ -46,15 +45,6 @@
46 self.assertIs(sentinel.uuid, kwargs["nodegroup"])45 self.assertIs(sentinel.uuid, kwargs["nodegroup"])
47 self.assertItemsEqual([image], json.loads(kwargs['images']))46 self.assertItemsEqual([image], json.loads(kwargs['images']))
4847
49 def test_does_nothing_without_maas_url(self):
50 os.environ.pop("MAAS_URL") # Ensure nothing is set.
51 self.set_api_credentials()
52 self.patch(
53 tftppath, 'list_boot_images',
54 Mock(return_value=make_boot_image_params()))
55 boot_images.report_to_server()
56 self.assertItemsEqual([], tftppath.list_boot_images.call_args_list)
57
58 def test_does_nothing_without_credentials(self):48 def test_does_nothing_without_credentials(self):
59 self.set_maas_url()49 self.set_maas_url()
60 self.patch(50 self.patch(
6151
=== added file 'src/provisioningserver/tests/test_cluster_config.py'
--- src/provisioningserver/tests/test_cluster_config.py 1970-01-01 00:00:00 +0000
+++ src/provisioningserver/tests/test_cluster_config.py 2012-12-11 13:35:25 +0000
@@ -0,0 +1,46 @@
1# Copyright 2012 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Tests for `provisioningserver.cluster_config`."""
5
6from __future__ import (
7 absolute_import,
8 print_function,
9 unicode_literals,
10 )
11
12__metaclass__ = type
13__all__ = []
14
15from fixtures import EnvironmentVariableFixture
16from maastesting.factory import factory
17from maastesting.testcase import TestCase
18from provisioningserver.cluster_config import (
19 get_cluster_uuid,
20 get_cluster_variable,
21 get_maas_url,
22 )
23
24
25class TestClusterConfig(TestCase):
26
27 def test_get_cluster_variable_reads_env(self):
28 var = factory.make_name('variable')
29 value = factory.make_name('value')
30 self.useFixture(EnvironmentVariableFixture(var, value))
31 self.assertEqual(value, get_cluster_variable(var))
32
33 def test_get_cluster_variable_fails_if_not_set(self):
34 self.assertRaises(
35 AssertionError,
36 get_cluster_variable, factory.make_name('nonexistent-variable'))
37
38 def test_get_cluster_uuid_reads_CLUSTER_UUID(self):
39 uuid = factory.make_name('uuid')
40 self.useFixture(EnvironmentVariableFixture('CLUSTER_UUID', uuid))
41 self.assertEqual(uuid, get_cluster_uuid())
42
43 def test_get_maas_url_reads_MAAS_URL(self):
44 maas_url = factory.make_name('maas_url')
45 self.useFixture(EnvironmentVariableFixture('MAAS_URL', maas_url))
46 self.assertEqual(maas_url, get_maas_url())
047
=== modified file 'src/provisioningserver/tftp.py'
--- src/provisioningserver/tftp.py 2012-12-04 05:02:05 +0000
+++ src/provisioningserver/tftp.py 2012-12-11 13:35:25 +0000
@@ -25,10 +25,10 @@
25 urlparse,25 urlparse,
26 )26 )
2727
28from provisioningserver.cluster_config import get_cluster_uuid
28from provisioningserver.enum import ARP_HTYPE29from provisioningserver.enum import ARP_HTYPE
29from provisioningserver.kernel_opts import KernelParameters30from provisioningserver.kernel_opts import KernelParameters
30from provisioningserver.pxe.config import render_pxe_config31from provisioningserver.pxe.config import render_pxe_config
31from provisioningserver.start_cluster_controller import get_cluster_uuid
32from provisioningserver.utils import deferred32from provisioningserver.utils import deferred
33from tftp.backend import (33from tftp.backend import (
34 FilesystemSynchronousBackend,34 FilesystemSynchronousBackend,
@@ -218,9 +218,6 @@
218 params["local"] = local_host218 params["local"] = local_host
219 remote_host, remote_port = get("remote", (None, None))219 remote_host, remote_port = get("remote", (None, None))
220 params["remote"] = remote_host220 params["remote"] = remote_host
221 # XXX 2012-12-04 JeroenVermeulen bug=1086239: move
222 # get_cluster_uuid to a properly reusable location, and
223 # implement it without the celery import (and side effects).
224 params["cluster_uuid"] = get_cluster_uuid()221 params["cluster_uuid"] = get_cluster_uuid()
225 d = self.get_config_reader(params)222 d = self.get_config_reader(params)
226 d.addErrback(self.get_page_errback, file_name)223 d.addErrback(self.get_page_errback, file_name)