Merge lp:~alecu/ubuntuone-client/ziggy-for-syncdaemon into lp:ubuntuone-client
- ziggy-for-syncdaemon
- Merge into trunk
Proposed by
Alejandro J. Cura
on 2010-12-07
| Status: | Merged |
|---|---|
| Approved by: | dobey on 2010-12-09 |
| Approved revision: | 763 |
| Merged at revision: | 769 |
| Proposed branch: | lp:~alecu/ubuntuone-client/ziggy-for-syncdaemon |
| Merge into: | lp:ubuntuone-client |
| Prerequisite: | lp:~alecu/ubuntuone-client/add-simple-zeitgeist |
| Diff against target: |
582 lines (+502/-5) 7 files modified
contrib/testing/testcase.py (+34/-0) tests/syncdaemon/test_action_queue.py (+21/-0) tests/syncdaemon/test_event_logging.py (+282/-0) ubuntuone/syncdaemon/action_queue.py (+2/-4) ubuntuone/syncdaemon/event_logging.py (+159/-0) ubuntuone/syncdaemon/event_queue.py (+1/-0) ubuntuone/syncdaemon/main.py (+3/-1) |
| To merge this branch: | bzr merge lp:~alecu/ubuntuone-client/ziggy-for-syncdaemon |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Facundo Batista | Approve on 2010-12-09 | ||
| Guillermo Gonzalez | 2010-12-07 | Approve on 2010-12-09 | |
|
Review via email:
|
|||
Commit Message
Share invite, create, deleting and unsubscribe events are added to zeitgeist
Description of the Change
Share invite, create, deleting and unsubscribe events are added to zeitgeist
To post a comment you must log in.
| Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
No proposals found for merge of lp:~alecu/ubuntuone-client/add-simple-zeitgeist into lp:ubuntuone-client.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === modified file 'contrib/testing/testcase.py' |
| 2 | --- contrib/testing/testcase.py 2010-11-30 17:53:14 +0000 |
| 3 | +++ contrib/testing/testcase.py 2010-12-09 14:33:06 +0000 |
| 4 | @@ -305,6 +305,40 @@ |
| 5 | return TwistedTestCase.tearDown(self) |
| 6 | |
| 7 | |
| 8 | +class FakeMainTestCase(BaseTwistedTestCase): |
| 9 | + """A testcase that starts up a Main instance.""" |
| 10 | + |
| 11 | + def setUp(self): |
| 12 | + """Setup the infrastructure for the test.""" |
| 13 | + BaseTwistedTestCase.setUp(self) |
| 14 | + self.log = logging.getLogger("ubuntuone.SyncDaemon.TEST") |
| 15 | + self.log.info("starting test %s.%s", self.__class__.__name__, |
| 16 | + self._testMethodName) |
| 17 | + self.timeout = 2 |
| 18 | + self.data_dir = self.mktemp('data_dir') |
| 19 | + self.partials_dir = self.mktemp('partials') |
| 20 | + self.root_dir = self.mktemp('root_dir') |
| 21 | + self.shares_dir = self.mktemp('shares_dir') |
| 22 | + self.main = FakeMain(self.root_dir, self.shares_dir, |
| 23 | + self.data_dir, self.partials_dir) |
| 24 | + self.vm = self.main.vm |
| 25 | + self.fs = self.main.fs |
| 26 | + self.event_q = self.main.event_q |
| 27 | + self.action_q = self.main.action_q |
| 28 | + self.event_q.push('SYS_INIT_DONE') |
| 29 | + |
| 30 | + def tearDown(self): |
| 31 | + """Shutdown this testcase.""" |
| 32 | + BaseTwistedTestCase.tearDown(self) |
| 33 | + self.main.shutdown() |
| 34 | + self.rmtree(self.shares_dir) |
| 35 | + self.rmtree(self.root_dir) |
| 36 | + self.rmtree(self.data_dir) |
| 37 | + self.rmtree(self.partials_dir) |
| 38 | + self.log.info("finished test %s.%s", self.__class__.__name__, |
| 39 | + self._testMethodName) |
| 40 | + |
| 41 | + |
| 42 | class MementoHandler(logging.Handler): |
| 43 | """ A handler class which store logging records in a list """ |
| 44 | |
| 45 | |
| 46 | === modified file 'tests/syncdaemon/test_action_queue.py' |
| 47 | --- tests/syncdaemon/test_action_queue.py 2010-12-06 15:01:06 +0000 |
| 48 | +++ tests/syncdaemon/test_action_queue.py 2010-12-09 14:33:06 +0000 |
| 49 | @@ -2958,6 +2958,27 @@ |
| 50 | res = [getattr(cmd, x) for x in cmd.possible_markers] |
| 51 | self.assertEqual(res, ['node_id']) |
| 52 | |
| 53 | + def test_handle_success_sends_invitation(self): |
| 54 | + """The success handler sends the AQ_SHARE_INVITATION_SENT event.""" |
| 55 | + marker_id = "marker" |
| 56 | + share_name = "share name" |
| 57 | + share_to = "share_to@example.com" |
| 58 | + |
| 59 | + class MockResult(object): |
| 60 | + """A mock result.""" |
| 61 | + share_id = SHARE |
| 62 | + |
| 63 | + mock_success = MockResult() |
| 64 | + cmd = CreateShare(self.request_queue, NODE, share_to, |
| 65 | + share_name, 'View', marker_id) |
| 66 | + cmd.log = cmd.make_logger() |
| 67 | + cmd.use_http = True |
| 68 | + cmd.handle_success(mock_success) |
| 69 | + |
| 70 | + event_params = { 'marker': marker_id } |
| 71 | + events = [('AQ_SHARE_INVITATION_SENT', (), event_params)] |
| 72 | + self.assertEqual(events, cmd.action_queue.event_queue.events) |
| 73 | + |
| 74 | |
| 75 | class RequestQueueManagerTestCase(FactoryBaseTestCase): |
| 76 | """Test how RequestQueue manages the queues.""" |
| 77 | |
| 78 | === added file 'tests/syncdaemon/test_event_logging.py' |
| 79 | --- tests/syncdaemon/test_event_logging.py 1970-01-01 00:00:00 +0000 |
| 80 | +++ tests/syncdaemon/test_event_logging.py 2010-12-09 14:33:06 +0000 |
| 81 | @@ -0,0 +1,282 @@ |
| 82 | +# tests.syncdaemon.test_event_logging - test logging ZG events |
| 83 | +# |
| 84 | +# Author: Alejandro J. Cura <alecu@canonical.com> |
| 85 | +# |
| 86 | +# Copyright 2010 Canonical Ltd. |
| 87 | +# |
| 88 | +# This program is free software: you can redistribute it and/or modify it |
| 89 | +# under the terms of the GNU General Public License version 3, as published |
| 90 | +# by the Free Software Foundation. |
| 91 | +# |
| 92 | +# This program is distributed in the hope that it will be useful, but |
| 93 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 94 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 95 | +# PURPOSE. See the GNU General Public License for more details. |
| 96 | +# |
| 97 | +# You should have received a copy of the GNU General Public License along |
| 98 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 99 | +"""Test the event logging from SyncDaemon into Zeitgeist.""" |
| 100 | + |
| 101 | +import os |
| 102 | +import uuid |
| 103 | + |
| 104 | +from twisted.internet import defer |
| 105 | +from zeitgeist.datamodel import Interpretation, Manifestation |
| 106 | + |
| 107 | +from contrib.testing.testcase import FakeMainTestCase |
| 108 | +from ubuntuone.storageprotocol.sharersp import NotifyShareHolder |
| 109 | +from ubuntuone.syncdaemon.event_logging import ( |
| 110 | + zglog, ZeitgeistListener, ACTOR_UBUNTUONE, |
| 111 | + EVENT_INTERPRETATION_U1_FOLDER_SHARED, |
| 112 | + EVENT_INTERPRETATION_U1_FOLDER_UNSHARED, |
| 113 | + EVENT_INTERPRETATION_U1_SHARE_ACCEPTED, |
| 114 | + EVENT_INTERPRETATION_U1_SHARE_UNACCEPTED, |
| 115 | + MANIFESTATION_U1_CONTACT_DATA_OBJECT, DIRECTORY_MIMETYPE, |
| 116 | + INTERPRETATION_U1_CONTACT, URI_PROTOCOL_U1, STORAGE_NETWORK) |
| 117 | +from ubuntuone.syncdaemon.volume_manager import Share, Shared |
| 118 | + |
| 119 | + |
| 120 | +class MockLogger(object): |
| 121 | + """A mock logger that stores whatever is logged into it.""" |
| 122 | + |
| 123 | + def __init__(self): |
| 124 | + """Initialize this instance.""" |
| 125 | + self.events = [] |
| 126 | + |
| 127 | + def log(self, event): |
| 128 | + """Log the event.""" |
| 129 | + self.events.append(event) |
| 130 | + |
| 131 | + |
| 132 | +class ZeitgeistListenerTestCase(FakeMainTestCase): |
| 133 | + """Tests for ZeitgeistListener.""" |
| 134 | + |
| 135 | + def setUp(self): |
| 136 | + """Initialize this instance.""" |
| 137 | + super(ZeitgeistListenerTestCase, self).setUp() |
| 138 | + self.patch(zglog, "ZeitgeistLogger", MockLogger) |
| 139 | + self.listener = ZeitgeistListener(self.fs, self.vm) |
| 140 | + self.event_q.subscribe(self.listener) |
| 141 | + |
| 142 | + def _listen_for(self, event, callback, count=1, collect=False): |
| 143 | + """Setup a EQ listener for the specified event.""" |
| 144 | + event_q = self.main.event_q |
| 145 | + class Listener(object): |
| 146 | + """A basic listener to handle the pushed event.""" |
| 147 | + |
| 148 | + def __init__(self): |
| 149 | + self.hits = 0 |
| 150 | + self.events = [] |
| 151 | + |
| 152 | + def _handle_event(self, *args, **kwargs): |
| 153 | + self.hits += 1 |
| 154 | + if collect: |
| 155 | + self.events.append((args, kwargs)) |
| 156 | + if self.hits == count: |
| 157 | + event_q.unsubscribe(self) |
| 158 | + if collect: |
| 159 | + callback(self.events) |
| 160 | + elif kwargs: |
| 161 | + callback((args, kwargs)) |
| 162 | + else: |
| 163 | + callback(args) |
| 164 | + |
| 165 | + listener = Listener() |
| 166 | + setattr(listener, 'handle_'+event, listener._handle_event) |
| 167 | + event_q.subscribe(listener) |
| 168 | + return listener |
| 169 | + |
| 170 | + def test_share_created_with_username_is_logged(self): |
| 171 | + """A ShareCreated event is logged.""" |
| 172 | + fake_username = "fake user" |
| 173 | + path = os.path.join(self.vm.root.path, 'shared_path') |
| 174 | + sample_node_id = "node id" |
| 175 | + self.main.fs.create(path, "") |
| 176 | + self.main.fs.set_node_id(path, sample_node_id) |
| 177 | + |
| 178 | + def fake_create_share(node_id, user, name, access_level, marker): |
| 179 | + """Fake the creation of the share on the server.""" |
| 180 | + self.assertIn(marker, self.vm.marker_share_map) |
| 181 | + share_id = self.fs.get_by_mdid(marker).share_id |
| 182 | + self.main.event_q.push('AQ_CREATE_SHARE_OK', |
| 183 | + share_id=share_id, |
| 184 | + marker=marker) |
| 185 | + |
| 186 | + self.patch(self.main.action_q, "create_share", fake_create_share) |
| 187 | + self.vm.create_share(path, fake_username, 'shared_name', 'View') |
| 188 | + |
| 189 | + self.assert_folder_shared_is_logged(path, fake_username) |
| 190 | + |
| 191 | + def test_share_created_with_email_is_logged(self): |
| 192 | + """A ShareCreated event is logged.""" |
| 193 | + fake_username = "fakeuser@somewhere.com" |
| 194 | + path = os.path.join(self.vm.root.path, 'shared_path') |
| 195 | + sample_node_id = "node id" |
| 196 | + self.main.fs.create(path, "") |
| 197 | + self.main.fs.set_node_id(path, sample_node_id) |
| 198 | + |
| 199 | + def fake_create_share(node_id, user, name, access_level, marker): |
| 200 | + """Fake the creation of the share on the server.""" |
| 201 | + self.assertIn(marker, self.vm.marker_share_map) |
| 202 | + self.main.event_q.push('AQ_SHARE_INVITATION_SENT', |
| 203 | + marker=marker) |
| 204 | + |
| 205 | + self.patch(self.main.action_q, "create_share", fake_create_share) |
| 206 | + self.vm.create_share(path, fake_username, 'shared_name', 'View') |
| 207 | + |
| 208 | + self.assert_folder_shared_is_logged(path, fake_username) |
| 209 | + |
| 210 | + def assert_folder_shared_is_logged(self, path, fake_username): |
| 211 | + """Assert that the FolderShared event was logged.""" |
| 212 | + |
| 213 | + self.assertEquals(len(self.listener.zg.events), 1) |
| 214 | + event = self.listener.zg.events[0] |
| 215 | + |
| 216 | + self.assertEquals(event.interpretation, |
| 217 | + EVENT_INTERPRETATION_U1_FOLDER_SHARED) |
| 218 | + self.assertEquals(event.manifestation, |
| 219 | + Manifestation.USER_ACTIVITY) |
| 220 | + self.assertEquals(event.actor, ACTOR_UBUNTUONE) |
| 221 | + |
| 222 | + folder = event.subjects[0] |
| 223 | + self.assertTrue(folder.uri.startswith(URI_PROTOCOL_U1)) |
| 224 | + self.assertEquals(folder.interpretation, Interpretation.FOLDER) |
| 225 | + self.assertEquals(folder.manifestation, |
| 226 | + Manifestation.REMOTE_DATA_OBJECT) |
| 227 | + self.assertTrue(folder.origin.endswith(path)) |
| 228 | + self.assertEquals(folder.mimetype, DIRECTORY_MIMETYPE) |
| 229 | + self.assertEquals(folder.storage, STORAGE_NETWORK) |
| 230 | + |
| 231 | + other_user = event.subjects[1] |
| 232 | + self.assertEquals(other_user.uri, "mailto:" + fake_username) |
| 233 | + self.assertEquals(other_user.interpretation, INTERPRETATION_U1_CONTACT) |
| 234 | + self.assertEquals(other_user.manifestation, |
| 235 | + MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 236 | + |
| 237 | + |
| 238 | + @defer.inlineCallbacks |
| 239 | + def test_share_deleted_is_logged(self): |
| 240 | + """Test VolumeManager.delete_share.""" |
| 241 | + sample_share_id = "share id" |
| 242 | + sample_node_id = "node id" |
| 243 | + fake_username = "fake user" |
| 244 | + path = os.path.join(self.vm.root.path, 'shared_path') |
| 245 | + self.main.fs.create(path, "") |
| 246 | + self.main.fs.set_node_id(path, sample_node_id) |
| 247 | + share = Shared(path=path, volume_id=sample_share_id, |
| 248 | + node_id=sample_node_id, other_username=fake_username) |
| 249 | + self.vm.add_shared(share) |
| 250 | + |
| 251 | + def fake_delete_share(share_id): |
| 252 | + """Fake delete_share.""" |
| 253 | + self.assertEqual(share_id, share.volume_id) |
| 254 | + self.main.event_q.push('AQ_DELETE_SHARE_OK', share_id) |
| 255 | + |
| 256 | + self.patch(self.main.action_q, 'delete_share', fake_delete_share) |
| 257 | + d = defer.Deferred() |
| 258 | + self._listen_for('VM_SHARE_DELETED', d.callback, 1, collect=True) |
| 259 | + self.vm.delete_share(share.volume_id) |
| 260 | + yield d |
| 261 | + |
| 262 | + self.assertEquals(len(self.listener.zg.events), 1) |
| 263 | + event = self.listener.zg.events[0] |
| 264 | + |
| 265 | + self.assertEquals(event.interpretation, |
| 266 | + EVENT_INTERPRETATION_U1_FOLDER_UNSHARED) |
| 267 | + self.assertEquals(event.manifestation, |
| 268 | + Manifestation.USER_ACTIVITY) |
| 269 | + self.assertEquals(event.actor, ACTOR_UBUNTUONE) |
| 270 | + |
| 271 | + folder = event.subjects[0] |
| 272 | + self.assertTrue(folder.uri.startswith(URI_PROTOCOL_U1)) |
| 273 | + self.assertEquals(folder.interpretation, Interpretation.FOLDER) |
| 274 | + self.assertEquals(folder.manifestation, |
| 275 | + Manifestation.REMOTE_DATA_OBJECT) |
| 276 | + self.assertTrue(folder.origin.endswith(path)) |
| 277 | + self.assertEquals(folder.mimetype, DIRECTORY_MIMETYPE) |
| 278 | + self.assertEquals(folder.storage, STORAGE_NETWORK) |
| 279 | + |
| 280 | + other_user = event.subjects[1] |
| 281 | + self.assertEquals(other_user.uri, "mailto:" + fake_username) |
| 282 | + self.assertEquals(other_user.interpretation, INTERPRETATION_U1_CONTACT) |
| 283 | + self.assertEquals(other_user.manifestation, |
| 284 | + MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 285 | + |
| 286 | + def test_share_accepted_is_logged(self): |
| 287 | + """Test that an accepted share event is logged.""" |
| 288 | + # initialize the the root |
| 289 | + self.vm._got_root('root_uuid') |
| 290 | + fake_username = "fake user" |
| 291 | + path = os.path.join(self.vm.root.path, 'shared_path') |
| 292 | + self.main.fs.create(path, "") |
| 293 | + share_path = os.path.join(self.shares_dir, 'fake_share') |
| 294 | + share = Share(path=share_path, volume_id='volume_id', node_id="node_id", |
| 295 | + other_username=fake_username) |
| 296 | + self.vm.add_share(share) |
| 297 | + |
| 298 | + self.assertEquals(len(self.listener.zg.events), 1) |
| 299 | + event = self.listener.zg.events[0] |
| 300 | + |
| 301 | + self.assertEquals(event.interpretation, |
| 302 | + EVENT_INTERPRETATION_U1_SHARE_ACCEPTED) |
| 303 | + self.assertEquals(event.manifestation, |
| 304 | + Manifestation.USER_ACTIVITY) |
| 305 | + self.assertEquals(event.actor, ACTOR_UBUNTUONE) |
| 306 | + |
| 307 | + folder = event.subjects[0] |
| 308 | + self.assertTrue(folder.uri.startswith(URI_PROTOCOL_U1)) |
| 309 | + self.assertEquals(folder.interpretation, Interpretation.FOLDER) |
| 310 | + self.assertEquals(folder.manifestation, |
| 311 | + Manifestation.REMOTE_DATA_OBJECT) |
| 312 | + self.assertTrue(folder.origin.endswith(share_path)) |
| 313 | + self.assertEquals(folder.mimetype, DIRECTORY_MIMETYPE) |
| 314 | + self.assertEquals(folder.storage, STORAGE_NETWORK) |
| 315 | + |
| 316 | + other_user = event.subjects[1] |
| 317 | + self.assertEquals(other_user.uri, "mailto:" + fake_username) |
| 318 | + self.assertEquals(other_user.interpretation, INTERPRETATION_U1_CONTACT) |
| 319 | + self.assertEquals(other_user.manifestation, |
| 320 | + MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 321 | + |
| 322 | + |
| 323 | + @defer.inlineCallbacks |
| 324 | + def test_share_unaccepted_is_logged(self): |
| 325 | + """Test that an unaccepted share event is logged.""" |
| 326 | + fake_username = "fake user" |
| 327 | + d = defer.Deferred() |
| 328 | + |
| 329 | + share_path = os.path.join(self.main.shares_dir, 'share') |
| 330 | + holder = NotifyShareHolder.from_params(uuid.uuid4(), |
| 331 | + uuid.uuid4(), |
| 332 | + u'fake_share', |
| 333 | + fake_username, |
| 334 | + u'visible_name', 'Read') |
| 335 | + |
| 336 | + self.main.vm.add_share(Share.from_notify_holder(holder, share_path)) |
| 337 | + self._listen_for('VM_VOLUME_DELETED', d.callback, 1, collect=True) |
| 338 | + self.main.event_q.push('SV_SHARE_DELETED', holder.share_id) |
| 339 | + yield d |
| 340 | + |
| 341 | + self.assertEquals(len(self.listener.zg.events), 2) |
| 342 | + event = self.listener.zg.events[1] |
| 343 | + |
| 344 | + self.assertEquals(event.interpretation, |
| 345 | + EVENT_INTERPRETATION_U1_SHARE_UNACCEPTED) |
| 346 | + self.assertEquals(event.manifestation, |
| 347 | + Manifestation.USER_ACTIVITY) |
| 348 | + self.assertEquals(event.actor, ACTOR_UBUNTUONE) |
| 349 | + |
| 350 | + folder = event.subjects[0] |
| 351 | + self.assertTrue(folder.uri.startswith(URI_PROTOCOL_U1)) |
| 352 | + self.assertEquals(folder.interpretation, Interpretation.FOLDER) |
| 353 | + self.assertEquals(folder.manifestation, |
| 354 | + Manifestation.REMOTE_DATA_OBJECT) |
| 355 | + self.assertTrue(folder.origin.endswith(share_path)) |
| 356 | + self.assertEquals(folder.mimetype, DIRECTORY_MIMETYPE) |
| 357 | + self.assertEquals(folder.storage, STORAGE_NETWORK) |
| 358 | + |
| 359 | + other_user = event.subjects[1] |
| 360 | + self.assertEquals(other_user.uri, "mailto:" + fake_username) |
| 361 | + self.assertEquals(other_user.interpretation, INTERPRETATION_U1_CONTACT) |
| 362 | + self.assertEquals(other_user.manifestation, |
| 363 | + MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 364 | |
| 365 | === modified file 'ubuntuone/syncdaemon/action_queue.py' |
| 366 | --- ubuntuone/syncdaemon/action_queue.py 2010-12-06 15:01:06 +0000 |
| 367 | +++ ubuntuone/syncdaemon/action_queue.py 2010-12-09 14:33:06 +0000 |
| 368 | @@ -1718,14 +1718,12 @@ |
| 369 | """It worked! Push the event.""" |
| 370 | # We don't get a share_id back from the HTTP REST method |
| 371 | if not self.use_http: |
| 372 | - self.log.debug('Pushing AQ_CREATE_SHARE_OK (share_id: %s) because ' |
| 373 | - 'self.use_http is False.', success.share_id) |
| 374 | self.action_queue.event_queue.push('AQ_CREATE_SHARE_OK', |
| 375 | share_id=success.share_id, |
| 376 | marker=self.marker) |
| 377 | else: |
| 378 | - self.log.warn('not pushing AQ_CREATE_SHARE_OK because ' |
| 379 | - 'self.use_http is True.') |
| 380 | + self.action_queue.event_queue.push('AQ_SHARE_INVITATION_SENT', |
| 381 | + marker=self.marker) |
| 382 | return success |
| 383 | |
| 384 | def handle_failure(self, failure): |
| 385 | |
| 386 | === added file 'ubuntuone/syncdaemon/event_logging.py' |
| 387 | --- ubuntuone/syncdaemon/event_logging.py 1970-01-01 00:00:00 +0000 |
| 388 | +++ ubuntuone/syncdaemon/event_logging.py 2010-12-09 14:33:06 +0000 |
| 389 | @@ -0,0 +1,159 @@ |
| 390 | +# ubuntuone.syncdaemon.event_logging - listen for SD events, log into ZG |
| 391 | +# |
| 392 | +# Author: Alejandro J. Cura <alecu@canonical.com> |
| 393 | +# |
| 394 | +# Copyright 2010 Canonical Ltd. |
| 395 | +# |
| 396 | +# This program is free software: you can redistribute it and/or modify it |
| 397 | +# under the terms of the GNU General Public License version 3, as published |
| 398 | +# by the Free Software Foundation. |
| 399 | +# |
| 400 | +# This program is distributed in the hope that it will be useful, but |
| 401 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
| 402 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
| 403 | +# PURPOSE. See the GNU General Public License for more details. |
| 404 | +# |
| 405 | +# You should have received a copy of the GNU General Public License along |
| 406 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
| 407 | +"""Event logging from SyncDaemon into Zeitgeist.""" |
| 408 | + |
| 409 | +from zeitgeist.datamodel import Event, Interpretation, Manifestation, Subject |
| 410 | + |
| 411 | +from ubuntuone.eventlog import zglog |
| 412 | +from ubuntuone.syncdaemon.volume_manager import Share |
| 413 | + |
| 414 | +ACTOR_UBUNTUONE = "dbus://com.ubuntuone.SyncDaemon.service" |
| 415 | +DIRECTORY_MIMETYPE = "inode/directory" |
| 416 | +EVENT_INTERPRETATION_U1_FOLDER_SHARED = "u1://FolderShared" |
| 417 | +EVENT_INTERPRETATION_U1_FOLDER_UNSHARED = "u1://FolderUnshared" |
| 418 | +EVENT_INTERPRETATION_U1_SHARE_ACCEPTED = "u1://ShareAccepted" |
| 419 | +EVENT_INTERPRETATION_U1_SHARE_UNACCEPTED = "u1://ShareUnaccepted" |
| 420 | +MANIFESTATION_U1_CONTACT_DATA_OBJECT = "u1://ContactDataObject" |
| 421 | +INTERPRETATION_U1_CONTACT = "u1://Contact" |
| 422 | +URI_PROTOCOL_U1 = "ubuntuone:" |
| 423 | +STORAGE_NETWORK = "net" |
| 424 | + |
| 425 | +class ZeitgeistListener(object): |
| 426 | + """An Event Queue listener that logs into ZG.""" |
| 427 | + |
| 428 | + def __init__(self, fsm, vm): |
| 429 | + """Initialize this instance.""" |
| 430 | + self.fsm = fsm |
| 431 | + self.vm = vm |
| 432 | + self.zg = zglog.ZeitgeistLogger() |
| 433 | + |
| 434 | + def handle_AQ_CREATE_SHARE_OK(self, share_id=None, marker=None): |
| 435 | + """Log the 'directory shared thru the server' event.""" |
| 436 | + share = self.vm.shared[share_id] |
| 437 | + self.log_folder_shared(share, share_id) |
| 438 | + |
| 439 | + def handle_AQ_SHARE_INVITATION_SENT(self, marker): |
| 440 | + """Log the 'directory shared thru http' event.""" |
| 441 | + share = self.vm.marker_share_map[marker] |
| 442 | + mdo = self.fsm.get_by_mdid(marker) |
| 443 | + self.log_folder_shared(share, mdo.share_id) |
| 444 | + |
| 445 | + def log_folder_shared(self, share, share_id): |
| 446 | + """Log the 'directory shared' event.""" |
| 447 | + fullpath = self.fsm.get_abspath(share_id, share.path) |
| 448 | + |
| 449 | + folder = Subject.new_for_values( |
| 450 | + uri=URI_PROTOCOL_U1 + str(share.node_id), |
| 451 | + interpretation=Interpretation.FOLDER, |
| 452 | + manifestation=Manifestation.REMOTE_DATA_OBJECT, |
| 453 | + origin="file:///" + fullpath, |
| 454 | + mimetype=DIRECTORY_MIMETYPE, |
| 455 | + storage=STORAGE_NETWORK) |
| 456 | + |
| 457 | + other_username = share.other_username |
| 458 | + other_user = Subject.new_for_values( |
| 459 | + uri="mailto:" + other_username, |
| 460 | + interpretation=INTERPRETATION_U1_CONTACT, |
| 461 | + manifestation=MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 462 | + |
| 463 | + event = Event.new_for_values( |
| 464 | + interpretation=EVENT_INTERPRETATION_U1_FOLDER_SHARED, |
| 465 | + manifestation=Manifestation.USER_ACTIVITY, |
| 466 | + actor=ACTOR_UBUNTUONE, |
| 467 | + subjects=[folder, other_user]) |
| 468 | + |
| 469 | + self.zg.log(event) |
| 470 | + |
| 471 | + def handle_VM_SHARE_DELETED(self, share): |
| 472 | + """Log the share deleted event.""" |
| 473 | + folder = Subject.new_for_values( |
| 474 | + uri=URI_PROTOCOL_U1 + str(share.node_id), |
| 475 | + interpretation=Interpretation.FOLDER, |
| 476 | + manifestation=Manifestation.REMOTE_DATA_OBJECT, |
| 477 | + origin="file:///" + share.path, |
| 478 | + mimetype=DIRECTORY_MIMETYPE, |
| 479 | + storage=STORAGE_NETWORK) |
| 480 | + |
| 481 | + other_username = share.other_username |
| 482 | + other_user = Subject.new_for_values( |
| 483 | + uri="mailto:" + other_username, |
| 484 | + interpretation=INTERPRETATION_U1_CONTACT, |
| 485 | + manifestation=MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 486 | + |
| 487 | + event = Event.new_for_values( |
| 488 | + interpretation=EVENT_INTERPRETATION_U1_FOLDER_UNSHARED, |
| 489 | + manifestation=Manifestation.USER_ACTIVITY, |
| 490 | + actor=ACTOR_UBUNTUONE, |
| 491 | + subjects=[folder, other_user]) |
| 492 | + |
| 493 | + self.zg.log(event) |
| 494 | + |
| 495 | + def handle_VM_SHARE_CREATED(self, share_id): |
| 496 | + """Log the share accepted event.""" |
| 497 | + share = self.vm.shares[share_id] |
| 498 | + |
| 499 | + folder = Subject.new_for_values( |
| 500 | + uri=URI_PROTOCOL_U1 + str(share.node_id), |
| 501 | + interpretation=Interpretation.FOLDER, |
| 502 | + manifestation=Manifestation.REMOTE_DATA_OBJECT, |
| 503 | + origin="file:///" + share.path, |
| 504 | + mimetype=DIRECTORY_MIMETYPE, |
| 505 | + storage=STORAGE_NETWORK) |
| 506 | + |
| 507 | + other_username = share.other_username |
| 508 | + other_user = Subject.new_for_values( |
| 509 | + uri="mailto:" + other_username, |
| 510 | + interpretation=INTERPRETATION_U1_CONTACT, |
| 511 | + manifestation=MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 512 | + |
| 513 | + event = Event.new_for_values( |
| 514 | + interpretation=EVENT_INTERPRETATION_U1_SHARE_ACCEPTED, |
| 515 | + manifestation=Manifestation.USER_ACTIVITY, |
| 516 | + actor=ACTOR_UBUNTUONE, |
| 517 | + subjects=[folder, other_user]) |
| 518 | + |
| 519 | + self.zg.log(event) |
| 520 | + |
| 521 | + def log_share_unaccepted(self, share): |
| 522 | + """Log the share unaccepted event.""" |
| 523 | + folder = Subject.new_for_values( |
| 524 | + uri=URI_PROTOCOL_U1 + str(share.node_id), |
| 525 | + interpretation=Interpretation.FOLDER, |
| 526 | + manifestation=Manifestation.REMOTE_DATA_OBJECT, |
| 527 | + origin="file:///" + share.path, |
| 528 | + mimetype=DIRECTORY_MIMETYPE, |
| 529 | + storage=STORAGE_NETWORK) |
| 530 | + |
| 531 | + other_username = share.other_username |
| 532 | + other_user = Subject.new_for_values( |
| 533 | + uri="mailto:" + other_username, |
| 534 | + interpretation=INTERPRETATION_U1_CONTACT, |
| 535 | + manifestation=MANIFESTATION_U1_CONTACT_DATA_OBJECT) |
| 536 | + |
| 537 | + event = Event.new_for_values( |
| 538 | + interpretation=EVENT_INTERPRETATION_U1_SHARE_UNACCEPTED, |
| 539 | + manifestation=Manifestation.USER_ACTIVITY, |
| 540 | + actor=ACTOR_UBUNTUONE, |
| 541 | + subjects=[folder, other_user]) |
| 542 | + |
| 543 | + self.zg.log(event) |
| 544 | + |
| 545 | + def handle_VM_VOLUME_DELETED(self, volume): |
| 546 | + """Log the share/UDF unaccepted event.""" |
| 547 | + if isinstance(volume, Share): |
| 548 | + self.log_share_unaccepted(volume) |
| 549 | |
| 550 | === modified file 'ubuntuone/syncdaemon/event_queue.py' |
| 551 | --- ubuntuone/syncdaemon/event_queue.py 2010-11-30 19:06:17 +0000 |
| 552 | +++ ubuntuone/syncdaemon/event_queue.py 2010-12-09 14:33:06 +0000 |
| 553 | @@ -64,6 +64,7 @@ |
| 554 | 'AQ_UPLOAD_ERROR': ('share_id', 'node_id', 'error', 'hash'), |
| 555 | 'AQ_SHARES_LIST': ('shares_list',), |
| 556 | 'AQ_LIST_SHARES_ERROR': ('error',), |
| 557 | + 'AQ_SHARE_INVITATION_SENT': ('marker',), |
| 558 | 'AQ_CREATE_SHARE_OK': ('share_id', 'marker'), |
| 559 | 'AQ_CREATE_SHARE_ERROR': ('marker', 'error'), |
| 560 | 'AQ_DELETE_SHARE_OK': ('share_id',), |
| 561 | |
| 562 | === modified file 'ubuntuone/syncdaemon/main.py' |
| 563 | --- ubuntuone/syncdaemon/main.py 2010-12-01 20:56:01 +0000 |
| 564 | +++ ubuntuone/syncdaemon/main.py 2010-12-09 14:33:06 +0000 |
| 565 | @@ -30,6 +30,7 @@ |
| 566 | event_queue, |
| 567 | filesystem_manager, |
| 568 | hash_queue, |
| 569 | + event_logging, |
| 570 | events_nanny, |
| 571 | local_rescan, |
| 572 | sync, |
| 573 | @@ -123,7 +124,8 @@ |
| 574 | self, glib_loop, broadcast_events) |
| 575 | self.action_q.content_queue.set_change_notification_cb( |
| 576 | self.external.change_notification) |
| 577 | - |
| 578 | + self.zg_listener = event_logging.ZeitgeistListener(self.fs, self.vm) |
| 579 | + self.event_q.subscribe(self.zg_listener) |
| 580 | self.logger.info("Using %r as root dir", self.root_dir) |
| 581 | self.logger.info("Using %r as data dir", self.data_dir) |
| 582 | self.logger.info("Using %r as shares root dir", self.shares_dir) |


looks good.