def deploy_chef(ask="yes", version="11"): """Install chef-solo on a node""" env.host_string = lib.get_env_host_string() if ask == "no" or littlechef.noninteractive: print("Deploying Chef using omnibus installer version: ...".format(version)) else: message = ('\nAre you sure you want to install Chef version:' '{0} on node {1}?'.format(version, env.host_string)) if not confirm(message): abort('Aborted by user') lib.print_header("Configuring Chef Solo on {0}".format(env.host_string)) if not __testing__: solo.install(version) solo.configure() # Build a basic node file if there isn't one already # with some properties from ohai with settings(hide('stdout'), warn_only=True): output = sudo('ohai -l warn') if output.succeeded: try: ohai = json.loads(output) except ValueError: abort("Could not parse ohai's output" ":\n {0}".format(output)) node = {"run_list": []} for attribute in ["ipaddress", "platform", "platform_family", "platform_version"]: if ohai.get(attribute): node[attribute] = ohai[attribute] chef.save_config(node)
def test_attribute_merge_cookbook_not_found(self): """Should print a warning when merging a node and a cookbook is not found """ # Save new node with a non-existing cookbook assigned env.host_string = 'extranode' chef.save_config({"run_list": ["recipe[phantom_cookbook]"]}) self.assertRaises(SystemExit, chef.build_node_data_bag)
def test_attribute_merge_cookbook_not_found(self): """Should print a warning when merging a node and a cookbook is not found """ # Save new node with a non-existing cookbook assigned env.host_string = 'extranode' chef.save_config({"run_list": ["recipe[phantom_cookbook]"]}) self.assertRaises(SystemExit, chef._build_node_data_bag)
def deploy_chef(gems="no", ask="yes", version="0.10", distro_type=None, distro=None, platform=None, stop_client='yes', method=None): """Install chef-solo on a node""" if not env.host_string: abort('no node specified\nUsage: fix node:MYNODES deploy_chef') deprecated_parameters = [distro_type, distro, platform] if any(param is not None for param in deprecated_parameters) or gems != 'no': print("DeprecationWarning: the parameters 'gems', distro_type'," " 'distro' and 'platform' will no longer be supported " "in future versions of LittleChef. Use 'method' instead") if distro_type is None and distro is None: distro_type, distro, platform = solo.check_distro() elif distro_type is None or distro is None: abort('Must specify both or neither of distro_type and distro') if method: if method not in ['omnibus', 'gentoo', 'pacman']: abort('Invalid omnibus method {0}. Supported methods are ' 'omnibus, gentoo and pacman'.format(method)) msg = "{0} using the {1} installer".format(version, method) else: if gems == "yes": msg = 'using gems for "{0}"'.format(distro) else: msg = '{0} using "{1}" packages'.format(version, distro) if method == 'omnibus' or ask == "no" or littlechef.noninteractive: print("Deploying Chef {0}...".format(msg)) else: message = ('\nAre you sure you want to install Chef ' '{0} on node {1}?'.format(msg, env.host_string)) if not confirm(message): abort('Aborted by user') _configure_fabric_for_platform(platform) if not __testing__: solo.install(distro_type, distro, gems, version, stop_client, method) solo.configure() # Build a basic node file if there isn't one already # with some properties from ohai with settings(hide('stdout'), warn_only=True): output = sudo('ohai -l warn') if output.succeeded: try: ohai = json.loads(output) except ValueError: abort("Could not parse ohai's output" ":\n {0}".format(output)) node = {"run_list": []} for attribute in ["ipaddress", "platform", "platform_family", "platform_version"]: if ohai.get(attribute): node[attribute] = ohai[attribute] chef.save_config(node)
def deploy_chef(gems="no", ask="yes", version="0.10", distro_type=None, distro=None, platform=None, stop_client='yes'): """Install chef-solo on a node""" if not env.host_string: abort('no node specified\nUsage: fix node:MYNODES deploy_chef') chef_versions = ["0.9", "0.10"] if version not in chef_versions: abort('Wrong Chef version specified. Valid versions are {0}'.format( ", ".join(chef_versions))) if distro_type is None and distro is None: distro_type, distro, platform = solo.check_distro() elif distro_type is None or distro is None: abort('Must specify both or neither of distro_type and distro') if ask == "yes": message = '\nAre you sure you want to install Chef {0}'.format(version) message += ' on node {0}'.format(env.host_string) if gems == "yes": message += ', using gems for "{0}"?'.format(distro) else: message += ', using "{0}" packages?'.format(distro) if not confirm(message): abort('Aborted by user') else: if gems == "yes": method = 'using gems for "{0}"'.format(distro) else: method = '{0} using "{1}" packages'.format(version, distro) print("Deploying Chef {0}...".format(method)) _configure_fabric_for_platform(platform) if not __testing__: solo.install(distro_type, distro, gems, version, stop_client) solo.configure() # Build a basic node file if there isn't one already with some properties from ohai with settings(hide('stdout'), warn_only=True): output = sudo('ohai -l warn') if output.succeeded: try: ohai = json.loads(output) except json.JSONDecodeError: abort("Could not parse ohai's output" ":\n {0}".format(output)) node = {"run_list": []} for prop in ["ipaddress", "platform", "platform_family", "platform_version"]: if ohai[prop]: node[prop] = ohai[prop] chef.save_config(node)
def execute(node): """Uses ohai to get virtualization information which is then saved to then node file """ with hide('everything'): virt = json.loads(sudo('ohai virtualization')) if not len(virt) or virt[0][1] != "host": # It may work for virtualization solutions other than Xen print("This node is not a Xen host, doing nothing") return node['virtualization'] = { 'role': 'host', 'system': 'xen', 'vms': [], } # VMs with hide('everything'): vm_list = sudo("xm list") for vm in vm_list.split("\n")[2:]: data = vm.split() if len(data) != 6: break node['virtualization']['vms'].append({ 'fqdn': data[0], 'RAM': data[2], 'cpus': data[3] }) print("Found {0} VMs for this Xen host".format( len(node['virtualization']['vms']))) # Save node file and remove the returned temp file del node['name'] os.remove(chef.save_config(node, True))
def get_ips(): """Ping all nodes and update their 'ipaddress' field""" import subprocess for node in lib.get_nodes(): # For each node, ping the hostname env.host_string = node['name'] proc = subprocess.Popen(['ping', '-c', '1', node['name']], stdout=subprocess.PIPE, stderr=subprocess.PIPE) resp, error = proc.communicate() if not error: # Get lines from output and parse the first line to get the IP lines = resp.split("\n") # IP Address Regex http://www.regular-expressions.info/examples.html ip_matches = re.findall(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b', lines[0]) ip = ip_matches[0] if ip_matches else None if not ip: print "Warning: could not get IP address from node {0}".format( node['name']) continue print "Node {0} has IP {1}".format(node['name'], ip) # Update with the ipaddress field in the corresponding node.json del node['name'] node['ipaddress'] = ip os.remove(chef.save_config(node, ip)) else: print "Warning: could not resolve node {0}".format(node['name'])
def execute(node): "Uses ohai to get cloud info and save to the node" with hide('everything'): ohai = json.loads(sudo('ohai')) if not len(ohai): print("Not a cloud node, skipping") return node['cloud'] = ohai['cloud'] del node['name'] os.remove(chef.save_config(node, True))
def execute(node): "Uses ohai to get cloud info and save to the node" with hide('everything'): ohai = json.loads(sudo('ohai -d /etc/chef/ohai_plugins')) if not len(ohai): print("No network? This is wrong") return del(ohai['network']['interfaces']) node['network'] = ohai['network'] del node['name'] os.remove(chef.save_config(node, True))
def test_save_config(self): """Should create a tmp_testnode4.json and a nodes/testnode4.json config file """ # Save a new node env.host_string = 'testnode4' run_list = ["role[base]"] chef.save_config({"run_list": run_list}) file_path = os.path.join('nodes', 'testnode4.json') self.assertTrue(os.path.exists(file_path)) with open(file_path, 'r') as f: data = json.loads(f.read()) self.assertEquals(data['run_list'], run_list) # It should't overwrite existing config files env.host_string = 'testnode1' # This node exists run_list = ["role[base]"] chef.save_config({"run_list": run_list}) with open(os.path.join('nodes', 'testnode1.json'), 'r') as f: data = json.loads(f.read()) # It should *NOT* have "base" assigned self.assertEquals(data['run_list'], ["recipe[subversion]"])
def test_save_config(self): """Should create a tmp_extranode.json and a nodes/extranode.json config file """ # Save a new node env.host_string = "extranode" run_list = ["role[base]"] chef.save_config({"run_list": run_list}) file_path = os.path.join("nodes", "extranode.json") self.assertTrue(os.path.exists(file_path)) with open(file_path, "r") as f: data = json.loads(f.read()) self.assertEquals(data["run_list"], run_list) # It should't overwrite existing config files env.host_string = "testnode1" # This node exists run_list = ["role[base]"] chef.save_config({"run_list": run_list}) with open(os.path.join("nodes", "testnode1.json"), "r") as f: data = json.loads(f.read()) # It should *NOT* have "base" assigned self.assertEquals(data["run_list"], ["recipe[subversion]"])
def deploy_chef(ask="yes", version="13.12.14"): """Install chef-solo on a node""" env.host_string = lib.get_env_host_string() if ask == "no" or littlechef.noninteractive: print("Deploying Chef using omnibus installer version: ...".format( version)) else: message = ('\nAre you sure you want to install Chef version:' '{0} on node {1}?'.format(version, env.host_string)) if not confirm(message): abort('Aborted by user') lib.print_header("Configuring Chef Solo on {0}".format(env.host_string)) if not __testing__: solo.install(version) solo.configure() # Build a basic node file if there isn't one already # with some properties from ohai with settings(hide('stdout'), warn_only=True): output = sudo('ohai -l warn') if output.succeeded: try: ohai = json.loads(output) except ValueError: abort("Could not parse ohai's output" ":\n {0}".format(output)) node = {"run_list": []} for attribute in [ "ipaddress", "platform", "platform_family", "platform_version" ]: if ohai.get(attribute): node[attribute] = ohai[attribute] chef.save_config(node)
def execute(node): proc = subprocess.Popen(['ping', '-c', '1', node['name']], stdout=subprocess.PIPE, stderr=subprocess.PIPE) resp, error = proc.communicate() if not error: # Split output into lines and parse the first line to get the IP ip = parse_ip(resp.split("\n")[0]) if not ip: print "Warning: could not get IP address from node {0}".format( node['name']) print "Node {0} has IP {1}".format(node['name'], ip) # Update with the ipaddress field in the corresponding node.json node['ipaddress'] = ip os.remove(chef.save_config(node, ip)) else: print "Warning: could not resolve node {0}".format(node['name'])
def get_ips(): """Ping all nodes and update their 'ipaddress' field""" import subprocess for node in lib.get_nodes(): # For each node, ping the hostname env.host_string = node["name"] proc = subprocess.Popen(["ping", "-c", "1", node["name"]], stdout=subprocess.PIPE, stderr=subprocess.PIPE) resp, error = proc.communicate() if not error: # Get lines from output and parse the first line to get the IP lines = resp.split("\n") ip = lines[0].split()[2].lstrip("(").rstrip(")") if not ip: print "Warning: could not get IP address from node {0}".format(node["name"]) continue print "Node {0} has IP {1}".format(node["name"], ip) # Update with the ipaddress field in the corresponding node.json del node["name"] node["ipaddress"] = ip os.remove(chef.save_config(node, ip)) else: print "Warning: could not resolve node {0}".format(node["name"])
def execute(node): """Uses ohai to get virtualization information which is then saved to then node file """ with hide("everything"): virt = json.loads(sudo("ohai virtualization")) if not len(virt) or virt[0][1] != "host": # It may work for virtualization solutions other than Xen print("This node is not a Xen host, doing nothing") return node["virtualization"] = {"role": "host", "system": "xen", "vms": []} # VMs with hide("everything"): vm_list = sudo("xm list") for vm in vm_list.split("\n")[2:]: data = vm.split() if len(data) != 6: break node["virtualization"]["vms"].append({"fqdn": data[0], "RAM": data[2], "cpus": data[3]}) print("Found {0} VMs for this Xen host".format(len(node["virtualization"]["vms"]))) # Save node file and remove the returned temp file os.remove(chef.save_config(node, True))
def execute(node): """ Uses vmrunwrapper to get the IP fo the vm - assumes that the config file is all set up and it is either in ~/.vmrunwrapper.conf or the environment variable VMRUNWRAPPER_CONF points to it """ wrapper = VmrunWrapper(get_config()) ip = None try: ip = wrapper.update_ssh_config() except: pass if ip is None: print "Warning: could not get IP address from node {0}".format( node['name']) print "Node {0} has IP {1}".format(node['name'], ip) # Update with the ipaddress field in the corresponding node.json node['ipaddress'] = ip os.remove(chef.save_config(node, ip))
def get_ips(): """Ping all nodes and update their 'ipaddress' field""" import subprocess for node in lib.get_nodes(): # For each node, ping the hostname env.host_string = node['name'] proc = subprocess.Popen(['ping', '-c', '1', node['name']], stdout=subprocess.PIPE, stderr=subprocess.PIPE) resp, error = proc.communicate() if not error: # Split output into lines and parse the first line to get the IP ip = lib.parse_ip(resp.split("\n")[0]) if not ip: print "Warning: could not get IP address from node {0}".format( node['name']) continue print "Node {0} has IP {1}".format(node['name'], ip) # Update with the ipaddress field in the corresponding node.json del node['name'] node['ipaddress'] = ip os.remove(chef.save_config(node, ip)) else: print "Warning: could not resolve node {0}".format(node['name'])
def test_attribute_merge_role_not_found(self): """Should print a warning when an assigned role if not found""" # Save new node with a non-existing cookbook assigned env.host_string = 'testnode4' chef.save_config({"run_list": ["role[phantom_role]"]}) self.assertRaises(SystemExit, chef._build_node_data_bag)
def execute(node): node['run_list'] = ["role[base]"] del node['name'] os.remove(chef.save_config(node, True))