Skip to content

Commit ef225f9

Browse files
committed
Add support for network Flavor
There is an existing feature in neutron for creating flavors for networks. Partially-Implements: blueprint neutron-client-flavors Change-Id: I57ad6a26cf70f314c594a8440da9418f29395e27
1 parent 809f2fa commit ef225f9

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-0
lines changed

doc/source/users/resources/network/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Network Resources
88
v2/agent
99
v2/availability_zone
1010
v2/extension
11+
v2/flavor
1112
v2/floating_ip
1213
v2/health_monitor
1314
v2/listener
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
openstack.network.v2.flavor
2+
===========================
3+
4+
.. automodule:: openstack.network.v2.flavor
5+
6+
The Flavor Class
7+
----------------
8+
9+
The ``Flavor`` class inherits from :class:`~openstack.resource.Resource`.
10+
11+
.. autoclass:: openstack.network.v2.flavor.Flavor
12+
:members:

openstack/network/v2/_proxy.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from openstack.network.v2 import agent as _agent
1515
from openstack.network.v2 import availability_zone
1616
from openstack.network.v2 import extension
17+
from openstack.network.v2 import flavor as _flavor
1718
from openstack.network.v2 import floating_ip as _floating_ip
1819
from openstack.network.v2 import health_monitor as _health_monitor
1920
from openstack.network.v2 import listener as _listener
@@ -822,6 +823,86 @@ def update_network(self, network, **attrs):
822823
"""
823824
return self._update(_network.Network, network, **attrs)
824825

826+
def create_flavor(self, **attrs):
827+
"""Create a new network service flavor from attributes
828+
829+
:param dict attrs: Keyword arguments which will be used to create
830+
a :class:`~openstack.network.v2.flavor.Flavor`,
831+
comprised of the properties on the Flavor class.
832+
833+
:returns: The results of flavor creation
834+
:rtype: :class:`~openstack.network.v2.flavor.Flavor`
835+
"""
836+
return self._create(_flavor.Flavor, **attrs)
837+
838+
def delete_flavor(self, flavor, ignore_missing=True):
839+
"""Delete a network service flavor
840+
841+
:param flavor:
842+
The value can be either the ID of a flavor or a
843+
:class:`~openstack.network.v2.flavor.Flavor` instance.
844+
:param bool ignore_missing: When set to ``False``
845+
:class:`~openstack.exceptions.ResourceNotFound` will be
846+
raised when the flavor does not exist.
847+
When set to ``True``, no exception will be set when
848+
attempting to delete a nonexistent flavor.
849+
850+
:returns: ``None``
851+
"""
852+
self._delete(_flavor.Flavor, flavor, ignore_missing=ignore_missing)
853+
854+
def find_flavor(self, name_or_id, ignore_missing=True):
855+
"""Find a single network service flavor
856+
857+
:param name_or_id: The name or ID of a flavor.
858+
:param bool ignore_missing: When set to ``False``
859+
:class:`~openstack.exceptions.ResourceNotFound` will be
860+
raised when the resource does not exist.
861+
When set to ``True``, None will be returned when
862+
attempting to find a nonexistent resource.
863+
:returns: One :class:`~openstack.network.v2.flavor.Flavor` or None
864+
"""
865+
return self._find(_flavor.Flavor, name_or_id,
866+
ignore_missing=ignore_missing)
867+
868+
def get_flavor(self, flavor):
869+
"""Get a single network service flavor
870+
871+
:param flavor:
872+
The value can be the ID of a flavor or a
873+
:class:`~openstack.network.v2.flavor.Flavor` instance.
874+
875+
:returns: One :class:`~openstack.network.v2.flavor.Flavor`
876+
:raises: :class:`~openstack.exceptions.ResourceNotFound`
877+
when no resource can be found.
878+
"""
879+
return self._get(_flavor.Flavor, flavor)
880+
881+
def update_flavor(self, flavor, **attrs):
882+
"""Update a network service flavor
883+
884+
:param flavor:
885+
Either the id of a flavor or a
886+
:class:`~openstack.network.v2.flavor.Flavor` instance.
887+
:attrs kwargs: The attributes to update on the flavor represented
888+
by ``value``.
889+
890+
:returns: The updated flavor
891+
:rtype: :class:`~openstack.network.v2.flavor.Flavor`
892+
"""
893+
return self._update(_flavor.Flavor, flavor, **attrs)
894+
895+
def flavors(self, **query):
896+
"""Return a generator of network service flavors
897+
898+
:param kwargs \*\*query: Optional query parameters to be sent to limit
899+
the resources being returned.
900+
901+
:returns: A generator of flavor objects
902+
:rtype: :class:`~openstack.network.v2.flavor.Flavor`
903+
"""
904+
return self._list(_flavor.Flavor, paginated=True, **query)
905+
825906
def find_network_ip_availability(self, name_or_id, ignore_missing=True):
826907
"""Find IP availability of a network
827908

