diff --git a/README.md b/README.md index de73ee33..2270267e 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,8 @@ of the modules present in `lib`. (TODO: probably move to its own document?) +### SSH into Anaconda + Anaconda-based remediation can be debugged on a virtual machine by issuing `virsh domifaddr contest` (where `contest` is the default VM name) to acquire an IP address of the guest (which gets assigned just before Anaconda launches) @@ -164,6 +166,21 @@ and doing `ssh root@that-ip-addr` from the host running the test itself (and hosting the VM). There is no password for the Anaconda environment, so this will just log you in. +### SSH into installed VMs + +You can use a handy script in the home directory of the VM host's user. +Simply run: + +``` +./contest-sshvm [vm-name] +``` + +The script will find the first contest-installed VM if `vm-name` is not given, +it will check whether the VM is running (as a result of you starting it earlier +or `CONTEST_LEAVE_GUEST_RUNNING=1`) and if not, it will start it and wait for +`sshd` to start responding. It will then `ssh` you into the VM, using +pre-generated SSH keys (no passwords needed). + ## License Unless specified otherwise, any content within this repository is distributed diff --git a/lib/virt.py b/lib/virt.py index 1c5cc0b4..e00276f3 100644 --- a/lib/virt.py +++ b/lib/virt.py @@ -185,6 +185,38 @@ def define_our_network(): else: define_our_network() + @staticmethod + def create_sshvm(dest): + dest = Path(dest) + if dest.exists(): + return + script = util.dedent(r''' + #!/bin/bash + function list { virsh -q list "$@" | sed -rn 's/^ *[-0-9]+ +([^ ]+).*/\1/p'; } + function get_sshkey { f="%SSHKEY_DIR%/$1.sshkey"; [[ -f $f ]] && echo "$f"; } + if [[ $1 ]]; then + vm=$1 sshkey=$(get_sshkey "$vm") + [[ $(virsh -q domstate "$vm") != running ]] && virsh start "$vm" + else + # try running VMs first, fall back to shut off ones + for vm in $(list); do sshkey=$(get_sshkey "$vm") && break; done + [[ -z $sshkey ]] && for vm in $(list --inactive); do + sshkey=$(get_sshkey "$vm") && virsh start "$vm" && break + done + fi + [[ -z $sshkey ]] && { echo "no valid VM found" >&2; exit 1; } + # get ip and ssh to it + ip=$(virsh -q domifaddr "$vm" | sed -rn 's/.+ +([^ ]+)\/[0-9]+$/\1/p') + [[ -z $ip ]] && { echo "could not get IP addr for $vm" >&2; exit 1; } + echo "waiting for ssh on $vm: root@$ip:22" + while ! ncat --send-only -w 1 "$ip" 22 &0; do sleep 0.1; done + ssh -q -i "$sshkey" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ + "root@$ip" + ''') + script = script.replace('%SSHKEY_DIR%', GUEST_IMG_DIR) # f-strings cannot have \ + dest.write_text(script) + dest.chmod(0o755) + @classmethod def setup(self): if not self.check_virt_capability(): @@ -195,6 +227,7 @@ def setup(self): util.subprocess_run(['systemctl', 'start', 'libvirtd'], check=True) self.setup_network() + self.create_sshvm('/root/contest-sshvm') # @@ -570,10 +603,10 @@ def _destroy_snapshotted(self): os.remove(self.snapshot_path) def _log_leave_running_notice(self): - out = textwrap.dedent(f"""\n + out = textwrap.dedent("""\n Leaving guest running, the test might break! To ssh into it, log in (ssh) into the VM host first, then do: - ssh -i {self.ssh_keyfile_path} root@{self.ipaddr} + ./contest-sshvm """) util.log(textwrap.indent(out, ' '), skip_frames=1)