def get_dummy_ssh(self, retry=False): ssh = SSH("", "", "") ssh.test_connectivity = Mock(return_value=True) ssh.execute = Mock(return_value=("10", "", 0)) ssh.sftp_put_files = Mock(return_value=True) ssh.sftp_mkdir = Mock(return_value=True) ssh.sftp_put_dir = Mock(return_value=True) ssh.sftp_put = Mock(return_value=True) return ssh
def sftp_get(self, src, dest): return SSH.sftp_get(self, src, dest)
def changeVMCredentials(vm, pk_file): if vm['os'] == "windows": if 'passwd' in vm and vm['passwd'] and 'new_passwd' in vm and vm[ 'new_passwd']: try: import winrm except: CtxtAgent.logger.exception("Error importing winrm.") return False try: url = "https://" + vm['ip'] + ":5986" s = winrm.Session(url, auth=(vm['user'], vm['passwd'])) r = s.run_cmd('net', ['user', vm['user'], vm['new_passwd']]) # this part of the code is never reached ... if r.status_code == 0: vm['passwd'] = vm['new_passwd'] return True else: CtxtAgent.logger.error( "Error changing password to Windows VM: " + r.std_out) return False except winrm.exceptions.AuthenticationError: # if the password is correctly changed the command returns this # error try: # let's check that the new password works s = winrm.Session(url, auth=(vm['user'], vm['new_passwd'])) r = s.run_cmd('echo', ['OK']) if r.status_code == 0: vm['passwd'] = vm['new_passwd'] return True else: CtxtAgent.logger.error( "Error changing password to Windows VM: " + r.std_out) return False except: CtxtAgent.logger.exception( "Error changing password to Windows VM: " + vm['ip'] + ".") return False except: CtxtAgent.logger.exception( "Error changing password to Windows VM: " + vm['ip'] + ".") return False else: # Linux VMs # Check if we must change user credentials in the VM if 'passwd' in vm and vm['passwd'] and 'new_passwd' in vm and vm[ 'new_passwd']: CtxtAgent.logger.info("Changing password to VM: " + vm['ip']) private_key = vm['private_key'] if pk_file: private_key = pk_file try: ssh_client = SSH(vm['ip'], vm['user'], vm['passwd'], private_key, vm['remote_port']) sudo_pass = "" if ssh_client.password: sudo_pass = "******" + ssh_client.password + "' | " (out, err, code) = ssh_client.execute( sudo_pass + 'sudo -S bash -c \'echo "' + vm['user'] + ':' + vm['new_passwd'] + '" | /usr/sbin/chpasswd && echo "OK"\' 2> /dev/null') except: CtxtAgent.logger.exception( "Error changing password to VM: " + vm['ip'] + ".") return False if code == 0: vm['passwd'] = vm['new_passwd'] return True else: CtxtAgent.logger.error("Error changing password to VM: " + vm['ip'] + ". " + out + err) return False if 'new_public_key' in vm and vm[ 'new_public_key'] and 'new_private_key' in vm and vm[ 'new_private_key']: CtxtAgent.logger.info("Changing public key to VM: " + vm['ip']) private_key = vm['private_key'] if pk_file: private_key = pk_file try: ssh_client = SSH(vm['ip'], vm['user'], vm['passwd'], private_key, vm['remote_port']) (out, err, code) = ssh_client.execute_timeout( 'echo ' + vm['new_public_key'] + ' >> .ssh/authorized_keys', 5) except: CtxtAgent.logger.exception( "Error changing public key to VM: " + vm['ip'] + ".") return False if code != 0: CtxtAgent.logger.error( "Error changing public key to VM:: " + vm['ip'] + ". " + out + err) return False else: vm['private_key'] = vm['new_private_key'] return True return False
def sftp_remove(self, path): return SSH.sftp_remove(self, path)
def sftp_list_attr(self, directory): return SSH.sftp_list_attr(self, directory)
def sftp_put_content(self, content, dest): return SSH.sftp_put_content(self, content, dest)
def sftp_put_files(self, files): return SSH.sftp_put_files(self, files)
def sftp_mkdir(self, directory, mode=0o777): return SSH.sftp_mkdir(self, directory, mode)
def sftp_put_dir(self, src, dest): return SSH.sftp_put_dir(self, src, dest)
def sftp_get_files(self, src, dest): return SSH.sftp_get_files(self, src, dest)
def wait_ssh_access(vm, delay=10, max_wait=None, quiet=False): """ Test the SSH access to the VM return: init, new or pk_file or None if it fails """ if not max_wait: max_wait = CtxtAgent.SSH_WAIT_TIMEOUT wait = 0 success = False res = None last_tested_private = False while wait < max_wait: if 'ctxt_ip' in vm: vm_ip = vm['ctxt_ip'] elif 'private_ip' in vm and not last_tested_private: # First test the private one vm_ip = vm['private_ip'] last_tested_private = True else: vm_ip = vm['ip'] last_tested_private = False if not quiet: CtxtAgent.logger.debug("Testing SSH access to VM: %s:%s" % (vm_ip, vm['remote_port'])) wait += delay try: ssh_client = SSH(vm_ip, vm['user'], vm['passwd'], vm['private_key'], vm['remote_port']) success = ssh_client.test_connectivity(delay) res = 'init' except AuthenticationException: try_ansible_key = True if 'new_passwd' in vm: try_ansible_key = False # If the process of changing credentials has finished in the # VM, we must use the new ones if not quiet: CtxtAgent.logger.debug( "Error connecting with SSH with initial credentials with: " + vm_ip + ". Try to use new ones.") try: ssh_client = SSH(vm_ip, vm['user'], vm['new_passwd'], vm['private_key'], vm['remote_port']) success = ssh_client.test_connectivity() res = "new" except AuthenticationException: try_ansible_key = True except: if not quiet: CtxtAgent.logger.exception( "Error connecting with SSH with: " + vm_ip) success = False if try_ansible_key: # In some very special cases the last two cases fail, so check # if the ansible key works if not quiet: CtxtAgent.logger.debug( "Error connecting with SSH with initial credentials with: " + vm_ip + ". Try to ansible_key.") try: ssh_client = SSH(vm_ip, vm['user'], None, CtxtAgent.PK_FILE, vm['remote_port']) success = ssh_client.test_connectivity() res = 'pk_file' except: if not quiet: CtxtAgent.logger.exception( "Error connecting with SSH with: " + vm_ip) success = False except: if not quiet: CtxtAgent.logger.exception( "Error connecting with SSH with: " + vm_ip) success = False if success: vm['ctxt_ip'] = vm_ip return res else: time.sleep(delay) return None
def sftp_chmod(self, path, mode): return SSH.sftp_chmod(self, path, mode)
def execute(self, command, timeout = None): return SSH.execute(self, command, timeout)
def test_ssh(self, vm, vm_ip, remote_port, quiet, delay=10): """ Test the SSH access to the VM return: init, new or pk_file or None if it fails """ success = False res = None if not quiet: self.logger.debug("Testing SSH access to VM: %s:%s" % (vm_ip, remote_port)) try: ssh_client = SSH(vm_ip, vm['user'], vm['passwd'], vm['private_key'], remote_port) success = ssh_client.test_connectivity(delay) res = 'init' except AuthenticationException: try_ansible_key = True if 'new_passwd' in vm: try_ansible_key = False # If the process of changing credentials has finished in the # VM, we must use the new ones if not quiet: self.logger.debug( "Error connecting with SSH with initial credentials with: " + vm_ip + ". Try to use new ones.") try: ssh_client = SSH(vm_ip, vm['user'], vm['new_passwd'], vm['private_key'], remote_port) success = ssh_client.test_connectivity() res = "new" except AuthenticationException: try_ansible_key = True except Exception: if not quiet: self.logger.exception( "Error connecting with SSH with: " + vm_ip) success = False if try_ansible_key: # In some very special cases the last two cases fail, so check # if the ansible key works if not quiet: self.logger.debug( "Error connecting with SSH with initial credentials with: " + vm_ip + ". Try to ansible_key.") try: ssh_client = SSH(vm_ip, vm['user'], None, CtxtAgentBase.PK_FILE, remote_port) success = ssh_client.test_connectivity() res = 'pk_file' except Exception: if not quiet: self.logger.exception( "Error connecting with SSH with: " + vm_ip) success = False except Exception: if not quiet: self.logger.exception("Error connecting with SSH with: " + vm_ip) success = False return success, res
def getcwd(self): return SSH.getcwd(self)
def sftp_mkdir(self, directory): return SSH.sftp_mkdir(self, directory)
def execute(self, command, timeout=None): return SSH.execute(self, command, timeout)
def contextualize_vm(general_conf_data, vm_conf_data): vault_pass = None if 'VAULT_PASS' in os.environ: vault_pass = os.environ['VAULT_PASS'] res_data = {} CtxtAgent.logger.info('Generate and copy the ssh key') # If the file exists, do not create it again if not os.path.isfile(CtxtAgent.PK_FILE): out = CtxtAgent.run_command('ssh-keygen -t rsa -C ' + getpass.getuser() + ' -q -N "" -f ' + CtxtAgent.PK_FILE) CtxtAgent.logger.debug(out) # Check that we can SSH access the node ctxt_vm = None for vm in general_conf_data['vms']: if vm['id'] == vm_conf_data['id']: ctxt_vm = vm if not ctxt_vm: CtxtAgent.logger.error("No VM to Contextualize!") res_data['OK'] = False return res_data for task in vm_conf_data['tasks']: task_ok = False num_retries = 0 while not task_ok and num_retries < CtxtAgent.PLAYBOOK_RETRIES: num_retries += 1 CtxtAgent.logger.info('Launch task: ' + task) if ctxt_vm['os'] == "windows": # playbook = general_conf_data['conf_dir'] + "/" + task + "_task_all_win.yml" playbook = general_conf_data[ 'conf_dir'] + "/" + task + "_task.yml" else: playbook = general_conf_data[ 'conf_dir'] + "/" + task + "_task_all.yml" inventory_file = general_conf_data['conf_dir'] + "/hosts" ansible_thread = None if task == "basic": # This is always the fist step, so put the SSH test, the # requiretty removal and change password here for vm in general_conf_data['vms']: if vm['os'] == "windows": CtxtAgent.logger.info( "Waiting WinRM access to VM: " + vm['ip']) ssh_res = CtxtAgent.wait_winrm_access(vm) else: CtxtAgent.logger.info( "Waiting SSH access to VM: " + vm['ip']) ssh_res = CtxtAgent.wait_ssh_access(vm) # the IP has changed public for private and we are the # master VM if 'ctxt_ip' in vm and vm['ctxt_ip'] != vm[ 'ip'] and ctxt_vm['master']: # update the ansible inventory CtxtAgent.logger.info( "Changing the IP %s for %s in config files." % (vm['ctxt_ip'], vm['ip'])) CtxtAgent.replace_vm_ip(vm) if vm['id'] == vm_conf_data['id']: cred_used = ssh_res if not ssh_res: CtxtAgent.logger.error( "Error Waiting access to VM: " + vm['ip']) res_data['SSH_WAIT'] = False res_data['OK'] = False return res_data else: res_data['SSH_WAIT'] = True CtxtAgent.logger.info("Remote access to VM: " + vm['ip'] + " Open!") # The basic task uses the credentials of VM stored in ctxt_vm pk_file = None if cred_used == "pk_file": pk_file = CtxtAgent.PK_FILE # First remove requiretty in the node if ctxt_vm['os'] != "windows": success = CtxtAgent.removeRequiretty(ctxt_vm, pk_file) if success: CtxtAgent.logger.info( "Requiretty successfully removed") else: CtxtAgent.logger.error("Error removing Requiretty") # Check if we must chage user credentials # Do not change it on the master. It must be changed only by # the ConfManager change_creds = False if not ctxt_vm['master']: change_creds = CtxtAgent.changeVMCredentials( ctxt_vm, pk_file) res_data['CHANGE_CREDS'] = change_creds if ctxt_vm['os'] != "windows": # this step is not needed in windows systems ansible_thread = CtxtAgent.LaunchAnsiblePlaybook( CtxtAgent.logger, vm_conf_data['remote_dir'], playbook, ctxt_vm, 2, inventory_file, pk_file, CtxtAgent.INTERNAL_PLAYBOOK_RETRIES, change_creds, vault_pass) else: # In some strange cases the pk_file disappears. So test it and # remake basic recipe if ctxt_vm['os'] != "windows": success = False try: ssh_client = SSH(ctxt_vm['ip'], ctxt_vm['user'], None, CtxtAgent.PK_FILE, ctxt_vm['remote_port']) success = ssh_client.test_connectivity() except: success = False if not success: CtxtAgent.logger.warn( "Error connecting with SSH using the ansible key with: " + ctxt_vm['ip'] + ". Call the basic playbook again.") basic_playbook = general_conf_data[ 'conf_dir'] + "/basic_task_all.yml" output_basic = StringIO() ansible_thread = CtxtAgent.LaunchAnsiblePlaybook( output_basic, vm_conf_data['remote_dir'], basic_playbook, ctxt_vm, 2, inventory_file, None, CtxtAgent.INTERNAL_PLAYBOOK_RETRIES, True, vault_pass) (task_ok, _) = CtxtAgent.wait_thread(ansible_thread) # in the other tasks pk_file can be used ansible_thread = CtxtAgent.LaunchAnsiblePlaybook( CtxtAgent.logger, vm_conf_data['remote_dir'], playbook, ctxt_vm, 2, inventory_file, CtxtAgent.PK_FILE, CtxtAgent.INTERNAL_PLAYBOOK_RETRIES, vm_conf_data['changed_pass'], vault_pass) if ansible_thread: (task_ok, _) = CtxtAgent.wait_thread(ansible_thread) else: task_ok = True if not task_ok: CtxtAgent.logger.warn( "ERROR executing task %s: (%s/%s)" % (task, num_retries, CtxtAgent.PLAYBOOK_RETRIES)) else: CtxtAgent.logger.info('Task %s finished successfully' % task) res_data[task] = task_ok if not task_ok: res_data['OK'] = False return res_data res_data['OK'] = True CtxtAgent.logger.info('Process finished') return res_data