return
raise RuntimeError("Could not determine interface/CIDR!")
+
+ def resolve_ip(self, name=None, ipv='4') -> str:
+ """
+ Resolve IP address of the remote host via remote host
+
+ Because remote object maybe behind bastion host we need
+ the remote host address resolvable from remote side.
+ So in order to the ip address we just call `host` remotely
+ and parse output like:
+ 'smithi001.front.sepia.ceph.com has address 172.21.15.1\n'
+
+ :param name: hostname to resolve, by defaults remote host itself.
+ :param ipv: the IP version, 4 or 6, defaults to 4.
+
+ :raises: :class:`Exception`: when the hostname cannot be resolved.
+ :raises: :class:`ValueError`: when the ipv argument mismatch 4 or 6.
+
+ :returns: str object, the ip addres of the remote host.
+ """
+ hostname = name or self.hostname
+ version = str(ipv)
+ if version in ['4', '6']:
+ remote_host_ip = self.sh(f'host -{ipv} {hostname}')
+ else:
+ raise ValueError(f'Unknown IP version {ipv}, expected 4 or 6')
+ # `host -4` or `host -6` may have multiline output: a host can have
+ # several address; thus try and find the first suitable
+ for info in remote_host_ip.split("\n"):
+ if version == '4' and 'has address' in info:
+ (host, ip) = info.strip().split(' has address ')
+ if hostname in host:
+ return ip
+ elif version == '6' and 'has IPv6 address' in info:
+ (host, ip) = info.strip().split(' has IPv6 address ')
+ if hostname in host:
+ return ip
+ else:
+ raise Exception(f'Cannot get IPv{ipv} address for the host "{hostname}" via remote "{self.hostname}"')
+
+
@property
def hostname(self):
if not hasattr(self, '_hostname'):
rem2._runner = m_run
assert not rem2.is_container
+ @patch("teuthology.orchestra.remote.Remote.sh")
+ def test_resolve_ip(self, m_sh):
+ r = remote.Remote(name="jdoe@xyzzy.example.com", ssh=self.m_ssh)
+ m_sh.return_value = "smithi001.front.sepia.ceph.com has address 172.21.15.1\n"
+ ip4 = remote.Remote.resolve_ip(r, 'smithi001')
+ assert ip4 == "172.21.15.1"
+ m_sh.return_value = "\n"
+ try:
+ ip4 = remote.Remote.resolve_ip(r, 'smithi001')
+ except Exception as e:
+ assert 'Cannot get IPv4 address' in str(e)
+ try:
+ ip4 = remote.Remote.resolve_ip(r, 'smithi001', 5)
+ except Exception as e:
+ assert 'Unknown IP version' in str(e)
+
+ m_sh.return_value = ("google.com has address 142.251.37.14\n"
+ "google.com has IPv6 address 2a00:1450:4016:80b::200e\n"
+ "google.com mail is handled by 10 smtp.google.com.\n")
+ ip4 = remote.Remote.resolve_ip(r, 'google.com')
+ assert ip4 == "142.251.37.14"
+ ip6 = remote.Remote.resolve_ip(r, 'google.com', '6')
+ assert ip6 == "2a00:1450:4016:80b::200e"
+
+
@patch("teuthology.orchestra.remote.Remote.run")
def test_write_file(self, m_run):
file = "fakefile"