diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f13d496d..662d21d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.10.0 + rev: 25.1.0 hooks: - id: black language_version: python3.11 @@ -21,7 +21,7 @@ repos: - id: upgrade-type-hints - repo: https://github.com/PyCQA/isort - rev: 5.13.2 + rev: 6.0.0 hooks: - id: isort diff --git a/portal_client.thrift b/portal_client.thrift index a21054a2..5dd79ab6 100644 --- a/portal_client.thrift +++ b/portal_client.thrift @@ -675,6 +675,7 @@ service VirtualMachineService { void delete_keypair(1:string key_name) void add_default_security_groups_to_server(1:string openstack_id) throws (1:ServerNotFoundException e) + string get_server_console(1:string openstack_id) throws (1:ServerNotFoundException e) /** * Get a Server. * Returns: A server instance. diff --git a/requirements.txt b/requirements.txt index e1c25a37..14d83de2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ setuptools==75.8.0 thrift==0.21.0 openstacksdk==4.0.1 -deprecated==1.2.15 +deprecated==1.2.18 Click==8.1.8 ansible==10.5.0 flake8==7.1.1 diff --git a/simple_vm_client/VirtualMachineHandler.py b/simple_vm_client/VirtualMachineHandler.py index 30a51bd3..48086b8b 100644 --- a/simple_vm_client/VirtualMachineHandler.py +++ b/simple_vm_client/VirtualMachineHandler.py @@ -42,7 +42,7 @@ def __init__(self, config_file: str): self.metadata_connetor = MetadataConnector(config_file=config_file) def keyboard_interrupt_handler_playbooks(self) -> None: - for k, v in self.forc_connector._active_playbooks.items(): + for k, v in self.forc_connector.active_playbooks.items(): logger.info(f"Clearing traces of Playbook-VM for (openstack_id): {k}") self.openstack_connector.delete_keypair( key_name=self.forc_connector.redis_connection.hget(k, "name").decode( @@ -182,6 +182,10 @@ def get_server(self, openstack_id: str, no_connection: bool = False) -> VM: server = thrift_converter.os_to_thrift_server(openstack_server=server) return server + def get_server_console(self, openstack_id: str) -> str: + logs = self.openstack_connector.get_server_console(openstack_id=openstack_id) + return logs + def get_servers(self) -> list[VM]: servers = self.openstack_connector.get_servers() servers_full = [] diff --git a/simple_vm_client/VirtualMachineService-remote b/simple_vm_client/VirtualMachineService-remote index e74fa049..e1a1864c 100755 --- a/simple_vm_client/VirtualMachineService-remote +++ b/simple_vm_client/VirtualMachineService-remote @@ -107,6 +107,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == "--help": print(" string get_keypair_public_key_by_name(string key_name)") print(" void delete_keypair(string key_name)") print(" void add_default_security_groups_to_server(string openstack_id)") + print(" string get_server_console(string openstack_id)") print(" VM get_server(string openstack_id, bool no_connection)") print(" VM get_server_by_unique_name(string unique_name, bool no_connection)") print(" void stop_server(string openstack_id)") @@ -801,6 +802,16 @@ elif cmd == "add_default_security_groups_to_server": ) ) +elif cmd == "get_server_console": + if len(args) != 1: + print("get_server_console requires 1 args") + sys.exit(1) + pp.pprint( + client.get_server_console( + args[0], + ) + ) + elif cmd == "get_server": if len(args) != 2: print("get_server requires 2 args") diff --git a/simple_vm_client/VirtualMachineService.py b/simple_vm_client/VirtualMachineService.py index 312ed8e3..58e5d79d 100644 --- a/simple_vm_client/VirtualMachineService.py +++ b/simple_vm_client/VirtualMachineService.py @@ -568,6 +568,13 @@ def add_default_security_groups_to_server(self, openstack_id): """ + def get_server_console(self, openstack_id): + """ + Parameters: + - openstack_id + + """ + def get_server(self, openstack_id, no_connection): """ Get a Server. @@ -3180,6 +3187,45 @@ def recv_add_default_security_groups_to_server(self): raise result.e return + def get_server_console(self, openstack_id): + """ + Parameters: + - openstack_id + + """ + self.send_get_server_console(openstack_id) + return self.recv_get_server_console() + + def send_get_server_console(self, openstack_id): + self._oprot.writeMessageBegin( + "get_server_console", TMessageType.CALL, self._seqid + ) + args = get_server_console_args() + args.openstack_id = openstack_id + args.write(self._oprot) + self._oprot.writeMessageEnd() + self._oprot.trans.flush() + + def recv_get_server_console(self): + iprot = self._iprot + (fname, mtype, rseqid) = iprot.readMessageBegin() + if mtype == TMessageType.EXCEPTION: + x = TApplicationException() + x.read(iprot) + iprot.readMessageEnd() + raise x + result = get_server_console_result() + result.read(iprot) + iprot.readMessageEnd() + if result.success is not None: + return result.success + if result.e is not None: + raise result.e + raise TApplicationException( + TApplicationException.MISSING_RESULT, + "get_server_console failed: unknown result", + ) + def get_server(self, openstack_id, no_connection): """ Get a Server. @@ -4115,6 +4161,7 @@ def __init__(self, handler): self._processMap["add_default_security_groups_to_server"] = ( Processor.process_add_default_security_groups_to_server ) + self._processMap["get_server_console"] = Processor.process_get_server_console self._processMap["get_server"] = Processor.process_get_server self._processMap["get_server_by_unique_name"] = ( Processor.process_get_server_by_unique_name @@ -5851,6 +5898,34 @@ def process_add_default_security_groups_to_server(self, seqid, iprot, oprot): oprot.writeMessageEnd() oprot.trans.flush() + def process_get_server_console(self, seqid, iprot, oprot): + args = get_server_console_args() + args.read(iprot) + iprot.readMessageEnd() + result = get_server_console_result() + try: + result.success = self._handler.get_server_console(args.openstack_id) + msg_type = TMessageType.REPLY + except TTransport.TTransportException: + raise + except ServerNotFoundException as e: + msg_type = TMessageType.REPLY + result.e = e + except TApplicationException as ex: + logging.exception("TApplication exception in handler") + msg_type = TMessageType.EXCEPTION + result = ex + except Exception: + logging.exception("Unexpected exception in handler") + msg_type = TMessageType.EXCEPTION + result = TApplicationException( + TApplicationException.INTERNAL_ERROR, "Internal error" + ) + oprot.writeMessageBegin("get_server_console", msg_type, seqid) + result.write(oprot) + oprot.writeMessageEnd() + oprot.trans.flush() + def process_get_server(self, seqid, iprot, oprot): args = get_server_args() args.read(iprot) @@ -18435,6 +18510,200 @@ def __ne__(self, other): ) +class get_server_console_args(object): + """ + Attributes: + - openstack_id + + """ + + thrift_spec = None + + def __init__( + self, + openstack_id=None, + ): + self.openstack_id = openstack_id + + def read(self, iprot): + if ( + iprot._fast_decode is not None + and isinstance(iprot.trans, TTransport.CReadableTransport) + and self.thrift_spec is not None + ): + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 1: + if ftype == TType.STRING: + self.openstack_id = ( + iprot.readString().decode("utf-8", errors="replace") + if sys.version_info[0] == 2 + else iprot.readString() + ) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + self.validate() + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write( + oprot._fast_encode(self, [self.__class__, self.thrift_spec]) + ) + return + oprot.writeStructBegin("get_server_console_args") + if self.openstack_id is not None: + oprot.writeFieldBegin("openstack_id", TType.STRING, 1) + oprot.writeString( + self.openstack_id.encode("utf-8") + if sys.version_info[0] == 2 + else self.openstack_id + ) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ["%s=%r" % (key, value) for key, value in self.__dict__.items()] + return "%s(%s)" % (self.__class__.__name__, ", ".join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +all_structs.append(get_server_console_args) +get_server_console_args.thrift_spec = ( + None, # 0 + ( + 1, + TType.STRING, + "openstack_id", + "UTF8", + None, + ), # 1 +) + + +class get_server_console_result(object): + """ + Attributes: + - success + - e + + """ + + thrift_spec = None + + def __init__( + self, + success=None, + e=None, + ): + self.success = success + self.e = e + + def read(self, iprot): + if ( + iprot._fast_decode is not None + and isinstance(iprot.trans, TTransport.CReadableTransport) + and self.thrift_spec is not None + ): + iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) + return + iprot.readStructBegin() + while True: + (fname, ftype, fid) = iprot.readFieldBegin() + if ftype == TType.STOP: + break + if fid == 0: + if ftype == TType.STRING: + self.success = ( + iprot.readString().decode("utf-8", errors="replace") + if sys.version_info[0] == 2 + else iprot.readString() + ) + else: + iprot.skip(ftype) + elif fid == 1: + if ftype == TType.STRUCT: + self.e = ServerNotFoundException.read(iprot) + else: + iprot.skip(ftype) + else: + iprot.skip(ftype) + iprot.readFieldEnd() + iprot.readStructEnd() + + def write(self, oprot): + self.validate() + if oprot._fast_encode is not None and self.thrift_spec is not None: + oprot.trans.write( + oprot._fast_encode(self, [self.__class__, self.thrift_spec]) + ) + return + oprot.writeStructBegin("get_server_console_result") + if self.success is not None: + oprot.writeFieldBegin("success", TType.STRING, 0) + oprot.writeString( + self.success.encode("utf-8") + if sys.version_info[0] == 2 + else self.success + ) + oprot.writeFieldEnd() + if self.e is not None: + oprot.writeFieldBegin("e", TType.STRUCT, 1) + self.e.write(oprot) + oprot.writeFieldEnd() + oprot.writeFieldStop() + oprot.writeStructEnd() + + def validate(self): + return + + def __repr__(self): + L = ["%s=%r" % (key, value) for key, value in self.__dict__.items()] + return "%s(%s)" % (self.__class__.__name__, ", ".join(L)) + + def __eq__(self, other): + return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not (self == other) + + +all_structs.append(get_server_console_result) +get_server_console_result.thrift_spec = ( + ( + 0, + TType.STRING, + "success", + "UTF8", + None, + ), # 0 + ( + 1, + TType.STRUCT, + "e", + [ServerNotFoundException, None], + None, + ), # 1 +) + + class get_server_args(object): """ Attributes: diff --git a/simple_vm_client/config/config_local.yml b/simple_vm_client/config/config_local.yml index b5591e49..9b35b708 100644 --- a/simple_vm_client/config/config_local.yml +++ b/simple_vm_client/config/config_local.yml @@ -82,10 +82,10 @@ forc: # Access URL for FORC - optional - default is forc_url without port. github_playbooks_repo: https://github.com/deNBI/resenvs/archive/refs/heads/staging.zip # GitHub repository URL for FORC playbooks. - update_templates_schedule: 0.01 + update_templates_schedule: 1.01 metadata_server: - activated: True + activated: False use_https: False host: simplevm_metadata_server port: 8000 diff --git a/simple_vm_client/openstack_connector/openstack_connector.py b/simple_vm_client/openstack_connector/openstack_connector.py index e310d926..1bf9d9a0 100644 --- a/simple_vm_client/openstack_connector/openstack_connector.py +++ b/simple_vm_client/openstack_connector/openstack_connector.py @@ -1264,6 +1264,21 @@ def get_server_by_unique_name( message=f"Error when getting server {unique_name}! - multiple entries" ) + def get_server_console(self, openstack_id: str): + logger.info(f"Get Server console log by id: {openstack_id}") + server: Server = self.openstack_connection.get_server_by_id(id=openstack_id) + if server is None: + logger.exception(f"Instance {openstack_id} not found") + raise ServerNotFoundException( + message=f"Instance {openstack_id} not found", + name_or_id=openstack_id, + ) + logs: str = self.openstack_connection.get_server_console( + server=server, length=50 + ) + logger.info(f"retrieves log: {logs}") + return logs + def get_server(self, openstack_id: str, no_connection: bool = False) -> Server: try: logger.info(f"Get Server by id: {openstack_id}")