Merge "Add network segment create, delete and update support"
This commit is contained in:
@@ -2099,6 +2099,40 @@ class Proxy(proxy.BaseProxy):
|
|||||||
return self._list(_security_group_rule.SecurityGroupRule,
|
return self._list(_security_group_rule.SecurityGroupRule,
|
||||||
paginated=False, **query)
|
paginated=False, **query)
|
||||||
|
|
||||||
|
def create_segment(self, **attrs):
|
||||||
|
"""Create a new segment from attributes
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
BETA: This API is a work in progress and is subject to change.
|
||||||
|
|
||||||
|
:param dict attrs: Keyword arguments which will be used to create
|
||||||
|
a :class:`~openstack.network.v2.segment.Segment`,
|
||||||
|
comprised of the properties on the Segment class.
|
||||||
|
|
||||||
|
:returns: The results of segment creation
|
||||||
|
:rtype: :class:`~openstack.network.v2.segment.Segment`
|
||||||
|
"""
|
||||||
|
return self._create(_segment.Segment, **attrs)
|
||||||
|
|
||||||
|
def delete_segment(self, segment, ignore_missing=True):
|
||||||
|
"""Delete a segment
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
BETA: This API is a work in progress and is subject to change.
|
||||||
|
|
||||||
|
:param segment: The value can be either the ID of a segment or a
|
||||||
|
:class:`~openstack.network.v2.segment.Segment`
|
||||||
|
instance.
|
||||||
|
:param bool ignore_missing: When set to ``False``
|
||||||
|
:class:`~openstack.exceptions.ResourceNotFound` will be
|
||||||
|
raised when the segment does not exist.
|
||||||
|
When set to ``True``, no exception will be set when
|
||||||
|
attempting to delete a nonexistent segment.
|
||||||
|
|
||||||
|
:returns: ``None``
|
||||||
|
"""
|
||||||
|
self._delete(_segment.Segment, segment, ignore_missing=ignore_missing)
|
||||||
|
|
||||||
def find_segment(self, name_or_id, ignore_missing=True):
|
def find_segment(self, name_or_id, ignore_missing=True):
|
||||||
"""Find a single segment
|
"""Find a single segment
|
||||||
|
|
||||||
@@ -2141,6 +2175,7 @@ class Proxy(proxy.BaseProxy):
|
|||||||
:param kwargs \*\*query: Optional query parameters to be sent to limit
|
:param kwargs \*\*query: Optional query parameters to be sent to limit
|
||||||
the resources being returned. Available parameters include:
|
the resources being returned. Available parameters include:
|
||||||
|
|
||||||
|
* name: Name of the segments
|
||||||
* network_id: ID of the network that owns the segments
|
* network_id: ID of the network that owns the segments
|
||||||
* network_type: Network type for the segments
|
* network_type: Network type for the segments
|
||||||
* physical_network: Physical network name for the segments
|
* physical_network: Physical network name for the segments
|
||||||
@@ -2151,6 +2186,23 @@ class Proxy(proxy.BaseProxy):
|
|||||||
"""
|
"""
|
||||||
return self._list(_segment.Segment, paginated=False, **query)
|
return self._list(_segment.Segment, paginated=False, **query)
|
||||||
|
|
||||||
|
def update_segment(self, segment, **attrs):
|
||||||
|
"""Update a segment
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
BETA: This API is a work in progress and is subject to change.
|
||||||
|
|
||||||
|
:param segment: Either the id of a segment or a
|
||||||
|
:class:`~openstack.network.v2.segment.Segment`
|
||||||
|
instance.
|
||||||
|
:attrs kwargs: The attributes to update on the segment represented
|
||||||
|
by ``value``.
|
||||||
|
|
||||||
|
:returns: The update segment
|
||||||
|
:rtype: :class:`~openstack.network.v2.segment.Segment`
|
||||||
|
"""
|
||||||
|
return self._update(_segment.Segment, segment, **attrs)
|
||||||
|
|
||||||
def create_subnet(self, **attrs):
|
def create_subnet(self, **attrs):
|
||||||
"""Create a new subnet from attributes
|
"""Create a new subnet from attributes
|
||||||
|
|
||||||
|
|||||||
@@ -22,24 +22,26 @@ class Segment(resource.Resource):
|
|||||||
service = network_service.NetworkService()
|
service = network_service.NetworkService()
|
||||||
|
|
||||||
# capabilities
|
# capabilities
|
||||||
allow_create = False
|
allow_create = True
|
||||||
allow_retrieve = True
|
allow_retrieve = True
|
||||||
allow_update = False
|
allow_update = True
|
||||||
allow_delete = False
|
allow_delete = True
|
||||||
allow_list = True
|
allow_list = True
|
||||||
|
|
||||||
# TODO(rtheis): Add description and name properties when support
|
|
||||||
# is available.
|
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
|
#: The segment description.
|
||||||
|
description = resource.prop('description')
|
||||||
|
#: The segment name.
|
||||||
|
name = resource.prop('name')
|
||||||
#: The ID of the network associated with this segment.
|
#: The ID of the network associated with this segment.
|
||||||
network_id = resource.prop('network_id')
|
network_id = resource.prop('network_id')
|
||||||
#: The type of network associated with this segment, such as
|
#: The type of network associated with this segment, such as
|
||||||
#: ``flat``, ``gre``, ``vlan`` or ``vxlan``.
|
#: ``flat``, ``geneve``, ``gre``, ``local``, ``vlan`` or ``vxlan``.
|
||||||
network_type = resource.prop('network_type')
|
network_type = resource.prop('network_type')
|
||||||
#: The name of the physical network associated with this segment.
|
#: The name of the physical network associated with this segment.
|
||||||
physical_network = resource.prop('physical_network')
|
physical_network = resource.prop('physical_network')
|
||||||
#: The segmentation ID for this segment. The network type
|
#: The segmentation ID for this segment. The network type
|
||||||
#: defines the segmentation model, VLAN ID for ``vlan`` network type
|
#: defines the segmentation model, VLAN ID for ``vlan`` network type
|
||||||
#: and tunnel ID for ``gre`` and ``vxlan`` network types. *Type: int*
|
#: and tunnel ID for ``geneve``, ``gre`` and ``vxlan`` network types.
|
||||||
|
#: *Type: int*
|
||||||
segmentation_id = resource.prop('segmentation_id', type=int)
|
segmentation_id = resource.prop('segmentation_id', type=int)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import unittest
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openstack.network.v2 import network
|
from openstack.network.v2 import network
|
||||||
@@ -18,8 +17,6 @@ from openstack.network.v2 import segment
|
|||||||
from openstack.tests.functional import base
|
from openstack.tests.functional import base
|
||||||
|
|
||||||
|
|
||||||
# NOTE(rtheis): Routed networks is still a WIP and not enabled by default.
|
|
||||||
@unittest.skip("bp/routed-networks")
|
|
||||||
class TestSegment(base.BaseFunctionalTest):
|
class TestSegment(base.BaseFunctionalTest):
|
||||||
|
|
||||||
NETWORK_NAME = uuid.uuid4().hex
|
NETWORK_NAME = uuid.uuid4().hex
|
||||||
@@ -28,26 +25,32 @@ class TestSegment(base.BaseFunctionalTest):
|
|||||||
SEGMENTATION_ID = None
|
SEGMENTATION_ID = None
|
||||||
NETWORK_ID = None
|
NETWORK_ID = None
|
||||||
SEGMENT_ID = None
|
SEGMENT_ID = None
|
||||||
|
SEGMENT_EXTENSION = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
super(TestSegment, cls).setUpClass()
|
super(TestSegment, cls).setUpClass()
|
||||||
|
|
||||||
|
# NOTE(rtheis): The segment extension is not yet enabled by default.
|
||||||
|
# Skip the tests if not enabled.
|
||||||
|
cls.SEGMENT_EXTENSION = cls.conn.network.find_extension('segment')
|
||||||
|
|
||||||
# Create a network to hold the segment.
|
# Create a network to hold the segment.
|
||||||
net = cls.conn.network.create_network(name=cls.NETWORK_NAME)
|
net = cls.conn.network.create_network(name=cls.NETWORK_NAME)
|
||||||
assert isinstance(net, network.Network)
|
assert isinstance(net, network.Network)
|
||||||
cls.assertIs(cls.NETWORK_NAME, net.name)
|
cls.assertIs(cls.NETWORK_NAME, net.name)
|
||||||
cls.NETWORK_ID = net.id
|
cls.NETWORK_ID = net.id
|
||||||
|
|
||||||
# Get the segment for the network.
|
if cls.SEGMENT_EXTENSION:
|
||||||
for seg in cls.conn.network.segments():
|
# Get the segment for the network.
|
||||||
assert isinstance(seg, segment.Segment)
|
for seg in cls.conn.network.segments():
|
||||||
if cls.NETWORK_ID == seg.network_id:
|
assert isinstance(seg, segment.Segment)
|
||||||
cls.NETWORK_TYPE = seg.network_type
|
if cls.NETWORK_ID == seg.network_id:
|
||||||
cls.PHYSICAL_NETWORK = seg.physical_network
|
cls.NETWORK_TYPE = seg.network_type
|
||||||
cls.SEGMENTATION_ID = seg.segmentation_id
|
cls.PHYSICAL_NETWORK = seg.physical_network
|
||||||
cls.SEGMENT_ID = seg.id
|
cls.SEGMENTATION_ID = seg.segmentation_id
|
||||||
break
|
cls.SEGMENT_ID = seg.id
|
||||||
|
break
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
@@ -55,18 +58,57 @@ class TestSegment(base.BaseFunctionalTest):
|
|||||||
ignore_missing=False)
|
ignore_missing=False)
|
||||||
cls.assertIs(None, sot)
|
cls.assertIs(None, sot)
|
||||||
|
|
||||||
|
def test_create_delete(self):
|
||||||
|
if self.SEGMENT_EXTENSION:
|
||||||
|
sot = self.conn.network.create_segment(
|
||||||
|
description='test description',
|
||||||
|
name='test name',
|
||||||
|
network_id=self.NETWORK_ID,
|
||||||
|
network_type='geneve',
|
||||||
|
segmentation_id=2055,
|
||||||
|
)
|
||||||
|
self.assertIsInstance(sot, segment.Segment)
|
||||||
|
del_sot = self.conn.network.delete_segment(sot.id)
|
||||||
|
self.assertEqual('test description', sot.description)
|
||||||
|
self.assertEqual('test name', sot.name)
|
||||||
|
self.assertEqual(self.NETWORK_ID, sot.network_id)
|
||||||
|
self.assertEqual('geneve', sot.network_type)
|
||||||
|
self.assertIsNone(sot.physical_network)
|
||||||
|
self.assertEqual(2055, sot.segmentation_id)
|
||||||
|
self.assertIsNone(del_sot)
|
||||||
|
else:
|
||||||
|
self.skipTest('Segment extension disabled')
|
||||||
|
|
||||||
def test_find(self):
|
def test_find(self):
|
||||||
sot = self.conn.network.find_segment(self.SEGMENT_ID)
|
if self.SEGMENT_EXTENSION:
|
||||||
self.assertEqual(self.SEGMENT_ID, sot.id)
|
sot = self.conn.network.find_segment(self.SEGMENT_ID)
|
||||||
|
self.assertEqual(self.SEGMENT_ID, sot.id)
|
||||||
|
else:
|
||||||
|
self.skipTest('Segment extension disabled')
|
||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
sot = self.conn.network.get_segment(self.SEGMENT_ID)
|
if self.SEGMENT_EXTENSION:
|
||||||
self.assertEqual(self.SEGMENT_ID, sot.id)
|
sot = self.conn.network.get_segment(self.SEGMENT_ID)
|
||||||
self.assertEqual(self.NETWORK_ID, sot.network_id)
|
self.assertEqual(self.SEGMENT_ID, sot.id)
|
||||||
self.assertEqual(self.NETWORK_TYPE, sot.network_type)
|
self.assertIsNone(sot.name)
|
||||||
self.assertEqual(self.PHYSICAL_NETWORK, sot.physical_network)
|
self.assertEqual(self.NETWORK_ID, sot.network_id)
|
||||||
self.assertEqual(self.SEGMENTATION_ID, sot.segmentation_id)
|
self.assertEqual(self.NETWORK_TYPE, sot.network_type)
|
||||||
|
self.assertEqual(self.PHYSICAL_NETWORK, sot.physical_network)
|
||||||
|
self.assertEqual(self.SEGMENTATION_ID, sot.segmentation_id)
|
||||||
|
else:
|
||||||
|
self.skipTest('Segment extension disabled')
|
||||||
|
|
||||||
def test_list(self):
|
def test_list(self):
|
||||||
ids = [o.id for o in self.conn.network.segments()]
|
if self.SEGMENT_EXTENSION:
|
||||||
self.assertIn(self.SEGMENT_ID, ids)
|
ids = [o.id for o in self.conn.network.segments(name=None)]
|
||||||
|
self.assertIn(self.SEGMENT_ID, ids)
|
||||||
|
else:
|
||||||
|
self.skipTest('Segment extension disabled')
|
||||||
|
|
||||||
|
def test_update(self):
|
||||||
|
if self.SEGMENT_EXTENSION:
|
||||||
|
sot = self.conn.network.update_segment(self.SEGMENT_ID,
|
||||||
|
description='update')
|
||||||
|
self.assertEqual('update', sot.description)
|
||||||
|
else:
|
||||||
|
self.skipTest('Segment extension disabled')
|
||||||
|
|||||||
@@ -725,6 +725,15 @@ class TestNetworkProxy(test_proxy_base.TestProxyBase):
|
|||||||
security_group_rule.SecurityGroupRule,
|
security_group_rule.SecurityGroupRule,
|
||||||
paginated=False)
|
paginated=False)
|
||||||
|
|
||||||
|
def test_segment_create_attrs(self):
|
||||||
|
self.verify_create(self.proxy.create_segment, segment.Segment)
|
||||||
|
|
||||||
|
def test_segment_delete(self):
|
||||||
|
self.verify_delete(self.proxy.delete_segment, segment.Segment, False)
|
||||||
|
|
||||||
|
def test_segment_delete_ignore(self):
|
||||||
|
self.verify_delete(self.proxy.delete_segment, segment.Segment, True)
|
||||||
|
|
||||||
def test_segment_find(self):
|
def test_segment_find(self):
|
||||||
self.verify_find(self.proxy.find_segment, segment.Segment)
|
self.verify_find(self.proxy.find_segment, segment.Segment)
|
||||||
|
|
||||||
@@ -734,6 +743,9 @@ class TestNetworkProxy(test_proxy_base.TestProxyBase):
|
|||||||
def test_segments(self):
|
def test_segments(self):
|
||||||
self.verify_list(self.proxy.segments, segment.Segment, paginated=False)
|
self.verify_list(self.proxy.segments, segment.Segment, paginated=False)
|
||||||
|
|
||||||
|
def test_segment_update(self):
|
||||||
|
self.verify_update(self.proxy.update_segment, segment.Segment)
|
||||||
|
|
||||||
def test_subnet_create_attrs(self):
|
def test_subnet_create_attrs(self):
|
||||||
self.verify_create(self.proxy.create_subnet, subnet.Subnet)
|
self.verify_create(self.proxy.create_subnet, subnet.Subnet)
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ from openstack.network.v2 import segment
|
|||||||
|
|
||||||
IDENTIFIER = 'IDENTIFIER'
|
IDENTIFIER = 'IDENTIFIER'
|
||||||
EXAMPLE = {
|
EXAMPLE = {
|
||||||
|
'description': '1',
|
||||||
'id': IDENTIFIER,
|
'id': IDENTIFIER,
|
||||||
'network_id': '1',
|
'name': '2',
|
||||||
'network_type': 'vxlan',
|
'network_id': '3',
|
||||||
|
'network_type': 'geneve',
|
||||||
'physical_network': None,
|
'physical_network': None,
|
||||||
'segmentation_id': 2,
|
'segmentation_id': 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -32,15 +34,17 @@ class TestSegment(testtools.TestCase):
|
|||||||
self.assertEqual('segments', sot.resources_key)
|
self.assertEqual('segments', sot.resources_key)
|
||||||
self.assertEqual('/segments', sot.base_path)
|
self.assertEqual('/segments', sot.base_path)
|
||||||
self.assertEqual('network', sot.service.service_type)
|
self.assertEqual('network', sot.service.service_type)
|
||||||
self.assertFalse(sot.allow_create)
|
self.assertTrue(sot.allow_create)
|
||||||
self.assertTrue(sot.allow_retrieve)
|
self.assertTrue(sot.allow_retrieve)
|
||||||
self.assertFalse(sot.allow_update)
|
self.assertTrue(sot.allow_update)
|
||||||
self.assertFalse(sot.allow_delete)
|
self.assertTrue(sot.allow_delete)
|
||||||
self.assertTrue(sot.allow_list)
|
self.assertTrue(sot.allow_list)
|
||||||
|
|
||||||
def test_make_it(self):
|
def test_make_it(self):
|
||||||
sot = segment.Segment(EXAMPLE)
|
sot = segment.Segment(EXAMPLE)
|
||||||
|
self.assertEqual(EXAMPLE['description'], sot.description)
|
||||||
self.assertEqual(EXAMPLE['id'], sot.id)
|
self.assertEqual(EXAMPLE['id'], sot.id)
|
||||||
|
self.assertEqual(EXAMPLE['name'], sot.name)
|
||||||
self.assertEqual(EXAMPLE['network_id'], sot.network_id)
|
self.assertEqual(EXAMPLE['network_id'], sot.network_id)
|
||||||
self.assertEqual(EXAMPLE['network_type'], sot.network_type)
|
self.assertEqual(EXAMPLE['network_type'], sot.network_type)
|
||||||
self.assertEqual(EXAMPLE['physical_network'], sot.physical_network)
|
self.assertEqual(EXAMPLE['physical_network'], sot.physical_network)
|
||||||
|
|||||||
Reference in New Issue
Block a user