Merge lp:~therve/landscape-client/ec2-no-ramdisk into lp:~landscape/landscape-client/trunk
- ec2-no-ramdisk
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sidnei da Silva |
Approved revision: | 242 |
Merged at revision: | 248 |
Proposed branch: | lp:~therve/landscape-client/ec2-no-ramdisk |
Merge into: | lp:~landscape/landscape-client/trunk |
Diff against target: |
274 lines (+64/-30) 3 files modified
landscape/broker/registration.py (+8/-2) landscape/broker/tests/test_registration.py (+55/-27) landscape/message_schemas.py (+1/-1) |
To merge this branch: | bzr merge lp:~therve/landscape-client/ec2-no-ramdisk |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sidnei da Silva (community) | Approve | ||
Free Ekanayaka (community) | Approve | ||
Review via email: mp+24727@code.launchpad.net |
Commit message
Description of the change
Andreas Hasenack (ahasenack) wrote : | # |
I don't think it's working, or I did something wrong. The registration doesn't "stick". Attached is the full broker log of this client running on a lucid instance in the APAC region. Below are the last bits of my broker.log, but the pattern is the same all over the log:
2010-05-05 14:43:40,370 INFO [MainThread] Broker stopped with config /etc/landscape/
2010-05-05 14:43:41,865 INFO [MainThread] Broker started with config /etc/landscape/
2010-05-05 14:43:41,881 ERROR [MainThread] None
Traceback (most recent call last):
File "/usr/lib/
result = context.call(ctx, function, *args, **kwargs)
File "/usr/lib/
return self.currentCon
File "/usr/lib/
return func(*args,**kw)
File "/usr/lib/
raise HTTPCodeError(
HTTPCodeError: Server returned HTTP code 404
2010-05-05 14:44:41,870 INFO [MainThread] Queueing message to register with OTP
2010-05-05 14:44:41,872 INFO [MainThread] Starting urgent message exchange with https:/
2010-05-05 14:44:44,462 INFO [Dummy-1 ] Sent 1146 bytes and received 70 bytes in 2.59s.
2010-05-05 14:44:44,466 INFO [MainThread] Switching to normal exchange mode.
2010-05-05 14:44:44,466 INFO [MainThread] Server UUID changed (old=af6f2dcf-
2010-05-05 14:44:44,467 INFO [MainThread] Message exchange completed in 2.60s.
2010-05-05 14:59:44,474 INFO [MainThread] Queueing message to register with OTP
2010-05-05 14:59:44,477 INFO [MainThread] Starting message exchange with https:/
2010-05-05 14:59:47,343 INFO [Dummy-1 ] Sent 1146 bytes and received 70 bytes in 2.87s.
2010-05-05 14:59:47,348 INFO [MainThread] Message exchange completed in 2.87s.
Thomas Herve (therve) wrote : | # |
It can't work against staging or production because I updated the message schema to allow the ramdisk to be None.
Andreas Hasenack (ahasenack) wrote : | # |
Cool. Works fine after I start a trunk server using this client branch.
Sidnei da Silva (sidnei) wrote : | # |
Looks good. Please add a comment as per Free's request. +1.
- 243. By Thomas Herve
-
Add comment
Preview Diff
1 | === modified file 'landscape/broker/registration.py' |
2 | --- landscape/broker/registration.py 2010-04-28 13:07:53 +0000 |
3 | +++ landscape/broker/registration.py 2010-05-11 09:40:57 +0000 |
4 | @@ -146,19 +146,23 @@ |
5 | "/meta-data/public-hostname", |
6 | "/meta-data/ami-launch-index", |
7 | "/meta-data/kernel-id", |
8 | - "/meta-data/ramdisk-id", |
9 | "/meta-data/ami-id"] |
10 | # We're not using a DeferredList here because we want to keep the |
11 | # number of connections to the backend minimal. See lp:567515. |
12 | for path in paths: |
13 | deferred.addCallback( |
14 | lambda ignore, path=path: self._get_data(path, ec2_data)) |
15 | + # Special case the ramdisk retrieval, because it may not be present |
16 | + deferred.addCallback( |
17 | + lambda ignore: self._fetch_async( |
18 | + EC2_API + "/meta-data/ramdisk-id").addErrback(log_failure)) |
19 | + deferred.addCallback(ec2_data.append) |
20 | |
21 | def record_data(ignore): |
22 | """Record the instance data returned by the EC2 API.""" |
23 | (raw_user_data, instance_key, reservation_key, |
24 | local_hostname, public_hostname, launch_index, |
25 | - kernel_key, ramdisk_key, ami_key) = ec2_data |
26 | + kernel_key, ami_key, ramdisk_key) = ec2_data |
27 | self._ec2_data = { |
28 | "instance_key": instance_key, |
29 | "reservation_key": reservation_key, |
30 | @@ -169,6 +173,8 @@ |
31 | "ramdisk_key": ramdisk_key, |
32 | "image_key": ami_key} |
33 | for k, v in self._ec2_data.items(): |
34 | + if v is None and k == "ramdisk_key": |
35 | + continue |
36 | self._ec2_data[k] = v.decode("utf-8") |
37 | self._ec2_data["launch_index"] = int( |
38 | self._ec2_data["launch_index"]) |
39 | |
40 | === modified file 'landscape/broker/tests/test_registration.py' |
41 | --- landscape/broker/tests/test_registration.py 2010-01-06 15:11:24 +0000 |
42 | +++ landscape/broker/tests/test_registration.py 2010-05-11 09:40:57 +0000 |
43 | @@ -35,8 +35,9 @@ |
44 | self.assertEquals(getattr(self.identity, attr), value, |
45 | "%r attribute should be %r, not %r" % |
46 | (attr, value, getattr(self.identity, attr))) |
47 | - self.assertEquals(self.persist.get(persist_name), value, |
48 | - "%r not set to %r in persist" % (persist_name, value)) |
49 | + self.assertEquals( |
50 | + self.persist.get(persist_name), value, |
51 | + "%r not set to %r in persist" % (persist_name, value)) |
52 | |
53 | def check_config_property(self, attr): |
54 | value = "VALUE" |
55 | @@ -151,8 +152,7 @@ |
56 | "account_name": "account_name", |
57 | "registration_password": None, |
58 | "hostname": "ooga.local", |
59 | - "tags": None,} |
60 | - ]) |
61 | + "tags": None}]) |
62 | self.assertEquals(self.logfile.getvalue().strip(), |
63 | "INFO: Queueing message to register with account " |
64 | "'account_name' without a password.") |
65 | @@ -170,8 +170,7 @@ |
66 | "account_name": "account_name", |
67 | "registration_password": "SEKRET", |
68 | "hostname": "ooga.local", |
69 | - "tags": None,} |
70 | - ]) |
71 | + "tags": None}]) |
72 | self.assertEquals(self.logfile.getvalue().strip(), |
73 | "INFO: Queueing message to register with account " |
74 | "'account_name' with a password.") |
75 | @@ -193,8 +192,7 @@ |
76 | "account_name": "account_name", |
77 | "registration_password": "SEKRET", |
78 | "hostname": "ooga.local", |
79 | - "tags": u"computer,tag"} |
80 | - ]) |
81 | + "tags": u"computer,tag"}]) |
82 | self.assertEquals(self.logfile.getvalue().strip(), |
83 | "INFO: Queueing message to register with account " |
84 | "'account_name' and tags computer,tag " |
85 | @@ -219,8 +217,7 @@ |
86 | "account_name": "account_name", |
87 | "registration_password": "SEKRET", |
88 | "hostname": "ooga.local", |
89 | - "tags": None} |
90 | - ]) |
91 | + "tags": None}]) |
92 | self.assertEquals(self.logfile.getvalue().strip(), |
93 | "ERROR: Invalid tags provided for cloud " |
94 | "registration.\n " |
95 | @@ -238,14 +235,14 @@ |
96 | self.config.registration_password = "SEKRET" |
97 | self.config.tags = u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o" |
98 | self.reactor.fire("pre-exchange") |
99 | - self.assertMessages(self.mstore.get_pending_messages(), |
100 | - [{"type": "register", |
101 | - "computer_title": "Computer Title", |
102 | - "account_name": "account_name", |
103 | - "registration_password": "SEKRET", |
104 | - "hostname": "ooga.local", |
105 | - "tags": u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o"} |
106 | - ]) |
107 | + self.assertMessages( |
108 | + self.mstore.get_pending_messages(), |
109 | + [{"type": "register", |
110 | + "computer_title": "Computer Title", |
111 | + "account_name": "account_name", |
112 | + "registration_password": "SEKRET", |
113 | + "hostname": "ooga.local", |
114 | + "tags": u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o"}]) |
115 | self.assertEquals(self.logfile.getvalue().strip(), |
116 | "INFO: Queueing message to register with account " |
117 | "'account_name' and tags prova\xc4\xb5o " |
118 | @@ -333,9 +330,11 @@ |
119 | |
120 | calls = [0] |
121 | d = self.handler.register() |
122 | + |
123 | def add_call(result): |
124 | self.assertEquals(result, None) |
125 | calls[0] += 1 |
126 | + |
127 | d.addCallback(add_call) |
128 | |
129 | # This should somehow callback the deferred. |
130 | @@ -355,8 +354,10 @@ |
131 | def test_resynchronize_fired_when_registration_done(self): |
132 | |
133 | results = [] |
134 | + |
135 | def append(): |
136 | results.append(True) |
137 | + |
138 | self.reactor.call_on("resynchronize-clients", append) |
139 | |
140 | self.handler.register() |
141 | @@ -373,10 +374,12 @@ |
142 | |
143 | calls = [0] |
144 | d = self.handler.register() |
145 | + |
146 | def add_call(failure): |
147 | exception = failure.value |
148 | self.assertTrue(isinstance(exception, InvalidCredentialsError)) |
149 | calls[0] += 1 |
150 | + |
151 | d.addErrback(add_call) |
152 | |
153 | # This should somehow callback the deferred. |
154 | @@ -428,8 +431,7 @@ |
155 | "account_name": "account_name", |
156 | "registration_password": "SEKRET", |
157 | "hostname": socket.getfqdn(), |
158 | - "tags": None,} |
159 | - ]) |
160 | + "tags": None}]) |
161 | |
162 | |
163 | class CloudRegistrationHandlerTest(RegistrationHandlerTestBase): |
164 | @@ -550,9 +552,10 @@ |
165 | # This *should* be asynchronous, but I think a billion tests are |
166 | # written like this |
167 | self.assertEquals(len(self.transport.payloads), 1) |
168 | - self.assertMessages(self.transport.payloads[0]["messages"], |
169 | - [self.get_expected_cloud_message(tags=u"server,london")]) |
170 | - |
171 | + self.assertMessages( |
172 | + self.transport.payloads[0]["messages"], |
173 | + [self.get_expected_cloud_message(tags=u"server,london")]) |
174 | + |
175 | def test_cloud_registration_with_invalid_tags(self): |
176 | """ |
177 | Invalid tags in the configuration should result in the tags not being |
178 | @@ -694,7 +697,8 @@ |
179 | self.prepare_cloud_registration() |
180 | |
181 | failed = [] |
182 | - self.reactor.call_on("registration-failed", lambda: failed.append(True)) |
183 | + self.reactor.call_on( |
184 | + "registration-failed", lambda: failed.append(True)) |
185 | |
186 | self.log_helper.ignore_errors("Got error while fetching meta-data") |
187 | self.reactor.fire("run") |
188 | @@ -724,6 +728,24 @@ |
189 | account_name=u"onward", |
190 | registration_password=u"password")]) |
191 | |
192 | + def test_cloud_registration_continues_without_ramdisk(self): |
193 | + """ |
194 | + If the instance doesn't have a ramdisk (ie, the query for ramdisk |
195 | + returns a 404), then register-cloud-vm still occurs. |
196 | + """ |
197 | + self.log_helper.ignore_errors(HTTPCodeError) |
198 | + self.prepare_query_results(ramdisk_key=HTTPCodeError(404, "ohno")) |
199 | + self.prepare_cloud_registration() |
200 | + |
201 | + self.reactor.fire("run") |
202 | + self.exchanger.exchange() |
203 | + self.assertIn("HTTPCodeError: Server returned HTTP code 404", |
204 | + self.logfile.getvalue()) |
205 | + self.assertEquals(len(self.transport.payloads), 1) |
206 | + self.assertMessages(self.transport.payloads[0]["messages"], |
207 | + [self.get_expected_cloud_message( |
208 | + ramdisk_key=None)]) |
209 | + |
210 | def test_fall_back_to_normal_registration_when_metadata_fetch_fails(self): |
211 | """ |
212 | If fetching metadata fails, but we do have an account name, then we |
213 | @@ -747,7 +769,7 @@ |
214 | "account_name": u"onward", |
215 | "registration_password": u"password", |
216 | "hostname": socket.getfqdn(), |
217 | - "tags": None,}]) |
218 | + "tags": None}]) |
219 | |
220 | def test_should_register_in_cloud(self): |
221 | """ |
222 | @@ -830,8 +852,9 @@ |
223 | |
224 | def test_is_managed(self): |
225 | """ |
226 | - L{is_cloud_managed} returns True if the EC2 user-data contains Landscape |
227 | - instance information. It fetches the EC2 data with low timeouts. |
228 | + L{is_cloud_managed} returns True if the EC2 user-data contains |
229 | + Landscape instance information. It fetches the EC2 data with low |
230 | + timeouts. |
231 | """ |
232 | user_data = {"otps": ["otp1"], "exchange-url": "http://exchange", |
233 | "ping-url": "http://ping"} |
234 | @@ -890,15 +913,19 @@ |
235 | self.assertFalse(is_cloud_managed(self.fake_fetch)) |
236 | |
237 | def test_is_managed_fetch_not_found(self): |
238 | + |
239 | def fake_fetch(url, connect_timeout=None): |
240 | raise HTTPCodeError(404, "ohnoes") |
241 | + |
242 | self.mock_socket() |
243 | self.mocker.replay() |
244 | self.assertFalse(is_cloud_managed(fake_fetch)) |
245 | |
246 | def test_is_managed_fetch_error(self): |
247 | + |
248 | def fake_fetch(url, connect_timeout=None): |
249 | raise FetchError(7, "couldn't connect to host") |
250 | + |
251 | self.mock_socket() |
252 | self.mocker.replay() |
253 | self.assertFalse(is_cloud_managed(fake_fetch)) |
254 | @@ -930,6 +957,7 @@ |
255 | """ |
256 | We'll only wait five minutes for the network to come up. |
257 | """ |
258 | + |
259 | def fake_fetch(url, connect_timeout=None): |
260 | raise FetchError(7, "couldn't connect to host") |
261 | |
262 | |
263 | === modified file 'landscape/message_schemas.py' |
264 | --- landscape/message_schemas.py 2010-04-26 21:55:00 +0000 |
265 | +++ landscape/message_schemas.py 2010-05-11 09:40:57 +0000 |
266 | @@ -153,7 +153,7 @@ |
267 | "public_hostname": Unicode(), |
268 | "local_hostname": Unicode(), |
269 | "kernel_key": Unicode(), |
270 | - "ramdisk_key": Unicode(), |
271 | + "ramdisk_key": Any(Unicode(), Constant(None)), |
272 | "launch_index": Int(), |
273 | "image_key": Unicode(), |
274 | "tags": Any(utf8, Constant(None))}, |
Looks good! +1
[1]
+ deferred. addCallback( data/ramdisk- id").addErrback (log_failure) ) addCallback( ec2_data. append)
+ lambda ignore: self._fetch_async(
+ EC2_API + "/meta-
+ deferred.
Maybe it'd be worth adding a comment about why we need to special case ramdisk-id.