Merge lp:~alecu/ubuntuone-client/proxy-tunnel-webcalls into lp:ubuntuone-client

Proposed by Alejandro J. Cura
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 1231
Merged at revision: 1208
Proposed branch: lp:~alecu/ubuntuone-client/proxy-tunnel-webcalls
Merge into: lp:ubuntuone-client
Diff against target: 524 lines (+97/-205)
2 files modified
tests/syncdaemon/test_action_queue.py (+51/-137)
ubuntuone/syncdaemon/action_queue.py (+46/-68)
To merge this branch: bzr merge lp:~alecu/ubuntuone-client/proxy-tunnel-webcalls
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Eric Casteleijn (community) Approve
Diego Sarmentero (community) Approve
Review via email: mp+97134@code.launchpad.net

Commit message

- Use the txweb webclient from sso for webcalls, so they can be proxied too (LP: #929207, LP: #929212).

Description of the change

- Use the txweb webclient from sso for webcalls, so they can be proxied too. (LP: #929207, LP: #929212)

**NOTE** This branch depends on this SSO branch: lp:~alecu/ubuntu-sso-client/updated-txweb

To post a comment you must log in.
1231. By Alejandro J. Cura

timestamp is already corrected by txweb in sso

Revision history for this message
Alejandro J. Cura (alecu) wrote :

*** NOTE ***

This branch depends on this SSO branch: lp:~alecu/ubuntu-sso-client/updated-txweb

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

GREAT WORK!
+1

review: Approve
Revision history for this message
Eric Casteleijn (thisfred) wrote :

Looks good to me

review: Approve
Revision history for this message
Roberto Alsina (ralsina) wrote :

looks good, seems to work...

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/syncdaemon/test_action_queue.py'
--- tests/syncdaemon/test_action_queue.py 2012-03-06 20:32:14 +0000
+++ tests/syncdaemon/test_action_queue.py 2012-03-13 03:12:18 +0000
@@ -23,7 +23,6 @@
23import operator23import operator
24import os24import os
25import unittest25import unittest
26import urllib2
27import uuid26import uuid
2827
29from functools import wraps28from functools import wraps
@@ -33,7 +32,7 @@
3332
34from mocker import Mocker, MockerTestCase, ANY, expect33from mocker import Mocker, MockerTestCase, ANY, expect
35from oauth import oauth34from oauth import oauth
36from twisted.internet import defer, threads, reactor35from twisted.internet import defer, reactor
37from twisted.internet import error as twisted_error36from twisted.internet import error as twisted_error
38from twisted.python.failure import DefaultException, Failure37from twisted.python.failure import DefaultException, Failure
39from twisted.web import server38from twisted.web import server
@@ -399,6 +398,21 @@
399 self.assertEqual(defined_args[0], 'self')398 self.assertEqual(defined_args[0], 'self')
400 self.assertEqual(set(defined_args[1:]), set(evtargs))399 self.assertEqual(set(defined_args[1:]), set(evtargs))
401400
401 @defer.inlineCallbacks
402 def test_get_webclient(self):
403 """The webclient is created if it does not exist."""
404 self.assertEqual(self.action_queue.webclient, None)
405 webclient = yield self.action_queue.get_webclient()
406 self.assertNotEqual(webclient, None)
407
408 @defer.inlineCallbacks
409 def test_get_webclient_existing(self):
410 """The webclient is not created again if it exists."""
411 fake_wc = object()
412 self.patch(self.action_queue, "webclient", fake_wc)
413 webclient = yield self.action_queue.get_webclient()
414 self.assertEqual(webclient, fake_wc)
415
402416
403class TestLoggingStorageClient(TwistedTestCase):417class TestLoggingStorageClient(TwistedTestCase):
404 """Tests for ensuring magic hash dont show in logs."""418 """Tests for ensuring magic hash dont show in logs."""
@@ -2519,67 +2533,26 @@
2519 self.assertEqual(NODE, self.command.node_id)2533 self.assertEqual(NODE, self.command.node_id)
2520 self.assertEqual(True, self.command.is_public)2534 self.assertEqual(True, self.command.is_public)
25212535
2522 def test_run_defers_work_to_thread(self):2536 @defer.inlineCallbacks
2523 """Test that work is deferred to a thread."""
2524 original = threads.deferToThread
2525 self.called = False
2526
2527 def check(function):
2528 self.called = True
2529 self.assertEqual(
2530 self.command._change_public_access_http, function)
2531 return defer.Deferred()
2532
2533 threads.deferToThread = check
2534 try:
2535 res = self.command._run()
2536 finally:
2537 threads.deferToThread = original
2538
2539 self.assertIsInstance(res, defer.Deferred)
2540 self.assertTrue(self.called, "deferToThread was called")
2541
2542 def test_change_public_access_http(self):2537 def test_change_public_access_http(self):
2543 """Test the blocking portion of the command."""2538 """Test the command."""
2544 self.called = False2539
2545 def check(request):2540 def check_webcall(request_iri, method=None, post_content=None):
2546 self.called = True2541 """Check the webcall made by this command."""
2547 url = 'https://one.ubuntu.com/files/api/set_public/%s:%s' % (2542 iri = u'https://one.ubuntu.com/files/api/set_public/%s:%s' % (
2548 base64.urlsafe_b64encode(VOLUME.bytes).strip("="),2543 base64.urlsafe_b64encode(VOLUME.bytes).strip("="),
2549 base64.urlsafe_b64encode(NODE.bytes).strip("="))2544 base64.urlsafe_b64encode(NODE.bytes).strip("="))
2550 self.assertEqual(url, request.get_full_url())2545 self.assertEqual(iri, request_iri)
2551 self.assertEqual("is_public=True", request.get_data())2546 self.assertEqual("is_public=True", post_content)
2552 return StringIO(2547 content = '{"is_public": true, "public_url": "http://example.com"}'
2553 '{"is_public": true, "public_url": "http://example.com"}')2548 response = action_queue.txweb.Response(content)
25542549 return defer.succeed(response)
2555 from ubuntuone.syncdaemon import action_queue2550
2556 self.patch(action_queue.timestamp_checker, "get_faithful_time",2551 self.patch(self.action_queue, "webcall", check_webcall)
2557 lambda: 1)2552 res = yield self.command._run()
2558 action_queue.urlopen = check
2559 try:
2560 res = self.command._change_public_access_http()
2561 finally:
2562 action_queue.urlopen = urllib2.urlopen
2563
2564 self.assertEqual(2553 self.assertEqual(
2565 {'is_public': True, 'public_url': 'http://example.com'}, res)2554 {'is_public': True, 'public_url': 'http://example.com'}, res)
25662555
2567 def test_change_public_access_http_uses_timestamp(self):
2568 """The timestamp is used for oauth signing."""
2569 fake_timestamp = 12345678
2570
2571 def fake_urlopen(request):
2572 """A fake urlopen."""
2573 auth = request.headers["Authorization"]
2574 expected = 'oauth_timestamp="%d"' % fake_timestamp
2575 self.assertIn(expected, auth)
2576 return StringIO("[]")
2577
2578 self.patch(action_queue.timestamp_checker, "get_faithful_time",
2579 lambda: fake_timestamp)
2580 self.patch(action_queue, "urlopen", fake_urlopen)
2581 self.command._change_public_access_http()
2582
2583 def test_handle_success_push_event(self):2556 def test_handle_success_push_event(self):
2584 """Test AQ_CHANGE_PUBLIC_ACCESS_OK is pushed on success."""2557 """Test AQ_CHANGE_PUBLIC_ACCESS_OK is pushed on success."""
2585 response = {'is_public': True, 'public_url': 'http://example.com'}2558 response = {'is_public': True, 'public_url': 'http://example.com'}
@@ -2592,8 +2565,7 @@
2592 def test_handle_failure_push_event(self):2565 def test_handle_failure_push_event(self):
2593 """Test AQ_CHANGE_PUBLIC_ACCESS_ERROR is pushed on failure."""2566 """Test AQ_CHANGE_PUBLIC_ACCESS_ERROR is pushed on failure."""
2594 msg = 'Something went wrong'2567 msg = 'Something went wrong'
2595 failure = Failure(urllib2.HTTPError(2568 failure = Failure(action_queue.txweb.WebClientError("Misc Error", msg))
2596 "http://example.com", 500, "Error", [], StringIO(msg)))
2597 self.command.handle_failure(failure=failure)2569 self.command.handle_failure(failure=failure)
2598 event = ('AQ_CHANGE_PUBLIC_ACCESS_ERROR',2570 event = ('AQ_CHANGE_PUBLIC_ACCESS_ERROR',
2599 {'share_id': VOLUME, 'node_id': NODE, 'error': msg})2571 {'share_id': VOLUME, 'node_id': NODE, 'error': msg})
@@ -2620,11 +2592,11 @@
2620 default_url = 'https://one.ubuntu.com/files/api/public_files'2592 default_url = 'https://one.ubuntu.com/files/api/public_files'
2621 request_queue = RequestQueue(action_queue=self.action_queue)2593 request_queue = RequestQueue(action_queue=self.action_queue)
2622 command = GetPublicFiles(request_queue)2594 command = GetPublicFiles(request_queue)
2623 self.assertEqual(command._url, default_url)2595 self.assertEqual(command._iri, default_url)
2624 custom_url = 'http://example.com:1234/files/api/public_files'2596 custom_url = 'http://example.com:1234/files/api/public_files'
2625 command_2 = GetPublicFiles(request_queue,2597 command_2 = GetPublicFiles(request_queue,
2626 base_url='http://example.com:1234')2598 base_iri=u'http://example.com:1234')
2627 self.assertEqual(command_2._url, custom_url)2599 self.assertEqual(command_2._iri, custom_url)
26282600
2629 def test_change_public_access(self):2601 def test_change_public_access(self):
2630 """Test the get_public_files method.."""2602 """Test the get_public_files method.."""
@@ -2634,75 +2606,39 @@
2634 """Test proper inheritance."""2606 """Test proper inheritance."""
2635 self.assertTrue(isinstance(self.command, ActionQueueCommand))2607 self.assertTrue(isinstance(self.command, ActionQueueCommand))
26362608
2637 def test_run_defers_work_to_thread(self):2609 @defer.inlineCallbacks
2638 """Test that work is deferred to a thread."""
2639 original = threads.deferToThread
2640 self.called = False
2641
2642 def check(function):
2643 self.called = True
2644 self.assertEqual(
2645 self.command._get_public_files_http, function)
2646 return defer.Deferred()
2647
2648 threads.deferToThread = check
2649 try:
2650 res = self.command._run()
2651 finally:
2652 threads.deferToThread = original
2653
2654 self.assertIsInstance(res, defer.Deferred)
2655 self.assertTrue(self.called, "deferToThread was called")
2656
2657 def test_get_public_files_http(self):2610 def test_get_public_files_http(self):
2658 """Test the blocking portion of the command."""2611 """Test the _run method of the command."""
2659 self.called = False
2660 node_id = uuid.uuid4()2612 node_id = uuid.uuid4()
2661 nodekey = '%s' % (base64.urlsafe_b64encode(node_id.bytes).strip("="))2613 nodekey = '%s' % (base64.urlsafe_b64encode(node_id.bytes).strip("="))
2662 node_id_2 = uuid.uuid4()2614 node_id_2 = uuid.uuid4()
2663 nodekey_2 = '%s' % (base64.urlsafe_b64encode(2615 nodekey_2 = '%s' % (base64.urlsafe_b64encode(
2664 node_id_2.bytes).strip("="))2616 node_id_2.bytes).strip("="))
2665 volume_id = uuid.uuid4()2617 volume_id = uuid.uuid4()
2666 def check(request):2618
2667 self.called = True2619 def check_webcall(request_iri, method=None):
2668 url = 'https://one.ubuntu.com/files/api/public_files'2620 """Check the webcall made by this command."""
2669 self.assertEqual(url, request.get_full_url())2621 """Check the webcall made by this command."""
2670 return StringIO(2622 iri = u'https://one.ubuntu.com/files/api/public_files'
2623 self.assertEqual(method.upper(), "GET")
2624 self.assertEqual(iri, request_iri)
2625 content = (
2671 '[{"nodekey": "%s", "volume_id": null,"public_url": '2626 '[{"nodekey": "%s", "volume_id": null,"public_url": '
2672 '"http://example.com"}, '2627 '"http://example.com"}, '
2673 '{"nodekey": "%s", "volume_id": "%s", "public_url": '2628 '{"nodekey": "%s", "volume_id": "%s", "public_url": '
2674 '"http://example.com"}]' % (nodekey, nodekey_2, volume_id))2629 '"http://example.com"}]' % (nodekey, nodekey_2, volume_id))
26752630 response = action_queue.txweb.Response(content)
2676 from ubuntuone.syncdaemon import action_queue2631 return defer.succeed(response)
2677 self.patch(action_queue.timestamp_checker, "get_faithful_time",2632
2678 lambda: 1)2633 self.patch(self.action_queue, "webcall", check_webcall)
2679 action_queue.urlopen = check2634 res = yield self.command._run()
2680 try:2635
2681 res = self.command._get_public_files_http()
2682 finally:
2683 action_queue.urlopen = urllib2.urlopen
2684 self.assertEqual([{'node_id': str(node_id), 'volume_id': '',2636 self.assertEqual([{'node_id': str(node_id), 'volume_id': '',
2685 'public_url': 'http://example.com'},2637 'public_url': 'http://example.com'},
2686 {'node_id': str(node_id_2),2638 {'node_id': str(node_id_2),
2687 'volume_id': str(volume_id),2639 'volume_id': str(volume_id),
2688 'public_url': 'http://example.com'}], res)2640 'public_url': 'http://example.com'}], res)
26892641
2690 def test_get_public_files_http_uses_timestamp(self):
2691 """The timestamp is used for oauth signing."""
2692 fake_timestamp = 12345678
2693
2694 def fake_urlopen(request):
2695 """A fake urlopen."""
2696 auth = request.headers["Authorization"]
2697 expected = 'oauth_timestamp="%d"' % fake_timestamp
2698 self.assertIn(expected, auth)
2699 return StringIO("[]")
2700
2701 self.patch(action_queue.timestamp_checker, "get_faithful_time",
2702 lambda: fake_timestamp)
2703 self.patch(action_queue, "urlopen", fake_urlopen)
2704 self.command._get_public_files_http()
2705
2706 def test_handle_success_push_event(self):2642 def test_handle_success_push_event(self):
2707 """Test AQ_PUBLIC_FILES_LIST_OK is pushed on success."""2643 """Test AQ_PUBLIC_FILES_LIST_OK is pushed on success."""
2708 response = [{'node_id': uuid.uuid4(), 'volume_id':None,2644 response = [{'node_id': uuid.uuid4(), 'volume_id':None,
@@ -2714,8 +2650,7 @@
2714 def test_handle_failure_push_event(self):2650 def test_handle_failure_push_event(self):
2715 """Test AQ_PUBLIC_FILES_LIST_ERROR is pushed on failure."""2651 """Test AQ_PUBLIC_FILES_LIST_ERROR is pushed on failure."""
2716 msg = 'Something went wrong'2652 msg = 'Something went wrong'
2717 failure = Failure(urllib2.HTTPError(2653 failure = Failure(action_queue.txweb.WebClientError("Misc Error", msg))
2718 "http://example.com", 500, "Error", [], StringIO(msg)))
2719 self.command.handle_failure(failure=failure)2654 self.command.handle_failure(failure=failure)
2720 event = ('AQ_PUBLIC_FILES_LIST_ERROR', {'error': msg})2655 event = ('AQ_PUBLIC_FILES_LIST_ERROR', {'error': msg})
2721 self.assertIn(event, self.command.action_queue.event_queue.events)2656 self.assertIn(event, self.command.action_queue.event_queue.events)
@@ -3700,27 +3635,6 @@
3700 self.assertEqual('share_name', name)3635 self.assertEqual('share_name', name)
3701 self.assertTrue(read_only)3636 self.assertTrue(read_only)
37023637
3703 @defer.inlineCallbacks
3704 def test_create_share_http_uses_timestamp(self):
3705 """The timestamp is used for oauth signing."""
3706 fake_timestamp = 12345678
3707
3708 def fake_urlopen(request):
3709 """A fake urlopen."""
3710 auth = request.headers["Authorization"]
3711 expected = 'oauth_timestamp="%d"' % fake_timestamp
3712 self.assertIn(expected, auth)
3713
3714 self.patch(action_queue.timestamp_checker, "get_faithful_time",
3715 lambda: fake_timestamp)
3716 self.patch(action_queue, "urlopen", fake_urlopen)
3717 self.user_connect()
3718 command = CreateShare(self.request_queue, 'node_id',
3719 'share_to@example.com', 'share_name',
3720 ACCESS_LEVEL_RO, 'marker', 'path')
3721 self.assertTrue(command.use_http, 'CreateShare should be in http mode')
3722 yield command._run()
3723
3724 def test_possible_markers(self):3638 def test_possible_markers(self):
3725 """Test that it returns the correct values."""3639 """Test that it returns the correct values."""
3726 cmd = CreateShare(self.request_queue, 'node_id', 'shareto@example.com',3640 cmd = CreateShare(self.request_queue, 'node_id', 'shareto@example.com',
37273641
=== modified file 'ubuntuone/syncdaemon/action_queue.py'
--- ubuntuone/syncdaemon/action_queue.py 2012-03-10 00:39:26 +0000
+++ ubuntuone/syncdaemon/action_queue.py 2012-03-13 03:12:18 +0000
@@ -31,19 +31,18 @@
31from collections import deque, defaultdict31from collections import deque, defaultdict
32from functools import partial32from functools import partial
33from urllib import urlencode33from urllib import urlencode
34from urllib2 import urlopen, Request, HTTPError
35from urlparse import urljoin34from urlparse import urljoin
3635
37import OpenSSL.SSL36import OpenSSL.SSL
3837
39from zope.interface import implements38from zope.interface import implements
40from twisted.internet import reactor, defer, threads, task39from twisted.internet import reactor, defer, task
41from twisted.internet import error as twisted_errors40from twisted.internet import error as twisted_errors
42from twisted.names import client as dns_client41from twisted.names import client as dns_client
43from twisted.python.failure import Failure, DefaultException42from twisted.python.failure import Failure, DefaultException
4443
45from oauth import oauth44from oauth import oauth
46from ubuntu_sso.utils import timestamp_checker45from ubuntu_sso.utils.webclient import txweb
47from ubuntuone import clientdefs46from ubuntuone import clientdefs
48from ubuntuone.platform import platform, remove_file47from ubuntuone.platform import platform, remove_file
49from ubuntuone.storageprotocol import protocol_pb2, content_hash48from ubuntuone.storageprotocol import protocol_pb2, content_hash
@@ -685,6 +684,8 @@
685 # credentials684 # credentials
686 self.token = None685 self.token = None
687 self.consumer = None686 self.consumer = None
687 self.credentials = None
688 self.webclient = None
688689
689 self.client = None # an instance of self.protocol690 self.client = None # an instance of self.protocol
690691
@@ -730,6 +731,7 @@
730731
731 def handle_SYS_USER_CONNECT(self, access_token):732 def handle_SYS_USER_CONNECT(self, access_token):
732 """Stow the access token away for later use."""733 """Stow the access token away for later use."""
734 self.credentials = access_token
733 self.token = oauth.OAuthToken(access_token['token'],735 self.token = oauth.OAuthToken(access_token['token'],
734 access_token['token_secret'])736 access_token['token_secret'])
735 self.consumer = oauth.OAuthConsumer(access_token['consumer_key'],737 self.consumer = oauth.OAuthConsumer(access_token['consumer_key'],
@@ -818,6 +820,25 @@
818 else:820 else:
819 return defer.succeed((self.host, self.port))821 return defer.succeed((self.host, self.port))
820822
823
824 @defer.inlineCallbacks
825 def webcall(self, iri, **kwargs):
826 """Perform a web call to the api servers."""
827 webclient = yield self.get_webclient()
828 response = yield webclient.request(iri,
829 oauth_credentials=self.credentials, **kwargs)
830 defer.returnValue(response)
831
832 @defer.inlineCallbacks
833 def get_webclient(self):
834 """Get the webclient, creating it if needed."""
835 if self.webclient is None:
836 client = yield self.tunnel_runner.get_client()
837 self.webclient = txweb.WebClient(connector=client,
838 appname="Ubuntu One",
839 oauth_sign_plain=True)
840 defer.returnValue(self.webclient)
841
821 @defer.inlineCallbacks842 @defer.inlineCallbacks
822 def _make_connection(self, result):843 def _make_connection(self, result):
823 """Do the real connect call."""844 """Do the real connect call."""
@@ -1778,36 +1799,23 @@
1778 if share_to and re.match(EREGEX, share_to):1799 if share_to and re.match(EREGEX, share_to):
1779 self.use_http = True1800 self.use_http = True
17801801
1802 @defer.inlineCallbacks
1781 def _create_share_http(self, node_id, user, name, read_only):1803 def _create_share_http(self, node_id, user, name, read_only):
1782 """Create a share using the HTTP Web API method."""1804 """Create a share using the HTTP Web API method."""
17831805
1784 url = "https://one.ubuntu.com/files/api/offer_share/"1806 iri = u"https://one.ubuntu.com/files/api/offer_share/"
1785 method = oauth.OAuthSignatureMethod_PLAINTEXT()
1786 timestamp = timestamp_checker.get_faithful_time()
1787 parameters = {"oauth_timestamp": timestamp}
1788 request = oauth.OAuthRequest.from_consumer_and_token(
1789 http_url=url,
1790 http_method="POST",
1791 parameters=parameters,
1792 oauth_consumer=self.action_queue.consumer,
1793 token=self.action_queue.token)
1794 request.sign_request(method, self.action_queue.consumer,
1795 self.action_queue.token)
1796 data = dict(offer_to_email=user,1807 data = dict(offer_to_email=user,
1797 read_only=read_only,1808 read_only=read_only,
1798 node_id=node_id,1809 node_id=node_id,
1799 share_name=name)1810 share_name=name)
1800 pdata = urlencode(data)1811 pdata = urlencode(data)
1801 headers = request.to_header()1812 yield self.action_queue.webcall(iri, method="POST", post_content=pdata)
1802 req = Request(url, pdata, headers)
1803 urlopen(req)
18041813
1805 def _run(self):1814 def _run(self):
1806 """Do the actual running."""1815 """Do the actual running."""
1807 if self.use_http:1816 if self.use_http:
1808 # External user, do the HTTP REST method1817 # External user, do the HTTP REST method
1809 return threads.deferToThread(self._create_share_http,1818 return self._create_share_http(self.node_id, self.share_to,
1810 self.node_id, self.share_to,
1811 self.name,1819 self.name,
1812 self.access_level != ACCESS_LEVEL_RW)1820 self.access_level != ACCESS_LEVEL_RW)
1813 else:1821 else:
@@ -1831,7 +1839,7 @@
1831 """It didn't work! Push the event."""1839 """It didn't work! Push the event."""
1832 self.action_queue.event_queue.push('AQ_CREATE_SHARE_ERROR',1840 self.action_queue.event_queue.push('AQ_CREATE_SHARE_ERROR',
1833 marker=self.marker,1841 marker=self.marker,
1834 error=failure.getErrorMessage())1842 error=failure.value[1])
18351843
1836 def _acquire_pathlock(self):1844 def _acquire_pathlock(self):
1837 """Acquire pathlock."""1845 """Acquire pathlock."""
@@ -2113,6 +2121,7 @@
2113 self.node_id = node_id2121 self.node_id = node_id
2114 self.is_public = is_public2122 self.is_public = is_public
21152123
2124 @defer.inlineCallbacks
2116 def _change_public_access_http(self):2125 def _change_public_access_http(self):
2117 """Change public access using the HTTP Web API method."""2126 """Change public access using the HTTP Web API method."""
21182127
@@ -2123,28 +2132,16 @@
2123 base64.urlsafe_b64encode(self.share_id.bytes).strip("="),2132 base64.urlsafe_b64encode(self.share_id.bytes).strip("="),
2124 node_key)2133 node_key)
21252134
2126 url = "https://one.ubuntu.com/files/api/set_public/%s" % (node_key,)2135 iri = u"https://one.ubuntu.com/files/api/set_public/%s" % (node_key,)
2127 method = oauth.OAuthSignatureMethod_PLAINTEXT()
2128 timestamp = timestamp_checker.get_faithful_time()
2129 parameters = {"oauth_timestamp": timestamp}
2130 request = oauth.OAuthRequest.from_consumer_and_token(
2131 http_url=url,
2132 http_method="POST",
2133 parameters=parameters,
2134 oauth_consumer=self.action_queue.consumer,
2135 token=self.action_queue.token)
2136 request.sign_request(method, self.action_queue.consumer,
2137 self.action_queue.token)
2138 data = dict(is_public=bool(self.is_public))2136 data = dict(is_public=bool(self.is_public))
2139 pdata = urlencode(data)2137 pdata = urlencode(data)
2140 headers = request.to_header()2138 response = yield self.action_queue.webcall(iri, method="POST",
2141 req = Request(url, pdata, headers)2139 post_content=pdata)
2142 response = urlopen(req)2140 defer.returnValue(simplejson.loads(response.content))
2143 return simplejson.load(response)
21442141
2145 def _run(self):2142 def _run(self):
2146 """See ActionQueueCommand."""2143 """See ActionQueueCommand."""
2147 return threads.deferToThread(self._change_public_access_http)2144 return self._change_public_access_http()
21482145
2149 def handle_success(self, success):2146 def handle_success(self, success):
2150 """See ActionQueueCommand."""2147 """See ActionQueueCommand."""
@@ -2156,51 +2153,36 @@
21562153
2157 def handle_failure(self, failure):2154 def handle_failure(self, failure):
2158 """It didn't work! Push the event."""2155 """It didn't work! Push the event."""
2159 if issubclass(failure.type, HTTPError):
2160 message = failure.value.read()
2161 else:
2162 message = failure.getErrorMessage()
2163 self.action_queue.event_queue.push('AQ_CHANGE_PUBLIC_ACCESS_ERROR',2156 self.action_queue.event_queue.push('AQ_CHANGE_PUBLIC_ACCESS_ERROR',
2164 share_id=self.share_id,2157 share_id=self.share_id,
2165 node_id=self.node_id,2158 node_id=self.node_id,
2166 error=message)2159 error=failure.value[1])
21672160
21682161
2169class GetPublicFiles(ActionQueueCommand):2162class GetPublicFiles(ActionQueueCommand):
2170 """Get the list of public files."""2163 """Get the list of public files."""
21712164
2172 __slots__ = ('_url',)2165 __slots__ = ('_iri',)
2173 logged_attrs = ActionQueueCommand.logged_attrs + __slots__2166 logged_attrs = ActionQueueCommand.logged_attrs + __slots__
21742167
2175 def __init__(self, request_queue, base_url='https://one.ubuntu.com'):2168 def __init__(self, request_queue, base_iri=u'https://one.ubuntu.com'):
2176 super(GetPublicFiles, self).__init__(request_queue)2169 super(GetPublicFiles, self).__init__(request_queue)
2177 self._url = urljoin(base_url, 'files/api/public_files')2170 self._iri = urljoin(base_iri, u'files/api/public_files')
21782171
2172 @defer.inlineCallbacks
2179 def _get_public_files_http(self):2173 def _get_public_files_http(self):
2180 """Get public files list using the HTTP Web API method."""2174 """Get public files list using the HTTP Web API method."""
21812175
2182 method = oauth.OAuthSignatureMethod_PLAINTEXT()2176 response = yield self.action_queue.webcall(self._iri, method="GET")
2183 timestamp = timestamp_checker.get_faithful_time()2177
2184 parameters = {"oauth_timestamp": timestamp}2178 files = simplejson.loads(response.content)
2185 request = oauth.OAuthRequest.from_consumer_and_token(
2186 http_url=self._url,
2187 http_method="GET",
2188 parameters=parameters,
2189 oauth_consumer=self.action_queue.consumer,
2190 token=self.action_queue.token)
2191 request.sign_request(method, self.action_queue.consumer,
2192 self.action_queue.token)
2193 headers = request.to_header()
2194 req = Request(self._url, headers=headers)
2195 response = urlopen(req)
2196 files = simplejson.load(response)
2197 # translate nodekeys to (volume_id, node_id)2179 # translate nodekeys to (volume_id, node_id)
2198 for pf in files:2180 for pf in files:
2199 _, node_id = self.split_nodekey(pf.pop('nodekey'))2181 _, node_id = self.split_nodekey(pf.pop('nodekey'))
2200 volume_id = pf['volume_id']2182 volume_id = pf['volume_id']
2201 pf['volume_id'] = '' if volume_id is None else volume_id2183 pf['volume_id'] = '' if volume_id is None else volume_id
2202 pf['node_id'] = node_id2184 pf['node_id'] = node_id
2203 return files2185 defer.returnValue(files)
22042186
2205 @property2187 @property
2206 def uniqueness(self):2188 def uniqueness(self):
@@ -2213,7 +2195,7 @@
22132195
2214 def _run(self):2196 def _run(self):
2215 """See ActionQueueCommand."""2197 """See ActionQueueCommand."""
2216 return threads.deferToThread(self._get_public_files_http)2198 return self._get_public_files_http()
22172199
2218 def handle_success(self, success):2200 def handle_success(self, success):
2219 """See ActionQueueCommand."""2201 """See ActionQueueCommand."""
@@ -2222,12 +2204,8 @@
22222204
2223 def handle_failure(self, failure):2205 def handle_failure(self, failure):
2224 """It didn't work! Push the event."""2206 """It didn't work! Push the event."""
2225 if issubclass(failure.type, HTTPError):
2226 message = failure.value.read()
2227 else:
2228 message = failure.getErrorMessage()
2229 self.action_queue.event_queue.push('AQ_PUBLIC_FILES_LIST_ERROR',2207 self.action_queue.event_queue.push('AQ_PUBLIC_FILES_LIST_ERROR',
2230 error=message)2208 error=failure.value[1])
22312209
2232 def split_nodekey(self, nodekey):2210 def split_nodekey(self, nodekey):
2233 """Split a node key into a share_id, node_id."""2211 """Split a node key into a share_id, node_id."""

Subscribers

People subscribed via source and target branches