Merge "Network tag support"
This commit is contained in:
commit
0727000428
|
@ -332,6 +332,13 @@ Service Profile Operations
|
|||
.. automethod:: openstack.network.v2._proxy.Proxy.associate_flavor_with_service_profile
|
||||
.. automethod:: openstack.network.v2._proxy.Proxy.disassociate_flavor_from_service_profile
|
||||
|
||||
Tag Operations
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openstack.network.v2._proxy.Proxy
|
||||
|
||||
.. automethod:: openstack.network.v2._proxy.Proxy.set_tags
|
||||
|
||||
VPN Operations
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from openstack import exceptions
|
||||
from openstack.network.v2 import address_scope as _address_scope
|
||||
from openstack.network.v2 import agent as _agent
|
||||
from openstack.network.v2 import auto_allocated_topology as \
|
||||
|
@ -2927,6 +2928,30 @@ class Proxy(proxy2.BaseProxy):
|
|||
"""
|
||||
return self._update(_subnet_pool.SubnetPool, subnet_pool, **attrs)
|
||||
|
||||
@staticmethod
|
||||
def _check_tag_support(resource):
|
||||
try:
|
||||
# Check 'tags' attribute exists
|
||||
resource.tags
|
||||
except AttributeError:
|
||||
raise exceptions.InvalidRequest(
|
||||
'%s resource does not support tag' %
|
||||
resource.__class__.__name__)
|
||||
|
||||
def set_tags(self, resource, tags):
|
||||
"""Replace tags of a specified resource with specified tags
|
||||
|
||||
:param resource:
|
||||
:class:`~openstack.resource2.Resource` instance.
|
||||
:param tags: New tags to be set.
|
||||
:type tags: "list"
|
||||
|
||||
:returns: The updated resource
|
||||
:rtype: :class:`~openstack.resource2.Resource`
|
||||
"""
|
||||
self._check_tag_support(resource)
|
||||
return resource.set_tags(self._session, tags)
|
||||
|
||||
def create_vpn_service(self, **attrs):
|
||||
"""Create a new vpn service from attributes
|
||||
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
# under the License.
|
||||
|
||||
from openstack.network import network_service
|
||||
from openstack.network.v2 import tag
|
||||
from openstack import resource2 as resource
|
||||
|
||||
|
||||
class Network(resource.Resource):
|
||||
class Network(resource.Resource, tag.TagMixin):
|
||||
resource_key = 'network'
|
||||
resources_key = 'networks'
|
||||
base_path = '/networks'
|
||||
|
@ -39,6 +40,7 @@ class Network(resource.Resource):
|
|||
provider_network_type='provider:network_type',
|
||||
provider_physical_network='provider:physical_network',
|
||||
provider_segmentation_id='provider:segmentation_id',
|
||||
**tag.TagMixin._tag_query_parameters
|
||||
)
|
||||
|
||||
# Properties
|
||||
|
@ -111,6 +113,9 @@ class Network(resource.Resource):
|
|||
updated_at = resource.Body('updated_at')
|
||||
#: Indicates the VLAN transparency mode of the network
|
||||
is_vlan_transparent = resource.Body('vlan_transparent', type=bool)
|
||||
#: A list of assocaited tags
|
||||
#: *Type: list of tag strings*
|
||||
tags = resource.Body('tags', type=list)
|
||||
|
||||
|
||||
class DHCPAgentHostingNetwork(Network):
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
# under the License.
|
||||
|
||||
from openstack.network import network_service
|
||||
from openstack.network.v2 import tag
|
||||
from openstack import resource2 as resource
|
||||
|
||||
|
||||
class Port(resource.Resource):
|
||||
class Port(resource.Resource, tag.TagMixin):
|
||||
resource_key = 'port'
|
||||
resources_key = 'ports'
|
||||
base_path = '/ports'
|
||||
|
@ -34,6 +35,7 @@ class Port(resource.Resource):
|
|||
is_admin_state_up='admin_state_up',
|
||||
is_port_security_enabled='port_security_enabled',
|
||||
project_id='tenant_id',
|
||||
**tag.TagMixin._tag_query_parameters
|
||||
)
|
||||
|
||||
# Properties
|
||||
|
@ -127,3 +129,6 @@ class Port(resource.Resource):
|
|||
trunk_details = resource.Body('trunk_details', type=dict)
|
||||
#: Timestamp when the port was last updated.
|
||||
updated_at = resource.Body('updated_at')
|
||||
#: A list of assocaited tags
|
||||
#: *Type: list of tag strings*
|
||||
tags = resource.Body('tags', type=list)
|
||||
|
|
|
@ -11,11 +11,12 @@
|
|||
# under the License.
|
||||
|
||||
from openstack.network import network_service
|
||||
from openstack.network.v2 import tag
|
||||
from openstack import resource2 as resource
|
||||
from openstack import utils
|
||||
|
||||
|
||||
class Router(resource.Resource):
|
||||
class Router(resource.Resource, tag.TagMixin):
|
||||
resource_key = 'router'
|
||||
resources_key = 'routers'
|
||||
base_path = '/routers'
|
||||
|
@ -35,6 +36,7 @@ class Router(resource.Resource):
|
|||
is_distributed='distributed',
|
||||
is_ha='ha',
|
||||
project_id='tenant_id',
|
||||
**tag.TagMixin._tag_query_parameters
|
||||
)
|
||||
|
||||
# Properties
|
||||
|
@ -74,6 +76,9 @@ class Router(resource.Resource):
|
|||
status = resource.Body('status')
|
||||
#: Timestamp when the router was created.
|
||||
updated_at = resource.Body('updated_at')
|
||||
#: A list of assocaited tags
|
||||
#: *Type: list of tag strings*
|
||||
tags = resource.Body('tags', type=list)
|
||||
|
||||
def add_interface(self, session, **body):
|
||||
"""Add an internal interface to a logical router.
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
# under the License.
|
||||
|
||||
from openstack.network import network_service
|
||||
from openstack.network.v2 import tag
|
||||
from openstack import resource2 as resource
|
||||
|
||||
|
||||
class Subnet(resource.Resource):
|
||||
class Subnet(resource.Resource, tag.TagMixin):
|
||||
resource_key = 'subnet'
|
||||
resources_key = 'subnets'
|
||||
base_path = '/subnets'
|
||||
|
@ -36,6 +37,7 @@ class Subnet(resource.Resource):
|
|||
project_id='tenant_id',
|
||||
subnet_pool_id='subnetpool_id',
|
||||
use_default_subnet_pool='use_default_subnetpool',
|
||||
**tag.TagMixin._tag_query_parameters
|
||||
)
|
||||
|
||||
# Properties
|
||||
|
@ -87,3 +89,6 @@ class Subnet(resource.Resource):
|
|||
'use_default_subnetpool',
|
||||
type=bool
|
||||
)
|
||||
#: A list of assocaited tags
|
||||
#: *Type: list of tag strings*
|
||||
tags = resource.Body('tags', type=list)
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
# under the License.
|
||||
|
||||
from openstack.network import network_service
|
||||
from openstack.network.v2 import tag
|
||||
from openstack import resource2 as resource
|
||||
|
||||
|
||||
class SubnetPool(resource.Resource):
|
||||
class SubnetPool(resource.Resource, tag.TagMixin):
|
||||
resource_key = 'subnetpool'
|
||||
resources_key = 'subnetpools'
|
||||
base_path = '/subnetpools'
|
||||
|
@ -32,6 +33,7 @@ class SubnetPool(resource.Resource):
|
|||
'name',
|
||||
is_shared='shared',
|
||||
project_id='tenant_id',
|
||||
**tag.TagMixin._tag_query_parameters
|
||||
)
|
||||
|
||||
# Properties
|
||||
|
@ -77,3 +79,6 @@ class SubnetPool(resource.Resource):
|
|||
revision_number = resource.Body('revision_number', type=int)
|
||||
#: Timestamp when the subnet pool was last updated.
|
||||
updated_at = resource.Body('updated_at')
|
||||
#: A list of assocaited tags
|
||||
#: *Type: list of tag strings*
|
||||
tags = resource.Body('tags', type=list)
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# 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 import utils
|
||||
|
||||
|
||||
class TagMixin(object):
|
||||
|
||||
_tag_query_parameters = {
|
||||
'tags': 'tags',
|
||||
'any_tags': 'tags-any',
|
||||
'not_tags': 'not-tags',
|
||||
'not_any_tags': 'not-tags-any',
|
||||
}
|
||||
|
||||
def set_tags(self, session, tags):
|
||||
url = utils.urljoin(self.base_path, self.id, 'tags')
|
||||
session.put(url, endpoint_filter=self.service,
|
||||
json={'tags': tags})
|
||||
self._body.attributes.update({'tags': tags})
|
||||
return self
|
|
@ -110,7 +110,11 @@ class TestNetwork(testtools.TestCase):
|
|||
'is_shared': 'shared',
|
||||
'provider_network_type': 'provider:network_type',
|
||||
'provider_physical_network': 'provider:physical_network',
|
||||
'provider_segmentation_id': 'provider:segmentation_id'
|
||||
'provider_segmentation_id': 'provider:segmentation_id',
|
||||
'tags': 'tags',
|
||||
'any_tags': 'tags-any',
|
||||
'not_tags': 'not-tags',
|
||||
'not_any_tags': 'not-tags-any',
|
||||
},
|
||||
sot._query_mapping._mapping)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import deprecation
|
|||
import mock
|
||||
import uuid
|
||||
|
||||
from openstack import exceptions
|
||||
from openstack.network.v2 import _proxy
|
||||
from openstack.network.v2 import address_scope
|
||||
from openstack.network.v2 import agent
|
||||
|
@ -1064,3 +1065,19 @@ class TestNetworkProxy(test_proxy_base2.TestProxyBase):
|
|||
auto_allocated_topology.ValidateTopology],
|
||||
expected_kwargs={"project": mock.sentinel.project_id,
|
||||
"requires_id": False})
|
||||
|
||||
def test_set_tags(self):
|
||||
x_network = network.Network.new(id='NETWORK_ID')
|
||||
self._verify('openstack.network.v2.network.Network.set_tags',
|
||||
self.proxy.set_tags,
|
||||
method_args=[x_network, ['TAG1', 'TAG2']],
|
||||
expected_args=[['TAG1', 'TAG2']],
|
||||
expected_result=mock.sentinel.result_set_tags)
|
||||
|
||||
@mock.patch('openstack.network.v2.network.Network.set_tags')
|
||||
def test_set_tags_resource_without_tag_suport(self, mock_set_tags):
|
||||
no_tag_resource = object()
|
||||
self.assertRaises(exceptions.InvalidRequest,
|
||||
self.proxy.set_tags,
|
||||
no_tag_resource, ['TAG1', 'TAG2'])
|
||||
self.assertEqual(0, mock_set_tags.call_count)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# 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 mock
|
||||
import testtools
|
||||
|
||||
from openstack.network.v2 import network
|
||||
|
||||
|
||||
ID = 'IDENTIFIER'
|
||||
|
||||
|
||||
class TestTag(testtools.TestCase):
|
||||
|
||||
@staticmethod
|
||||
def _create_resource(tags=None):
|
||||
tags = tags or []
|
||||
return network.Network(id=ID, name='test-net', tags=tags)
|
||||
|
||||
def test_tags_attribute(self):
|
||||
net = self._create_resource()
|
||||
self.assertTrue(hasattr(net, 'tags'))
|
||||
self.assertIsInstance(net.tags, list)
|
||||
|
||||
def test_set_tags(self):
|
||||
net = self._create_resource()
|
||||
sess = mock.Mock()
|
||||
result = net.set_tags(sess, ['blue', 'green'])
|
||||
# Check tags attribute is updated
|
||||
self.assertEqual(['blue', 'green'], net.tags)
|
||||
# Check the passed resource is returned
|
||||
self.assertEqual(net, result)
|
||||
url = 'networks/' + ID + '/tags'
|
||||
sess.put.assert_called_once_with(url, endpoint_filter=net.service,
|
||||
json={'tags': ['blue', 'green']})
|
Loading…
Reference in New Issue