From 1c39cd198513ed983c2025f9a6ed8022c76509f5 Mon Sep 17 00:00:00 2001 From: gryf Date: Fri, 22 Apr 2022 07:53:50 +0200 Subject: [PATCH] Add ability to set different default username. During cloud init user might want to change default user from the distribution to something else. It will not be possible to ssh to such machine using boxpy ssh command - only using ssh directly with the correct user name would be possible. In this change there is added possibility for setting username in boxpy_data section with desired value to be used in ssh command. --- box.py | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/box.py b/box.py index 8661007..805ecce 100755 --- a/box.py +++ b/box.py @@ -349,7 +349,7 @@ class FakeLogger: class Config: ATTRS = ('cpus', 'config', 'creator', 'disable_nested', 'disk_size', 'distro', 'forwarding', 'hostname', 'key', 'memory', 'name', - 'port', 'version') + 'port', 'version', 'username') def __init__(self, args, vbox=None): self.advanced = None @@ -365,6 +365,7 @@ class Config: self.name = args.name # this one is not stored anywhere self.port = None # at least is not even tried to be retrieved self.version = None + self.username = None self._conf = {} # set defaults stored in hard coded yaml @@ -1181,32 +1182,50 @@ def vmcreate(args, conf=None): # than, let's try to see if boostraping process has finished LOG.info('Waiting for cloud init to finish ', end='') + username = DISTROS[conf.distro]["username"] cmd = ['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'ConnectTimeout=2', '-i', conf.ssh_key_path[:-4], - f'ssh://{DISTROS[conf.distro]["username"]}' - f'@localhost:{vbox.vm_info["port"]}', 'sudo cloud-init status'] + f'ssh://{username}@localhost:{vbox.vm_info["port"]}', + 'sudo cloud-init status'] try: while True: - out = Run(cmd).stdout - LOG.debug('Out: %s', out) + out = Run(cmd) + LOG.debug('Out: %s', out.stdout) - if (not out) or ('status' in out and 'running' in out): + if (not out.stdout) or ('status' in out.stdout and + 'running' in out.stdout): LOG.info('.', end='') sys.stdout.flush() + if 'Permission denied (publickey)' in out.stderr: + if conf.username and conf.username != username: + username = conf.username + vbox.setextradata('username', username) + cmd[9] = (f'ssh://{username}' + f'@localhost:{vbox.vm_info["port"]}') + continue + raise PermissionError(f'There is an issue with accessing ' + f'VM with ssh for user {username}. ' + f'Check output in debug mode.') time.sleep(3) continue LOG.info(' done') break - out = out.split(':')[1].strip() + out = out.stdout.split(':')[1].strip() if out != 'done': cmd = cmd[:-1] cmd.append('cloud-init status -l') LOG.warning('Cloud init finished with "%s" status:\n%s', out, Run(cmd).stdout) + except PermissionError: + LOG.info('\n') + iso.cleanup() + image.cleanup() + vbox.destroy() + raise except KeyboardInterrupt: LOG.warning('\nInterrupted, cleaning up') iso.cleanup() @@ -1220,9 +1239,14 @@ def vmcreate(args, conf=None): # reread config to update fields conf = Config(args, vbox) + username = DISTROS[conf.distro]["username"] LOG.info('You can access your VM by issuing:') - LOG.info(f'ssh -p {conf.port} -i {conf.ssh_key_path[:-4]} ' - f'{DISTROS[conf.distro]["username"]}@localhost') + if conf.username and conf.username != username: + LOG.info(f'ssh -p {conf.port} -i {conf.ssh_key_path[:-4]} ' + f'{conf.username}@localhost') + else: + LOG.info(f'ssh -p {conf.port} -i {conf.ssh_key_path[:-4]} ' + f'{username}@localhost') LOG.info('or simply:') LOG.info(f'boxpy ssh {conf.name}') return 0 @@ -1388,10 +1412,11 @@ def connect(args): f'file.') return 16 + username = conf.username or DISTROS[conf.distro]["username"] return Run(['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-i', conf.ssh_key_path[:-4], - f'ssh://{DISTROS[conf.distro]["username"]}' + f'ssh://{username}' f'@localhost:{conf.port}'], False).returncode