blob: c7ed044647407744254861e2be6d412fc50eedcf [file] [log] [blame]
dwallecke62b9f02012-10-10 23:34:42 -05001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
ZhiQiang Fan39f97222013-09-20 04:49:44 +08003# Copyright 2012 OpenStack Foundation
dwallecke62b9f02012-10-10 23:34:42 -05004# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Tiago Melloeda03b52012-08-22 23:47:29 -030018import urllib
19
20from lxml import etree
21
22from tempest.common.rest_client import RestClientXML
dwallecke62b9f02012-10-10 23:34:42 -050023from tempest.services.compute.xml.common import Document
24from tempest.services.compute.xml.common import Element
25from tempest.services.compute.xml.common import xml_to_json
26from tempest.services.compute.xml.common import XMLNS_11
Tiago Melloeda03b52012-08-22 23:47:29 -030027
28
29XMLNS_OS_FLV_EXT_DATA = \
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +053030 "http://docs.openstack.org/compute/ext/flavor_extra_data/api/v1.1"
31XMLNS_OS_FLV_ACCESS = \
32 "http://docs.openstack.org/compute/ext/flavor_access/api/v1.1"
Tiago Melloeda03b52012-08-22 23:47:29 -030033
34
35class FlavorsClientXML(RestClientXML):
36
37 def __init__(self, config, username, password, auth_url, tenant_name=None):
38 super(FlavorsClientXML, self).__init__(config, username, password,
39 auth_url, tenant_name)
40 self.service = self.config.compute.catalog_type
41
42 def _format_flavor(self, f):
43 flavor = {'links': []}
44 for k, v in f.items():
45 if k == 'link':
46 flavor['links'].append(v)
47 continue
48
49 if k == '{%s}ephemeral' % XMLNS_OS_FLV_EXT_DATA:
50 k = 'OS-FLV-EXT-DATA:ephemeral'
51
Aditi Raveeshccfa6532013-08-19 17:11:05 +053052 if k == 'extra_specs':
Aarti Kriplanic04a0fc2013-08-06 05:10:49 -050053 k = 'OS-FLV-WITH-EXT-SPECS:extra_specs'
54 flavor[k] = dict(v)
55 continue
56
Tiago Melloeda03b52012-08-22 23:47:29 -030057 try:
58 v = int(v)
59 except ValueError:
60 try:
61 v = float(v)
62 except ValueError:
63 pass
64
65 flavor[k] = v
66
67 return flavor
68
69 def _parse_array(self, node):
70 return [self._format_flavor(xml_to_json(x)) for x in node]
71
72 def _list_flavors(self, url, params):
Matthew Treinish26dd0fa2012-12-04 17:14:37 -050073 if params:
Tiago Melloeda03b52012-08-22 23:47:29 -030074 url += "?%s" % urllib.urlencode(params)
75
76 resp, body = self.get(url, self.headers)
77 flavors = self._parse_array(etree.fromstring(body))
78 return resp, flavors
79
80 def list_flavors(self, params=None):
81 url = 'flavors'
82 return self._list_flavors(url, params)
83
84 def list_flavors_with_detail(self, params=None):
85 url = 'flavors/detail'
86 return self._list_flavors(url, params)
87
88 def get_flavor_details(self, flavor_id):
89 resp, body = self.get("flavors/%s" % str(flavor_id), self.headers)
90 body = xml_to_json(etree.fromstring(body))
91 flavor = self._format_flavor(body)
92 return resp, flavor
93
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +053094 def create_flavor(self, name, ram, vcpus, disk, flavor_id, **kwargs):
Sean Daguef237ccb2013-01-04 15:19:14 -050095 """Creates a new flavor or instance type."""
Tiago Melloeda03b52012-08-22 23:47:29 -030096 flavor = Element("flavor",
97 xmlns=XMLNS_11,
98 ram=ram,
99 vcpus=vcpus,
100 disk=disk,
101 id=flavor_id,
Tiago Melloeda03b52012-08-22 23:47:29 -0300102 name=name)
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +0530103 if kwargs.get('rxtx'):
104 flavor.add_attr('rxtx_factor', kwargs.get('rxtx'))
105 if kwargs.get('swap'):
106 flavor.add_attr('swap', kwargs.get('swap'))
107 if kwargs.get('ephemeral'):
108 flavor.add_attr('OS-FLV-EXT-DATA:ephemeral',
109 kwargs.get('ephemeral'))
110 if kwargs.get('is_public'):
111 flavor.add_attr('os-flavor-access:is_public',
112 kwargs.get('is_public'))
Tiago Melloeda03b52012-08-22 23:47:29 -0300113 flavor.add_attr('xmlns:OS-FLV-EXT-DATA', XMLNS_OS_FLV_EXT_DATA)
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +0530114 flavor.add_attr('xmlns:os-flavor-access', XMLNS_OS_FLV_ACCESS)
Tiago Melloeda03b52012-08-22 23:47:29 -0300115 resp, body = self.post('flavors', str(Document(flavor)), self.headers)
116 body = xml_to_json(etree.fromstring(body))
117 flavor = self._format_flavor(body)
118 return resp, flavor
119
120 def delete_flavor(self, flavor_id):
Sean Daguef237ccb2013-01-04 15:19:14 -0500121 """Deletes the given flavor."""
Tiago Melloeda03b52012-08-22 23:47:29 -0300122 return self.delete("flavors/%s" % str(flavor_id), self.headers)
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +0530123
124 def is_resource_deleted(self, id):
Attila Fazekasa8b5fe72013-08-01 16:59:06 +0200125 # Did not use get_flavor_details(id) for verification as it gives
126 # 200 ok even for deleted id. LP #981263
127 # we can remove the loop here and use get by ID when bug gets sortedout
rajalakshmi-ganesanf344cc32012-12-31 20:02:27 +0530128 resp, flavors = self.list_flavors_with_detail()
129 for flavor in flavors:
130 if flavor['id'] == id:
131 return False
132 return True
rajalakshmi-ganesan6d0e7a22012-12-18 20:52:38 +0530133
134 def set_flavor_extra_spec(self, flavor_id, specs):
135 """Sets extra Specs to the mentioned flavor."""
136 extra_specs = Element("extra_specs")
137 for key in specs.keys():
138 extra_specs.add_attr(key, specs[key])
139 resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
140 str(Document(extra_specs)), self.headers)
141 body = xml_to_json(etree.fromstring(body))
142 return resp, body
143
144 def get_flavor_extra_spec(self, flavor_id):
145 """Gets extra Specs of the mentioned flavor."""
146 resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id,
147 self.headers)
148 body = xml_to_json(etree.fromstring(body))
149 return resp, body
150
lijunjbj9feaa212013-10-14 02:11:49 -0500151 def get_flavor_extra_spec_with_key(self, flavor_id, key):
152 """Gets a specified key detail for the mentioned flavor."""
153 resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
154 key), self.headers)
155 body = xml_to_json(etree.fromstring(body))
156 return resp, body
157
rajalakshmi-ganesan6d0e7a22012-12-18 20:52:38 +0530158 def unset_flavor_extra_spec(self, flavor_id, key):
159 """Unsets an extra spec based on the mentioned flavor and key."""
160 return self.delete('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
161 key))
Mitsuhiko Yamazakif5f4da62013-03-29 17:40:03 +0900162
163 def _parse_array_access(self, node):
164 return [xml_to_json(x) for x in node]
165
166 def add_flavor_access(self, flavor_id, tenant_id):
167 """Add flavor access for the specified tenant."""
168 doc = Document()
169 server = Element("addTenantAccess")
170 doc.append(server)
171 server.add_attr("tenant", tenant_id)
172 resp, body = self.post('flavors/%s/action' % str(flavor_id),
173 str(doc), self.headers)
174 body = self._parse_array_access(etree.fromstring(body))
175 return resp, body
176
177 def remove_flavor_access(self, flavor_id, tenant_id):
178 """Remove flavor access from the specified tenant."""
179 doc = Document()
180 server = Element("removeTenantAccess")
181 doc.append(server)
182 server.add_attr("tenant", tenant_id)
183 resp, body = self.post('flavors/%s/action' % str(flavor_id),
184 str(doc), self.headers)
185 body = self._parse_array_access(etree.fromstring(body))
186 return resp, body