def _host_ssh(creds={}, commands=[]): """ Connect to the host machine. Namely the user's local machine. """ if creds == {}: raise RuntimeError("No credentials provided to _host_ssh()") command = ' && '.join(commands) # First check if we can access the host machine. It's likely that their # IP address changes every time they request a DHCP lease. # TODO: Find a way of passing this error onto the CLI client. try: subprocess.check_call(['nc', '-z', '-w2', creds['host'], '22'], stderr=subprocess.PIPE) except subprocess.CalledProcessError: raise RuntimeError("Couldn't ping port 22 at host with IP " + creds['host']) ssh = connect_ssh(creds['user'], creds['host'], 22, PKEY, timeout=120) result, status = exec_ssh(ssh, command) if status > 0: raise RuntimeError('SSH to Vagrant host error: ' + result.decode('utf-8') + 'Command: ' + command.decode('utf-8')) return result
def _host_ssh(creds={}, commands=[]): """ Connect to the host machine. Namely the user's local machine. """ if creds == {}: raise RuntimeError("No credentials provided to _host_ssh()") command = ' && '.join(commands) # First check if we can access the host machine. It's likely that their # IP address changes every time they request a DHCP lease. # TODO: Find a way of passing this error onto the CLI client. try: subprocess.check_call([ 'nc', '-z', '-w2', creds['host'], '22' ], stderr=subprocess.PIPE) except subprocess.CalledProcessError: raise RuntimeError("Couldn't ping port 22 at host with IP " + creds['host']) ssh = connect_ssh(creds['user'], creds['host'], 22, PKEY, timeout=120) result, status = exec_ssh(ssh, command) if status > 0: raise RuntimeError( 'SSH to Vagrant host error: ' + result.decode('utf-8') + 'Command: ' + command.decode('utf-8')) return result
def converge_node(node): ssh = connect_ssh(node['ssh_username'], node['fqdn'], 22, node['ssh_private_key']) output, rc = exec_ssh(ssh, 'sudo chef-client') if rc != 0: e = RuntimeError('Node converge error') e.output = output raise e return output, rc
def bootstrap_node(node): """ Bootstrap the Chef configuration management tools onto a node. :param node: a dict containing the node's fully-qualified domain name and SSH info :raises: RuntimeError """ # block until we can connect over ssh ssh = connect_ssh(node['ssh_username'], node['fqdn'], node.get('ssh_port', 22), node['ssh_private_key'], timeout=120) # block until ubuntu cloud-init is finished initializing = True while initializing: time.sleep(10) initializing, _rc = exec_ssh( ssh, 'ps auxw | egrep "cloud-init" | grep -v egrep') # write out private key and prepare to `knife bootstrap` try: _, pk_path = tempfile.mkstemp() _, output_path = tempfile.mkstemp() with open(pk_path, 'w') as f: f.write(node['ssh_private_key']) # build knife bootstrap command args = ['knife', 'bootstrap', node['fqdn']] args.extend(['--identity-file', pk_path]) args.extend(['--node-name', node['id']]) args.extend(['--sudo', '--ssh-user', node['ssh_username']]) args.extend(['--ssh-port', str(node.get('ssh_port', 22))]) args.extend(['--bootstrap-version', CHEF_CLIENT_VERSION]) args.extend(['--no-host-key-verify']) args.extend(['--run-list', _construct_run_list(node)]) print(' '.join(args)) # tee the command's output to a tempfile args.extend(['|', 'tee', output_path]) # TODO: figure out why home isn't being set correctly for knife exec env = os.environ.copy() env['HOME'] = '/opt/deis' # execute knife bootstrap p = subprocess.Popen(' '.join(args), env=env, shell=True) rc = p.wait() # always print knife output with open(output_path) as f: output = f.read() print(output) # raise an exception if bootstrap failed if rc != 0: raise RuntimeError('Node Bootstrap Error') # remove temp files from filesystem finally: os.remove(pk_path) os.remove(output_path)
def run_node(node, command): """ Run a command on a node. :param node: a dict containing the node's fully-qualified domain name and SSH info :param command: the command-line to execute on the node :returns: a tuple of the command's (output, return_code) """ ssh = connect_ssh(node['ssh_username'], node['fqdn'], node['ssh_port'], node['ssh_private_key']) output, rc = exec_ssh(ssh, command, pty=True) return output, rc
def bootstrap_node(node): """ Bootstrap the Chef configuration management tools onto a node. :param node: a dict containing the node's fully-qualified domain name and SSH info :raises: RuntimeError """ # block until we can connect over ssh ssh = connect_ssh(node['ssh_username'], node['fqdn'], node.get('ssh_port', 22), node['ssh_private_key'], timeout=120) # block until ubuntu cloud-init is finished initializing = True while initializing: time.sleep(10) initializing, _rc = exec_ssh(ssh, 'ps auxw | egrep "cloud-init" | grep -v egrep') # write out private key and prepare to `knife bootstrap` try: _, pk_path = tempfile.mkstemp() _, output_path = tempfile.mkstemp() with open(pk_path, 'w') as f: f.write(node['ssh_private_key']) # build knife bootstrap command args = ['knife', 'bootstrap', node['fqdn']] args.extend(['--identity-file', pk_path]) args.extend(['--node-name', node['id']]) args.extend(['--sudo', '--ssh-user', node['ssh_username']]) args.extend(['--ssh-port', str(node.get('ssh_port', 22))]) args.extend(['--bootstrap-version', CHEF_CLIENT_VERSION]) args.extend(['--no-host-key-verify']) args.extend(['--run-list', _construct_run_list(node)]) print(' '.join(args)) # tee the command's output to a tempfile args.extend(['|', 'tee', output_path]) # TODO: figure out why home isn't being set correctly for knife exec env = os.environ.copy() env['HOME'] = '/opt/deis' # execute knife bootstrap p = subprocess.Popen(' '.join(args), env=env, shell=True) rc = p.wait() # always print knife output with open(output_path) as f: output = f.read() print(output) # raise an exception if bootstrap failed if rc != 0 or 'incorrect password' in output: raise RuntimeError('Node Bootstrap Error:\n' + output) # remove temp files from filesystem finally: os.remove(pk_path) os.remove(output_path)
def converge_node(node): """ Converge a node. "Converge" means to change a node's configuration to match that defined by configuration management. :param node: a dict containing the node's fully-qualified domain name and SSH info :returns: a tuple of the convergence command's (output, return_code) """ ssh = connect_ssh(node['ssh_username'], node['fqdn'], 22, node['ssh_private_key']) output, rc = exec_ssh(ssh, 'sudo chef-client') print(output) if rc != 0: e = RuntimeError('Node converge error') e.output = output raise e return output, rc
def converge_node(node): """ Converge a node. "Converge" means to change a node's configuration to match that defined by configuration management. :param node: a dict containing the node's fully-qualified domain name and SSH info :returns: a tuple of the convergence command's (output, return_code) """ ssh = connect_ssh(node['ssh_username'], node['fqdn'], 22, node['ssh_private_key']) output, rc = exec_ssh(ssh, 'sudo chef-client') if rc != 0: e = RuntimeError('Node converge error') e.output = output raise e return output, rc
def bootstrap_node(node): # block until we can connect over ssh ssh = connect_ssh(node['ssh_username'], node['fqdn'], node.get('ssh_port', 22), node['ssh_private_key'], timeout=120) # block until ubuntu cloud-init is finished initializing = True while initializing: time.sleep(10) initializing, _rc = exec_ssh(ssh, 'ps auxw | egrep "cloud-init" | grep -v egrep') # write out private key and prepare to `knife bootstrap` try: _, pk_path = tempfile.mkstemp() with open(pk_path, 'w') as f: f.write(node['ssh_private_key']) # build knife bootstrap command args = ['knife', 'bootstrap', node['fqdn']] args.extend(['--identity-file', pk_path]) args.extend(['--node-name', node['id']]) args.extend(['--sudo', '--ssh-user', node['ssh_username']]) args.extend(['--ssh-port', str(node.get('ssh_port', 22))]) args.extend(['--bootstrap-version', CHEF_CLIENT_VERSION]) args.extend(['--no-host-key-verify']) args.extend(['--run-list', _construct_run_list(node)]) print(' '.join(args)) # TODO: figure out why home isn't being set correctly for knife exec env = os.environ.copy() env['HOME'] = '/opt/deis' # execute knife bootstrap p = subprocess.Popen(args, env=env, stderr=subprocess.PIPE) rc = p.wait() if rc != 0: print(p.stderr.read()) raise RuntimeError('Node Bootstrap Error') # remove private key from fileystem finally: pass # os.remove(pk_path)
def run_node(node, command): ssh = connect_ssh(node['ssh_username'], node['fqdn'], node['ssh_port'], node['ssh_private_key']) output, rc = exec_ssh(ssh, command, pty=True) return output, rc