Merge "Network tag support"

This commit is contained in:
Jenkins 2017-06-14 12:27:12 +00:00 committed by Gerrit Code Review
commit 0727000428
11 changed files with 158 additions and 6 deletions

View File

@ -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
^^^^^^^^^^^^^^

View File

@ -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

View File

@ -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):

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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']})