def _search_resource_until_status(self, resource_name, limit=HEAT_RESOURCE_LIMIT, status=RESOURCE_COMPLETED_STATUS): fields = { 'stack_id': self._name, 'nested_depth': 1, } while limit > 0: try: resources = self._heat_client.resources.list(**fields) except exc.HTTPNotFound: raise exceptions.ArgusError('Stack not found: %s' % self._name) else: for resource in resources: if resource.resource_type == resource_name: # Found the resource we were needing if resource.resource_status == status: return resource.physical_resource_id else: limit -= 1 time.sleep(HEAT_RESOURCE_TIMEOUT) break else: break raise exceptions.ArgusError("No resource %s found with name %s" % (resource_name, self._name))
def _get_git_link(): content = _read_url("http://git-scm.com/download/win") soup = bs4.BeautifulSoup(content) download_div = soup.find('div', {'class': 'callout downloading'}) if not download_div: raise exceptions.ArgusError( "Could not find callout_downloading div.") for a_object in download_div.find_all('a'): href = a_object.get('href', '') if not href.endswith('.exe'): continue return href raise exceptions.ArgusError("git download link not found.")
def get_mtu(self): """Get the MTU value, from the back-end.""" try: return self.primary_credentials().network["mtu"] except Exception as exc: raise exceptions.ArgusError('Could not get the MTU from the ' 'tempest backend: %s' % exc)
def get_cbinit_dir(execute_function): """Get the location of Cloudbase-Init from the instance.""" stdout = execute_function('$ENV:PROCESSOR_ARCHITECTURE', command_type=util.POWERSHELL) architecture = stdout.strip() locations = [ execute_function('echo "$ENV:ProgramFiles"', command_type=util.POWERSHELL) ] if architecture == 'AMD64': location = execute_function('echo "${ENV:ProgramFiles(x86)}"', command_type=util.POWERSHELL) locations.append(location) for location in locations: location = location.strip() _location = escape_path(location) status = execute_function( 'Test-Path "{}\\Cloudbase` Solutions"'.format(_location), command_type=util.POWERSHELL).strip().lower() if status == "true": return ntpath.join(location, "Cloudbase Solutions", "Cloudbase-Init") raise exceptions.ArgusError('Cloudbase-Init installation directory' ' not found')
def _run_command(protocol_client, shell_id, command, command_type=util.POWERSHELL): command_id = None bare_command = command command = util.get_command(command, command_type) try: command_id = protocol_client.run_command(shell_id, command) stdout, stderr, exit_code = protocol_client.get_command_output( shell_id, command_id) if exit_code: output = "\n\n".join([out for out in (stdout, stderr) if out]) raise exceptions.ArgusError( "Executing command {command!r} with encoded Command" "{encoded_command!r} failed with exit code {exit_code!r}" " and output {output!r}.".format(command=bare_command, encoded_command=command, exit_code=exit_code, output=output)) return stdout, stderr, exit_code finally: protocol_client.cleanup_command(shell_id, command_id)
def get_cbinit_dir(execute_function): """Get the location of cloudbase-init from the instance.""" stdout = execute_function( '(Get-WmiObject Win32_OperatingSystem).' 'OSArchitecture', command_type=util.POWERSHELL) architecture = stdout.strip() locations = [ execute_function('powershell "$ENV:ProgramFiles"', command_type=util.CMD) ] if architecture == '64-bit': location = execute_function('powershell "${ENV:ProgramFiles(x86)}"', command_type=util.CMD) locations.append(location) for location in locations: location = location.strip() _location = escape_path(location) status = execute_function( 'Test-Path "{}\\Cloudbase` Solutions"'.format(_location), command_type=util.POWERSHELL).strip().lower() if status == "true": return ntpath.join(location, "Cloudbase Solutions", "Cloudbase-Init") raise exceptions.ArgusError('cloudbase-init installation dir not found')
def _run_command(protocol_client, shell_id, command, command_type=util.POWERSHELL, upper_timeout=CONFIG.argus.upper_timeout): command_id = None bare_command = command thread_pool = pool.ThreadPool(processes=THREADS) command = util.get_command(command, command_type) try: command_id = protocol_client.run_command(shell_id, command) result = thread_pool.apply_async( protocol_client.get_command_output, args=(shell_id, command_id)) stdout, stderr, exit_code = result.get( timeout=upper_timeout) if exit_code: output = "\n\n".join([out for out in (stdout, stderr) if out]) raise exceptions.ArgusError( "Executing command {command!r} with encoded Command" "{encoded_command!r} failed with exit code {exit_code!r}" " and output {output!r}." .format(command=bare_command, encoded_command=command, exit_code=exit_code, output=output)) return util.sanitize_command_output(stdout), stderr, exit_code except multiprocessing.TimeoutError: raise exceptions.ArgusTimeoutError( "The command '{cmd}' has timed out.".format(cmd=bare_command)) finally: thread_pool.terminate() protocol_client.cleanup_command(shell_id, command_id)
def test_get_mtu_fails(self, mock_primary_credentials): mock_primary_credentials.side_effect = exceptions.ArgusError( "fake exception") with self.assertRaises(exceptions.ArgusError): result = self._api_manager.get_mtu() self.assertEqual('Could not get the MTU from the ' 'tempest backend: fake exception', result) mock_primary_credentials.assert_called_once()
def _execute(self, cmd): """Execute the given command and fail when the command fails.""" stdout, stderr, return_code = self._remote_client.run_remote_cmd(cmd) if return_code: raise exceptions.ArgusError("Command {command!r} failed with " "return code {return_code!r}".format( command=cmd, return_code=return_code)) return stdout, stderr
def introspection(self): if not self.introspection_class: raise exceptions.ArgusError( 'introspection_class must be set') # pylint: disable=not-callable return self.introspection_class(self.remote_client, self.server['id'], image=self.image)
def _prepare_instance(self): if self._recipee is None: raise exceptions.ArgusError('recipee must be set') LOG.info("Preparing instance.") # pylint: disable=not-callable self._recipee( instance_id=self._server['id'], api_manager=self._manager, remote_client=self.remote_client, image=self._image).prepare()
def test_search_resoutce_until_status_http_error(self): self._base_heat_backend._name = "fake name" raised_exception = exceptions.ArgusError('Stack not found: %s' % self._base_heat_backend._name) self._base_heat_backend._heat_client.resources.list = mock.Mock() (self._base_heat_backend._heat_client.resources.list.side_effect ) = exc.HTTPNotFound() with self.assertRaises(exceptions.ArgusError) as ex: self._base_heat_backend._search_resource_until_status( mock.sentinel) self.assertEqual(ex.exception.message, str(raised_exception))
def setup_instance(self): # Just like a normal preparer, but this time # with explicitly specified attached networks. if not isinstance(self._manager.isolated_creds, dynamic_creds.DynamicCredentialProvider): raise exceptions.ArgusError("Network resources are not available.") self._create_private_network() self._networks = self._get_networks() super(NetworkWindowsBackend, self).setup_instance()
def replace_code(self): """Replace the code of Cloudbase-Init.""" if not CONFIG.argus.git_command: # Nothing to replace. return LOG.info("Replacing Cloudbase-Init's code " "with %s", CONFIG.argus.git_command) LOG.debug("Getting Cloudbase-Init location...") # Get Cloudbase-Init python location. python_dir = introspection.get_python_dir(self._execute) # Remove everything from the Cloudbase-Init installation. LOG.debug("Recursively removing Cloudbase-Init...") cloudbaseinit = ntpath.join(python_dir, "Lib", "site-packages", "cloudbaseinit") self._execute('rmdir "{}" /S /q'.format(cloudbaseinit), command_type=util.CMD) # Clone the repository clone_res = self._backend.remote_client.manager.git_clone( repo_url=_CBINIT_REPO, location=_CBINIT_TARGET_LOCATION) if not clone_res: raise exceptions.ArgusError('Code repository could not ' 'be cloned.') # Run the command provided at cli. LOG.debug("Applying cli patch...") self._execute("cd {location} && {command}".format( location=_CBINIT_TARGET_LOCATION, command=CONFIG.argus.git_command), command_type=util.CMD) # Replace the code, by moving the code from Cloudbase-Init # to the installed location. LOG.debug("Replacing code...") self._execute('Copy-Item {location}\\cloudbaseinit \'{folder}\'' '-Recurse'.format(location=_CBINIT_TARGET_LOCATION, folder=cloudbaseinit), command_type=util.POWERSHELL) # Auto-install packages from the new requirements.txt python = ntpath.join(python_dir, "python.exe") command = '"{folder}" -m pip install -r {location}\\requirements.txt' self._execute(command.format(folder=python, location=_CBINIT_TARGET_LOCATION), command_type=util.CMD) command = '"{folder}" -m pip install {location}' self._execute(command.format(folder=python, location=_CBINIT_TARGET_LOCATION), command_type=util.CMD)
def test_search_resource_until_status_limit_exceded(self): resource_name = "fake resource" self._base_heat_backend._name = "fake name" raised_exception = exceptions.ArgusError( "No resource %s found with name %s" % (resource_name, self._base_heat_backend._name)) self._base_heat_backend._name = "fake name" (self._base_heat_backend._heat_client.resources.list.side_effect ) = raised_exception with self.assertRaises(exceptions.ArgusError) as ex: self._base_heat_backend._search_resource_until_status( resource_name, 0) self.assertEqual(ex.exception.message, str(raised_exception))
def _run_command(protocol_client, shell_id, command): try: command_id = protocol_client.run_command(shell_id, command) stdout, stderr, exit_code = protocol_client.get_command_output( shell_id, command_id) if exit_code: raise exceptions.ArgusError( "Executing command {command!r} failed with " "exit code {exit_code!r} and output {output!r}".format( command=command, exit_code=exit_code, output=stdout)) return stdout, stderr, exit_code finally: protocol_client.cleanup_command(shell_id, command_id)
def test_search_resource_until_status_(self, _): resource_name = mock.sentinel status_completed = mock.sentinel exp = exceptions.ArgusError( "No resource %s found with name %s" % (resource_name, self._base_heat_backend._name)) mock_list = mock.Mock() mock_resource = mock.Mock() mock_resource.resource_type = "fake_resource" mock_list.return_value = [mock_resource] self._base_heat_backend._heat_client.resources.list = mock_list with self.assertRaises(exceptions.ArgusError) as ex: self._base_heat_backend._search_resource_until_status( resource_name, status=status_completed) self.assertEqual(ex.exception.message, str(exp))
def _get_networks(self): """Explicitly gather and return the private networks. All these networks will be attached to the newly created instance without letting nova to handle this part. """ _networks = self._manager.networks_client.list_networks() try: _networks = _networks["networks"] except KeyError: raise exceptions.ArgusError('Networks not found.') # Skip external/private networks. networks = [ net["id"] for net in _networks if not net["router:external"] ] # Put in front the main private network. head = self._get_isolated_network()["id"] networks.remove(head) networks.insert(0, head) # Adapt the list to a format accepted by the API. return [{"uuid": net} for net in networks]
def _admin_credentials(self): try: return self._isolated_creds.get_admin_creds() except NotImplementedError: raise exceptions.ArgusError( 'Admin Credentials are not available')
def _get_mtu(self): try: return self._manager.primary_credentials().network["mtu"] except Exception as exc: raise exceptions.ArgusError('Could not get the MTU from the ' 'tempest backend: %s' % exc)