Rework novaclient floating ips actions
Methods for association floating ips and dissociation were deprecated in novaclient a year ago and latest major release (python-novaclient 10) doesn't include them[*]. These actions should be performed via neutronclient now. It requires more work, but there is no other options. [*] https://github.com/openstack/python-novaclient/blob/master/releasenotes/notes/remove-virt-interfaces-add-rm-fixed-floating-398c905d9c91cca8.yaml Change-Id: I6c019fe84fb3d6dfcef5dfadbbccff01bde4a102
This commit is contained in:
parent
7174452c13
commit
d89eb07a02
@ -287,6 +287,40 @@
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 1
|
||||
-
|
||||
title: NovaServers.boot_and_associate_floating_ip tests
|
||||
scenario:
|
||||
NovaServers.boot_and_associate_floating_ip:
|
||||
flavor:
|
||||
name: {{flavor_name}}
|
||||
image:
|
||||
name: {{image_name}}
|
||||
runner:
|
||||
constant:
|
||||
times: 2
|
||||
concurrency: 2
|
||||
contexts:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 1
|
||||
network: {}
|
||||
-
|
||||
title: NovaServers.boot_server_associate_and_dissociate_floating_ip tests
|
||||
scenario:
|
||||
NovaServers.boot_server_associate_and_dissociate_floating_ip:
|
||||
flavor:
|
||||
name: {{flavor_name}}
|
||||
image:
|
||||
name: {{image_name}}
|
||||
runner:
|
||||
constant:
|
||||
times: 2
|
||||
concurrency: 2
|
||||
contexts:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
network: {}
|
||||
-
|
||||
title: NovaServers.list_servers tests
|
||||
scenario:
|
||||
|
@ -682,3 +682,136 @@
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
VMTasks.boot_runcommand_delete:
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: "m1.tiny"
|
||||
image:
|
||||
name: {{image_name}}
|
||||
command:
|
||||
script_file: "~/.rally/extra/instance_test.sh"
|
||||
interpreter: "/bin/sh"
|
||||
username: "cirros"
|
||||
runner:
|
||||
type: "constant"
|
||||
times: {{smoke or 2}}
|
||||
concurrency: {{smoke or 2}}
|
||||
context:
|
||||
users:
|
||||
tenants: {{smoke or 2}}
|
||||
users_per_tenant: {{smoke or 2}}
|
||||
network: {}
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: "m1.tiny"
|
||||
image:
|
||||
name: {{image_name}}
|
||||
command:
|
||||
script_file: "~/.rally/extra/instance_test.sh"
|
||||
interpreter: "/bin/sh"
|
||||
username: "cirros"
|
||||
volume_args:
|
||||
size: 2
|
||||
runner:
|
||||
type: "constant"
|
||||
times: {{smoke or 2}}
|
||||
concurrency: {{smoke or 2}}
|
||||
context:
|
||||
users:
|
||||
tenants: {{smoke or 2}}
|
||||
users_per_tenant: {{smoke or 1}}
|
||||
network: {}
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: {{flavor_name}}
|
||||
image:
|
||||
name: {{image_name}}
|
||||
floating_network: "public"
|
||||
command:
|
||||
script_inline: |
|
||||
time_seconds(){ (time -p $1 ) 2>&1 |awk '/real/{print $2}'; }
|
||||
file=/tmp/test.img
|
||||
c=100 #100M
|
||||
write_seq=$(time_seconds "dd if=/dev/zero of=$file bs=1M count=$c")
|
||||
read_seq=$(time_seconds "dd if=$file of=/dev/null bs=1M count=$c")
|
||||
[ -f $file ] && rm $file
|
||||
|
||||
echo "{
|
||||
\"write_seq\": $write_seq,
|
||||
\"read_seq\": $read_seq
|
||||
}"
|
||||
interpreter: "/bin/sh"
|
||||
username: "cirros"
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
network: {}
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
-
|
||||
args:
|
||||
command:
|
||||
# The `image_command_customizer` context prepares an image and
|
||||
# executes `rally-jobs/extra/install_benchmark.sh` script. The script
|
||||
# itself creates a new file inside the image "dd_test.sh" which is
|
||||
# called in the scenario. It doesn't have anything related to
|
||||
# VMTask.dd_load_test scenario
|
||||
remote_path: "./dd_test.sh"
|
||||
flavor:
|
||||
name: "m1.tiny"
|
||||
username: "cirros"
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 1
|
||||
concurrency: 1
|
||||
context:
|
||||
image_command_customizer:
|
||||
command:
|
||||
local_path: "~/.rally/extra/install_benchmark.sh"
|
||||
remote_path: "./install_benchmark.sh"
|
||||
flavor:
|
||||
name: "m1.tiny"
|
||||
image:
|
||||
name: {{image_name}}
|
||||
username: "cirros"
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
network:
|
||||
dns_nameservers: []
|
||||
|
||||
VMTasks.dd_load_test:
|
||||
-
|
||||
args:
|
||||
flavor:
|
||||
name: "m1.tiny"
|
||||
image:
|
||||
name: {{image_name}}
|
||||
floating_network: "public"
|
||||
force_delete: false
|
||||
username: "cirros"
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 1
|
||||
network: {}
|
||||
|
@ -606,13 +606,42 @@ class NovaScenario(scenario.OpenStackScenario):
|
||||
"""Add floating IP to an instance
|
||||
|
||||
:param server: The :class:`Server` to add an IP to.
|
||||
:param address: The ip address or FloatingIP to add to the instance
|
||||
:param address: The dict-like representation of FloatingIP to add
|
||||
to the instance
|
||||
:param fixed_address: The fixedIP address the FloatingIP is to be
|
||||
associated with (optional)
|
||||
"""
|
||||
server.add_floating_ip(address, fixed_address=fixed_address)
|
||||
with atomic.ActionTimer(self, "neutron.list_ports"):
|
||||
ports = self.clients("neutron").list_ports(device_id=server.id)
|
||||
port = ports["ports"][0]
|
||||
|
||||
fip = address
|
||||
if not isinstance(address, dict):
|
||||
LOG.warning(
|
||||
"The argument 'address' of "
|
||||
"NovaScenario._associate_floating_ip method accepts a "
|
||||
"dict-like representation of floating ip. Transmitting a "
|
||||
"string with just an IP is deprecated.")
|
||||
with atomic.ActionTimer(self, "neutron.list_floating_ips"):
|
||||
all_fips = self.clients("neutron").list_floatingips(
|
||||
tenant_id=self.context["tenant"]["id"])
|
||||
filtered_fip = [f for f in all_fips["floatingips"]
|
||||
if f["floating_ip_address"] == address]
|
||||
if not filtered_fip:
|
||||
raise exceptions.NotFoundException(
|
||||
"There is no floating ip with '%s' address." % address)
|
||||
fip = filtered_fip[0]
|
||||
# the first case: fip object is returned from network wrapper
|
||||
# the second case: from neutronclient directly
|
||||
fip_ip = fip.get("ip", fip.get("floating_ip_address", None))
|
||||
fip_update_dict = {"port_id": port["id"]}
|
||||
if fixed_address:
|
||||
fip_update_dict["fixed_ip_address"] = fixed_address
|
||||
self.clients("neutron").update_floatingip(
|
||||
fip["id"], {"floatingip": fip_update_dict}
|
||||
)
|
||||
utils.wait_for(server,
|
||||
is_ready=self.check_ip_address(address),
|
||||
is_ready=self.check_ip_address(fip_ip),
|
||||
update_resource=utils.get_from_manager())
|
||||
# Update server data
|
||||
server.addresses = server.manager.get(server.id).addresses
|
||||
@ -622,12 +651,34 @@ class NovaScenario(scenario.OpenStackScenario):
|
||||
"""Remove floating IP from an instance
|
||||
|
||||
:param server: The :class:`Server` to add an IP to.
|
||||
:param address: The ip address or FloatingIP to remove
|
||||
:param address: The dict-like representation of FloatingIP to remove
|
||||
"""
|
||||
server.remove_floating_ip(address)
|
||||
fip = address
|
||||
if not isinstance(fip, dict):
|
||||
LOG.warning(
|
||||
"The argument 'address' of "
|
||||
"NovaScenario._dissociate_floating_ip method accepts a "
|
||||
"dict-like representation of floating ip. Transmitting a "
|
||||
"string with just an IP is deprecated.")
|
||||
with atomic.ActionTimer(self, "neutron.list_floating_ips"):
|
||||
all_fips = self.clients("neutron").list_floatingips(
|
||||
tenant_id=self.context["tenant"]["id"]
|
||||
)
|
||||
filtered_fip = [f for f in all_fips["floatingips"]
|
||||
if f["floating_ip_address"] == address]
|
||||
if not filtered_fip:
|
||||
raise exceptions.NotFoundException(
|
||||
"There is no floating ip with '%s' address." % address)
|
||||
fip = filtered_fip[0]
|
||||
self.clients("neutron").update_floatingip(
|
||||
fip["id"], {"floatingip": {"port_id": None}}
|
||||
)
|
||||
# the first case: fip object is returned from network wrapper
|
||||
# the second case: from neutronclient directly
|
||||
fip_ip = fip.get("ip", fip.get("floating_ip_address", None))
|
||||
utils.wait_for(
|
||||
server,
|
||||
is_ready=self.check_ip_address(address, must_exist=False),
|
||||
is_ready=self.check_ip_address(fip_ip, must_exist=False),
|
||||
update_resource=utils.get_from_manager()
|
||||
)
|
||||
# Update server data
|
||||
@ -640,8 +691,8 @@ class NovaScenario(scenario.OpenStackScenario):
|
||||
def _check_addr(resource):
|
||||
for network, addr_list in resource.addresses.items():
|
||||
for addr in addr_list:
|
||||
if ip_to_check == addr["addr"]:
|
||||
return must_exist
|
||||
if ip_to_check == addr["addr"]:
|
||||
return must_exist
|
||||
return not must_exist
|
||||
return _check_addr
|
||||
|
||||
|
@ -170,7 +170,7 @@ class VMScenario(nova_utils.NovaScenario):
|
||||
ext_network=floating_network,
|
||||
tenant_id=server.tenant_id, fixed_ip=fixed_ip)
|
||||
|
||||
self._associate_floating_ip(server, fip["ip"], fixed_address=fixed_ip)
|
||||
self._associate_floating_ip(server, fip, fixed_address=fixed_ip)
|
||||
|
||||
return fip
|
||||
|
||||
@ -179,7 +179,7 @@ class VMScenario(nova_utils.NovaScenario):
|
||||
with logging.ExceptionLogger(
|
||||
LOG, "Unable to delete IP: %s" % fip["ip"]):
|
||||
if self.check_ip_address(fip["ip"])(server):
|
||||
self._dissociate_floating_ip(server, fip["ip"])
|
||||
self._dissociate_floating_ip(server, fip)
|
||||
with atomic.ActionTimer(self, "neutron.delete_floating_ip"):
|
||||
network_wrapper.wrap(self.clients,
|
||||
self).delete_floating_ip(
|
||||
|
@ -38,12 +38,8 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
|
||||
self.floating_ip = mock.Mock()
|
||||
self.image = mock.Mock()
|
||||
self.context.update(
|
||||
{"user": {"id": "fake_user_id", "credential": mock.MagicMock()}})
|
||||
|
||||
def _context_with_networks(self, networks):
|
||||
retval = {"tenant": {"networks": networks}}
|
||||
retval.update(self.context)
|
||||
return retval
|
||||
{"user": {"id": "fake_user_id", "credential": mock.MagicMock()},
|
||||
"tenant": {"id": "fake_tenant"}})
|
||||
|
||||
def _context_with_secgroup(self, secgroup):
|
||||
retval = {"user": {"secgroup": secgroup,
|
||||
@ -140,9 +136,12 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
|
||||
"nova.boot_server")
|
||||
|
||||
def test__boot_server_with_network_exception(self):
|
||||
self.context.update({"tenant": {"networks": None}})
|
||||
|
||||
self.clients("nova").servers.create.return_value = self.server
|
||||
|
||||
nova_scenario = utils.NovaScenario(
|
||||
context=self._context_with_networks(None))
|
||||
context=self.context)
|
||||
self.assertRaises(TypeError, nova_scenario._boot_server,
|
||||
"image_id", "flavor_id",
|
||||
auto_assign_nic=True)
|
||||
@ -506,32 +505,121 @@ class NovaScenarioTestCase(test.ScenarioTestCase):
|
||||
|
||||
def test__associate_floating_ip(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
nova_scenario._associate_floating_ip(self.server, self.floating_ip)
|
||||
self.server.add_floating_ip.assert_called_once_with(self.floating_ip,
|
||||
fixed_address=None)
|
||||
neutronclient = nova_scenario.clients("neutron")
|
||||
neutronclient.list_ports.return_value = {"ports": [{"id": "p1"},
|
||||
{"id": "p2"}]}
|
||||
|
||||
fip_ip = "172.168.0.1"
|
||||
fip_id = "some"
|
||||
# case #1- an object from neutronclient
|
||||
floating_ip = {"floating_ip_address": fip_ip, "id": fip_id}
|
||||
|
||||
nova_scenario._associate_floating_ip(self.server, floating_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": "p1"}}
|
||||
)
|
||||
# case #2 - an object from network wrapper
|
||||
neutronclient.update_floatingip.reset_mock()
|
||||
floating_ip = {"ip": fip_ip, "id": fip_id}
|
||||
|
||||
nova_scenario._associate_floating_ip(self.server, floating_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": "p1"}}
|
||||
)
|
||||
|
||||
# these should not be called in both cases
|
||||
self.assertFalse(neutronclient.list_floatingips.called)
|
||||
# it is an old behavior. let's check that it was not called
|
||||
self.assertFalse(self.server.add_floating_ip.called)
|
||||
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.associate_floating_ip", count=2)
|
||||
|
||||
def test__associate_floating_ip_deprecated_behavior(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
neutronclient = nova_scenario.clients("neutron")
|
||||
neutronclient.list_ports.return_value = {"ports": [{"id": "p1"},
|
||||
{"id": "p2"}]}
|
||||
|
||||
fip_id = "fip1"
|
||||
fip_ip = "172.168.0.1"
|
||||
neutronclient.list_floatingips.return_value = {
|
||||
"floatingips": [
|
||||
{"id": fip_id, "floating_ip_address": fip_ip},
|
||||
{"id": "fip2", "floating_ip_address": "127.0.0.1"}]}
|
||||
|
||||
nova_scenario._associate_floating_ip(self.server, fip_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": "p1"}}
|
||||
)
|
||||
|
||||
neutronclient.list_floatingips.assert_called_once_with(
|
||||
tenant_id="fake_tenant")
|
||||
|
||||
# it is an old behavior. let's check that it was not called
|
||||
self.assertFalse(self.server.add_floating_ip.called)
|
||||
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.associate_floating_ip")
|
||||
|
||||
def test__associate_floating_ip_with_no_atomic_action(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
nova_scenario._associate_floating_ip(self.server, self.floating_ip)
|
||||
self.server.add_floating_ip.assert_called_once_with(self.floating_ip,
|
||||
fixed_address=None)
|
||||
|
||||
def test__dissociate_floating_ip(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
nova_scenario._dissociate_floating_ip(self.server, self.floating_ip)
|
||||
self.server.remove_floating_ip.assert_called_once_with(
|
||||
self.floating_ip)
|
||||
neutronclient = nova_scenario.clients("neutron")
|
||||
|
||||
fip_ip = "172.168.0.1"
|
||||
fip_id = "some"
|
||||
# case #1- an object from neutronclient
|
||||
floating_ip = {"floating_ip_address": fip_ip, "id": fip_id}
|
||||
|
||||
nova_scenario._dissociate_floating_ip(self.server, floating_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": None}}
|
||||
)
|
||||
# case #2 - an object from network wrapper
|
||||
neutronclient.update_floatingip.reset_mock()
|
||||
floating_ip = {"ip": fip_ip, "id": fip_id}
|
||||
|
||||
nova_scenario._dissociate_floating_ip(self.server, floating_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": None}}
|
||||
)
|
||||
|
||||
# these should not be called in both cases
|
||||
self.assertFalse(neutronclient.list_floatingips.called)
|
||||
# it is an old behavior. let's check that it was not called
|
||||
self.assertFalse(self.server.add_floating_ip.called)
|
||||
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.dissociate_floating_ip", count=2)
|
||||
|
||||
def test__disassociate_floating_ip_deprecated_behavior(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
neutronclient = nova_scenario.clients("neutron")
|
||||
|
||||
fip_id = "fip1"
|
||||
fip_ip = "172.168.0.1"
|
||||
neutronclient.list_floatingips.return_value = {
|
||||
"floatingips": [
|
||||
{"id": fip_id, "floating_ip_address": fip_ip},
|
||||
{"id": "fip2", "floating_ip_address": "127.0.0.1"}]}
|
||||
|
||||
nova_scenario._dissociate_floating_ip(self.server, fip_ip)
|
||||
|
||||
neutronclient.update_floatingip.assert_called_once_with(
|
||||
fip_id, {"floatingip": {"port_id": None}}
|
||||
)
|
||||
|
||||
neutronclient.list_floatingips.assert_called_once_with(
|
||||
tenant_id="fake_tenant")
|
||||
|
||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||
"nova.dissociate_floating_ip")
|
||||
|
||||
def test__dissociate_floating_ip_with_no_atomic_action(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
nova_scenario._dissociate_floating_ip(self.server, self.floating_ip)
|
||||
self.server.remove_floating_ip.assert_called_once_with(
|
||||
self.floating_ip)
|
||||
|
||||
def test__check_ip_address(self):
|
||||
nova_scenario = utils.NovaScenario(context=self.context)
|
||||
fake_server = fakes.FakeServerManager().create("test_server",
|
||||
|
@ -209,8 +209,8 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
scenario, server = self.get_scenario()
|
||||
|
||||
netwrap = mock_wrap.return_value
|
||||
netwrap.create_floating_ip.return_value = {
|
||||
"id": "foo_id", "ip": "foo_ip"}
|
||||
fip = {"id": "foo_id", "ip": "foo_ip"}
|
||||
netwrap.create_floating_ip.return_value = fip
|
||||
|
||||
scenario._attach_floating_ip(
|
||||
server, floating_network="bar_network")
|
||||
@ -221,7 +221,7 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
tenant_id="foo_tenant", fixed_ip="foo_ip")
|
||||
|
||||
scenario._associate_floating_ip.assert_called_once_with(
|
||||
server, "foo_ip", fixed_address="foo_ip")
|
||||
server, fip, fixed_address="foo_ip")
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".network_wrapper.wrap")
|
||||
def test__delete_floating_ip(self, mock_wrap):
|
||||
@ -231,14 +231,14 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
scenario.check_ip_address = mock.Mock(return_value=_check_addr)
|
||||
scenario._dissociate_floating_ip = mock.Mock()
|
||||
|
||||
scenario._delete_floating_ip(
|
||||
server, fip={"id": "foo_id", "ip": "foo_ip"})
|
||||
fip = {"id": "foo_id", "ip": "foo_ip"}
|
||||
scenario._delete_floating_ip(server, fip=fip)
|
||||
|
||||
scenario.check_ip_address.assert_called_once_with(
|
||||
"foo_ip")
|
||||
_check_addr.assert_called_once_with(server)
|
||||
scenario._dissociate_floating_ip.assert_called_once_with(
|
||||
server, "foo_ip")
|
||||
server, fip)
|
||||
mock_wrap.assert_called_once_with(scenario.clients, scenario)
|
||||
mock_wrap.return_value.delete_floating_ip.assert_called_once_with(
|
||||
"foo_id", wait=True)
|
||||
|
Loading…
Reference in New Issue
Block a user