def create_ps_exec_playbook(user_dir, play_vars): """Creates the playbook to execute Windows PowerShell scripts. :param user_dir: user directory :param play_vars: determines if playbook vars are required """ filename = join(user_dir, WIN_EXEC_YAML) playbook = dict(gather_facts='False', hosts='{{ hosts }}', name='Execute Windows PowerShell') if play_vars == 'file': playbook['vars'] = dict(win_var_path='c:/my_vars.json') playbook['tasks'] = [ dict(name='Copy JSON vars to Windows system', win_copy='src={{ psv }} dest={{ win_var_path }}'), dict(name='Execute PowerShell on Windows system', script='{{ ps }} {{ win_var_path }}') ] elif play_vars == 'str': playbook['tasks'] = [ dict(name='Execute PowerShell on Windows system', script='{{ ps }} {{ psv }}') ] elif play_vars is None: playbook['tasks'] = [ dict(name='Execute PowerShell on Windows system', script='{{ ps }}') ] file_mgmt('w', filename, [playbook]) LOG.debug('Playbook %s created.', filename) return filename
def inventory_init(filename): """Initialize a inventory file. This will just touch an empty inventory file in the user directory. It is primarily called to ignore ansible warning messages when running commands on the local host. :param filename: inventory file """ file_mgmt('w', filename, '')
def param(request): """Parameters used for each test execution. :param request: pytest request fixture """ # define vm name and image test_data = dict(name='paws-%s' % str(uuid4())[:8], image=str(request.param)) # set windows image in paws resources file before test execution update_resources_yml(test_data['name'], test_data['image']) LOG.info('\n TESTING WINDOWS IMAGE: %s \n' % test_data['image']) LOG.info(pformat(file_mgmt('r', RESOURCES_YML))) # add the finalizer to run after all test execution def fin(): """Finalizer to clean up left over vms after test execution.""" LOG.info('\n' + DIV + ' FINALIZER ' + DIV) try: node = LIB_CLOUD.get_node(test_data['name']) LOG.info('VM: %s exists, need to delete before next test.' % test_data['name']) LIB_CLOUD.driver.destroy_node(node) LOG.info('VM: %s successfully terminated.' % test_data['name']) except NotFound: LOG.info('VM: %s was cleaned up during test execution.' % test_data['name']) request.addfinalizer(fin) return test_data
def __set_playbook_vars(self): """Construct the playbook variables from the users input.""" # set attributes to control parsing results self.results_class = ResultsHandler self.default_callback = True data = dict() try: # variables defined vars_file = os.path.join(self.userdir, self.script_vars) if os.path.isfile(vars_file): # variables in file format data = file_mgmt('r', vars_file) elif isinstance(self.script_vars, string_types): # variables in string format data = ast.literal_eval(self.script_vars) # set playbook variables for key, value in data.items(): self.extra_vars[key] = value except (AttributeError, TypeError): # variables undefined pass
def update_resources_yml(vm_name, image_name): """Update the resource topology file with the windows image to test. It will update the resources.yaml file located within the defined user directory above (USER_DIR constant). :param vm_name: name for the vm to be provisioned :type vm_name: str :param image_name: name for the image to be used when booting vm :type image_name: str """ data = file_mgmt('r', RESOURCES_YML) for item in data['resources']: item['name'] = vm_name item['image'] = image_name file_mgmt('w', RESOURCES_YML, data)
def create_inventory(filename, resources=None): """Create a inventory file. :param filename: inventory file :param resources: windows resources """ # can we reuse a existing inventory file? if inventory_reuse(filename, resources): return config = RawConfigParser() for item in resources['resources']: section = item['name'].replace(" ", "") config.add_section(section) try: config.set(section, str(item['public_v4'])) except KeyError: config.set(section, item['ip']) section = section + ":vars" config.add_section(section) config.set(section, "ansible_user", item['win_username']) config.set(section, "ansible_password", item['win_password']) config.set(section, "ansible_port", "5986") config.set(section, "ansible_connection", "winrm") config.set(section, "ansible_winrm_server_cert_validation", "ignore") file_mgmt('w', filename, cfg_parser=config) # clean file, remove '= None' inv_data = file_mgmt('r', filename) inv_data = inv_data.replace(' = None', '') file_mgmt('w', filename, inv_data) LOG.debug("Inventory file %s created.", filename)
def generate_resources_paws(self, conn): """Generate or Update resources.paws file. If resources.paws file exists function will not delete the file or even just append new data into this. First of all any element decldared into resources.paws from provider different than libvirt will be preserved and new data just appended to the file. :param conn: Libvirt connection :type conn: object """ LOG.debug("Generating %s" % self.args.resources_paws_file) vms = [] for res in self.args.resources: if self.vm_exist(conn, res['name']): vm_info = self.get_vm_info(conn, res) if vm_info: vms.append(vm_info) # Write resources.paws if len(vms) > 0: if exists(self.args.resources_paws_file): res_paws = file_mgmt('r', self.args.resources_paws_file) for x in res_paws['resources']: if x['provider'] != self.args.name: vms.append(x) self.args.resources_paws = {'resources': vms} file_mgmt( 'w', self.args.resources_paws_file, self.args.resources_paws ) LOG.debug("Successfully created %s", self.args.resources_paws_file)
def show(self): """Show OpenStack resources.""" resources = list() for index, res in enumerate(self.resources): try: node = self.get_node(res['name']) except NotFound as ex: self.logger.warning(ex.message) continue # get the ip res['public_v4'] = str(self.get_floating_ip(node)) if ADMINISTRADOR_PWD in res: res['win_username'] = ADMINISTRATOR res['win_password'] = res[ADMINISTRADOR_PWD] resources.append(res) # create resources.paws resources_paws = dict(resources=deepcopy(resources)) file_mgmt('w', self.resources_paws_file, resources_paws) return resources_paws
def pre_run(self): """Perform any necessary pre task actions.""" # Clean files generated by paws cleanup([self.winsetup_yaml, self.playbook.inventory_file]) # Use paws generated topology file? if exists(self.resources_paws_file): self.resources = file_mgmt('r', self.resources_paws_file) # Create inventory file create_inventory(self.playbook.inventory_file, self.resources) # Verify PowerShell script exists if not exists(self.pshell): self.logger.error("PowerShell script: %s does not exist!", self.pshell) raise SystemExit(1)
def inventory_reuse(filename, resources): """Determine if we can re-use an existing inventory file. This will check if the resources given exist within the existing inventory file. If they are we can reuse the file! :param filename: inventory file :param resources: windows resources """ if not os.path.exists(filename): # inventory not found return False try: # load existing inventory data = file_mgmt('r', filename) count = 0 # do the active resources exist within the inventory? for res in resources['resources']: sec = res['name'] sec_vars = res['name'] + ':vars' user = '******' % res['win_username'] password = '******' % res['win_password'] if sec in data and sec_vars in data and user in data and \ password in data: count += 1 if count == len(resources['resources']): LOG.debug('Reusing inventory file.') return True except KeyError as ex: LOG.error('Required resource key %s missing!', ex) raise SystemExit(1) except IOError: return False
def run(self): """The main method for group. This method will run a ordered list of paws tasks.""" # pre run tasks self.pre_run() self.logger.info("START: %s", self.name) # save the start time self.start() for item in self.tasklist: task = item['task'].lower() self.logger.info("Running: %s (task=%s)" % (item['name'], task)) # wait if task == 'wait': try: duration = item['duration'] self.logger.info("Delaying %ss" % duration) sleep(int(duration)) continue except KeyError: self.logger.warning( "Delay duration was not set! Skipping.." ) continue if 'args' in item: # combine list of dict into one dict args = {key: value for item in item[ 'args'] for key, value in item.items()} # set task specific arguments into memory self.set_task_attr(self.map_task_args(args)) # import task module pmodule = import_module(get_task_module_path(task)) # get task class task_cls = getattr(pmodule, task.title()) # read files _vars = self.groupdata['vars'] try: credentials = file_mgmt( 'r', join(self.userdir, _vars['credentials']) ) except (AttributeError, IOError): credentials = None resources = file_mgmt( 'r', join(self.userdir, _vars['topology']) ) # create object from task class task = task_cls( self.userdir, resources, credentials, self.verbose, args=self.args ) # run task exit_code = task.run() # quit group execution if exit code is not zero if exit_code != 0: self.exit_code = exit_code break if 'args' in item: # delete task arguments values from memory self.del_task_attr(self.map_task_args(args)) # save end time self.end() self.logger.info("END: Group, TIME: %dh:%dm:%ds", self.hours, self.minutes, self.seconds) return self.exit_code
LOG = logging.getLogger(__name__) # define constants used by all functions USER_DIR = getenv('USER_DIR') if not USER_DIR: LOG.error('Environment variable: USER_DIR undefined!') raise SystemExit(1) RESOURCES_YML = join(USER_DIR, 'resources.yaml') CREDENTIALS_YML = join(USER_DIR, 'credentials.yaml') LINE = '*' * 80 DIV = '=' * 20 # create the libcloud object establishing connection to openstack credentials = file_mgmt('r', CREDENTIALS_YML) for credential in credentials['credentials']: if credential['provider'].lower() == 'openstack': LIB_CLOUD = LibCloud( dict(os_username=credential['os_username'], os_password=credential['os_password'], os_auth_url=credential['os_auth_url'], os_project_name=credential['os_project_name'])) def get_windows_images(): """Get all the available windows images. :return: windows images names :rtype: list """
def __init__(self, userdir, resources, credentials, verbose=0, **kwargs): """Constructor. :param userdir: User directory. :type userdir: str :param resources: System resources. :type resources: dict :param credentials: Provider credentials. :type credentials: dict :param verbose: Verbosity level. :type verbose: int :param kwargs: Extra key:value data. :type kwargs: dict Usage: -- CLI -- .. code-block: bash $ paws <options> configure [SCRIPT] <options> -- API -- .. code-block:: python from paws.tasks import Configure configure = Configure( userdir, resources, credentials, script='<script>, variables='<variables>' ) configure.run() """ super(Configure, self).__init__(userdir, verbose) self.resources = resources self.credentials = credentials self.verbose = verbose self.playbook = PlaybookCall(self.userdir) # cache options for later use try: self.script = os.path.join(self.userdir, getattr(kwargs['args'], 'script')) self.script_vars = getattr(kwargs['args'], 'script_vars', None) self.systems = getattr(kwargs['args'], 'systems', 'all') except KeyError: self.script = os.path.join(self.userdir, getattr(Namespace(kwargs), 'script')) self.script_vars = getattr(Namespace(kwargs), 'script_vars', None) self.systems = getattr(Namespace(kwargs), 'systems', 'all') # script exist if not os.path.exists(self.script): self.logger.error('Script %s not found!' % self.script) raise SystemExit(1) # override resources if resources.paws exists if os.path.exists(self.resources_paws_file): self.resources = file_mgmt('r', self.resources_paws_file) # clean up prior inventory file cleanup([self.playbook.inventory_file]) # create ansible inventory create_inventory(self.playbook.inventory_file, self.resources) # set the systems under test self.set_sut() # use smart technology to determine script type self.discover()
def provision(self): """Provision OpenStack resources.""" for res in self.resources: node = None try: self.get_node(res['name']) raise ProvisionError('Resource %s exits. Skipping provision!' % res['name']) except NotFound: self.logger.debug( 'Resource %s does not exist. Lets ' 'provision!', res['name']) # lets handle getting libcloud objects ext_net = res['network'] int_net = None if 'network' in res and 'floating_ip_pools' in res: # more than one internal network # network=internal & floating_ip_pools=external try: int_net = self.get_network(res['network']) ext_net = self.get_float_ip_pool(res['floating_ip_pools']) except NotFound as ex: raise ProvisionError(ex.message + ' for %s.' % res['name']) else: try: ext_net = self.get_float_ip_pool(res['network']) except NotFound as ex: raise ProvisionError(ex.message + ' for %s.' % res['name']) try: image = self.get_image(res['image']) flavor = self.get_flavor(res['flavor']) self.get_key_pair(res['keypair']) except NotFound as ex: raise ProvisionError(ex.message + ' for %s.' % res['name']) try: # boot vm node = self.boot_vm(res['name'], image, flavor, res['keypair'], network=int_net) # wait for vm to finish building self.wait_for_building_finish(node, res) # create/attach floating ip res['public_v4'] = self.attach_floating_ip(node, ext_net) except BootError as ex: raise ProvisionError(ex.message) except (BuildError, NetworkError, SSHError) as ex: self.logger.error(ex.message) self.logger.info('Tearing down vm: %s.', res['name']) self.driver.destroy_node(node) raise ProvisionError('Provision task failed.') # set administrator password self.resources = set_administrator_password(self.resources, self.user_dir) # create inventory file resources_paws = dict(resources=self.resources) create_inventory( PlayCall(self.user_dir).inventory_file, resources_paws) # create resources.paws resources_paws = dict(resources=deepcopy(self.resources)) file_mgmt('w', self.resources_paws_file, resources_paws) return resources_paws