Skip to content

Commit a614c16

Browse files
authored
Merge pull request #2067 from kshtsk/wip-remote-resolve-ip
orchestra/remote: add resolve_ip method
2 parents 6fb2580 + 00ab01d commit a614c16

File tree

5 files changed

+71
-2
lines changed

5 files changed

+71
-2
lines changed

.github/workflows/dependencies.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ jobs:
3434
cd ./virtualenv/lib/python*
3535
touch no-global-site-packages.txt
3636
working-directory: ./teuthology
37+
- name: Refresh system repos
38+
run: |
39+
sudo apt update -y
40+
sudo apt upgrade -y
3741
- name: Initial bootstrap
3842
run: ./bootstrap install
3943
working-directory: ./teuthology

bootstrap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ PY_MAJOR=$($VENV/bin/python -c "import sys; print(sys.version_info[0])")
128128
PY_MINOR=$($VENV/bin/python -c "import sys; print(sys.version_info[1])")
129129

130130
# Python version check
131-
if [ "$PY_MAJOR" -ne 3 || "$PY_MINOR" -lt 10 ]; then
131+
if [[ "$PY_MAJOR" -ne 3 || "$PY_MINOR" -lt 10 ]]; then
132132
echo "Python version should be 3.10 or higher, found $PY_MAJOR.$PY_MINOR"
133133
exit 1
134134
fi

containers/teuthology-dev/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ RUN \
3131
PIP_INSTALL_FLAGS="-r requirements.txt" ./bootstrap
3232
COPY . /teuthology
3333
RUN \
34-
git config -f ./.git/config --unset 'http.https://github.com/.extraheader' && \
34+
(git config -f ./.git/config --unset 'http.https://github.com/.extraheader' || true ) && \
3535
./bootstrap
3636
COPY containers/teuthology-dev/containerized_node.yaml /teuthology
3737
COPY containers/teuthology-dev/.teuthology.yaml /root

teuthology/orchestra/remote.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,46 @@ def _set_iface_and_cidr(self):
461461
return
462462
raise RuntimeError("Could not determine interface/CIDR!")
463463

464+
465+
def resolve_ip(self, name=None, ipv='4') -> str:
466+
"""
467+
Resolve IP address of the remote host via remote host
468+
469+
Because remote object maybe behind bastion host we need
470+
the remote host address resolvable from remote side.
471+
So in order to the ip address we just call `host` remotely
472+
and parse output like:
473+
'smithi001.front.sepia.ceph.com has address 172.21.15.1\n'
474+
475+
:param name: hostname to resolve, by defaults remote host itself.
476+
:param ipv: the IP version, 4 or 6, defaults to 4.
477+
478+
:raises: :class:`Exception`: when the hostname cannot be resolved.
479+
:raises: :class:`ValueError`: when the ipv argument mismatch 4 or 6.
480+
481+
:returns: str object, the ip addres of the remote host.
482+
"""
483+
hostname = name or self.hostname
484+
version = str(ipv)
485+
if version in ['4', '6']:
486+
remote_host_ip = self.sh(f'host -{ipv} {hostname}')
487+
else:
488+
raise ValueError(f'Unknown IP version {ipv}, expected 4 or 6')
489+
# `host -4` or `host -6` may have multiline output: a host can have
490+
# several address; thus try and find the first suitable
491+
for info in remote_host_ip.split("\n"):
492+
if version == '4' and 'has address' in info:
493+
(host, ip) = info.strip().split(' has address ')
494+
if hostname in host:
495+
return ip
496+
elif version == '6' and 'has IPv6 address' in info:
497+
(host, ip) = info.strip().split(' has IPv6 address ')
498+
if hostname in host:
499+
return ip
500+
else:
501+
raise Exception(f'Cannot get IPv{ipv} address for the host "{hostname}" via remote "{self.hostname}"')
502+
503+
464504
@property
465505
def hostname(self):
466506
if not hasattr(self, '_hostname'):

teuthology/orchestra/test/test_remote.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,31 @@ def test_is_container(self):
221221
rem2._runner = m_run
222222
assert not rem2.is_container
223223

224+
@patch("teuthology.orchestra.remote.Remote.sh")
225+
def test_resolve_ip(self, m_sh):
226+
r = remote.Remote(name="jdoe@xyzzy.example.com", ssh=self.m_ssh)
227+
m_sh.return_value = "smithi001.front.sepia.ceph.com has address 172.21.15.1\n"
228+
ip4 = remote.Remote.resolve_ip(r, 'smithi001')
229+
assert ip4 == "172.21.15.1"
230+
m_sh.return_value = "\n"
231+
try:
232+
ip4 = remote.Remote.resolve_ip(r, 'smithi001')
233+
except Exception as e:
234+
assert 'Cannot get IPv4 address' in str(e)
235+
try:
236+
ip4 = remote.Remote.resolve_ip(r, 'smithi001', 5)
237+
except Exception as e:
238+
assert 'Unknown IP version' in str(e)
239+
240+
m_sh.return_value = ("google.com has address 142.251.37.14\n"
241+
"google.com has IPv6 address 2a00:1450:4016:80b::200e\n"
242+
"google.com mail is handled by 10 smtp.google.com.\n")
243+
ip4 = remote.Remote.resolve_ip(r, 'google.com')
244+
assert ip4 == "142.251.37.14"
245+
ip6 = remote.Remote.resolve_ip(r, 'google.com', '6')
246+
assert ip6 == "2a00:1450:4016:80b::200e"
247+
248+
224249
@patch("teuthology.orchestra.remote.Remote.run")
225250
def test_write_file(self, m_run):
226251
file = "fakefile"

0 commit comments

Comments
 (0)