openstack/network/v2/flavor.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
from openstack.network import network_service
14+
from openstack import resource
15+
16+
17+
class Flavor(resource.Resource):
18+
resource_key = 'flavor'
19+
resources_key = 'flavors'
20+
base_path = '/flavors'
21+
service = network_service.NetworkService()
22+
23+
# capabilities
24+
allow_create = True
25+
allow_retrieve = True
26+
allow_update = True
27+
allow_delete = True
28+
allow_list = True
29+
30+
# properties
31+
#: description for the flavor
32+
description = resource.prop('description')
33+
#: Sets enabled flag
34+
is_enabled = resource.prop('enabled', type=bool)
35+
#: The name of the flavor
36+
name = resource.prop('name')
37+
#: The owner project ID
38+
project_id = resource.prop('tenant_id')
39+
#: Service type to which the flavor applies
40+
service_type = resource.prop('service_type')
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import uuid
14+
15+
from openstack.network.v2 import flavor
16+
from openstack.tests.functional import base
17+
18+
19+
class TestFlavor(base.BaseFunctionalTest):
20+
21+
FLAVOR_NAME = uuid.uuid4().hex
22+
UPDATE_NAME = "UPDATED-NAME"
23+
SERVICE_TYPE = "FLAVORS"
24+
ID = None
25+
26+
@classmethod
27+
def setUpClass(cls):
28+
super(TestFlavor, cls).setUpClass()
29+
flavors = cls.conn.network.create_flavor(name=cls.FLAVOR_NAME,
30+
service_type=cls.SERVICE_TYPE)
31+
assert isinstance(flavors, flavor.Flavor)
32+
cls.assertIs(cls.FLAVOR_NAME, flavors.name)
33+
cls.assertIs(cls.SERVICE_TYPE, flavors.service_type)
34+
35+
cls.ID = flavors.id
36+
37+
@classmethod
38+
def tearDownClass(cls):
39+
flavors = cls.conn.network.delete_flavor(cls.ID, ignore_missing=True)
40+
cls.assertIs(None, flavors)
41+
42+
def test_find(self):
43+
flavors = self.conn.network.find_flavor(self.FLAVOR_NAME)
44+
self.assertEqual(self.ID, flavors.id)
45+
46+
def test_get(self):
47+
flavors = self.conn.network.get_flavor(self.ID)
48+
self.assertEqual(self.FLAVOR_NAME, flavors.name)
49+
self.assertEqual(self.ID, flavors.id)
50+
51+
def test_list(self):
52+
names = [f.name for f in self.conn.network.flavors()]
53+
self.assertIn(self.FLAVOR_NAME, names)
54+
55+
def test_update(self):
56+
flavor = self.conn.network.update_flavor(self.ID,
57+
name=self.UPDATE_NAME)
58+
self.assertEqual(self.UPDATE_NAME, flavor.name)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import testtools
14+
15+
from openstack.network.v2 import flavor
16+
17+
IDENTIFIER = 'IDENTIFIER'
18+
EXAMPLE_WITH_OPTIONAL = {
19+
'name': 'test-flavor',
20+
'service_type': 'VPN',
21+
'tenant_id': '5',
22+
'description': 'VPN flavor',
23+
'enabled': True,
24+
}
25+
26+
EXAMPLE = {
27+
'name': 'test-flavor',
28+
'service_type': 'VPN',
29+
}
30+
31+
32+
class TestFlavor(testtools.TestCase):
33+
def test_basic(self):
34+
flavors = flavor.Flavor()
35+
self.assertEqual('flavor', flavors.resource_key)
36+
self.assertEqual('flavors', flavors.resources_key)
37+
self.assertEqual('/flavors', flavors.base_path)
38+
self.assertEqual('network', flavors.service.service_type)
39+
self.assertTrue(flavors.allow_create)
40+
self.assertTrue(flavors.allow_retrieve)
41+
self.assertTrue(flavors.allow_update)
42+
self.assertTrue(flavors.allow_delete)
43+
self.assertTrue(flavors.allow_list)
44+
45+
def test_make_it(self):
46+
flavors = flavor.Flavor(EXAMPLE)
47+
self.assertEqual(EXAMPLE['name'], flavors.name)
48+
self.assertEqual(EXAMPLE['service_type'], flavors.service_type)
49+
50+
def test_make_it_with_optional(self):
51+
flavors = flavor.Flavor(EXAMPLE_WITH_OPTIONAL)
52+
self.assertEqual(EXAMPLE_WITH_OPTIONAL['name'], flavors.name)
53+
self.assertEqual(EXAMPLE_WITH_OPTIONAL['service_type'],
54+
flavors.service_type)
55+
self.assertEqual(EXAMPLE_WITH_OPTIONAL['tenant_id'],
56+
flavors.tenant_id)
57+
self.assertEqual(EXAMPLE_WITH_OPTIONAL['description'],
58+
flavors.description)
59+
self.assertEqual(EXAMPLE_WITH_OPTIONAL['enabled'], flavors.is_enabled)

openstack/tests/unit/network/v2/test_proxy.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from openstack.network.v2 import agent
1919
from openstack.network.v2 import availability_zone
2020
from openstack.network.v2 import extension
21+
from openstack.network.v2 import flavor
2122
from openstack.network.v2 import floating_ip
2223
from openstack.network.v2 import health_monitor
2324
from openstack.network.v2 import listener
@@ -297,6 +298,25 @@ def test_networks(self):
297298
def test_network_update(self):
298299
self.verify_update(self.proxy.update_network, network.Network)
299300

301+
def test_flavor_create_attrs(self):
302+
self.verify_create(self.proxy.create_flavor, flavor.Flavor)
303+
304+
def test_flavor_delete(self):
305+
self.verify_delete(self.proxy.delete_flavor, flavor.Flavor, True)
306+
307+
def test_flavor_find(self):
308+
self.verify_find(self.proxy.find_flavor, flavor.Flavor)
309+
310+
def test_flavor_get(self):
311+
self.verify_get(self.proxy.get_flavor, flavor.Flavor)
312+
313+
def test_flavor_update(self):
314+
self.verify_update(self.proxy.update_flavor, flavor.Flavor)
315+
316+
def test_flavors(self):
317+
self.verify_list(self.proxy.flavors, flavor.Flavor,
318+
paginated=True)
319+
300320
def test_network_ip_availability_find(self):
301321
self.verify_find(self.proxy.find_network_ip_availability,
302322
network_ip_availability.NetworkIPAvailability)

0 commit comments

Comments
 (0)