diff --git a/openstack/object_store/v1/_base.py b/openstack/object_store/v1/_base.py new file mode 100644 index 00000000..9459929d --- /dev/null +++ b/openstack/object_store/v1/_base.py @@ -0,0 +1,39 @@ +# Licensed 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. + +from openstack.object_store import object_store_service +from openstack import resource + + +class BaseResource(resource.Resource): + service = object_store_service.ObjectStoreService() + + @classmethod + def update_by_id(cls, session, resource_id, attrs, path_args=None): + """Update a Resource with the given attributes. + + :param session: The session to use for making this request. + :type session: :class:`~openstack.session.Session` + :param resource_id: This resource's identifier, if needed by + the request. The default is ``None``. + :param dict attrs: The attributes to be sent in the body + of the request. + :param dict path_args: This parameter is sent by the base + class but is ignored for this method. + + :return: A ``dict`` representing the response headers. + """ + url = cls._get_url(None, resource_id) + headers = attrs.get(resource.HEADERS, dict()) + return session.post(url, service=cls.service, accept=None, + headers=headers).headers diff --git a/openstack/object_store/v1/_proxy.py b/openstack/object_store/v1/_proxy.py index 008545ea..95eea45b 100644 --- a/openstack/object_store/v1/_proxy.py +++ b/openstack/object_store/v1/_proxy.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from openstack.object_store.v1 import account as _account from openstack.object_store.v1 import container as _container from openstack.object_store.v1 import obj as _obj from openstack import proxy @@ -21,22 +22,22 @@ class Proxy(proxy.BaseProxy): """Get metatdata for this account :rtype: - :class:`~openstack.object_store.v1.container.Container` + :class:`~openstack.object_store.v1.account.Account` """ - return self._head(_container.Container) + return self._head(_account.Account) - def set_account_metadata(self, container): + def set_account_metadata(self, account): """Set metatdata for this account. - :param container: Account metadata specified on a - :class:`~openstack.object_store.v1.container.Container` object + :param account: Account metadata specified on a + :class:`~openstack.object_store.v1.account.Account` object to be sent to the server. - :type container: - :class:`~openstack.object_store.v1.container.Container` + :type account: + :class:`~openstack.object_store.v1.account.Account` :rtype: ``None`` """ - container.update(self.session) + account.update(self.session) def containers(self, **query): """Obtain Container objects for this account. diff --git a/openstack/object_store/v1/account.py b/openstack/object_store/v1/account.py new file mode 100644 index 00000000..d6a16852 --- /dev/null +++ b/openstack/object_store/v1/account.py @@ -0,0 +1,38 @@ +# Licensed 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. + +from openstack.object_store.v1 import _base +from openstack import resource + + +class Account(_base.BaseResource): + base_path = "/" + + allow_retrieve = True + allow_update = True + allow_head = True + + #: The total number of bytes that are stored in Object Storage for + #: the account. + account_bytes_used = resource.header("x-account-bytes-used", type=int) + #: The number of containers. + account_container_count = resource.header("x-account-container-count", + type=int) + #: The number of objects in the account. + account_object_count = resource.header("x-account-object-count", type=int) + #: The secret key value for temporary URLs. If not set, + #: this header is not returned by this operation. + meta_temp_url_key = resource.header("x-account-meta-temp-url-key") + #: A second secret key value for temporary URLs. If not set, + #: this header is not returned by this operation. + meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2") diff --git a/openstack/object_store/v1/container.py b/openstack/object_store/v1/container.py index aa730853..3e431016 100644 --- a/openstack/object_store/v1/container.py +++ b/openstack/object_store/v1/container.py @@ -11,13 +11,12 @@ # License for the specific language governing permissions and limitations # under the License. -from openstack.object_store import object_store_service +from openstack.object_store.v1 import _base from openstack import resource -class Container(resource.Resource): +class Container(_base.BaseResource): base_path = "/" - service = object_store_service.ObjectStoreService() id_attribute = "name" allow_create = True @@ -27,22 +26,6 @@ class Container(resource.Resource): allow_list = True allow_head = True - # Account data (when id=None) - #: The total number of bytes that are stored in Object Storage for - #: the account. - account_bytes_used = resource.header("x-account-bytes-used", type=int) - #: The number of containers. - account_container_count = resource.header("x-account-container-count", - type=int) - #: The number of objects in the account. - account_object_count = resource.header("x-account-object-count", type=int) - #: The secret key value for temporary URLs. If not set, - #: this header is not returned by this operation. - meta_temp_url_key = resource.header("x-account-meta-temp-url-key") - #: A second secret key value for temporary URLs. If not set, - #: this header is not returned by this operation. - meta_temp_url_key_2 = resource.header("x-account-meta-temp-url-key-2") - # Container body data (when id=None) #: The name of the container. name = resource.prop("name") @@ -97,29 +80,9 @@ class Container(resource.Resource): #: has a copy of the object before any data is sent. if_none_match = resource.header("if-none-match") - @classmethod - def update_by_id(cls, session, resource_id, attrs, path_args=None): - """Update a Container with the given attributes. - - :param session: The session to use for making this request. - :type session: :class:`~openstack.session.Session` - :param resource_id: This resource's identifier, if needed by - the request. The default is ``None``. - :param dict attrs: The attributes to be sent in the body - of the request. - :param dict path_args: This parameter is sent by the base - class but is ignored for this method. - - :return: A ``dict`` representing the response headers. - """ - url = cls._get_url(None, resource_id) - headers = attrs.get(resource.HEADERS, dict()) - return session.post(url, service=cls.service, accept=None, - headers=headers).headers - @classmethod def create_by_id(cls, session, attrs, resource_id=None): - """Create a Container from its attributes. + """Create a Resource from its attributes. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` @@ -136,13 +99,12 @@ class Container(resource.Resource): headers=headers).headers def create(self, session): - """Create a Container from this instance. + """Create a Resource from this instance. :param session: The session to use for making this request. :type session: :class:`~openstack.session.Session` - :return: This :class:`~openstack.object_store.v1.container.Container` - instance. + :return: This instance. """ resp = self.create_by_id(session, self._attrs, self.id) self.set_headers(resp) diff --git a/openstack/tests/unit/object_store/v1/test_account.py b/openstack/tests/unit/object_store/v1/test_account.py new file mode 100644 index 00000000..41adc86c --- /dev/null +++ b/openstack/tests/unit/object_store/v1/test_account.py @@ -0,0 +1,54 @@ +# Licensed 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 testtools + +from openstack.object_store.v1 import account + + +CONTAINER_NAME = "mycontainer" + +ACCOUNT_EXAMPLE = { + 'content-length': '0', + 'accept-ranges': 'bytes', + 'date': 'Sat, 05 Jul 2014 19:17:40 GMT', + 'x-account-bytes-used': '12345', + 'x-account-container-count': '678', + 'content-type': 'text/plain; charset=utf-8', + 'x-account-object-count': '98765' +} + + +class TestAccount(testtools.TestCase): + + def test_basic(self): + sot = account.Account.new(**ACCOUNT_EXAMPLE) + self.assertIsNone(sot.resources_key) + self.assertIsNone(sot.id) + self.assertEqual('/', sot.base_path) + self.assertEqual('object-store', sot.service.service_type) + self.assertTrue(sot.allow_update) + self.assertTrue(sot.allow_head) + self.assertTrue(sot.allow_retrieve) + self.assertFalse(sot.allow_delete) + self.assertFalse(sot.allow_list) + self.assertFalse(sot.allow_create) + + def test_make_it(self): + sot = account.Account.new(**{'headers': ACCOUNT_EXAMPLE}) + self.assertIsNone(sot.id) + self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-bytes-used']), + sot.account_bytes_used) + self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-container-count']), + sot.account_container_count) + self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-object-count']), + sot.account_object_count) diff --git a/openstack/tests/unit/object_store/v1/test_container.py b/openstack/tests/unit/object_store/v1/test_container.py index ff666c94..bd60072e 100644 --- a/openstack/tests/unit/object_store/v1/test_container.py +++ b/openstack/tests/unit/object_store/v1/test_container.py @@ -18,17 +18,6 @@ from openstack.object_store.v1 import container CONTAINER_NAME = "mycontainer" -ACCOUNT_EXAMPLE = { - 'content-length': '0', - 'accept-ranges': 'bytes', - 'id': 'tx4272aa0d6e1e4f8f971f8-0053b84f54', - 'date': 'Sat, 05 Jul 2014 19:17:40 GMT', - 'x-account-bytes-used': '12345', - 'x-account-container-count': '678', - 'content-type': 'text/plain; charset=utf-8', - 'x-account-object-count': '98765' -} - CONT_EXAMPLE = { "count": 999, "bytes": 12345, @@ -64,19 +53,6 @@ LIST_EXAMPLE = [ ] -class TestAccount(testtools.TestCase): - - def test_make_it(self): - sot = container.Container.new(**{'headers': ACCOUNT_EXAMPLE}) - self.assertIsNone(sot.id) - self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-bytes-used']), - sot.account_bytes_used) - self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-container-count']), - sot.account_container_count) - self.assertEqual(int(ACCOUNT_EXAMPLE['x-account-object-count']), - sot.account_object_count) - - class TestContainer(testtools.TestCase): def setUp(self): diff --git a/openstack/tests/unit/object_store/v1/test_proxy.py b/openstack/tests/unit/object_store/v1/test_proxy.py index 7ba82988..aa38a47e 100644 --- a/openstack/tests/unit/object_store/v1/test_proxy.py +++ b/openstack/tests/unit/object_store/v1/test_proxy.py @@ -14,6 +14,7 @@ import mock import six from openstack.object_store.v1 import _proxy +from openstack.object_store.v1 import account from openstack.object_store.v1 import container from openstack.object_store.v1 import obj from openstack import session @@ -30,7 +31,7 @@ class TestObjectStoreProxy(test_proxy_base.TestProxyBase): self.proxy = _proxy.Proxy(self.session) def test_account_metadata_get(self): - self.verify_head(self.proxy.get_account_metadata, container.Container) + self.verify_head(self.proxy.get_account_metadata, account.Account) def test_container_metadata_get(self): self.verify_head(self.proxy.get_container_metadata,