[VM] refactor wait_for_ping
Old error message was awful in case of ip is icmp down. In this patch: * Method `wait_for` is replaced by `wait_for_statuses`, since `wait_for` is deprecated and will be removed in near future; * Representation of ready statuses for TimeoutException is changed( example: `to become set(['ok', 'success']) -> `to become ('ok', 'success')`) * All logic related to `host` is moved to separate class, since it is just a helper and doesn't relate to VMUtils class and scenarios. Error message before this patch: Rally tired waiting for IPAddress IPAddress('172.24.4.16'):<no id> to become ICMP UP current status NONE After: Rally tired waiting for Host ip:172.24.4.16 to become ('ICMP UP') current status ICMP DOWN Change-Id: I4d950bfd097731611188dc7f302fedbb83669a39
This commit is contained in:
parent
1863ac6a69
commit
d90ab5e8b5
@ -32,9 +32,6 @@ from rally.task import validation
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
ICMP_UP_STATUS = "ICMP UP"
|
||||
ICMP_DOWN_STATUS = "ICMP DOWN"
|
||||
|
||||
VM_BENCHMARK_OPTS = [
|
||||
cfg.FloatOpt("vm_ping_poll_interval", default=1.0,
|
||||
help="Interval between checks when waiting for a VM to "
|
||||
@ -47,6 +44,49 @@ benchmark_group = cfg.OptGroup(name="benchmark", title="benchmark options")
|
||||
CONF.register_opts(VM_BENCHMARK_OPTS, group=benchmark_group)
|
||||
|
||||
|
||||
class Host(object):
|
||||
|
||||
ICMP_UP_STATUS = "ICMP UP"
|
||||
ICMP_DOWN_STATUS = "ICMP DOWN"
|
||||
|
||||
name = "ip"
|
||||
|
||||
def __init__(self, ip):
|
||||
self.ip = netaddr.IPAddress(ip)
|
||||
self.status = self.ICMP_DOWN_STATUS
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.ip.format()
|
||||
|
||||
@classmethod
|
||||
def update_status(cls, server):
|
||||
"""Check ip address is pingable and update status."""
|
||||
ping = "ping" if server.ip.version == 4 else "ping6"
|
||||
if sys.platform.startswith("linux"):
|
||||
cmd = [ping, "-c1", "-w1", server.ip.format()]
|
||||
else:
|
||||
cmd = [ping, "-c1", server.ip.format()]
|
||||
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
proc.wait()
|
||||
LOG.debug("Host %s is ICMP %s"
|
||||
% (server.ip.format(), proc.returncode and "down" or "up"))
|
||||
if proc.returncode == 0:
|
||||
server.status = cls.ICMP_UP_STATUS
|
||||
else:
|
||||
server.status = cls.ICMP_DOWN_STATUS
|
||||
return server
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Host):
|
||||
raise TypeError("%s should be an instance of %s" % (
|
||||
other, Host.__class__.__name__))
|
||||
return self.ip == other.ip and self.status == other.status
|
||||
|
||||
|
||||
class VMScenario(nova_utils.NovaScenario, cinder_utils.CinderScenario):
|
||||
"""Base class for VM scenarios with basic atomic actions.
|
||||
|
||||
@ -158,10 +198,11 @@ class VMScenario(nova_utils.NovaScenario, cinder_utils.CinderScenario):
|
||||
|
||||
@atomic.action_timer("vm.wait_for_ping")
|
||||
def _wait_for_ping(self, server_ip):
|
||||
server_ip = netaddr.IPAddress(server_ip)
|
||||
utils.wait_for(
|
||||
server_ip,
|
||||
is_ready=utils.resource_is(ICMP_UP_STATUS, self._ping_ip_address),
|
||||
server = Host(server_ip)
|
||||
utils.wait_for_status(
|
||||
server,
|
||||
ready_statuses=[Host.ICMP_UP_STATUS],
|
||||
update_resource=Host.update_status,
|
||||
timeout=CONF.benchmark.vm_ping_timeout,
|
||||
check_interval=CONF.benchmark.vm_ping_poll_interval
|
||||
)
|
||||
@ -191,23 +232,3 @@ class VMScenario(nova_utils.NovaScenario, cinder_utils.CinderScenario):
|
||||
pkey=pkey, password=password)
|
||||
self._wait_for_ssh(ssh)
|
||||
return self._run_command_over_ssh(ssh, command)
|
||||
|
||||
@staticmethod
|
||||
def _ping_ip_address(host):
|
||||
"""Check ip address that it is pingable.
|
||||
|
||||
:param host: instance of `netaddr.IPAddress`
|
||||
"""
|
||||
ping = "ping" if host.version == 4 else "ping6"
|
||||
if sys.platform.startswith("linux"):
|
||||
cmd = [ping, "-c1", "-w1", str(host)]
|
||||
else:
|
||||
cmd = [ping, "-c1", str(host)]
|
||||
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
proc.wait()
|
||||
LOG.debug("Host %s is ICMP %s"
|
||||
% (host, proc.returncode and "down" or "up"))
|
||||
return ICMP_UP_STATUS if (proc.returncode == 0) else ICMP_DOWN_STATUS
|
||||
|
@ -112,13 +112,12 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
vm_scenario = utils.VMScenario(self.context)
|
||||
vm_scenario._ping_ip_address = mock.Mock(return_value=True)
|
||||
vm_scenario._wait_for_ping(netaddr.IPAddress("1.2.3.4"))
|
||||
self.mock_wait_for.mock.assert_called_once_with(
|
||||
netaddr.IPAddress("1.2.3.4"),
|
||||
is_ready=self.mock_resource_is.mock.return_value,
|
||||
self.mock_wait_for_status.mock.assert_called_once_with(
|
||||
utils.Host("1.2.3.4"),
|
||||
ready_statuses=[utils.Host.ICMP_UP_STATUS],
|
||||
update_resource=utils.Host.update_status,
|
||||
timeout=CONF.benchmark.vm_ping_timeout,
|
||||
check_interval=CONF.benchmark.vm_ping_poll_interval)
|
||||
self.mock_resource_is.mock.assert_called_once_with(
|
||||
"ICMP UP", vm_scenario._ping_ip_address)
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".VMScenario._run_command_over_ssh")
|
||||
@mock.patch("rally.common.sshutils.SSH")
|
||||
@ -137,66 +136,6 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
mock_sshutils_ssh.return_value,
|
||||
{"script_file": "foo", "interpreter": "bar"})
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_linux(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "linux2"
|
||||
|
||||
vm_scenario = utils.VMScenario(self.context)
|
||||
host_ip = netaddr.IPAddress("1.2.3.4")
|
||||
self.assertTrue(vm_scenario._ping_ip_address(host_ip))
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping", "-c1", "-w1", str(host_ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_linux_ipv6(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "linux2"
|
||||
|
||||
vm_scenario = utils.VMScenario(self.context)
|
||||
host_ip = netaddr.IPAddress("1ce:c01d:bee2:15:a5:900d:a5:11fe")
|
||||
self.assertTrue(vm_scenario._ping_ip_address(host_ip))
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping6", "-c1", "-w1", str(host_ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_other_os(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "freebsd10"
|
||||
|
||||
vm_scenario = utils.VMScenario(self.context)
|
||||
host_ip = netaddr.IPAddress("1.2.3.4")
|
||||
self.assertTrue(vm_scenario._ping_ip_address(host_ip))
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping", "-c1", str(host_ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_other_os_ipv6(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "freebsd10"
|
||||
|
||||
vm_scenario = utils.VMScenario(self.context)
|
||||
host_ip = netaddr.IPAddress("1ce:c01d:bee2:15:a5:900d:a5:11fe")
|
||||
self.assertTrue(vm_scenario._ping_ip_address(host_ip))
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping6", "-c1", str(host_ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
def get_scenario(self):
|
||||
server = mock.Mock(
|
||||
networks={"foo_net": "foo_data"},
|
||||
@ -308,3 +247,66 @@ class VMScenarioTestCase(test.ScenarioTestCase):
|
||||
mock_wrap.assert_called_once_with(scenario.clients, scenario)
|
||||
mock_wrap.return_value.delete_floating_ip.assert_called_once_with(
|
||||
"foo_id", wait=True)
|
||||
|
||||
|
||||
class HostTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_linux(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "linux2"
|
||||
|
||||
host = utils.Host("1.2.3.4")
|
||||
self.assertEqual(utils.Host.ICMP_UP_STATUS,
|
||||
utils.Host.update_status(host).status)
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping", "-c1", "-w1", str(host.ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_linux_ipv6(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "linux2"
|
||||
|
||||
host = utils.Host("1ce:c01d:bee2:15:a5:900d:a5:11fe")
|
||||
self.assertEqual(utils.Host.ICMP_UP_STATUS,
|
||||
utils.Host.update_status(host).status)
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping6", "-c1", "-w1", str(host.ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_other_os(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "freebsd10"
|
||||
|
||||
host = utils.Host("1.2.3.4")
|
||||
self.assertEqual(utils.Host.ICMP_UP_STATUS,
|
||||
utils.Host.update_status(host).status)
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping", "-c1", str(host.ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
||||
|
||||
@mock.patch(VMTASKS_UTILS + ".sys")
|
||||
@mock.patch("subprocess.Popen")
|
||||
def test__ping_ip_address_other_os_ipv6(self, mock_popen, mock_sys):
|
||||
mock_popen.return_value.returncode = 0
|
||||
mock_sys.platform = "freebsd10"
|
||||
|
||||
host = utils.Host("1ce:c01d:bee2:15:a5:900d:a5:11fe")
|
||||
self.assertEqual(utils.Host.ICMP_UP_STATUS,
|
||||
utils.Host.update_status(host).status)
|
||||
|
||||
mock_popen.assert_called_once_with(
|
||||
["ping6", "-c1", str(host.ip)],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
mock_popen.return_value.wait.assert_called_once_with()
|
Loading…
x
Reference in New Issue
Block a user