ubuntu-bugcontrol team mailing list archive
-
ubuntu-bugcontrol team
-
Mailing list archive
-
Message #04663
[Merge] ~jslarraz/ubuntu-qa-tools:add-vm-name-resolution into ubuntu-qa-tools:master
Jorge Sancho Larraz has proposed merging ~jslarraz/ubuntu-qa-tools:add-vm-name-resolution into ubuntu-qa-tools:master.
Commit message:
uvt: add cmd_ssh and perform address resolution using virsh when possible
Requested reviews:
Ubuntu Bug Control (ubuntu-bugcontrol)
For more details, see:
https://code.launchpad.net/~jslarraz/ubuntu-qa-tools/+git/ubuntu-qa-tools/+merge/460382
When trying to create a snap with uvt I was not able to make address resolution using libnss-libvirt to work.
This MR modifies uvt to perform the address resolution internally using `virsh domifaddr` instead of relying on the OS. It will fallback to the old behavior if this resolution does not work.
This MR also add a new command called `uvt ssh <vm-name> (pretty much a shortcut for `uvt cmd <vm-name> bash`) that opens an interactive session in the target machine.
Both changes together may remove the need of network setup (install libnss-libvirt + config /etc/nsswitch.conf) from the setup step on certain configurations. It will additionally enable us to package uvt as a snap
--
Your team Ubuntu Bug Control is requested to review the proposed merge of ~jslarraz/ubuntu-qa-tools:add-vm-name-resolution into ubuntu-qa-tools:master.
diff --git a/vm-tools/uvt b/vm-tools/uvt
index c7b0143..884b5bf 100755
--- a/vm-tools/uvt
+++ b/vm-tools/uvt
@@ -468,6 +468,58 @@ def cmd_cmd():
print("Error: VM '%s' command failed. Aborting." % machine, file=sys.stderr)
sys.exit(1)
+def cmd_ssh():
+ '''Run a command inside a virtual machine'''
+
+ usage = "usage: %prog ssh [options] <vm>"
+
+ epilog = "\n" + \
+ "Eg:\n" + \
+ "$ uvt ssh sec-jammy-amd64\n\n" + \
+ "This will open an interactive session on the single VM named 'sec-jammy-amd64'\n"
+
+ optparse.OptionParser.format_epilog = lambda self, formatter: self.epilog
+ parser = optparse.OptionParser(usage = usage, epilog = epilog)
+
+ parser.add_option("-s", "--start", dest="start", default=False, action='store_true',
+ help="Start the VM (and shutdown if it wasn't running")
+
+ parser.add_option("-t", "--timeout", dest="timeout", default=90, metavar="TIMEOUT",
+ help="wait TIMEOUT seconds for VM to come up if -s is used (default: %default)")
+
+ parser.add_option("-f", "--force-ssh", dest="force_ssh", default=False, action='store_true',
+ help="force the SSH keys to be taken")
+
+ parser.add_option("-r", "--root", dest="root", default=False, action='store_true',
+ help="login to the VM as root")
+
+ parser.add_option("-u", "--user", dest="user", default=None, metavar="USER",
+ help="login to the VM as user")
+
+ parser.add_option("-q", "--quiet", dest="quiet", default=False, action='store_true',
+ help="only report hostnames and output")
+
+ (opt, args) = parser.parse_args()
+ machine = args[0]
+
+ if opt.user is not None and opt.root:
+ print("Error: may specify only one of --root and --user.\n", file=sys.stderr)
+ sys.exit(1)
+
+ print("----- %s -----" % machine)
+ if check_vm_exists(machine) == False:
+ print("Error: VM '%s' does not exist, skipping." % machine, file=sys.stderr)
+ return
+
+ result = vm_run_command(machine, "bash", root=opt.root, start=opt.start,
+ start_timeout=opt.timeout, force_keys=opt.force_ssh,
+ quiet=opt.quiet, output=True, interactive=True,
+ verbose=False, user=opt.user)
+
+ if result == False:
+ print("Error: VM '%s' command failed. Aborting." % machine, file=sys.stderr)
+ sys.exit(1)
+
def cmd_repo():
'''Adds or removes a local repo to a VM'''
@@ -1415,8 +1467,8 @@ def vm_run_command(vm_name, command, root=False, start=False,
print("Could not start VM: %s" % vm_name)
return False
- dns_name = vm_ping(vm_name)
- if dns_name == "":
+ vm_addr = vm_ping(vm_name)
+ if vm_addr == "":
print("Could not ping VM: %s" % vm_name)
return False
@@ -1440,7 +1492,7 @@ def vm_run_command(vm_name, command, root=False, start=False,
ssh_command += ['-q']
ssh_command += ['-o', 'BatchMode=yes']
- ssh_command += [dns_name, command]
+ ssh_command += [vm_addr, command]
if interactive:
rc, out = runcmd(ssh_command, stderr = None, stdout = None, stdin = None)
@@ -1519,9 +1571,9 @@ def vm_stop(vm_name):
# a shutdown menu.
# If we can connect using ssh, issue a shutdown command
- dns_host = vm_ping(vm_name)
- if dns_host != "" and ssh_connect(dns_host):
- vm_run_command(dns_host, "shutdown -h now", root=True,
+ vm_addr = vm_ping(vm_name)
+ if vm_addr != "" and ssh_connect(vm_addr):
+ vm_run_command(vm_addr, "shutdown -h now", root=True,
force_keys=True, output=False, ignore_rc=True)
else:
rc, out = runcmd(["virsh", "--connect", uvt_conf["vm_connect"],
@@ -1563,9 +1615,16 @@ def vm_start_wait(vm_name, timeout=1800, quiet=False, clone_name=None):
def vm_ping(vm_name):
'''Attempts to ping a VM'''
- rc, out = runcmd(["ping", "-c1", "-w1", vm_name])
- if rc == 0 and ssh_connect(vm_name) == True:
- return vm_name
+
+ # Try to resolve address first
+ rc, out = runcmd(["virsh", "--connect", uvt_conf["vm_connect"],
+ "domifaddr", vm_name])
+ addr_search = re.search("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", out)
+ vm_addr = addr_search.group(0) if ((rc == 0) and (addr_search is not None)) else vm_name
+
+ rc, out = runcmd(["ping", "-c1", "-w1", vm_addr])
+ if rc == 0 and ssh_connect(vm_addr) == True:
+ return vm_addr
return ""
def ssh_connect(host, resolve=True):
@@ -3608,6 +3667,7 @@ commands = {
'update' : cmd_update,
'clone' : cmd_clone,
'cmd' : cmd_cmd,
+ 'ssh' : cmd_ssh,
'list' : cmd_list,
'config' : cmd_config,
'dump' : cmd_dump,
Follow ups