Adds an optional parameter to the create_network and create_router-methods, for use with availability zone-scheduling of network agents. Change-Id: Ifb93a10415dc676f5cc56b5315f2dff24fc395b8tags/1.26.0
@@ -0,0 +1,8 @@ | |||
--- | |||
features: | |||
- | | |||
availability_zone_hints now accepted for create_network() when | |||
network_availability_zone extension is enabled on target cloud. | |||
- | | |||
availability_zone_hints now accepted for create_router() when | |||
router_availability_zone extension is enabled on target cloud. |
@@ -3383,7 +3383,8 @@ class OpenStackCloud( | |||
return True | |||
def create_network(self, name, shared=False, admin_state_up=True, | |||
external=False, provider=None, project_id=None): | |||
external=False, provider=None, project_id=None, | |||
availability_zone_hints=None): | |||
"""Create a network. | |||
:param string name: Name of the network being created. | |||
@@ -3395,6 +3396,7 @@ class OpenStackCloud( | |||
{ 'network_type': 'vlan', 'segmentation_id': 'vlan1' } | |||
:param string project_id: Specify the project ID this network | |||
will be created on (admin-only). | |||
:param list availability_zone_hints: A list of availability zone hints. | |||
:returns: The network object. | |||
:raises: OpenStackCloudException on operation error. | |||
@@ -3410,6 +3412,16 @@ class OpenStackCloud( | |||
if project_id is not None: | |||
network['tenant_id'] = project_id | |||
if availability_zone_hints is not None: | |||
if not isinstance(availability_zone_hints, list): | |||
raise OpenStackCloudException( | |||
"Parameter 'availability_zone_hints' must be a list") | |||
if not self._has_neutron_extension('network_availability_zone'): | |||
raise OpenStackCloudUnavailableExtension( | |||
'network_availability_zone extension is not available on ' | |||
'target cloud') | |||
network['availability_zone_hints'] = availability_zone_hints | |||
if provider: | |||
if not isinstance(provider, dict): | |||
raise OpenStackCloudException( | |||
@@ -4245,7 +4257,8 @@ class OpenStackCloud( | |||
def create_router(self, name=None, admin_state_up=True, | |||
ext_gateway_net_id=None, enable_snat=None, | |||
ext_fixed_ips=None, project_id=None): | |||
ext_fixed_ips=None, project_id=None, | |||
availability_zone_hints=None): | |||
"""Create a logical router. | |||
:param string name: The router name. | |||
@@ -4263,6 +4276,7 @@ class OpenStackCloud( | |||
} | |||
] | |||
:param string project_id: Project ID for the router. | |||
:param list availability_zone_hints: A list of availability zone hints. | |||
:returns: The router object. | |||
:raises: OpenStackCloudException on operation error. | |||
@@ -4279,6 +4293,15 @@ class OpenStackCloud( | |||
) | |||
if ext_gw_info: | |||
router['external_gateway_info'] = ext_gw_info | |||
if availability_zone_hints is not None: | |||
if not isinstance(availability_zone_hints, list): | |||
raise OpenStackCloudException( | |||
"Parameter 'availability_zone_hints' must be a list") | |||
if not self._has_neutron_extension('router_availability_zone'): | |||
raise OpenStackCloudUnavailableExtension( | |||
'router_availability_zone extension is not available on ' | |||
'target cloud') | |||
router['availability_zone_hints'] = availability_zone_hints | |||
data = self._network_client.post( | |||
"/routers.json", json={"router": router}, |
@@ -47,6 +47,16 @@ class TestNetwork(base.RequestsMockTestCase): | |||
'mtu': 0 | |||
} | |||
network_availability_zone_extension = { | |||
"alias": "network_availability_zone", | |||
"updated": "2015-01-01T10:00:00-00:00", | |||
"description": "Availability zone support for router.", | |||
"links": [], | |||
"name": "Network Availability Zone" | |||
} | |||
enabled_neutron_extensions = [network_availability_zone_extension] | |||
def test_list_networks(self): | |||
net1 = {'id': '1', 'name': 'net1'} | |||
net2 = {'id': '2', 'name': 'net2'} | |||
@@ -151,6 +161,27 @@ class TestNetwork(base.RequestsMockTestCase): | |||
self.assertEqual(mock_new_network_rep, network) | |||
self.assert_calls() | |||
def test_create_network_with_availability_zone_hints(self): | |||
self.register_uris([ | |||
dict(method='GET', | |||
uri=self.get_mock_url( | |||
'network', 'public', append=['v2.0', 'extensions.json']), | |||
json={'extensions': self.enabled_neutron_extensions}), | |||
dict(method='POST', | |||
uri=self.get_mock_url( | |||
'network', 'public', append=['v2.0', 'networks.json']), | |||
json={'network': self.mock_new_network_rep}, | |||
validate=dict( | |||
json={'network': { | |||
'admin_state_up': True, | |||
'name': 'netname', | |||
'availability_zone_hints': ['nova']}})) | |||
]) | |||
network = self.cloud.create_network("netname", | |||
availability_zone_hints=['nova']) | |||
self.assertEqual(self.mock_new_network_rep, network) | |||
self.assert_calls() | |||
def test_create_network_provider_ignored_value(self): | |||
provider_opts = {'physical_network': 'mynet', | |||
'network_type': 'vlan', | |||
@@ -180,6 +211,15 @@ class TestNetwork(base.RequestsMockTestCase): | |||
self.assertEqual(mock_new_network_rep, network) | |||
self.assert_calls() | |||
def test_create_network_wrong_availability_zone_hints_type(self): | |||
azh_opts = "invalid" | |||
with testtools.ExpectedException( | |||
shade.OpenStackCloudException, | |||
"Parameter 'availability_zone_hints' must be a list" | |||
): | |||
self.cloud.create_network("netname", | |||
availability_zone_hints=azh_opts) | |||
def test_create_network_provider_wrong_type(self): | |||
provider_opts = "invalid" | |||
with testtools.ExpectedException( |
@@ -14,6 +14,7 @@ | |||
# limitations under the License. | |||
import copy | |||
import testtools | |||
from shade import exc | |||
from shade.tests.unit import base | |||
@@ -52,6 +53,16 @@ class TestRouter(base.RequestsMockTestCase): | |||
'request_ids': ['req-f1b0b1b4-ae51-4ef9-b371-0cc3c3402cf7'] | |||
} | |||
router_availability_zone_extension = { | |||
"alias": "router_availability_zone", | |||
"updated": "2015-01-01T10:00:00-00:00", | |||
"description": "Availability zone support for router.", | |||
"links": [], | |||
"name": "Router Availability Zone" | |||
} | |||
enabled_neutron_extensions = [router_availability_zone_extension] | |||
def test_get_router(self): | |||
self.register_uris([ | |||
dict(method='GET', | |||
@@ -112,6 +123,27 @@ class TestRouter(base.RequestsMockTestCase): | |||
project_id=new_router_tenant_id) | |||
self.assert_calls() | |||
def test_create_router_with_availability_zone_hints(self): | |||
self.register_uris([ | |||
dict(method='GET', | |||
uri=self.get_mock_url( | |||
'network', 'public', append=['v2.0', 'extensions.json']), | |||
json={'extensions': self.enabled_neutron_extensions}), | |||
dict(method='POST', | |||
uri=self.get_mock_url( | |||
'network', 'public', append=['v2.0', 'routers.json']), | |||
json={'router': self.mock_router_rep}, | |||
validate=dict( | |||
json={'router': { | |||
'name': self.router_name, | |||
'admin_state_up': True, | |||
'availability_zone_hints': ['nova']}})) | |||
]) | |||
self.cloud.create_router( | |||
name=self.router_name, admin_state_up=True, | |||
availability_zone_hints=['nova']) | |||
self.assert_calls() | |||
def test_create_router_with_enable_snat_True(self): | |||
"""Do not send enable_snat when same as neutron default.""" | |||
self.register_uris([ | |||
@@ -145,6 +177,16 @@ class TestRouter(base.RequestsMockTestCase): | |||
name=self.router_name, admin_state_up=True, enable_snat=False) | |||
self.assert_calls() | |||
def test_create_router_wrong_availability_zone_hints_type(self): | |||
azh_opts = "invalid" | |||
with testtools.ExpectedException( | |||
exc.OpenStackCloudException, | |||
"Parameter 'availability_zone_hints' must be a list" | |||
): | |||
self.cloud.create_router( | |||
name=self.router_name, admin_state_up=True, | |||
availability_zone_hints=azh_opts) | |||
def test_add_router_interface(self): | |||
self.register_uris([ | |||
dict(method='PUT', |