diff --git a/src/main.py b/src/main.py index a0facc4..8def5c0 100644 --- a/src/main.py +++ b/src/main.py @@ -66,6 +66,7 @@ class VMKer: self.config = None self.vm_list = set() self.template = None + self.cmds = {} @staticmethod def generate_key_from_password(password: str, salt: bytes) -> bytes: @@ -143,7 +144,7 @@ class VMKer: logger.error(f"TimeoutError: {e}") return False - def _edit(self, _first_init=False): + def _console(self, _first_init=False): self._load_config() logger.info("Entered to configuration mode.") @@ -250,6 +251,7 @@ class VMKer: print("Incorrect syntax.") print("Usage: edit [server|port|password|ssl|datacenter|datastore|respool] ") case "test": + self._load_yml(True) try: self._connect() except Exception as e: @@ -276,8 +278,62 @@ class VMKer: ipv6.append(ip.ipAddress) return ipv4, ipv6 - def _parse_yml(self, ssh): - pass + def _load_yml(self, test=False): + _f = args.get("f") + if not _f: + return + for f in _f: + try: + f = Path(f) + if not f.exists(): + return logger.error(f"[YML] File not exist: {f}") + if f.is_dir(): + return logger.error(f"[YML] Not a file: {f}") + if f.suffix != ".yml": + return logger.error(f"[YML] File not YAML: {f}") + y = yaml.load(f) + self.cmds[f] = y + if test: + s = f"{f}:" + br = y.get("before-reboot") + if br: + s += "\n Before-Reboot:" + for n, c in br.items(): + s += f"\n {n}:" + for _c in c: + s += f"\n {_c}" + ar = y.get("after-reboot") + if ar: + s += "\n After-Reboot:" + for n, c in ar.items(): + s += f"\n {n}:" + for _c in c: + s += f"\n {_c}" + logger.debug(s) + print(s) + except Exception as e: + logger.exception(e) + + def _execute_yml(self, name, ssh, _pre=True): + for p, f in self.cmds.items(): + try: + if _pre: + y = f.get('before-reboot') + logger.info(f"[{name}] [YML] Executing {f.name}..") + if not y: + return logger.debug(f"[{name}] [YML] Block 'before-reboot' not found. Skipping..") + for n, c in y.items(): + logger.info(f"[{name}] [YML] {n}. Steps: {len(c)}.") + for cmd, i in enumerate(c, 1): + logger.debug(f"executing: {cmd}") + logger.debug(ssh.send_command(cmd)) + logger.info(f"[{name}] [YML] {n}: {i}/{len(c)}") + else: + y = f.get('after-reboot') + if not y: + return logger.debug(f"[{name}] [YML] Block 'after-reboot' not found. Skipping..") + except Exception as e: + logger.exception(e) def _clone(self, new_name, destfolder, clone_spec): logger.info(f"[{new_name}] Cloning from {self.template.name!r}") @@ -322,14 +378,13 @@ class VMKer: try: ssh = ConnectHandler(**_ssh_connect) logger.success(f"[{_name}] [SSH] Connected to {ipv4[0]} as {user} ({key_file=})") - # TODO: length _pwd = ''.join(random.choice(chars) for _ in range(12)) ssh.send_command(f"echo '{user}:{_pwd}' | chpasswd") logger.info(f"[{_name}] Password for root: {_pwd}") ssh.send_command(f'echo {_name} > /etc/hostname') - # TODO: yml - logger.info(f"[{_name}] [YML] Executing %.yml") + logger.info(f"[{_name}] [YML] After-Reboot.") + self._execute_yml(_name, ssh) ssh.disconnect() vm.RebootGuest() @@ -348,7 +403,8 @@ class VMKer: logger.success(f"[{_name}] [SSH] Connected to {ipv4[0]} as {user}") logger.debug(f'[{_name}] uname {ssh.send_command("uname -a")}') - logger.info(f"[{_name}] [YML] Checks %.yml") + logger.info(f"[{_name}] [YML] Before-Reboot.") + self._execute_yml(_name, ssh, False) except NetmikoAuthenticationException as e: return logger.error(f"[{_name}] [SSH] Error: Authentication. ({e})") @@ -387,6 +443,7 @@ class VMKer: return logger.info("Loading...") + self._load_yml() datacenter = [dc for dc in self.content.rootFolder.childEntity if dc.name == self.config['datacenter']] if not datacenter: return logger.error(f"Datacenter not found: {self.config['datacenter']}") @@ -451,9 +508,9 @@ class VMKer: if len(sys.argv) > 1: match sys.argv[1]: case "init": - self._edit(True) - case "edit": - self._edit() + self._console(True) + case "console": + self._console() case "create": self._create() case _: