def removeRequiretty(vm, pk_file): if not vm['master']: CtxtAgent.logger.info("Removing requiretty to VM: " + vm['ip']) try: private_key = vm['private_key'] if pk_file: private_key = pk_file ssh_client = SSH(vm['ip'], vm['user'], vm['passwd'], private_key, vm['remote_port']) # Activate tty mode to avoid some problems with sudo in REL ssh_client.tty = True sudo_pass = "" if ssh_client.password: sudo_pass = "******" + ssh_client.password + "' | " (stdout, stderr, code) = ssh_client.execute_timeout( sudo_pass + "sudo -S sed -i 's/.*requiretty$/#Defaults requiretty/' /etc/sudoers", 5) CtxtAgent.logger.debug("OUT: " + stdout + stderr) return code == 0 except: CtxtAgent.logger.exception( "Error removing requiretty to VM: " + vm['ip']) return False else: return True
def get_ssh(self, retry=False, auto_close=True): """ Get SSH object to connect with this VM """ proxy_host = None with self._lock: (user, passwd, _, private_key) = self.getCredentialValues() ip = self.getPublicIP() if ip is None: ip = self.getPrivateIP() if ip and self.getProxyHost(): proxy_host = self.getProxyHost() if ip is None: self.log_warn( "VM ID %s does not have IP. Do not return SSH Object." % self.im_id) return None if retry: return SSHRetry(ip, user, passwd, private_key, self.getSSHPort(), proxy_host, auto_close=auto_close) else: return SSH(ip, user, passwd, private_key, self.getSSHPort(), proxy_host, auto_close=auto_close)
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 get_ssh(vm, pk_file, changed_pass=None): """ Get VM ssh connection """ private_key = vm['private_key'] if pk_file: private_key = pk_file return SSH(vm['ctxt_ip'], vm['user'], vm['passwd'], private_key, vm['ctxt_port'])
def get_ssh_from_auth_data(self, auth_data): auth = auth_data.getAuthInfo(LibVirtCloudConnector.type) if auth and 'username' in auth[0] and 'password' in auth[ 0] and 'host' in auth[0]: return SSH(auth[0]['host'], auth[0]['username'], auth[0]['password']) else: self.logger.error("Datos de autenticacion incorrectos") return None
def get_ssh_ansible_master(self, retry=True): ansible_host = self.get_ansible_host() if ansible_host: (user, passwd, private_key) = ansible_host.getCredentialValues() if retry: return SSHRetry(ansible_host.getHost(), user, passwd, private_key) else: return SSH(ansible_host.getHost(), user, passwd, private_key) else: if self.inf.vm_master: return self.inf.vm_master.get_ssh(retry=retry) else: return None
def get_ssh(self, retry=False): """ Get SSH object to connect with this VM """ (user, passwd, _, private_key) = self.getCredentialValues() ip = self.getPublicIP() if ip is None: ip = self.getPrivateIP() if ip is None: return None if retry: return SSHRetry(ip, user, passwd, private_key, self.getSSHPort()) else: return SSH(ip, user, passwd, private_key, self.getSSHPort())
def getProxyHost(self): """ Return the proxy_host data if available """ for netid in self.info.systems[0].getNetworkIDs(): net = self.info.get_network_by_id(netid) if net.getValue("proxy_host"): proxy_user, proxy_pass, proxy_ip, proxy_port = get_user_pass_host_port( net.getValue("proxy_host")) if not proxy_port: proxy_port = 22 return SSH(proxy_ip, proxy_user, proxy_pass, net.getValue("proxy_key"), proxy_port) return None
def get_ssh_ansible_master(self, retry=True): ansible_host = self.get_ansible_host() if ansible_host: (user, passwd, private_key) = ansible_host.getCredentialValues() if retry: return SSHRetry(ansible_host.getHost(), user, passwd, private_key) else: return SSH(ansible_host.getHost(), user, passwd, private_key) else: if self.inf.vm_master: return self.inf.vm_master.get_ssh(retry=retry) else: self.log_warn( "There is not master VM. Do not return SSH object.") return None
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 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 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 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