Additions for flavor access requests

* Added functions to flavors client for flavor access requests
* Added flavor access models
* Added metatests for flavor access models

Change-Id: Id54afed0b39050b8cec6cedae57d86a04393e4fa
This commit is contained in:
Daryl Walleck 2013-11-14 00:44:50 -06:00
parent c2e5c781b2
commit d237335a5a
3 changed files with 211 additions and 0 deletions

View File

@ -21,6 +21,8 @@ from cloudcafe.compute.flavors_api.models.flavor import \
Flavor, CreateFlavor, Flavors, FlavorMins
from cloudcafe.compute.flavors_api.models.flavor_extra_specs import \
FlavorExtraSpecs
from cloudcafe.compute.flavors_api.models.flavor_access import (
AddTenantFlavorAccess, FlavorAccessList, RemoveTenantFlavorAccess)
class FlavorsClient(AutoMarshallingRestClient):
@ -151,3 +153,30 @@ class FlavorsClient(AutoMarshallingRestClient):
response_entity_type=FlavorExtraSpecs,
requestslib_kwargs=requestslib_kwargs)
return response
def list_flavor_access(self, flavor_id, requestslib_kwargs=None):
url = '{base_url}/flavors/{flavor_id}/os-flavor-access'.format(
base_url=self.url, flavor_id=flavor_id)
response = self.request(
'GET', url, response_entity_type=FlavorAccessList,
requestslib_kwargs=requestslib_kwargs)
return response
def add_tenant_access(self, tenant, flavor_id, requestslib_kwargs=None):
request = AddTenantFlavorAccess(tenant=tenant)
url = '{base_url}/flavors/{flavor_id}/action'.format(
base_url=self.url, flavor_id=flavor_id)
response = self.request(
'POST', url, response_entity_type=FlavorAccessList,
request_entity=request, requestslib_kwargs=requestslib_kwargs)
return response
def remove_tenant_access(self, tenant, flavor_id,
requestslib_kwargs=None):
request = RemoveTenantFlavorAccess(tenant=tenant)
url = '{base_url}/flavors/{flavor_id}/action'.format(
base_url=self.url, flavor_id=flavor_id)
response = self.request(
'DELETE', url, response_entity_type=FlavorAccessList,
request_entity=request, requestslib_kwargs=requestslib_kwargs)
return response

View File

@ -0,0 +1,116 @@
"""
Copyright 2013 Rackspace
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 json
import xml.etree.ElementTree as ET
from cafe.engine.models.base import AutoMarshallingModel
from cafe.engine.models.base import AutoMarshallingListModel
from cloudcafe.compute.common.constants import Constants
from cloudcafe.compute.common.equality_tools import EqualityTools
class FlavorAccess(AutoMarshallingModel):
def __init__(self, flavor_id=None, tenant_id=None):
super(FlavorAccess, self).__init__()
self.flavor_id = flavor_id
self.tenant_id = tenant_id
@classmethod
def _json_to_obj(cls, json_dict):
access = FlavorAccess(flavor_id=json_dict.get('flavor_id'),
tenant_id=json_dict.get('tenant_id'))
return access
@classmethod
def _xml_to_obj(cls, element):
access_dict = element.attrib
access = FlavorAccess(flavor_id=access_dict.get('flavor_id'),
tenant_id=access_dict.get('tenant_id'))
return access
def __eq__(self, other):
return EqualityTools.are_objects_equal(self, other)
def __ne__(self, other):
return not self == other
class FlavorAccessList(AutoMarshallingListModel):
@classmethod
def _json_to_obj(cls, serialized_str):
json_dict = json.loads(serialized_str)
return cls._list_to_obj(json_dict.get('flavor_access'))
@classmethod
def _list_to_obj(cls, access_dict_list):
access_list = FlavorAccessList()
for flavor_dict in access_dict_list:
access = FlavorAccess._json_to_obj(flavor_dict)
access_list.append(access)
return access_list
@classmethod
def _xml_to_obj(cls, serialized_str):
element = ET.fromstring(serialized_str)
return cls._xml_list_to_obj(element.findall('access'))
@classmethod
def _xml_list_to_obj(cls, xml_list):
flavors = FlavorAccessList()
for ele in xml_list:
flavors.append(FlavorAccess._xml_to_obj(ele))
return flavors
class AddTenantFlavorAccess(AutoMarshallingModel):
def __init__(self, tenant=None):
super(AddTenantFlavorAccess, self).__init__()
self.tenant = tenant
def _obj_to_json(self):
ret = {'addTenantAccess': {'tenant': self.tenant}}
return json.dumps(ret)
def _obj_to_xml(self):
xml = Constants.XML_HEADER
element = ET.Element('addTenantAccess')
element.set('xmlns', Constants.XML_API_NAMESPACE)
element.set('tenant', self.tenant)
xml += ET.tostring(element)
return xml
class RemoveTenantFlavorAccess(AutoMarshallingModel):
def __init__(self, tenant=None):
super(RemoveTenantFlavorAccess, self).__init__()
self.tenant = tenant
def _obj_to_json(self):
ret = {'removeTenantAccess': {'tenant': self.tenant}}
return json.dumps(ret)
def _obj_to_xml(self):
xml = Constants.XML_HEADER
element = ET.Element('removeTenantAccess')
element.set('xmlns', Constants.XML_API_NAMESPACE)
element.set('tenant', self.tenant)
xml += ET.tostring(element)
return xml

View File

@ -0,0 +1,66 @@
"""
Copyright 2013 Rackspace
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 unittest2 as unittest
from cloudcafe.compute.flavors_api.models.flavor_access \
import FlavorAccess, FlavorAccessList
class FlavorAccessModelTest(object):
def test_flavor_access_entries(self):
first_entry = FlavorAccess(flavor_id='42', tenant_id='user1')
second_entry = FlavorAccess(flavor_id='84', tenant_id='user2')
self.assertIn(first_entry, self.access_list)
self.assertIn(second_entry, self.access_list)
class FlavorAccessXMLTest(unittest.TestCase, FlavorAccessModelTest):
@classmethod
def setUpClass(cls):
cls.access_xml = \
"""
<flavor_access>
<access tenant_id="user1" flavor_id="42"/>
<access tenant_id="user2" flavor_id="84"/>
</flavor_access>
"""
cls.access_list = FlavorAccessList.deserialize(cls.access_xml, 'xml')
class FlavorAccessJSONTest(unittest.TestCase, FlavorAccessModelTest):
@classmethod
def setUpClass(cls):
cls.access_json = \
"""
{
"flavor_access": [
{
"flavor_id": "42",
"tenant_id": "user1"
},
{
"flavor_id": "84",
"tenant_id": "user2"
}
]
}
"""
cls.access_list = FlavorAccessList.deserialize(cls.access_json, 'json')