def reboot(self): if self.opts.dry_run: log.debug('dry-run enabled, skipping reboot, quiting instead') self.signal.emit_signal('quit') else: # Should probably run curtin -c $CONFIG unmount -t TARGET first. utils.run_command(["/sbin/reboot"])
def add_user(self, result, is_dry_run=False): if is_dry_run: result = {'username': "******"} else: result = result.copy() self._user = User(**result) usergroups_path = '/usr/share/ubuntu-wsl-oobe/usergroups' build_usergroups_path = os.path.realpath(__file__ + '/../../../usergroups') if os.path.isfile(build_usergroups_path): usergroups_path = build_usergroups_path user_groups = set() if os.path.exists(usergroups_path): with open(usergroups_path) as fp: for line in fp: line = line.strip() if line.startswith('#') or not line: continue user_groups.add(line) oneline_usergroups = ",".join(user_groups) run_command([ "/usr/sbin/useradd", "-m", "-s", "/bin/bash", "-p", result['password'], result['username'] ]) run_command([ "/usr/sbin/usermod", "-a", "-G", oneline_usergroups, result['username'] ]) # creating location for UWP to read from if not os.path.exists('/var/lib/ubuntu-wsl/'): os.makedirs('/var/lib/ubuntu-wsl/') with open('/var/lib/ubuntu-wsl/assigned_account', 'w') as configfile: configfile.write(result['username'])
def reboot(self): if self.opts.dry_run: self.app.exit() else: if platform.machine() == 's390x': run_command(["chreipl", "/target/boot"]) run_command(["/sbin/reboot"])
def disable_ubuntu_wsl_oobe(): """ Stop running ubuntu_wsl_oobe and remove the package """ log.info('disabling ubuntu-wsl-oobe service') run_command([ "apt", "remove", "-y", "ubuntu-wsl-oobe", "ubuntu-wsl-oobe-subiquitycore" ]) return
def reboot(self, context): self.rebooting_event.set() if self.opts.dry_run: self.app.exit() else: if platform.machine() == 's390x': run_command(["chreipl", "/target/boot"]) run_command(["/sbin/reboot"])
def start_ui(self): # clean up old account setup if exist (although there is possibly none) if self.opts.dry_run: run_command( ["/usr/bin/rm", "-rf", "/var/lib/ubuntu-wsl/assigned_account"]) view = WelcomeView(self.model, self) if os.path.exists("/var/lib/ubuntu-wsl/assigned_account"): view = AlreadyCreatedView(self) self.ui.set_body(view)
def set_keyboard(self, layout, variant): path = self.config_path os.makedirs(os.path.dirname(path), exist_ok=True) self.layout = layout self.variant = variant with open(path, 'w') as fp: fp.write(self.config_content) if self.root == '/': run_command(['setupcon', '--save', '--force'])
def reboot(self): if self.opts.dry_run: log.debug('dry-run enabled, skipping reboot, quitting instead') self.signal.emit_signal('quit') else: # TODO Possibly run this earlier, to show a warning; or # switch to shutdown if chreipl fails if platform.machine() == 's390x': utils.run_command(["chreipl", "/target/boot"]) # Should probably run curtin -c $CONFIG unmount -t TARGET first. utils.run_command(["/sbin/reboot"])
def add_vlan(self, device, vlan): cmd = [ 'ip', 'link', 'add', 'name', '%s.%s' % (device.name, vlan), 'link', device.name, 'type', 'vlan', 'id', str(vlan) ] try: run_command(cmd, check=True) except subprocess.CalledProcessError: self.ui.frame.body.show_network_error('add-vlan')
def copy_logs_to_target(self): if self.opts.dry_run: return utils.run_command( ['cp', '-aT', '/var/log/installer', '/target/var/log/installer']) try: with open('/target/var/log/installer/installer-journal.txt', 'w') as output: utils.run_command(['journalctl'], stdout=output, stderr=subprocess.STDOUT) except Exception: log.exception("saving journal failed")
def _bg_copy_logs_to_target(self): if self.opts.dry_run: return target_logs = self.tpath('var/log/installer') utils.run_command(['cp', '-aT', '/var/log/installer', target_logs]) try: with open(os.path.join(target_logs, 'installer-journal.txt'), 'w') as output: utils.run_command(['journalctl'], stdout=output, stderr=subprocess.STDOUT) except Exception: log.exception("saving journal failed")
def add_bond(self, params): cmd = [ 'ip', 'link', 'add', 'name', '%(name)s' % params, 'type', 'bond', 'mode', '%(mode)s' % params ] if params['mode'] in ['balance-xor', '802.3ad', 'balance-tlb']: cmd += ['xmit_hash_policy', '%(xmit_hash_policy)s' % params] if params['mode'] == '802.3ad': cmd += ['lacp_rate', '%(lacp_rate)s' % params] try: run_command(cmd, check=True) except subprocess.CalledProcessError: self.ui.frame.body.show_network_error('add-bond')
def done(self, result): user_settings = result.copy() if not self.opts.dry_run: # reset to keep everything as refreshed as new run_command(["/usr/bin/ubuntuwsl", "reset", "-y"], stdout=subprocess.DEVNULL) # set the settings run_command(["/usr/bin/ubuntuwsl", "update", "WSL.automount.root", user_settings['custom_path']], stdout=subprocess.DEVNULL) run_command(["/usr/bin/ubuntuwsl", "update", "WSL.automount.options", user_settings['custom_mount_opt']], stdout=subprocess.DEVNULL) run_command(["/usr/bin/ubuntuwsl", "update", "WSL.network.generatehosts", user_settings['gen_host']], stdout=subprocess.DEVNULL) run_command(["/usr/bin/ubuntuwsl", "update", "WSL.network.generateresolvconf", user_settings['gen_resolvconf']], stdout=subprocess.DEVNULL) self.app.next_screen()
def identity_done(self, email): if self.opts.dry_run: result = { 'realname': email, 'username': email, } self.model.add_user(result) login_details_path = '.subiquity/login-details.txt' else: self.app.urwid_loop.draw_screen() cp = run_command( ["snap", "create-user", "--sudoer", "--json", email]) if cp.returncode != 0: if isinstance(self.ui.body, IdentityView): self.ui.body.snap_create_user_failed( "Creating user failed:", cp.stderr) return else: data = json.loads(cp.stdout) result = { 'realname': email, 'username': data['username'], } os.makedirs('/run/console-conf', exist_ok=True) login_details_path = '/run/console-conf/login-details.txt' self.model.add_user(result) ips = [] net_model = self.app.base_model.network for dev in net_model.get_all_netdevs(): ips.extend(dev.actual_global_ip_addresses) with open(login_details_path, 'w') as fp: write_login_details(fp, result['username'], ips) self.login()
def identity_done(self, email): if self.opts.dry_run: result = { 'realname': email, 'username': email, } self.model.add_user(result) else: self.ui.frame.body.progress.set_text("Contacting store...") self.loop.draw_screen() result = run_command(["snap", "create-user", "--sudoer", "--json", email]) self.ui.frame.body.progress.set_text("") if result['status'] != 0: self.ui.frame.body.error.set_text("Creating user failed:\n" + result['err']) return else: # mark ourselves complete mark_firstboot_complete() data = json.loads(result['output']) result = { 'realname': email, 'username': data['username'], } self.model.add_user(result) self.signal.emit_signal('identity:login')
def configure_proxy(self, proxy): log.debug("restarting snapd to pick up proxy config") dropin_dir = os.path.join(self.root, 'etc/systemd/system/snapd.service.d') os.makedirs(dropin_dir, exist_ok=True) with open(os.path.join(dropin_dir, 'snap_proxy.conf'), 'w') as fp: fp.write(proxy.proxy_systemd_dropin()) if self.root == '/': cmds = [ ['systemctl', 'daemon-reload'], ['systemctl', 'restart', 'snapd.service'], ] else: cmds = [['sleep', '2']] for cmd in cmds: run_command(cmd)
def start(self): for dev in self.devs_to_down: try: log.debug('downing %s', dev.name) self.rtlistener.unset_link_flags(dev.ifindex, IFF_UP) except RuntimeError: # We don't actually care very much about this log.exception('unset_link_flags failed for %s', dev.name) for dev in self.devs_to_delete: # XXX would be nicer to do this via rtlistener eventually. log.debug('deleting %s', dev.name) cmd = ['ip', 'link', 'delete', 'dev', dev.name] try: run_command(cmd, check=True) except subprocess.CalledProcessError as cp: log.info("deleting %s failed with %r", dev.name, cp.stderr)
def identity_done(self, email): if self.opts.dry_run: result = { 'realname': email, 'username': email, } self.model.add_user(result) login_details_path = '.subiquity/login-details.txt' else: self.ui.frame.body.progress.set_text("Contacting store...") self.loop.draw_screen() cp = run_command( ["snap", "create-user", "--sudoer", "--json", email]) self.ui.frame.body.progress.set_text("") if cp.returncode != 0: self.ui.frame.body.error.set_text("Creating user failed:\n" + cp.stderr) return else: data = json.loads(cp.stdout) result = { 'realname': email, 'username': data['username'], } os.makedirs('/run/console-conf', exist_ok=True) login_details_path = '/run/console-conf/login-details.txt' self.model.add_user(result) ips = [] net_model = self.controllers['Network'].model for dev in net_model.get_all_netdevs(): ips.extend(dev.actual_global_ip_addresses) with open(login_details_path, 'w') as fp: write_login_details(fp, result['username'], ips) self.login()
def curtin_apply_networking(actions, dryrun=True): log.info('Applying network actions:\n%s', actions) network_commands = [] for entry in actions: if entry['type'] == 'physical': for subnet in entry.get('subnets', []): if subnet['type'] == 'static': cmd = "ifconfig %s %s" % (entry['name'], subnet['address']) if 'netmask' in subnet: cmd += " netmask %s" % subnet['netmask'] cmd += " up" network_commands += [cmd] for cmd in network_commands: log.info('Running command: [%s]', cmd) if not dryrun: utils.run_command(cmd.split(), shell=False)
def get_target_groups(self): command = ['chroot', self.target, 'getent', 'group'] if self.root != '/': del command[:2] cp = run_command(command, check=True) groups = set() for line in cp.stdout.splitlines(): groups.add(line.split(':')[0]) return groups
def _data_ready(self, fd): cp = run_command(['udevadm', 'settle', '-t', '0']) if cp.returncode != 0: log.debug("waiting 0.1 to let udev event queue settle") self.stop_watching() loop = asyncio.get_event_loop() loop.call_later(0.1, self.start_watching) return self.observer.data_ready(fd)
def _data_ready(self, fd): cp = run_command(['udevadm', 'settle', '-t', '0']) if cp.returncode != 0: log.debug("waiting 0.1 to let udev event queue settle") self.loop.set_alarm_in(0.1, lambda loop, ud: self._data_ready(fd)) return self.observer.data_ready(fd) v = self.ui.frame.body if hasattr(v, 'refresh_model_inputs'): v.refresh_model_inputs()
def create_user(userinfo, dryrun=False, extra_args=[]): """Create a user according to the information in userinfo.""" usercmds = [] username = userinfo['username'] useradd = ["useradd", "-m", "-p", userinfo['confirm_password'], username] + extra_args usercmds.append(useradd) if 'ssh_import_id' in userinfo: target = "/home/{}/.ssh/authorized_keys".format(username) ssh_id = userinfo['ssh_import_id'] if ssh_id.startswith('sso'): log.info('call out to SSO login') else: ssh_import_id = ["ssh-import-id", "-o", target, ssh_id] usercmds.append(ssh_import_id) if not dryrun: for cmd in usercmds: # TODO(mwhudson): Check return value! run_command(cmd, shell=False) # always run chown last homedir = '/home/' + username retries = 10 while not os.path.exists(homedir) and retries > 0: log.debug('waiting on homedir') retries -= 1 time.sleep(0.2) if retries <= 0: raise ValueError('Failed to create homedir') chown = ["chown", "{0}.{0}".format(username), "-R", homedir] # TODO(mwhudson): Check return value! run_command(chown, shell=False) # add sudo rule with open('/etc/sudoers.d/firstboot-user', 'w') as fh: fh.write('# firstboot config added user\n\n') fh.write('{} ALL=(ALL) NOPASSWD:ALL\n'.format(username)) else: log.info('dry-run, skiping user configuration')
def add_master(self, device, master_dev=None, master_name=None): # Drop ip configs for ip in [4, 6]: device.remove_ip_networks_for_version(ip) device.set_dhcp_for_version(ip, False) down_cmd = ['ip', 'link', 'set', 'dev', device.name, 'down'] cmd = ['ip', 'link', 'set', 'dev', device.name] if master_dev: master_name = master_dev.name if master_name: cmd += ['master', master_name] else: cmd += ['nomaster'] try: # Down the interface, and set new master run_command(down_cmd, check=True) run_command(cmd, check=True) except subprocess.CalledProcessError: self.ui.frame.body.show_network_error('add-master')
def start_ui(self): self.ui.set_body(IdentityView(self.model, self)) device_owner = get_device_owner() if device_owner is not None: self.model.add_user(device_owner) key_file = os.path.join(device_owner['homedir'], ".ssh/authorized_keys") self.model.user.fingerprints = (run_command( ['ssh-keygen', '-lf', key_file]).stdout.replace('\r', '').splitlines()) self.login()
def fingerprints(keyfile): info = [] cp = run_command(['ssh-keygen', '-lf', keyfile]) if cp.returncode != 0: log.debug("ssh-keygen -lf %s failed %r", keyfile, cp.stderr) return info for line in cp.stdout.splitlines(): parts = line.strip().replace('\r', '').split() fingerprint = parts[1] keytype = parts[-1].strip('()') info.append((keytype, fingerprint)) return info
def _data_ready(self, fd): cp = run_command(['udevadm', 'settle', '-t', '0']) if cp.returncode != 0: log.debug("waiting 0.1 to let udev event queue settle") self.stop_watching() loop = asyncio.get_event_loop() loop.call_later(0.1, self.start_watching) return self.observer.data_ready(fd) v = self.ui.body if isinstance(v._w, StretchyOverlay): if hasattr(v._w.stretchy, 'refresh_model_inputs'): v._w.stretchy.refresh_model_inputs()
def make_ui(self): if get_managed(): device_owner = get_device_owner() if device_owner: self.model.add_user(device_owner) key_file = os.path.join(device_owner['homedir'], ".ssh/authorized_keys") cp = run_command(['ssh-keygen', '-lf', key_file]) self.model.user.fingerprints = (cp.stdout.replace( '\r', '').splitlines()) return self.make_login_view() else: return IdentityView(self.model, self)
def set_installer_password(self): if self.cloud is None: return passfile = self.state_path("installer-user-passwd") if os.path.exists(passfile): with open(passfile) as fp: contents = fp.read() self.installer_user_passwd_kind = PasswordKind.KNOWN self.installer_user_name, self.installer_user_passwd = \ contents.split(':', 1) return def use_passwd(passwd): self.installer_user_passwd = passwd self.installer_user_passwd_kind = PasswordKind.KNOWN with open(passfile, 'w') as fp: fp.write(self.installer_user_name + ':' + passwd) if self.opts.dry_run: self.installer_user_name = os.environ['USER'] use_passwd(rand_user_password()) return (users, _groups) = ug_util.normalize_users_groups( self.cloud.cfg, self.cloud.distro) (username, _user_config) = ug_util.extract_default(users) self.installer_user_name = username if self._user_has_password(username): # Was the password set to a random password by a version of # cloud-init that records the username in the log? (This is the # case we hit on upgrading the subiquity snap) passwd = get_installer_password_from_cloudinit_log() if passwd: use_passwd(passwd) else: self.installer_user_passwd_kind = PasswordKind.UNKNOWN elif not user_key_fingerprints(username): passwd = rand_user_password() cp = run_command('chpasswd', input=username + ':'+passwd+'\n') if cp.returncode == 0: use_passwd(passwd) else: log.info("setting installer password failed %s", cp) self.installer_user_passwd_kind = PasswordKind.NONE else: self.installer_user_passwd_kind = PasswordKind.NONE
def host_key_fingerprints(): """Query sshd to find the host keys and then fingerprint them. Returns a sequence of (key-type, fingerprint) pairs. """ config = run_command(['sshd', '-T']) if config.returncode != 0: log.debug("sshd -T failed %r", config['err']) return [] keyfiles = [] for line in config.stdout.splitlines(): if line.startswith('hostkey '): keyfiles.append(line.split(None, 1)[1]) info = [] for keyfile in keyfiles: cp = run_command(['ssh-keygen', '-lf', keyfile]) if cp.returncode != 0: log.debug("ssh-keygen -lf %s failed %r", keyfile, cp.stderr) continue parts = cp.stdout.strip().split() length, fingerprint, host, keytype = parts keytype = keytype.strip('()') info.append((keytype, fingerprint)) return info