def _setup_machine(self): # Create a new machine if custom flavor requested if self.flavor != DEFAULT_FLAVOR: return self._boot_machine() # Check for prereserved machine self.debug("Try to get a prereserved minute machine.") response = retry_session().get( f'{self.api_url}?image_name={self.mt_image}' f'&user={self.username}&osver=rhos10', verify=False) if not response.ok: return self.debug(f"Prereserved machine result: {response.text}") # No prereserved machine, boot a new one if 'prereserve' not in response.text: return self._boot_machine() # Rename the prereserved machine old_name, self.guest = response.text.split() self.debug( f"Rename the machine from '{old_name}' to '{self.instance_name}'.") _, rename_out = run_openstack( self.api_url, f'server set --name {self.instance_name} {old_name}') if rename_out is None or 'ERROR' in rename_out: return False # Machine renamed, set properties self.debug("Change properties of the prereserved machine.") run_openstack( self.api_url, f'server set --property local_user={self.username} ' f'--property reserved_time={self.instance_start}') return True
def start(self): """ Start provisioned guest """ if self.opt('dry'): return self.mt_image = self._convert_image(self.image) self.verbose('1mt-image', self.mt_image, 'green') date_service = self.api_url date_service += '/date-service.php?output_format=instantion' try: self.debug("Trying to get date from the date-service.") response = retry_session().get(date_service, verify=False) response.raise_for_status() self.instance_start = response.text except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError): # Fall-back to local datetime self.debug("Date-service failed, falling back to local time.") self.instance_start = datetime.datetime.utcnow().strftime( '%Y-%m-%d-%H-%M') self.debug(f"Instance start: {self.instance_start}") self.instance_name = (f'{self.username}-{self.mt_image}-' f'{os.getpid()}-{self.instance_start}') for i in range(NUMBER_OF_RETRIES): if self._setup_machine(): return raise tmt.utils.ProvisionError( "All attempts to provision a machine with 1minutetip failed.")
def run_openstack(url, cmd, cached_list=False): """ Runs an openstack command. Returns (exit_code, stdout) tuple. Both are None if the request failed. """ url += '/openstack.php' data = { 'CMD': base64.b64encode(cmd.encode('ascii')), 'base64': 1, } if cached_list: data['use_cached_list'] = 1 # Disable warning about insecure connection. Using insecure connection # is unfortunately necessary here for the plugin to work. requests.packages.urllib3.disable_warnings( category=urllib3.exceptions.InsecureRequestWarning) try: response = retry_session().post(url, verify=False, data=data) except requests.exceptions.ConnectionError: raise tmt.utils.ProvisionError( "The minute API is currently unavailable. " "Please check your connection or try again later.") if response.ok: # The output is in the form of: <stdout>\n<exit>\n. split = response.text.rsplit('\n', 2) return int(split[1]), split[0] return None, None
def _get_url(self, url, message): """ Get url, retry when fails, return response """ for i in range(1, DEFAULT_CONNECT_TIMEOUT): try: response = retry_session().get(url) if response.ok: return response except requests.RequestException: pass self.debug(f"Unable to {message} ({url}), retry {i}.") time.sleep(3) raise ProvisionError( f'Failed to {message} ({DEFAULT_CONNECT_TIMEOUT} attempts).')
def _get_url(self, url, message): """ Get url, retry when fails, return response """ timeout = DEFAULT_CONNECT_TIMEOUT wait = 1 while True: try: response = retry_session().get(url) if response.ok: return response except requests.RequestException: pass if timeout < 0: raise ProvisionError( f'Failed to {message} in {DEFAULT_CONNECT_TIMEOUT}s.') self.debug(f'Unable to {message} ({url}), retrying, ' f'{fmf.utils.listed(timeout, "second")} left.') time.sleep(wait) wait += 1 timeout -= wait