From 60f99204742d487669bffdb00e14978b8d240c02 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Wed, 11 Apr 2018 16:04:49 +0200 Subject: [PATCH] Implemented waiting for SSH available --- etc/create-vmware-template.ini.default | 2 +- lib/cr_vmware_tpl/config.py | 26 +++++++- lib/cr_vmware_tpl/handler.py | 84 +++++++++++++++++++++++++- 3 files changed, 108 insertions(+), 4 deletions(-) diff --git a/etc/create-vmware-template.ini.default b/etc/create-vmware-template.ini.default index 091dc88..1bf9925 100644 --- a/etc/create-vmware-template.ini.default +++ b/etc/create-vmware-template.ini.default @@ -28,7 +28,7 @@ ;mac_address = 00:16:3e:54:ab:2b - +;max_wait_for_finish_install = 3600 diff --git a/lib/cr_vmware_tpl/config.py b/lib/cr_vmware_tpl/config.py index 2002c1e..fcf9244 100644 --- a/lib/cr_vmware_tpl/config.py +++ b/lib/cr_vmware_tpl/config.py @@ -26,7 +26,7 @@ from .errors import FunctionNotImplementedError, PpError from .obj import PpBaseObject -__version__ = '0.4.5' +__version__ = '0.5.1' LOG = logging.getLogger(__name__) @@ -57,6 +57,9 @@ class CrTplConfiguration(PpBaseObject): default_ram_mb = 4 * 1024 default_network = '192.168.88.0_23' default_mac_address = '00:16:3e:54:ab:2b' + default_max_wait_for_finish_install = 60 * 60 + min_max_wait_for_finish_install = 3 * 60 + max_max_wait_for_finish_install = 24 * 60 * 60 # ------------------------------------------------------------------------- def __init__( @@ -76,6 +79,7 @@ class CrTplConfiguration(PpBaseObject): self.ram_mb = self.default_ram_mb self.network = self.default_network self.mac_address = self.default_mac_address + self.max_wait_for_finish_install = self.default_max_wait_for_finish_install self.encoding = 'utf-8' @@ -146,6 +150,9 @@ class CrTplConfiguration(PpBaseObject): res['default_ram_mb'] = self.default_ram_mb res['default_network'] = self.default_network res['default_mac_address'] = self.default_mac_address + res['default_max_wait_for_finish_install'] = self.default_max_wait_for_finish_install + res['min_max_wait_for_finish_install'] = self.min_max_wait_for_finish_install + res['max_max_wait_for_finish_install'] = self.max_max_wait_for_finish_install res['data_size_mb'] = self.data_size_mb res['data_size_kb'] = self.data_size_kb res['data_size'] = self.data_size @@ -208,7 +215,6 @@ class CrTplConfiguration(PpBaseObject): if val > self.verbose: self.verbose = val - if section.lower() == 'vsphere': for (key, value) in config.items(section): @@ -266,6 +272,22 @@ class CrTplConfiguration(PpBaseObject): v = value.strip().lower() if v: self.mac_address = v + if key.lower() == 'max_wait_for_finish_install': + v = float(value) + if v < self.min_max_wait_for_finish_install: + LOG.err(( + "Value {val} for max_wait_for_finish_install is less than {minval}, " + "using {default} seconds.").format(val=v, + minval=self.min_max_wait_for_finish_install, + default=self.default_max_wait_for_finish_install)) + elif v > self.max_max_wait_for_finish_install: + LOG.err(( + "Value {val} for max_wait_for_finish_install is greater than {maxval}, " + "using {default} seconds.").format(val=v, + maxval=self.max_max_wait_for_finish_install, + default=self.default_max_wait_for_finish_install)) + else: + self.max_wait_for_finish_install = v # ============================================================================= diff --git a/lib/cr_vmware_tpl/handler.py b/lib/cr_vmware_tpl/handler.py index 727a0ca..27a7229 100644 --- a/lib/cr_vmware_tpl/handler.py +++ b/lib/cr_vmware_tpl/handler.py @@ -37,7 +37,7 @@ from .obj import PpBaseObject from .config import CrTplConfiguration -__version__ = '0.6.1' +__version__ = '0.6.2' LOG = logging.getLogger(__name__) TZ = pytz.timezone('Europe/Berlin') @@ -633,6 +633,88 @@ class CrTplHandler(PpBaseObject): cur_duration = cur_time - self.ts_start_install print('', flush=True) + LOG.debug("Waiting for SSH available ...") + print(' ==> ', end='', flush=True) + + addr_infos = socket.getaddrinfo( + self.config.template_vm, 22, socket.AF_INET, socket.SOCK_STREAM) + if self.verbose > 1: + LOG.debug("Got following address_infos for {h!r}, IPv4 TCP port 22:\n{ai}".format( + h=self.config.template_vm, pp(addr_infos))) + if not addr_infos: + raise HandlerError("Did not get address infos for {!r}, IPv4 TCP port 22.".format( + self.config.template_vm)) + + addr_info = random.choice(addr_infos) + LOG.debug("Using address info: {}".format(pp(addr_info))) + family, socktype, proto, canonname, sockaddr = addr_info + + ssh_available = False + cur_duration = cur_time - self.ts_start_install + cur_time = time.time() + last_dot = cur_time + i = 0 + first = True + while not ssh_available and cur_duration <= self.config.max_wait_for_finish_install: + + if not first: + time.sleep(self.interval_poll) + else: + first = False + + cur_time = time.time() + cur_duration = cur_time - self.ts_start_install + if (cur_time - last_dot) >= self.interval_dot: + print('.', end='', flush=True) + i += 1 + if i >= 60: + print('', flush=True) + print(' ', end='', flush=True) + i = 0 + last_dot = cur_time + + if self.verbose > 2: + LOG.debug("Trying to connect to {a} via TCP port {p} ...".format( + a=sockaddr[0], p=sockaddr[1])) + + try: + sock = socket.socket(family, socktype, proto) + except socket.error as e: + sock = None + LOG.warn("Error creating socket: {}".format(e)) + continue + + try: + sock.connect(sockaddr) + except socket.error as e: + sock.close() + sock = None + if self.verbose > 2: + LOG.debug("Could not connect: {}".format(e)) + continue + + LOG.info("Connected to {a} via TCP port {p} ...".format( + a=sockaddr[0], p=sockaddr[1])) + data = sock.recv(4096) + if data: + msg = to_str(data).strip() + LOG.info("Got banner: {}".format(msg)) + sock.close() + sock = None + ssh_available = True + self.ts_finish_install = time.time() + + duration = self.ts_finish_install - self.ts_start_install + minutes = int(int(duration) / 60) + seconds = duration - float(minutes * 60) + + LOG.info("Needed {m} minutes and {s:0.1f} seconds.".format( + m=minutes, s=seconds)) + + if not ssh_available: + raise ExpectedHandlerError( + "SSH not available after {:0.1f} seconds, giving up.".format(duration)) + # ============================================================================= if __name__ == "__main__": -- 2.39.5