Merge lp:~mhall119/awstrial/add-logging into lp:~newz/awstrial/logging-tests
- add-logging
- Merge into logging-tests
Proposed by
Michael Hall
Status: | Merged |
---|---|
Merged at revision: | 267 |
Proposed branch: | lp:~mhall119/awstrial/add-logging |
Merge into: | lp:~newz/awstrial/logging-tests |
Diff against target: |
400 lines (+142/-38) 11 files modified
awstrial/templates/404.html (+8/-2) awstrial/templates/500.html (+7/-1) awstrial/templates/503.html (+24/-2) awstrial/templates/cloud-init/byobu-countdown (+3/-8) awstrial/templates/cloud-init/info-callback (+6/-1) awstrial/templates/contacts.html (+1/-1) awstrial/templates/instance.html (+1/-1) awstrial/trial/auth.py (+4/-3) awstrial/trial/ec2_helper.py (+10/-11) awstrial/trial/tests.py (+77/-6) awstrial/trial/views.py (+1/-2) |
To merge this branch: | bzr merge lp:~mhall119/awstrial/add-logging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthew Nuzum | Pending | ||
Review via email: mp+80013@code.launchpad.net |
Commit message
Description of the change
Mock out DNS.DnsRequest(
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'awstrial/templates/404.html' |
2 | --- awstrial/templates/404.html 2011-10-04 15:26:38 +0000 |
3 | +++ awstrial/templates/404.html 2011-10-20 23:51:23 +0000 |
4 | @@ -9,6 +9,12 @@ |
5 | {% endwith %} |
6 | {% endblock %} |
7 | |
8 | +{% block logo_img %} |
9 | +{% with '/ubuntu-website/media' as ubuntu_website_media %} |
10 | +{{ block.super }} |
11 | +{% endwith %} |
12 | +{% endblock %} |
13 | + |
14 | {% block extrahead %} |
15 | {% with '/media' as MEDIA_URL %} |
16 | {{ block.super }} |
17 | @@ -18,6 +24,6 @@ |
18 | |
19 | |
20 | {% block content %} |
21 | -<h3>Oops!</h3> |
22 | -<p>This page could not be found (404)</p> |
23 | +<h2>404</h2> |
24 | +<p>This page could not be found</p> |
25 | {% endblock %} |
26 | |
27 | === modified file 'awstrial/templates/500.html' |
28 | --- awstrial/templates/500.html 2011-10-04 15:26:38 +0000 |
29 | +++ awstrial/templates/500.html 2011-10-20 23:51:23 +0000 |
30 | @@ -9,6 +9,12 @@ |
31 | {% endwith %} |
32 | {% endblock %} |
33 | |
34 | +{% block logo_img %} |
35 | +{% with '/ubuntu-website/media' as ubuntu_website_media %} |
36 | +{{ block.super }} |
37 | +{% endwith %} |
38 | +{% endblock %} |
39 | + |
40 | {% block extrahead %} |
41 | {% with '/media' as MEDIA_URL %} |
42 | {{ block.super }} |
43 | @@ -17,6 +23,6 @@ |
44 | {% block main_nav_links %}{% endblock %} |
45 | |
46 | {% block content %} |
47 | -<h3>Oops!</h3> |
48 | +<h2>500</h2> |
49 | <p>It seems an error has been encountered, we have been informed. Please try again later.</p> |
50 | {% endblock %} |
51 | |
52 | === modified file 'awstrial/templates/503.html' |
53 | --- awstrial/templates/503.html 2011-09-15 15:20:29 +0000 |
54 | +++ awstrial/templates/503.html 2011-10-20 23:51:23 +0000 |
55 | @@ -1,7 +1,29 @@ |
56 | {% extends "base.html" %} |
57 | -{% block header %} |
58 | + |
59 | + |
60 | +{% block title %}Error | Try Ubuntu Cloud Guest{% endblock %} |
61 | + |
62 | +{% block defaulthead %} |
63 | +{% with '/ubuntu-website/media' as ubuntu_website_media %} |
64 | +{{ block.super }} |
65 | +{% endwith %} |
66 | +{% endblock %} |
67 | + |
68 | +{% block logo_img %} |
69 | +{% with '/ubuntu-website/media' as ubuntu_website_media %} |
70 | +{{ block.super }} |
71 | +{% endwith %} |
72 | +{% endblock %} |
73 | + |
74 | +{% block extrahead %} |
75 | +{% with '/media' as MEDIA_URL %} |
76 | +{{ block.super }} |
77 | +{% endwith %} |
78 | <meta http-equiv="REFRESH" content="0;url=http://ubuntu.com/cloud"></HEAD> |
79 | {% endblock %} |
80 | +{% block main_nav_links %}{% endblock %} |
81 | + |
82 | {% block content %} |
83 | -<h1>There was an error fulfilling the request at this time. Please try again later.</h1> |
84 | +<h2>503</h2> |
85 | +<p>There was an error fulfilling the request at this time. Please try again later.</p> |
86 | {% endblock %} |
87 | |
88 | === renamed file 'awstrial/templates/cloud-init/byobu-enable' => 'awstrial/templates/cloud-init/byobu-countdown' |
89 | --- awstrial/templates/cloud-init/byobu-enable 2010-09-30 12:58:03 +0000 |
90 | +++ awstrial/templates/cloud-init/byobu-countdown 2011-10-20 23:51:23 +0000 |
91 | @@ -1,14 +1,9 @@ |
92 | #!/bin/sh |
93 | -#sudo -Hu ubuntu byobu-launcher-install # single user |
94 | -sem="/var/lib/cloud/sem/byobu-enable.${INSTANCE_ID}" |
95 | + |
96 | +sem="/var/lib/cloud/sem/byobu-countdown.${INSTANCE_ID}" |
97 | [ -e "${sem}" ] && exit 0 |
98 | |
99 | -debconf-set-selections <<EOF |
100 | -byobu byobu/launch-by-default boolean true |
101 | -EOF |
102 | -dpkg-reconfigure byobu --frontend=noninteractive |
103 | - |
104 | -# above does it for all users, but below is only for 'ubuntu' user |
105 | +# Add AWSTrial countdown widget only for 'ubuntu' user |
106 | sudo -Hu ubuntu sh -c 'mkdir -p ~/.byobu/bin/ && |
107 | cat > ~/.byobu/bin/1_countdown && chmod +x ~/.byobu/bin/1_countdown' <<"EOF" |
108 | #!/bin/sh |
109 | |
110 | === modified file 'awstrial/templates/cloud-init/info-callback' |
111 | --- awstrial/templates/cloud-init/info-callback 2011-10-18 13:58:40 +0000 |
112 | +++ awstrial/templates/cloud-init/info-callback 2011-10-20 23:51:23 +0000 |
113 | @@ -6,9 +6,14 @@ |
114 | CALLBACK_URL="{{ callback_url }}" |
115 | |
116 | mdurl="http://169.254.169.254/2009-04-04/meta-data/%s" |
117 | + |
118 | dumpk=""" |
119 | hn=$1; set -e; f=$(mktemp); trap "rm -f '$f'" EXIT; |
120 | -ssh-keyscan -t rsa,dsa localhost 2>/dev/null > "$f" |
121 | +rkeys="rsa,dsa"; [ -f "/etc/ssh/ssh_host_ecdsa_key" ] && rkeys="$rkeys,ecdsa" |
122 | +{% if debug %} |
123 | +echo "Requesting fingerprints for: $rkeys" >> /var/log/instance-testing |
124 | +{% endif %} |
125 | +ssh-keyscan -t "$rkeys" localhost 2>/dev/null > "$f" |
126 | [ -n "${hn}" ] && sed -i "s,localhost,${hn}," "$f" |
127 | ssh-keygen -lf "$f" |
128 | """ |
129 | |
130 | === modified file 'awstrial/templates/contacts.html' |
131 | --- awstrial/templates/contacts.html 2011-10-04 15:26:38 +0000 |
132 | +++ awstrial/templates/contacts.html 2011-10-20 23:51:23 +0000 |
133 | @@ -14,7 +14,7 @@ |
134 | <p>We will give you the hostname and you can SSH directly to the instance with your public SSH key on file in <a href=http://launchpad.net>Launchpad</a>. You will have full <a href=https://help.ubuntu.com/community/RootSudo>sudo (root) access</a>, so take it for an hour-long joyride, install applications, configure services, test your programs, and evaluate the overall experience. We will terminate and clean up the instance automatically within an hour.</p> |
135 | |
136 | {% if set_password %} |
137 | - <p><em>You do not have ssh keys on file in your launchpad account. We strongly recommend you follow the documentation mentioned above and add keys to your launchpad account. Ssh key authentication is much more secure than password authentication. However, if you would like to launch an instance without using ssh keys, you may do so. Click 'Launch' below, and you will be generated a one-time use password and forced to change it on first login</em></p> |
138 | + <p><em>You do not have ssh keys on file in your launchpad account. We strongly recommend you follow the documentation mentioned above and add keys to your launchpad account. Ssh key authentication is much more secure than password authentication. However, if you would like to launch an instance without using ssh keys, you may do so. Click 'Launch' below, and you will be generated a random password which you can then change after login</em></p> |
139 | {% endif %} |
140 | <div id="contact" class="clearfix"> |
141 | <div id="c_form"> |
142 | |
143 | === modified file 'awstrial/templates/instance.html' |
144 | --- awstrial/templates/instance.html 2011-10-18 13:58:40 +0000 |
145 | +++ awstrial/templates/instance.html 2011-10-20 23:51:23 +0000 |
146 | @@ -82,7 +82,7 @@ |
147 | {% endif %} |
148 | {% else %} |
149 | {% if instance.password %} |
150 | - <p>Your randomly generated one time password is '<b>{{ instance.password }}</b>'. You will be forced to change that on initial login.</p> |
151 | + <p>Your randomly generated one time password is '<b>{{ instance.password }}</b>'.</p> |
152 | {% endif %} |
153 | <p>You can <a href=https://help.ubuntu.com/community/SSH/OpenSSH/ConnectingTo target="_blank" >SSH</a> to your Cloud Server using:</p> |
154 | <pre> ssh ubuntu@{{instance.ip}}</pre> |
155 | |
156 | === modified file 'awstrial/trial/auth.py' |
157 | --- awstrial/trial/auth.py 2011-10-19 19:20:08 +0000 |
158 | +++ awstrial/trial/auth.py 2011-10-20 23:51:23 +0000 |
159 | @@ -41,8 +41,9 @@ |
160 | if settings.USER_BLOCK_TOR_GATEWAY: |
161 | |
162 | DNS.ParseResolvConf() |
163 | - |
164 | - client = ".".join(reversed(request.META['REMOTE_ADDR'].strip().split('.'))) |
165 | + |
166 | + remote_addr = request.META['REMOTE_ADDR'] |
167 | + client = ".".join(reversed(remote_addr.strip().split('.'))) |
168 | |
169 | TARGET = ".".join(reversed(socket.gethostbyname(request.META['SERVER_NAME']).strip().split('.'))) |
170 | PORT = "443" |
171 | @@ -54,7 +55,7 @@ |
172 | |
173 | if answer.header['status'] == "NOERROR": |
174 | logger = logging.getLogger('root') |
175 | - logger.info('Client %s is using TOR' % client) |
176 | + logger.info('Client %s is using TOR' % remote_addr) |
177 | return True |
178 | return False |
179 | |
180 | |
181 | === modified file 'awstrial/trial/ec2_helper.py' |
182 | --- awstrial/trial/ec2_helper.py 2011-10-18 13:58:40 +0000 |
183 | +++ awstrial/trial/ec2_helper.py 2011-10-20 23:51:23 +0000 |
184 | @@ -21,6 +21,7 @@ |
185 | |
186 | from trial.models import Campaign, Instances |
187 | from django.contrib.auth.models import User |
188 | +from django.contrib.sites.models import Site |
189 | from django.template.loader import render_to_string |
190 | |
191 | from django.conf import settings |
192 | @@ -62,8 +63,7 @@ |
193 | |
194 | return connection |
195 | |
196 | -def runit(campaign,lpid=None,regions=None,config=None, byobu=False, |
197 | - password=None): |
198 | +def runit(campaign,lpid=None,regions=None,config=None, password=None): |
199 | sec_key = util.rand_str(32) |
200 | if regions is None: |
201 | regions = [r for r in settings.REGIONS_TRY_ORDER |
202 | @@ -72,7 +72,6 @@ |
203 | if settings.REGION2AMI.has_key(r)] |
204 | |
205 | cust = { } |
206 | - cust['byobu'] = False |
207 | cust['config'] = config |
208 | cust['password'] = password |
209 | |
210 | @@ -82,8 +81,9 @@ |
211 | render_to_string("import-launchpad-ssh-keys", |
212 | { 'debug' : settings.DEBUG, 'launchpad_id' : lpid, 'password' : password } ), |
213 | part_type=util.CI_SCRIPT, filename="10-launchpad-ssh-keys")) |
214 | - |
215 | - callback_url = "%s/info_callback/%s" % (settings.BASE_URL, sec_key) |
216 | + |
217 | + site = Site.objects.get(pk=settings.SITE_ID) |
218 | + callback_url = "%s/info_callback/%s" % (site.name, sec_key) |
219 | parts.append( |
220 | util.partItem( |
221 | render_to_string("info-callback", |
222 | @@ -113,12 +113,11 @@ |
223 | { 'debug' : settings.DEBUG, 'user': 'ubuntu', 'password' : password }), |
224 | part_type=util.CI_SCRIPT, filename="55-password-enable")) |
225 | |
226 | - if str(byobu).lower() == "true": |
227 | - parts.append( |
228 | - util.partItem( |
229 | - render_to_string("byobu-enable", { 'debug' : settings.DEBUG, }), |
230 | - part_type=util.CI_BOOTHOOK, filename="byobu-enable")) |
231 | - cust['byobu']=True |
232 | + parts.append( |
233 | + util.partItem( |
234 | + render_to_string("byobu-countdown", { 'debug' : settings.DEBUG, }), |
235 | + part_type=util.CI_BOOTHOOK, filename="byobu-countdown")) |
236 | + cust['byobu']=True |
237 | |
238 | instcfg = None |
239 | for c in settings.CONFIGS: |
240 | |
241 | === modified file 'awstrial/trial/tests.py' |
242 | --- awstrial/trial/tests.py 2011-10-20 20:41:18 +0000 |
243 | +++ awstrial/trial/tests.py 2011-10-20 23:51:23 +0000 |
244 | @@ -25,6 +25,7 @@ |
245 | from django.test import TestCase as DjangoTestCase |
246 | from django.conf import settings |
247 | from django.contrib.auth.models import User |
248 | +from django.contrib.sites.models import Site |
249 | from mock import patch, Mock |
250 | from trial import ec2_helper |
251 | from trial.models import Campaign, Instances |
252 | @@ -99,6 +100,7 @@ |
253 | self.old_access_key = getattr(settings, 'AWS_ACCESS_KEY_ID', None) |
254 | self.old_secret_key = getattr(settings, 'AWS_SECRET_ACCESS_KEY', None) |
255 | self.old_alternate_cloud = getattr(settings, 'ALTERNATE_CLOUD', None) |
256 | + self.old_site_id = getattr(settings, 'SITE_ID', None) |
257 | settings.AWS_ACCESS_KEY_ID = 'TestAccessKey' |
258 | settings.AWS_SECRET_ACCESS_KEY = 'TestSecretKey' |
259 | settings.ALTERNATE_CLOUD = None |
260 | @@ -107,6 +109,7 @@ |
261 | settings.AWS_ACCESS_KEY_ID = self.old_access_key |
262 | settings.AWS_SECRET_ACCESS_KEY = self.old_secret_key |
263 | settings.ALTERNATE_CLOUD = self.old_alternate_cloud |
264 | + settings.SITE_ID = self.old_site_id |
265 | |
266 | def call_run_instance(self, campaign): |
267 | post_data = { |
268 | @@ -117,6 +120,63 @@ |
269 | return self.client.post('/%s/run/' % campaign.name, post_data) |
270 | |
271 | @patch('boto.ec2.EC2Connection') |
272 | + def test_uses_sites_framework(self, mock_connection): |
273 | + """ |
274 | + Checks that the callback url is based off the Site.name for this |
275 | + configuration |
276 | + """ |
277 | + |
278 | + newsite = Site.objects.create( |
279 | + domain='testing.awstrial.org', |
280 | + name='http://testing.awstrial.org:8000', |
281 | + ) |
282 | + settings.SITE_ID = newsite.id |
283 | + self.call_count=0 |
284 | + class MockInstance(object): |
285 | + |
286 | + def __init__(self, instance_id): |
287 | + self.id = instance_id |
288 | + |
289 | + class MockReservation(object): |
290 | + |
291 | + def __init__(self, instance_ids): |
292 | + self.instances = [MockInstance(i) for i in instance_ids] |
293 | + |
294 | + campaign = Campaign.objects.create( |
295 | + name='test-campaign', |
296 | + verbose_name='Test Campaign', |
297 | + max_instances=5, |
298 | + active=True, |
299 | + ) |
300 | + |
301 | + def mock_run_instances(conn, *args, **kwargs): |
302 | + self.call_count += 1 |
303 | + self.assertTrue('user_data' in kwargs) |
304 | + |
305 | + import StringIO, gzip, email |
306 | + gzipped_mime_data = StringIO.StringIO() |
307 | + gzipped_mime_data.write(kwargs['user_data']) |
308 | + gzipped_mime_data.seek(0) |
309 | + gzipped_mime_file = gzip.GzipFile(fileobj=gzipped_mime_data, mode='r') |
310 | + mime_data = gzipped_mime_file.read() |
311 | + mime_msg = email.message_from_string(mime_data) |
312 | + self.assertTrue(mime_msg.is_multipart()) |
313 | + |
314 | + for mime_part in mime_msg.get_payload(): |
315 | + if mime_part.get_filename() == '99-info-callback': |
316 | + self.assertTrue('http://testing.awstrial.org:8000/info_callback/' in mime_part.get_payload()) |
317 | + |
318 | + return MockReservation(['i-test-%s'%self.call_count]) |
319 | + mock_connection.return_value.run_instances.side_effect = mock_run_instances |
320 | + |
321 | + user = User.objects.create_user('testuser', 'test@example.com', 'testpasswd') |
322 | + self.client.login(username='testuser', password='testpasswd') |
323 | + |
324 | + response = self.call_run_instance(campaign) |
325 | + self.assertEquals(1, Instances.objects.all().count()) |
326 | + instance = Instances.objects.all()[0] |
327 | + |
328 | + @patch('boto.ec2.EC2Connection') |
329 | def test_disallow_multiple_instances(self, mock_connection): |
330 | """ |
331 | Checks that a user can't create multiple isntances by making requests |
332 | @@ -333,11 +393,16 @@ |
333 | super(LogHandlerTestCase, self).setUp() |
334 | self.memento_handler = self.MementoHandler() |
335 | self.root_logger = logging.getLogger() |
336 | + self.root_logger.setLevel(logging.INFO) |
337 | self.root_logger.addHandler(self.memento_handler) |
338 | + self.old_block_tor = settings.USER_BLOCK_TOR_GATEWAY |
339 | + self.old_block_email = settings.USER_BLOCK_EMAIL_BLACKLIST |
340 | |
341 | def tearDown(self): |
342 | """Remove the memento handler from the root logger.""" |
343 | self.root_logger.removeHandler(self.memento_handler) |
344 | + settings.USER_BLOCK_TOR_GATEWAY = self.old_block_tor |
345 | + settings.USER_BLOCK_EMAIL_BLACKLIST = self.old_block_email |
346 | super(LogHandlerTestCase, self).tearDown() |
347 | |
348 | def assertLogLevelContains(self, level, message, with_exc_info=False): |
349 | @@ -346,19 +411,25 @@ |
350 | self.assertTrue( |
351 | self.memento_handler.check(level, message, with_exc_info)) |
352 | |
353 | - def test_client_using_tor(self): |
354 | + @patch('DNS.DnsRequest') |
355 | + def test_client_using_tor(self, mock_dns_request): |
356 | # verify that a client that is a TOR exit node is blocked |
357 | - tor_exit = socket.gethostbyname('ip-port.exitlist.torproject.org') |
358 | + settings.USER_BLOCK_TOR_GATEWAY = True |
359 | request = MockRequest() |
360 | request.META['SERVER_NAME'] = '127.0.0.1' |
361 | - request.META['REMOTE_ADDR'] = tor_exit |
362 | + request.META['REMOTE_ADDR'] = '127.0.0.2' |
363 | + mock_dns_request.return_value.req.side_effect = type('answer', (), {'header': {'status': 'NOERROR'}}) |
364 | self.assertTrue(client_using_tor(request)) |
365 | + self.assertLogLevelContains('INFO', 'Client 127.0.0.2 is using TOR') |
366 | |
367 | - def test_client_not_using_tor(self): |
368 | + @patch('DNS.DnsRequest') |
369 | + def test_client_not_using_tor(self, mock_dns_request): |
370 | # verify that a client that is not a TOR exit node is not blocked |
371 | - me = socket.gethostname() |
372 | + settings.USER_BLOCK_TOR_GATEWAY = True |
373 | request = MockRequest() |
374 | request.META['SERVER_NAME'] = '127.0.0.1' |
375 | - request.META['REMOTE_ADDR'] = me |
376 | + request.META['REMOTE_ADDR'] = '127.0.0.2' |
377 | + mock_dns_request.return_value.req.side_effect = type('answer', (), {'header': {'status': 'ERROR'}}) |
378 | self.assertFalse(client_using_tor(request)) |
379 | + self.assertFalse(self.memento_handler.check('INFO', 'Client 127.0.0.2 is using TOR')) |
380 | |
381 | |
382 | === modified file 'awstrial/trial/views.py' |
383 | --- awstrial/trial/views.py 2011-10-18 20:11:39 +0000 |
384 | +++ awstrial/trial/views.py 2011-10-20 23:51:23 +0000 |
385 | @@ -86,14 +86,13 @@ |
386 | else: |
387 | regions = settings.REGIONS_TRY_ORDER |
388 | config = request.POST.get('config', '') |
389 | - byobu = request.POST.get('byobu','') |
390 | set_password = request.POST.get('set_password',None) |
391 | |
392 | password=None |
393 | if set_password: |
394 | password=util.rand_user_password() |
395 | |
396 | - ec2_helper.runit(campaign,lpid=request.user, regions=regions, config=config, byobu=byobu, password=password) |
397 | + ec2_helper.runit(campaign,lpid=request.user, regions=regions, config=config, password=password) |
398 | #send_mail(subject, message, from_email, ['davewalker@ubuntu.com']) |
399 | #except BadHeaderError: #Example of basic error handling |
400 | # return HttpResponse('Invalid header found.') |