Merge lp:~gmb/maas/enlist-uscm-to-RPC into lp:~maas-committers/maas/trunk

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 2957
Proposed branch: lp:~gmb/maas/enlist-uscm-to-RPC
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~gmb/maas/enlist-mscm-to-RPC
Diff against target: 291 lines (+126/-33)
8 files modified
src/maasserver/api/tests/test_nodegroup.py (+9/-4)
src/maasserver/models/nodegroup.py (+15/-3)
src/maasserver/models/tests/test_nodegroup.py (+50/-0)
src/provisioningserver/rpc/cluster.py (+14/-0)
src/provisioningserver/rpc/clusterservice.py (+11/-0)
src/provisioningserver/rpc/tests/test_clusterservice.py (+27/-0)
src/provisioningserver/tasks.py (+0/-13)
src/provisioningserver/tests/test_tasks.py (+0/-13)
To merge this branch: bzr merge lp:~gmb/maas/enlist-uscm-to-RPC
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+234285@code.launchpad.net

This proposal supersedes a proposal from 2014-09-11.

Commit message

Convert the enlist_nodes_from_ucsm() task to use RPC.

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

Looks good. (These branches are a bit boring aren't they?)

review: Approve
Revision history for this message
Graham Binns (gmb) wrote :

On 11 September 2014 11:35, Raphaël Badin <email address hidden> wrote:
>
>
> When the method is called from the API it will be transformed into a 500 error. This is probably what we want but could you check that the error message in that case is meaningful? (I mean, I'd like to be sure it mentions at least the UUID problematic cluster.)

Yes, I'll check. I'll fix that in a followup branch if necessary;
there are several sites that follow this pattern and they could all do
with the same love :)

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

The attempt to merge lp:~gmb/maas/enlist-uscm-to-RPC into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Hit http://security.ubuntu.com trusty-security Release
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
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://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/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 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
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
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
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 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 python-s...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/api/tests/test_nodegroup.py'
2--- src/maasserver/api/tests/test_nodegroup.py 2014-09-11 11:21:49 +0000
3+++ src/maasserver/api/tests/test_nodegroup.py 2014-09-11 12:18:08 +0000
4@@ -57,6 +57,7 @@
5 from provisioningserver.auth import get_recorded_nodegroup_uuid
6 from provisioningserver.rpc.cluster import (
7 EnlistNodesFromMSCM,
8+ EnlistNodesFromUCSM,
9 ImportBootImages,
10 )
11 from testresources import FixtureResource
12@@ -347,7 +348,9 @@
13 password = factory.make_name('password')
14 self.become_admin()
15
16- mock = self.patch(nodegroup_module, 'enlist_nodes_from_ucsm')
17+ getClientFor = self.patch(nodegroup_module, 'getClientFor')
18+ client = getClientFor.return_value
19+ nodegroup = factory.make_NodeGroup()
20
21 response = self.client.post(
22 reverse('nodegroup_handler', args=[nodegroup.uuid]),
23@@ -362,9 +365,11 @@
24 httplib.OK, response.status_code,
25 explain_unexpected_response(httplib.OK, response))
26
27- args = (url, username, password)
28- matcher = MockCalledOnceWith(queue=nodegroup.uuid, args=args)
29- self.assertThat(mock.apply_async, matcher)
30+ self.expectThat(
31+ client,
32+ MockCalledOnceWith(
33+ EnlistNodesFromUCSM, url=url, username=username,
34+ password=password))
35
36 def test_probe_and_enlist_mscm_adds_mscm(self):
37 nodegroup = factory.make_NodeGroup()
38
39=== modified file 'src/maasserver/models/nodegroup.py'
40--- src/maasserver/models/nodegroup.py 2014-09-11 09:58:18 +0000
41+++ src/maasserver/models/nodegroup.py 2014-09-11 12:18:08 +0000
42@@ -42,10 +42,10 @@
43 AddSeaMicro15k,
44 AddVirsh,
45 EnlistNodesFromMSCM,
46+ EnlistNodesFromUCSM,
47 ImportBootImages,
48 )
49 from provisioningserver.rpc.exceptions import NoConnectionsAvailable
50-from provisioningserver.tasks import enlist_nodes_from_ucsm
51
52
53 class NodeGroupManager(Manager):
54@@ -302,9 +302,21 @@
55 :param URL: URL of the Cisco UCS Manager HTTP-XML API.
56 :param username: username for UCS Manager.
57 :param password: password for UCS Manager.
58+
59+ :raises NoConnectionsAvailable: If no connections to the cluster
60+ are available.
61 """
62- args = (url, username, password)
63- enlist_nodes_from_ucsm.apply_async(queue=self.uuid, args=args)
64+ try:
65+ client = getClientFor(self.uuid, timeout=1)
66+ except NoConnectionsAvailable:
67+ # No connection to the cluster so we can't do anything. We
68+ # let the caller handle the error, since we don't want to
69+ # just drop it.
70+ raise
71+ else:
72+ return client(
73+ EnlistNodesFromUCSM, url=url, username=username,
74+ password=password)
75
76 def enlist_nodes_from_mscm(self, host, username, password):
77 """ Add the servers from a Moonshot HP iLO Chassis Manager.
78
79=== modified file 'src/maasserver/models/tests/test_nodegroup.py'
80--- src/maasserver/models/tests/test_nodegroup.py 2014-09-11 09:53:46 +0000
81+++ src/maasserver/models/tests/test_nodegroup.py 2014-09-11 12:18:08 +0000
82@@ -50,6 +50,7 @@
83 AddSeaMicro15k,
84 AddVirsh,
85 EnlistNodesFromMSCM,
86+ EnlistNodesFromUCSM,
87 ImportBootImages,
88 )
89 from provisioningserver.rpc.exceptions import NoConnectionsAvailable
90@@ -563,3 +564,52 @@
91 self.assertRaises(
92 NoConnectionsAvailable, nodegroup.enlist_nodes_from_mscm,
93 host, username, password)
94+
95+ def test_enlist_nodes_from_ucsm_end_to_end(self):
96+ nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ACCEPTED)
97+
98+ self.useFixture(RegionEventLoopFixture("rpc"))
99+ self.useFixture(RunningEventLoopFixture())
100+ fixture = self.useFixture(MockLiveRegionToClusterRPCFixture())
101+ protocol = fixture.makeCluster(nodegroup, EnlistNodesFromUCSM)
102+ protocol.EnlistNodesFromUCSM.return_value = defer.succeed({})
103+
104+ url = factory.make_url()
105+ username = factory.make_name('user')
106+ password = factory.make_name('password')
107+ nodegroup.enlist_nodes_from_ucsm(
108+ url, username, password).wait(10)
109+
110+ self.expectThat(
111+ protocol.EnlistNodesFromUCSM,
112+ MockCalledOnceWith(
113+ ANY, url=url, username=username, password=password))
114+
115+ def test_enlist_nodes_from_ucsm_calls_client_with_resource_endpoint(self):
116+ getClientFor = self.patch(nodegroup_module, 'getClientFor')
117+ client = getClientFor.return_value
118+ nodegroup = factory.make_NodeGroup()
119+
120+ url = factory.make_url()
121+ username = factory.make_name('user')
122+ password = factory.make_name('password')
123+ nodegroup.enlist_nodes_from_ucsm(
124+ url, username, password).wait(10)
125+
126+ self.expectThat(
127+ client,
128+ MockCalledOnceWith(
129+ EnlistNodesFromUCSM, url=url, username=username,
130+ password=password))
131+
132+ def test_enlist_nodes_from_ucsm_raises_if_no_connection_to_cluster(self):
133+ getClientFor = self.patch(nodegroup_module, 'getClientFor')
134+ getClientFor.side_effect = NoConnectionsAvailable()
135+ nodegroup = factory.make_NodeGroup()
136+
137+ url = factory.make_url()
138+ username = factory.make_name('user')
139+ password = factory.make_name('password')
140+ self.assertRaises(
141+ NoConnectionsAvailable, nodegroup.enlist_nodes_from_ucsm,
142+ url, username, password)
143
144=== modified file 'src/provisioningserver/rpc/cluster.py'
145--- src/provisioningserver/rpc/cluster.py 2014-09-11 11:16:53 +0000
146+++ src/provisioningserver/rpc/cluster.py 2014-09-11 12:18:08 +0000
147@@ -391,3 +391,17 @@
148 ]
149 response = []
150 errors = {}
151+
152+
153+class EnlistNodesFromUCSM(amp.Command):
154+ """Probe for and enlist ucsm machines attached to the cluster.
155+
156+ :since: 1.7
157+ """
158+ arguments = [
159+ (b"url", amp.Unicode()),
160+ (b"username", amp.Unicode()),
161+ (b"password", amp.Unicode()),
162+ ]
163+ response = []
164+ errors = {}
165
166=== modified file 'src/provisioningserver/rpc/clusterservice.py'
167--- src/provisioningserver/rpc/clusterservice.py 2014-09-11 09:58:18 +0000
168+++ src/provisioningserver/rpc/clusterservice.py 2014-09-11 12:18:08 +0000
169@@ -33,6 +33,7 @@
170 from provisioningserver.drivers.hardware.seamicro import (
171 probe_seamicro15k_and_enlist,
172 )
173+from provisioningserver.drivers.hardware.ucsm import probe_and_enlist_ucsm
174 from provisioningserver.drivers.hardware.virsh import probe_virsh_and_enlist
175 from provisioningserver.logger.log import get_maas_logger
176 from provisioningserver.rpc import (
177@@ -277,6 +278,16 @@
178 probe_and_enlist_mscm(host, username, password)
179 return {}
180
181+ @cluster.EnlistNodesFromUCSM.responder
182+ def enlist_nodes_from_ucsm(self, url, username, password):
183+ """enlist_nodes_from_ucsm()
184+
185+ Implemention of
186+ :py:class:`~provisioningserver.rpc.cluster.EnlistNodesFromUCSM`.
187+ """
188+ probe_and_enlist_ucsm(url, username, password)
189+ return {}
190+
191
192 @implementer(IConnection)
193 class ClusterClient(Cluster):
194
195=== modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py'
196--- src/provisioningserver/rpc/tests/test_clusterservice.py 2014-09-11 09:53:18 +0000
197+++ src/provisioningserver/rpc/tests/test_clusterservice.py 2014-09-11 12:18:08 +0000
198@@ -1283,3 +1283,30 @@
199 self.assertThat(
200 probe_and_enlist_mscm, MockCalledOnceWith(
201 host, username, password))
202+
203+
204+class TestClusterProtocol_EnlistNodesFromUCSM(MAASTestCase):
205+
206+ def test__is_registered(self):
207+ protocol = Cluster()
208+ responder = protocol.locateResponder(
209+ cluster.EnlistNodesFromUCSM.commandName)
210+ self.assertIsNot(responder, None)
211+
212+ def test__calls_probe_and_enlist_ucsm(self):
213+ probe_and_enlist_ucsm = self.patch_autospec(
214+ clusterservice, 'probe_and_enlist_ucsm')
215+
216+ url = factory.make_url()
217+ username = factory.make_name('user')
218+ password = factory.make_name('password')
219+
220+ call_responder(Cluster(), cluster.EnlistNodesFromUCSM, {
221+ 'url': url,
222+ 'username': username,
223+ 'password': password,
224+ })
225+
226+ self.assertThat(
227+ probe_and_enlist_ucsm, MockCalledOnceWith(
228+ url, username, password))
229
230=== modified file 'src/provisioningserver/tasks.py'
231--- src/provisioningserver/tasks.py 2014-09-11 09:54:13 +0000
232+++ src/provisioningserver/tasks.py 2014-09-11 12:18:08 +0000
233@@ -42,7 +42,6 @@
234 set_up_options_conf,
235 setup_rndc,
236 )
237-from provisioningserver.drivers.hardware.ucsm import probe_and_enlist_ucsm
238 from provisioningserver.logger import get_maas_logger
239
240 # For each item passed to refresh_secrets, a refresh function to give it to.
241@@ -296,15 +295,3 @@
242 exc=exc, countdown=UPDATE_NODE_TAGS_RETRY_DELAY)
243 else:
244 raise
245-
246-
247-# =====================================================================
248-# Custom hardware tasks
249-# =====================================================================
250-
251-@task
252-@log_task_events()
253-@log_exception_text
254-def enlist_nodes_from_ucsm(url, username, password):
255- """ See `maasserver.api.NodeGroupHandler.enlist_nodes_from_ucsm`. """
256- probe_and_enlist_ucsm(url, username, password)
257
258=== modified file 'src/provisioningserver/tests/test_tasks.py'
259--- src/provisioningserver/tests/test_tasks.py 2014-09-11 10:56:06 +0000
260+++ src/provisioningserver/tests/test_tasks.py 2014-09-11 12:18:08 +0000
261@@ -31,7 +31,6 @@
262 FakeMethod,
263 MultiFakeMethod,
264 )
265-from maastesting.matchers import MockCalledOnceWith
266 from mock import Mock
267 from netaddr import IPNetwork
268 from provisioningserver import (
269@@ -55,7 +54,6 @@
270 )
271 from provisioningserver.tags import MissingCredentials
272 from provisioningserver.tasks import (
273- enlist_nodes_from_ucsm,
274 refresh_secrets,
275 report_boot_images,
276 rndc_command,
277@@ -391,14 +389,3 @@
278 self.assertRaises(
279 MissingCredentials, update_node_tags.delay, tag,
280 '//node', tag_nsmap=None, retry=True)
281-
282-
283-class TestAddUCSM(PservTestCase):
284-
285- def test_enlist_nodes_from_ucsm(self):
286- url = 'url'
287- username = 'username'
288- password = 'password'
289- mock = self.patch(tasks, 'probe_and_enlist_ucsm')
290- enlist_nodes_from_ucsm(url, username, password)
291- self.assertThat(mock, MockCalledOnceWith(url, username, password))