Merge "SDK for Neutron Routers"
This commit is contained in:
commit
21eceecbfb
@ -1927,11 +1927,9 @@ def port_update(request, port_id, **kwargs):
|
||||
@profiler.trace
|
||||
def router_create(request, **kwargs):
|
||||
LOG.debug("router_create():, kwargs=%s", kwargs)
|
||||
body = {'router': {}}
|
||||
if 'tenant_id' not in kwargs:
|
||||
kwargs['tenant_id'] = request.user.project_id
|
||||
body['router'].update(kwargs)
|
||||
router = neutronclient(request).create_router(body=body).get('router')
|
||||
router = networkclient(request).create_router(**kwargs)
|
||||
return Router(router)
|
||||
|
||||
|
||||
@ -1939,70 +1937,66 @@ def router_create(request, **kwargs):
|
||||
def router_update(request, r_id, **kwargs):
|
||||
LOG.debug("router_update(): router_id=%(r_id)s, kwargs=%(kwargs)s",
|
||||
{'r_id': r_id, 'kwargs': kwargs})
|
||||
body = {'router': {}}
|
||||
body['router'].update(kwargs)
|
||||
router = neutronclient(request).update_router(r_id, body=body)
|
||||
return Router(router['router'])
|
||||
router = networkclient(request).update_router(r_id, **kwargs).to_dict()
|
||||
return Router(router)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_get(request, router_id, **params):
|
||||
router = neutronclient(request).show_router(router_id,
|
||||
**params).get('router')
|
||||
router = networkclient(request).get_router(router_id)
|
||||
return Router(router)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_list(request, **params):
|
||||
routers = neutronclient(request).list_routers(**params).get('routers')
|
||||
routers = networkclient(request).routers(**params)
|
||||
if not isinstance(routers, (types.GeneratorType, list)):
|
||||
routers = [routers]
|
||||
return [Router(r) for r in routers]
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_list_on_l3_agent(request, l3_agent_id, **params):
|
||||
routers = neutronclient(request).\
|
||||
list_routers_on_l3_agent(l3_agent_id,
|
||||
**params).get('routers')
|
||||
routers = networkclient(request).agent_hosted_routers(l3_agent_id,
|
||||
**params)
|
||||
if not isinstance(routers, (types.GeneratorType, list)):
|
||||
routers = [routers]
|
||||
return [Router(r) for r in routers]
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_delete(request, router_id):
|
||||
neutronclient(request).delete_router(router_id)
|
||||
networkclient(request).delete_router(router_id)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_add_interface(request, router_id, subnet_id=None, port_id=None):
|
||||
body = {}
|
||||
if subnet_id:
|
||||
body['subnet_id'] = subnet_id
|
||||
if port_id:
|
||||
body['port_id'] = port_id
|
||||
client = neutronclient(request)
|
||||
return client.add_interface_router(router_id, body)
|
||||
client = networkclient(request)
|
||||
return client.add_interface_to_router(router=router_id,
|
||||
port_id=port_id,
|
||||
subnet_id=subnet_id)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_remove_interface(request, router_id, subnet_id=None, port_id=None):
|
||||
body = {}
|
||||
if subnet_id:
|
||||
body['subnet_id'] = subnet_id
|
||||
if port_id:
|
||||
body['port_id'] = port_id
|
||||
neutronclient(request).remove_interface_router(router_id, body)
|
||||
client = networkclient(request)
|
||||
return client.remove_interface_from_router(router=router_id,
|
||||
port_id=port_id,
|
||||
subnet_id=subnet_id)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_add_gateway(request, router_id, network_id, enable_snat=None):
|
||||
body = {'network_id': network_id}
|
||||
body = {'external_gateway_info': {'network_id': network_id}}
|
||||
if enable_snat is not None:
|
||||
body['enable_snat'] = enable_snat
|
||||
neutronclient(request).add_gateway_router(router_id, body)
|
||||
body['external_gateway_info']['enable_snat'] = enable_snat
|
||||
networkclient(request).update_router(router_id, **body)
|
||||
|
||||
|
||||
@profiler.trace
|
||||
def router_remove_gateway(request, router_id):
|
||||
neutronclient(request).remove_gateway_router(router_id)
|
||||
networkclient(request).update_router(router_id,
|
||||
**{'external_gateway_info': {}})
|
||||
|
||||
|
||||
@profiler.trace
|
||||
|
@ -219,16 +219,16 @@ class RoutersTable(tables.DataTable):
|
||||
verbose_name=_("Status"),
|
||||
status=True,
|
||||
display_choices=STATUS_DISPLAY_CHOICES)
|
||||
distributed = tables.Column("distributed",
|
||||
distributed = tables.Column("is_distributed",
|
||||
filters=(filters.yesno, filters.capfirst),
|
||||
verbose_name=_("Distributed"))
|
||||
ha = tables.Column("ha",
|
||||
ha = tables.Column("is_ha",
|
||||
filters=(filters.yesno, filters.capfirst),
|
||||
# Translators: High Availability mode of Neutron router
|
||||
verbose_name=_("HA mode"))
|
||||
ext_net = tables.Column(get_external_network,
|
||||
verbose_name=_("External Network"))
|
||||
admin_state = tables.Column("admin_state",
|
||||
admin_state = tables.Column("is_admin_state_up",
|
||||
verbose_name=_("Admin State"),
|
||||
display_choices=ADMIN_STATE_DISPLAY_CHOICES)
|
||||
availability_zones = tables.Column(get_availability_zones,
|
||||
|
@ -161,7 +161,7 @@ class DetailView(tabs.TabbedTableView):
|
||||
router.status_label = filters.get_display_label(choices, router.status)
|
||||
choices = rtables.ADMIN_STATE_DISPLAY_CHOICES
|
||||
router.admin_state_label = (
|
||||
filters.get_display_label(choices, router.admin_state))
|
||||
filters.get_display_label(choices, router.is_admin_state_up))
|
||||
return context
|
||||
|
||||
def get_tabs(self, request, *args, **kwargs):
|
||||
@ -222,10 +222,10 @@ class UpdateView(forms.ModalFormView):
|
||||
initial = {'router_id': router['id'],
|
||||
'tenant_id': router['tenant_id'],
|
||||
'name': router['name'],
|
||||
'admin_state': router['admin_state_up']}
|
||||
if hasattr(router, 'distributed'):
|
||||
initial['mode'] = ('distributed' if router.distributed
|
||||
'admin_state': router['is_admin_state_up']}
|
||||
if hasattr(router, 'is_distributed'):
|
||||
initial['mode'] = ('distributed' if router.is_distributed
|
||||
else 'centralized')
|
||||
if hasattr(router, 'ha'):
|
||||
initial['ha'] = router.ha
|
||||
if hasattr(router, 'is_ha'):
|
||||
initial['ha'] = router.is_ha
|
||||
return initial
|
||||
|
@ -16,6 +16,7 @@ import copy
|
||||
|
||||
from openstack.network.v2 import network as sdk_net
|
||||
from openstack.network.v2 import port as sdk_port
|
||||
from openstack.network.v2 import router as sdk_router
|
||||
from openstack.network.v2 import subnet as sdk_subnet
|
||||
from openstack.network.v2 import subnet_pool as sdk_subnet_pool
|
||||
from openstack.network.v2 import trunk as sdk_trunk
|
||||
@ -95,6 +96,8 @@ def data(TEST):
|
||||
TEST.api_ports_sdk = list()
|
||||
TEST.api_tp_ports_sdk = list()
|
||||
TEST.api_subnetpools_sdk = list()
|
||||
TEST.api_routers_sdk = list()
|
||||
TEST.api_routers_with_routes_sdk = list()
|
||||
|
||||
# 1st network.
|
||||
network_dict = {'is_admin_state_up': True,
|
||||
@ -665,27 +668,35 @@ def data(TEST):
|
||||
'name': 'router1',
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': True,
|
||||
'is_admin_state_up': True,
|
||||
'distributed': True,
|
||||
'is_distributed': True,
|
||||
'external_gateway_info':
|
||||
{'network_id': ext_net['id']},
|
||||
'tenant_id': '1',
|
||||
'availability_zone_hints': ['nova']}
|
||||
TEST.api_routers.add(router_dict)
|
||||
TEST.api_routers_sdk.append(sdk_router.Router(**router_dict))
|
||||
TEST.routers.add(neutron.Router(router_dict))
|
||||
router_dict = {'id': '10e3dc42-1ce1-4d48-87cf-7fc333055d6c',
|
||||
'name': 'router2',
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': False,
|
||||
'is_admin_state_up': False,
|
||||
'distributed': False,
|
||||
'is_distributed': False,
|
||||
'external_gateway_info': None,
|
||||
'tenant_id': '1'}
|
||||
TEST.api_routers.add(router_dict)
|
||||
TEST.api_routers_sdk.append(sdk_router.Router(**router_dict))
|
||||
TEST.routers.add(neutron.Router(router_dict))
|
||||
router_dict = {'id': '7180cede-bcd8-4334-b19f-f7ef2f331f53',
|
||||
'name': 'rulerouter',
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': True,
|
||||
'is_admin_state_up': True,
|
||||
'distributed': False,
|
||||
'is_distributed': False,
|
||||
'external_gateway_info':
|
||||
{'network_id': ext_net['id']},
|
||||
'tenant_id': '1',
|
||||
@ -700,12 +711,15 @@ def data(TEST):
|
||||
'destination': '8.8.8.8/32',
|
||||
'nexthops': ['1.0.0.2', '1.0.0.1']}]}
|
||||
TEST.api_routers.add(router_dict)
|
||||
TEST.api_routers_sdk.append(sdk_router.Router(**router_dict))
|
||||
TEST.routers_with_rules.add(neutron.Router(router_dict))
|
||||
router_dict_with_route = {'id': '725c24c9-061b-416b-b9d4-012392b32fd9',
|
||||
'name': 'routerouter',
|
||||
'status': 'ACTIVE',
|
||||
'admin_state_up': True,
|
||||
'is_admin_state_up': True,
|
||||
'distributed': False,
|
||||
'is_distributed': False,
|
||||
'external_gateway_info':
|
||||
{'network_id': ext_net['id']},
|
||||
'tenant_id': '1',
|
||||
@ -714,6 +728,8 @@ def data(TEST):
|
||||
{'nexthop': '10.0.0.2',
|
||||
'destination': '172.1.0.0/24'}]}
|
||||
TEST.api_routers_with_routes.add(router_dict_with_route)
|
||||
TEST.api_routers_with_routes_sdk.append(
|
||||
sdk_router.Router(**router_dict_with_route))
|
||||
TEST.routers_with_routes.add(neutron.Router(router_dict_with_route))
|
||||
|
||||
# Floating IP.
|
||||
|
@ -1482,85 +1482,85 @@ class NeutronApiTests(test.APIMockTestCase):
|
||||
[{'port_id': old_trunk['sub_ports'][0]['port_id']}]
|
||||
)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_list(self, mock_neutronclient):
|
||||
routers = {'routers': self.api_routers.list()}
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_list(self, mock_networkclient):
|
||||
routers = {'routers': self.api_routers_sdk}
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.list_routers.return_value = routers
|
||||
networklient = mock_networkclient.return_value
|
||||
networklient.routers.return_value = routers
|
||||
|
||||
ret_val = api.neutron.router_list(self.request)
|
||||
|
||||
for n in ret_val:
|
||||
self.assertIsInstance(n, api.neutron.Router)
|
||||
neutronclient.list_routers.assert_called_once_with()
|
||||
networklient.routers.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_get(self, mock_neutronclient):
|
||||
router = {'router': self.api_routers.first()}
|
||||
router_id = self.api_routers.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_get(self, mock_networkclient):
|
||||
router = {'router': self.api_routers_sdk[0]}
|
||||
router_id = self.api_routers_sdk[0]['id']
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.show_router.return_value = router
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.get_router.return_value = router
|
||||
|
||||
ret_val = api.neutron.router_get(self.request, router_id)
|
||||
|
||||
self.assertIsInstance(ret_val, api.neutron.Router)
|
||||
neutronclient.show_router.assert_called_once_with(router_id)
|
||||
networkclient.get_router.assert_called_once_with(router_id)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_create(self, mock_neutronclient):
|
||||
router = {'router': self.api_routers.first()}
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_create(self, mock_networkclient):
|
||||
router = {'router': self.api_routers_sdk[0]}
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
form_data = {'router': {'name': 'router1',
|
||||
'tenant_id': self.request.user.project_id}}
|
||||
neutronclient.create_router.return_value = router
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.create_router.return_value = router
|
||||
|
||||
ret_val = api.neutron.router_create(self.request, name='router1')
|
||||
|
||||
self.assertIsInstance(ret_val, api.neutron.Router)
|
||||
neutronclient.create_router.assert_called_once_with(body=form_data)
|
||||
networkclient.create_router.assert_called_once_with(
|
||||
name=self.api_routers_sdk[0]['name'],
|
||||
tenant_id=self.request.user.project_id
|
||||
)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_delete(self, mock_neutronclient):
|
||||
router_id = self.api_routers.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_delete(self, mock_networkclient):
|
||||
router_id = self.api_routers_sdk[0]['id']
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.delete_router.return_value = None
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.delete_router.return_value = None
|
||||
|
||||
api.neutron.router_delete(self.request, router_id)
|
||||
|
||||
neutronclient.delete_router.assert_called_once_with(router_id)
|
||||
networkclient.delete_router.assert_called_once_with(router_id)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_add_interface(self, mock_neutronclient):
|
||||
subnet_id = self.api_subnets.first()['id']
|
||||
router_id = self.api_routers.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_add_interface(self, mock_networklient):
|
||||
subnet_id = self.api_subnets_sdk[0]['id']
|
||||
router_id = self.api_routers_sdk[0]['id']
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
form_data = {'subnet_id': subnet_id}
|
||||
neutronclient.add_interface_router.return_value = None
|
||||
networkclient = mock_networklient.return_value
|
||||
networkclient.add_interface_to_router.return_value = None
|
||||
|
||||
api.neutron.router_add_interface(
|
||||
self.request, router_id, subnet_id=subnet_id)
|
||||
|
||||
neutronclient.add_interface_router.assert_called_once_with(router_id,
|
||||
form_data)
|
||||
networkclient.add_interface_to_router.assert_called_once_with(
|
||||
router=router_id, port_id=None, subnet_id=subnet_id)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_remove_interface(self, mock_neutronclient):
|
||||
router_id = self.api_routers.first()['id']
|
||||
fake_port = self.api_ports.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_remove_interface(self, mock_networkclient):
|
||||
router_id = self.api_routers_sdk[0]['id']
|
||||
fake_port = self.api_ports_sdk[0]['id']
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.remove_interface_router.return_value = None
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.remove_interface_from_router.return_value = None
|
||||
|
||||
api.neutron.router_remove_interface(
|
||||
self.request, router_id, port_id=fake_port)
|
||||
|
||||
neutronclient.remove_interface_router.assert_called_once_with(
|
||||
router_id, {'port_id': fake_port})
|
||||
networkclient.remove_interface_from_router.assert_called_once_with(
|
||||
router=router_id, port_id=fake_port, subnet_id=None)
|
||||
|
||||
# Mocking neutronclient() does not work because api.neutron.list_extensions
|
||||
# is decorated with memoized_with_request, so we need to mock
|
||||
@ -1576,57 +1576,55 @@ class NeutronApiTests(test.APIMockTestCase):
|
||||
|
||||
mock_list_extensions.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_static_route_list(self, mock_neutronclient):
|
||||
router = {'router': self.api_routers_with_routes.first()}
|
||||
router_id = self.api_routers_with_routes.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_static_route_list(self, mock_networkclient):
|
||||
router = self.api_routers_with_routes_sdk[0]
|
||||
router_id = self.api_routers_with_routes_sdk[0]['id']
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.show_router.return_value = router
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.get_router.return_value = router
|
||||
|
||||
ret_val = api.neutron.router_static_route_list(self.request, router_id)
|
||||
|
||||
self.assertIsInstance(ret_val[0], api.neutron.RouterStaticRoute)
|
||||
neutronclient.show_router.assert_called_once_with(router_id)
|
||||
networkclient.get_router.assert_called_once_with(router_id)
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_static_route_remove(self, mock_neutronclient):
|
||||
router = {'router': self.api_routers_with_routes.first()}
|
||||
router_id = self.api_routers_with_routes.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_static_route_remove(self, mock_networkclient):
|
||||
router = self.api_routers_with_routes_sdk[0]
|
||||
router_id = self.api_routers_with_routes_sdk[0]['id']
|
||||
post_router = copy.deepcopy(router)
|
||||
route = api.neutron.RouterStaticRoute(post_router['router']
|
||||
['routes'].pop())
|
||||
route = api.neutron.RouterStaticRoute(
|
||||
post_router['routes'].pop())
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.show_router.return_value = router
|
||||
neutronclient.update_router.return_value = post_router
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.get_router.return_value = router
|
||||
networkclient.update_router.return_value = post_router
|
||||
|
||||
api.neutron.router_static_route_remove(self.request,
|
||||
router_id, route.id)
|
||||
|
||||
neutronclient.show_router.assert_called_once_with(router_id)
|
||||
body = {'router': {'routes': post_router['router']['routes']}}
|
||||
neutronclient.update_router.assert_called_once_with(
|
||||
router_id, body=body)
|
||||
networkclient.get_router.assert_called_once_with(router_id)
|
||||
networkclient.update_router.assert_called_once_with(
|
||||
router_id, routes=post_router['routes'])
|
||||
|
||||
@mock.patch.object(api.neutron, 'neutronclient')
|
||||
def test_router_static_route_add(self, mock_neutronclient):
|
||||
router = {'router': self.api_routers_with_routes.first()}
|
||||
router_id = self.api_routers_with_routes.first()['id']
|
||||
@mock.patch.object(api.neutron, 'networkclient')
|
||||
def test_router_static_route_add(self, mock_networkclient):
|
||||
router = self.api_routers_with_routes_sdk[0]
|
||||
router_id = self.api_routers_with_routes_sdk[0]['id']
|
||||
post_router = copy.deepcopy(router)
|
||||
route = {'nexthop': '10.0.0.5', 'destination': '40.0.1.0/24'}
|
||||
post_router['router']['routes'].insert(0, route)
|
||||
body = {'router': {'routes': post_router['router']['routes']}}
|
||||
post_router['routes'].insert(0, route)
|
||||
|
||||
neutronclient = mock_neutronclient.return_value
|
||||
neutronclient.show_router.return_value = router
|
||||
neutronclient.update_router.return_value = post_router
|
||||
networkclient = mock_networkclient.return_value
|
||||
networkclient.get_router.return_value = router
|
||||
networkclient.update_router.return_value = post_router
|
||||
|
||||
api.neutron.router_static_route_add(self.request, router_id, route)
|
||||
|
||||
neutronclient.show_router.assert_called_once_with(router_id)
|
||||
neutronclient.update_router.assert_called_once_with(router_id,
|
||||
body=body)
|
||||
networkclient.get_router.assert_called_once_with(router_id)
|
||||
networkclient.update_router.assert_called_once_with(
|
||||
router_id, routes=post_router['routes'])
|
||||
|
||||
# NOTE(amotoki): "dvr" permission tests check most of
|
||||
# get_feature_permission features.
|
||||
@ -2615,8 +2613,7 @@ class NeutronApiFloatingIpTests(test.APIMockTestCase):
|
||||
if n['is_router_external']]
|
||||
list_networks_retvals = [ext_nets, shared_nets]
|
||||
self.netclient.networks.side_effect = list_networks_retvals
|
||||
self.qclient.list_routers.return_value = {'routers':
|
||||
self.api_routers.list()}
|
||||
self.netclient.routers.return_value = self.api_routers_sdk
|
||||
shared_subs = [s for s in self.api_subnets_sdk
|
||||
if s['id'] in shared_subnet_ids]
|
||||
self.netclient.subnets.return_value = shared_subs
|
||||
@ -2638,7 +2635,7 @@ class NeutronApiFloatingIpTests(test.APIMockTestCase):
|
||||
mock.call(**{'router:external': True}),
|
||||
mock.call(is_shared=True),
|
||||
])
|
||||
self.qclient.list_routers.assert_called_once_with()
|
||||
self.netclient.routers.assert_called_once_with()
|
||||
self.netclient.subnets.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(api._nova, 'novaclient')
|
||||
@ -2659,8 +2656,7 @@ class NeutronApiFloatingIpTests(test.APIMockTestCase):
|
||||
if n['is_router_external']]
|
||||
|
||||
list_nets_retvals.append(ext_nets)
|
||||
self.qclient.list_routers.side_effect = [{'routers':
|
||||
self.api_routers.list()}]
|
||||
self.netclient.routers.side_effect = self.api_routers_sdk
|
||||
rinfs = [p for p in ports
|
||||
if p['device_owner'] in api.neutron.ROUTER_INTERFACE_OWNERS]
|
||||
list_ports_retvals.append(rinfs)
|
||||
@ -2688,7 +2684,7 @@ class NeutronApiFloatingIpTests(test.APIMockTestCase):
|
||||
mock.call(**{'router:external': True}),
|
||||
mock.call(is_shared=True),
|
||||
])
|
||||
self.qclient.list_routers.assert_called_once_with()
|
||||
self.netclient.routers.assert_called_once_with()
|
||||
self.netclient.subnets.assert_called_once_with()
|
||||
novaclient.versions.get_current.assert_called_once_with()
|
||||
novaclient.servers.get.assert_called_once_with(server.id)
|
||||
|
Loading…
Reference in New Issue
Block a user