def __init__(conf: Configuration, name: str, hard: bool, own: bool): ostack = OpenStack(conf) def __work_unit(value: OpenStackVMInfo) -> bool: return ostack.start_instance(value) so = StatusOutput(__work_unit, pool_size=5, additional_errors=ostack.last_errors) servers = ostack.get_server_by_cluster( name, sort=True, filter_func=lambda x: x.state in ServerPowerState.stop_states(), only_owned=own) if not servers: print("No matches or already started") return if Console.confirm_operation("reboot", servers): flatten_servers = [ server for server_pair in servers.values() for server in server_pair ] so.start("Rebooting nodes", objects=flatten_servers) else: print("Aborted....")
def host_selector(ostack: OpenStack, name: str, node_index: Optional[int] = None, own: bool = False) -> OpenStackVMInfo: if name == "None": name = "" if name and node_index == -1: _name, _, _node_index = name.rpartition("-") try: node_index = int(_node_index) name = _name except (ValueError, TypeError): pass if "." in name: name, _ = name.split(".") search_result: Dict[str, List[OpenStackVMInfo]] = ostack.get_server_by_cluster(name, sort=True, only_owned=own) to = TableOutput( TableColumn("Cluster name", 40), print_row_number=True ) if len(search_result.keys()) > 1: to.print_header() for cluster_name in search_result.keys(): to.print_row(cluster_name) selection: int = Console.ask("Choose cluster from the list", int) try: name = list(search_result.keys())[selection:][0] except IndexError: raise ValueError("Wrong selection, please select item within an provided range") elif search_result: name = list(search_result.keys())[0] else: raise ValueError(f"No matching cluster matching pattern'{name}' found") nodes: List[OpenStackVMInfo] = search_result[name] if node_index == -1: if len(nodes) > 1: to = TableOutput( TableColumn("IP", 18), TableColumn("Host name", 40), print_row_number=True ) to.print_header() for node in nodes: to.print_row(node.ip_address, node.fqdn) node_index: int = Console.ask("Choose host from the list", int) if node_index > len(nodes): raise ValueError("Wrong selection, please select item within an provided range") else: node_index = 0 else: node_index -= 1 # the node name starts for 1, while list from 0 try: return nodes[node_index] except IndexError: raise ValueError("Unknown host name, please check the name")
def __init__(conf: Configuration, search_pattern: str, debug: bool, own: bool): vh: ValueHolder = ValueHolder(3) def __fake_filter(s: OpenStackVMInfo): vh.set_if_bigger(WidthConst.max_fqdn_len, len(s.fqdn)) vh.set_if_bigger(WidthConst.max_key_len, len(s.key_name)) vh.set_if_bigger(WidthConst.max_net_len, len(s.net_name)) return False ostack = OpenStack(conf, debug=debug) clusters = ostack.get_server_by_cluster(search_pattern=search_pattern, sort=True, only_owned=own, filter_func=__fake_filter) print_cluster(clusters, vh, ostack)
def __init__(conf: Configuration, search_pattern: str, own: bool): ostack = OpenStack(conf) vh = ValueHolder(2) def __fake_filter(s: OpenStackVMInfo): vh.set_if_bigger(WidthConst.max_cluster_name, len(s.cluster_name)) vh.set_if_bigger(WidthConst.max_vm_type_len, len(s.flavor.name)) return False clusters = ostack.get_server_by_cluster(search_pattern=search_pattern, sort=True, only_owned=own, filter_func=__fake_filter) if search_pattern and len(clusters) == 0: print(f"Query '{search_pattern}' returned no match") return print_cluster(clusters, vh)
def __init__(conf: Configuration, name: str, node_number: int, user_name: str, use_password: bool, use_key: str, own: bool, port: int, internal: bool): ostack = OpenStack(conf) if name == "None": name = "" if use_key == "None": use_key = None if name and node_number == -1: _name, _, _node_number = name.rpartition("-") try: node_number = int(_node_number) name = _name except (ValueError, TypeError): pass if "." in name: name, _ = name.split(".") search_result: Dict[str, List[OpenStackVMInfo]] = ostack.get_server_by_cluster(name, sort=True, only_owned=own) to = TableOutput( TableColumn("Cluster name", 40), print_row_number=True ) if len(search_result.keys()) > 1: to.print_header() for cluster_name in search_result.keys(): to.print_row(cluster_name) selection: int = Console.ask("Choose cluster from the list", int) try: name = list(search_result.keys())[selection:][0] except IndexError: raise ValueError("Wrong selection, please select item within an provided range") elif search_result: name = list(search_result.keys())[0] else: raise ValueError(f"No matching cluster matching pattern'{name}' found") nodes: List[OpenStackVMInfo] = search_result[name] if node_number == -1: if len(nodes) > 1: to = TableOutput( TableColumn("IP", 18), TableColumn("Host name", 40), print_row_number=True ) to.print_header() for node in nodes: to.print_row(node.ip_address, node.fqdn) node_number: int = Console.ask("Choose host from the list", int) if node_number > len(nodes): raise ValueError("Wrong selection, please select item within an provided range") else: node_number = 0 else: node_number -= 1 # the node name starts for 1, while list from 0 try: node: OpenStackVMInfo = nodes[node_number] except IndexError: raise ValueError("Unknown host name, please check the name") print(f"Establishing connection to {node.fqdn}({node.ip_address}) as '{user_name}' user...") if use_password: _open_console(internal, node.ip_address, port=port, user_name=user_name, password=True) else: if not os.path.exists(conf.local_key_dir): os.makedirs(conf.local_key_dir, exist_ok=True) if not use_key and node.key_name and node.key_name in conf.key_names and conf.get_key(node.key_name).private_key: #PKCS8 format -> openssl pkcs8_frmt_B = "-----BEGIN PRIVATE KEY-----" pkcs8_frmt_E ="-----END PRIVATE KEY-----" openssl_frmt_B = "-----BEGIN RSA PRIVATE KEY-----" openssl_frmt_E = "-----END RSA PRIVATE KEY-----" key = conf.get_key(node.key_name).private_key if pkcs8_frmt_B in key: key = key.replace(pkcs8_frmt_B, openssl_frmt_B) if pkcs8_frmt_E in key: key = key.replace(pkcs8_frmt_E, openssl_frmt_E) use_key = os.path.join(conf.local_key_dir, node.key_name) + ".key" with open(use_key, "w+", encoding="UTF-8") as f: f.write(key) try: os.chmod(use_key, 0o600) except OSError: pass else: raise ValueError("No custom key provided nor private key found in the key storage. Please add private key to" " storage or use custom one with 'use-key' argument") _open_console(internal, node.ip_address, user_name=user_name, port=port, key_file=use_key)
def __init__(conf: Configuration, name: str, count: int, flavor: str, image: str, key: str, password: str): def __work_unit(x: OpenStackVMInfo) -> bool: while True: if x.status == ServerState.active: return True if x.status not in [ ServerState.building, ServerState.build, ServerState.active ]: return False sleep(2) # ToDo: short term cache data by reservation_id x = ostack.get_server_by_id(x) # ====================================================================== ostack = OpenStack(conf) vh = ValueHolder(2) def __filter(vm: OpenStackVMInfo) -> bool: r = not str(vm.name).startswith(name) if not r: vh.set_if_bigger(0, len(vm.cluster_name)) vh.set_if_bigger(1, len(vm.flavor.name)) return r servers = ostack.get_server_by_cluster(name, True, filter_func=__filter) if len(servers) > 1: Console.print_warning( f"Cluster with name '{Colors.BRIGHT_WHITE.wrap(name)}' already exists, instance would be not be created" ) print_cluster(servers, vh) return elif len(servers) == 1: Console.print_info( f"The cluster already exists, will add requested amount of hosts to the cluster" ) with Console.status_context( f"Obtaining cluster information from existing {name}..."): cluster_name, hosts = next(iter(servers.items())) cluster_name: str = cluster_name hosts: List[OpenStackVMInfo] = hosts host: OpenStackVMInfo = hosts[0] # re-calculate host names last_host_name = hosts[-1:][0].name _, _, num = last_host_name.rpartition("-") _start_num: int = 1 if num and num.isnumeric(): _start_num: int = int(num) + 1 name: List[str] = [ f"{cluster_name}-{num}" for num in range(_start_num, _start_num + count) ] image: OSImageInfo = ostack.get_os_image(host.image) img_flavor: OSFlavor = host.flavor _default_key = ostack.get_keypairs()[0] if ostack.get_keypairs( ) else None _key = ostack.get_keypair(host.key_name, _default_key) _pass = conf.default_vm_password if not password else password print(f" |Image flavor to use: {img_flavor.name}") print(f" |Image to use : {image.alias}") print(f" |Key to use : {_key.name}") print(f" |Hosts to add : {', '.join(name)}") else: with Console.status_context("Resolving cluster configuration"): image: List[OSImageInfo] = list(ostack.get_image_by_alias(image)) if not image: raise RuntimeError("Cannot resolve image name for the request") image: OSImageInfo = image[0] img_flavor = ostack.get_flavor(image, flavor) _default_key = ostack.get_keypairs()[0] if ostack.get_keypairs( ) else None _key = _default_key if not key else ostack.get_keypair( key, _default_key) _pass = conf.default_vm_password if not password else password # == create nodes so = StatusOutput(__work_unit, pool_size=2, additional_errors=ostack.last_errors) with Console.status_context("Asking for node creation"): servers = ostack.create_instances(cluster_names=name, image=image, flavor=img_flavor, password=_pass, count=count, ssh_key=_key) if not servers: so.check_issues() return so.start("Creating nodes ", objects=servers) # == Configure nodes def __work_unit_waiter(x: OpenStackVMInfo) -> bool: tries: int = 0 while tries < 200: log = ostack.get_server_console_log(x.id) for l in log: if "finished" in l or "login:"******"Configure nodes", servers) console = ostack.get_server_console_log(servers[0], grep_by="cloud-init") to = TableOutput(TableColumn("Name", 15), TableColumn("Value", 30)) to.print_header(custom_header="SUMMARY") for line in console: if "@users@" in line: users = line.split("@users@:")[1].strip().split(" ") to.print_row("Accounts", ",".join(users)) to.print_row("Key", _key.name if _key else "Not used") to.print_row("Password", _pass)