Repository: libcloud Updated Branches: refs/heads/support_for_pickling_driver_instances [created] e9a2e6db2
Add support for pickling Driver instances. Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/e9a2e6db Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/e9a2e6db Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/e9a2e6db Branch: refs/heads/support_for_pickling_driver_instances Commit: e9a2e6db29a4a3dcc719a9ebcea0582ed7931dcb Parents: 79680b5 Author: Tomaz Muraus <[email protected]> Authored: Sun Jul 19 19:45:42 2015 +0800 Committer: Tomaz Muraus <[email protected]> Committed: Sun Jul 19 20:02:01 2015 +0800 ---------------------------------------------------------------------- libcloud/common/base.py | 23 ++++++++++ libcloud/test/common/test_pickling.py | 72 ++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/e9a2e6db/libcloud/common/base.py ---------------------------------------------------------------------- diff --git a/libcloud/common/base.py b/libcloud/common/base.py index ac0fdd7..f2365e4 100644 --- a/libcloud/common/base.py +++ b/libcloud/common/base.py @@ -1102,6 +1102,11 @@ class BaseDriver(object): 'backoff': kwargs.pop('backoff', None)}) self.connection = self.connectionCls(*args, **conn_kwargs) + # Note: We store this attributes on the class so we can re-create + # connection when unpickling driver instance + self._connection_cls_args = args + self._connection_cls_kwargs = conn_kwargs + self.connection.driver = self self.connection.connect() @@ -1111,3 +1116,21 @@ class BaseDriver(object): Connection class constructor. """ return {} + + def __getstate__(self): + # Note: "connection" attribute contains many unpicklable objects which + # is why we only store attributes which can be used to re-create the + # instance later when unpickling. + state = self.__dict__.copy() + del state['connection'] + return state + + def __setstate__(self, state): + for key, value in state.items(): + setattr(self, key, value) + + # Re-create connection class instance + args = self._connection_cls_args + kwargs = self._connection_cls_kwargs + self.connection = self.connectionCls(*args, **kwargs) + self.connection.connect() http://git-wip-us.apache.org/repos/asf/libcloud/blob/e9a2e6db/libcloud/test/common/test_pickling.py ---------------------------------------------------------------------- diff --git a/libcloud/test/common/test_pickling.py b/libcloud/test/common/test_pickling.py new file mode 100644 index 0000000..eda31e9 --- /dev/null +++ b/libcloud/test/common/test_pickling.py @@ -0,0 +1,72 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys +import pickle + +from libcloud.compute.drivers.rackspace import RackspaceNodeDriver +from libcloud.compute.drivers.digitalocean import DigitalOceanNodeDriver +from libcloud.test.compute.test_digitalocean_v2 import DigitalOceanMockHttp +from libcloud.test import unittest +from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS + + +class PickleDriverClassTestCase(unittest.TestCase): + + def setUp(self): + DigitalOceanNodeDriver.connectionCls.conn_classes = \ + (None, DigitalOceanMockHttp) + DigitalOceanMockHttp.type = None + self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v2_PARAMS) + + def test_pickle_and_unpickle_driver_instance(self): + driver = RackspaceNodeDriver('testkey', 'testsecret', region='iad') + + self.assertEqual(driver.key, 'testkey') + self.assertEqual(driver.secret, 'testsecret') + self.assertTrue(driver.connection) + self.assertEqual(driver.connection.user_id, 'testkey') + self.assertEqual(driver.connection.key, 'testsecret') + + pickled = pickle.dumps(driver) + unpickled = pickle.loads(pickled) + + self.assertEqual(unpickled.key, 'testkey') + self.assertEqual(unpickled.secret, 'testsecret') + self.assertTrue(unpickled.connection) + self.assertEqual(unpickled.connection.user_id, 'testkey') + self.assertEqual(unpickled.connection.key, 'testsecret') + + def test_pickle_and_unpickle_node_instance(self): + node = self.driver.list_nodes()[0] + + self.assertEqual(node.name, 'example.com') + self.assertEqual(node.public_ips, ['104.236.32.182']) + self.assertEqual(node.extra['image']['id'], 6918990) + self.assertEqual(node.extra['size_slug'], '512mb') + self.assertEqual(node.driver.name, self.driver.name) + + pickled = pickle.dumps(node) + unpickled = pickle.loads(pickled) + + self.assertEqual(unpickled.name, 'example.com') + self.assertEqual(unpickled.public_ips, ['104.236.32.182']) + self.assertEqual(unpickled.extra['image']['id'], 6918990) + self.assertEqual(unpickled.extra['size_slug'], '512mb') + self.assertEqual(unpickled.driver.name, self.driver.name) + + +if __name__ == '__main__': + sys.exit(unittest.main())
