def install_chef(cloud, chef_cfg, log): # If chef is not installed, we install chef based on 'install_type' install_type = util.get_cfg_option_str(chef_cfg, 'install_type', 'packages') run = util.get_cfg_option_bool(chef_cfg, 'exec', default=False) if install_type == "gems": # This will install and run the chef-client from gems chef_version = util.get_cfg_option_str(chef_cfg, 'version', None) ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version', RUBY_VERSION_DEFAULT) install_chef_from_gems(cloud.distro, ruby_version, chef_version) # Retain backwards compat, by preferring True instead of False # when not provided/overriden... run = util.get_cfg_option_bool(chef_cfg, 'exec', default=True) elif install_type == 'packages': # This will install and run the chef-client from packages cloud.distro.install_packages(('chef',)) elif install_type == 'omnibus': # This will install as a omnibus unified package url = util.get_cfg_option_str(chef_cfg, "omnibus_url", OMNIBUS_URL) retries = max(0, util.get_cfg_option_int(chef_cfg, "omnibus_url_retries", default=OMNIBUS_URL_RETRIES)) content = url_helper.readurl(url=url, retries=retries) with util.tempdir() as tmpd: # Use tmpdir over tmpfile to avoid 'text file busy' on execute tmpf = "%s/chef-omnibus-install" % tmpd util.write_file(tmpf, str(content), mode=0700) util.subp([tmpf], capture=False) else: log.warn("Unknown chef install type '%s'", install_type) run = False return run
def install_chef(cloud, chef_cfg, log): # If chef is not installed, we install chef based on 'install_type' install_type = util.get_cfg_option_str(chef_cfg, 'install_type', 'packages') run = util.get_cfg_option_bool(chef_cfg, 'exec', default=False) if install_type == "gems": # This will install and run the chef-client from gems chef_version = util.get_cfg_option_str(chef_cfg, 'version', None) ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version', RUBY_VERSION_DEFAULT) install_chef_from_gems(ruby_version, chef_version, cloud.distro) # Retain backwards compat, by preferring True instead of False # when not provided/overriden... run = util.get_cfg_option_bool(chef_cfg, 'exec', default=True) elif install_type == 'packages': # This will install and run the chef-client from packages cloud.distro.install_packages(('chef', )) elif install_type == 'omnibus': # This will install as a omnibus unified package url = util.get_cfg_option_str(chef_cfg, "omnibus_url", OMNIBUS_URL) retries = max( 0, util.get_cfg_option_int(chef_cfg, "omnibus_url_retries", default=OMNIBUS_URL_RETRIES)) content = url_helper.readurl(url=url, retries=retries) with util.tempdir() as tmpd: # Use tmpdir over tmpfile to avoid 'text file busy' on execute tmpf = "%s/chef-omnibus-install" % tmpd util.write_file(tmpf, content, mode=0o700) util.subp([tmpf], capture=False) else: log.warn("Unknown chef install type '%s'", install_type) run = False return run
def maybe_perform_dhcp_discovery(nic=None): """Perform dhcp discovery if nic valid and dhclient command exists. If the nic is invalid or undiscoverable or dhclient command is not found, skip dhcp_discovery and return an empty dict. @param nic: Name of the network interface we want to run dhclient on. @return: A dict of dhcp options from the dhclient discovery if run, otherwise an empty dict is returned. """ if nic is None: nic = find_fallback_nic() if nic is None: LOG.debug('Skip dhcp_discovery: Unable to find fallback nic.') return {} elif nic not in get_devicelist(): LOG.debug('Skip dhcp_discovery: nic %s not found in get_devicelist.', nic) return {} dhclient_path = util.which('dhclient') if not dhclient_path: LOG.debug('Skip dhclient configuration: No dhclient command found.') return {} with util.tempdir(prefix='cloud-init-dhcp-') as tmpdir: return dhcp_discovery(dhclient_path, nic, tmpdir)
def config_dhcp(interface, info, create=True): infile = "/etc/dhcpcd.ini" eat = 0 updated = 0 if interface is not None: with open(infile, 'r+') as f, util.tempdir() as tmpd: tmpf = "%s/dhcpcd.ini" % tmpd for line in f.readlines(): if create is False: util.append_file(tmpf, line) else: if eat == 0 and not line.startswith("interface "): util.append_file(tmpf, line) elif eat == 0 and line.startswith("interface "): eat = 1 elif eat == 1 and re.match("{", line.strip()): eat = 2 elif eat == 2: update_dhcp(tmpf, interface, info) updated = 1 eat = 3 if create is False: update_dhcp(tmpf, interface, info) else: if updated == 0: update_dhcp(tmpf, interface, info) util.copy(tmpf, infile)
def mount_cb(device, callback, data=None, rw=False, mtype=None, sync=True): """ Mount the device, call method 'callback' passing the directory in which it was mounted, then unmount. Return whatever 'callback' returned. If data != None, also pass data to callback. """ mounted = mounts() with util.tempdir() as tmpd: umount = False devname = "/dev/" + device if device in mounted: mountpoint = mounted[device]['mountpoint'] elif devname in mounted: mountpoint = mounted[devname]['mountpoint'] else: try: mountcmd = ['/usr/sbin/mount'] mountopts = [] if rw: mountopts.append('rw') else: mountopts.append('ro') if sync: # This seems like the safe approach to do # (ie where this is on by default) mountopts.append("sync") if mountopts: mountcmd.extend(["-o", ",".join(mountopts)]) if mtype: mountcmd.extend(['-t', mtype]) if "/cd" in devname: mountcmd.append('-vcdrfs') mountcmd.append(devname) else: mountcmd.append(device) mountcmd.append(tmpd) util.subp(mountcmd) umount = tmpd # This forces it to be unmounted (when set) mountpoint = tmpd except (IOError, OSError) as exc: raise util.MountFailedError( ("Failed mounting %s to %s due to: %s") % (device, tmpd, exc)) # Be nice and ensure it ends with a slash if not mountpoint.endswith("/"): mountpoint += "/" with unmounter(umount): if data is None: ret = callback(mountpoint) else: ret = callback(mountpoint, data) return ret
def mount_cb(device, callback, data=None, rw=False, mtype=None, sync=True): """ Mount the device, call method 'callback' passing the directory in which it was mounted, then unmount. Return whatever 'callback' returned. If data != None, also pass data to callback. """ mounted = mounts() with util.tempdir() as tmpd: umount = False devname="/dev/" + device if device in mounted: mountpoint = mounted[device]['mountpoint'] elif devname in mounted: mountpoint = mounted[devname]['mountpoint'] else: try: mountcmd = ['/usr/sbin/mount'] mountopts = [] if rw: mountopts.append('rw') else: mountopts.append('ro') if sync: # This seems like the safe approach to do # (ie where this is on by default) mountopts.append("sync") if mountopts: mountcmd.extend(["-o", ",".join(mountopts)]) if mtype: mountcmd.extend(['-t', mtype]) if "/cd" in devname: mountcmd.append('-vcdrfs') mountcmd.append(devname) else: mountcmd.append(device) mountcmd.append(tmpd) util.subp(mountcmd) umount = tmpd # This forces it to be unmounted (when set) mountpoint = tmpd except (IOError, OSError) as exc: raise util.MountFailedError(("Failed mounting %s to %s due to: %s") % (device, tmpd, exc)) # Be nice and ensure it ends with a slash if not mountpoint.endswith("/"): mountpoint += "/" with unmounter(umount): if data is None: ret = callback(mountpoint) else: ret = callback(mountpoint, data) return ret
def test_config_from_klibc_net_cfg(self): files = [] pairs = (('net-eth0.cfg', DHCP_CONTENT_1), ('net-eth1.cfg', STATIC_CONTENT_1)) macs = {'eth1': 'b8:ae:ed:75:ff:2b', 'eth0': 'b8:ae:ed:75:ff:2a'} dhcp = copy.deepcopy(DHCP_EXPECTED_1) dhcp['mac_address'] = macs['eth0'] static = copy.deepcopy(STATIC_EXPECTED_1) static['mac_address'] = macs['eth1'] expected = {'version': 1, 'config': [dhcp, static]} with util.tempdir() as tmpd: for fname, content in pairs: fp = os.path.join(tmpd, fname) files.append(fp) util.write_file(fp, content) found = net.config_from_klibc_net_cfg(files=files, mac_addrs=macs) self.assertEqual(found, expected)
def handle(name, cfg, cloud, log, _args): # If there isn't a chef key in the configuration don't do anything if 'chef' not in cfg: log.debug(("Skipping module named %s," " no 'chef' key in configuration"), name) return chef_cfg = cfg['chef'] # Ensure the chef directories we use exist for d in CHEF_DIRS: util.ensure_dir(d) # Set the validation key based on the presence of either 'validation_key' # or 'validation_cert'. In the case where both exist, 'validation_key' # takes precedence for key in ('validation_key', 'validation_cert'): if key in chef_cfg and chef_cfg[key]: util.write_file('/etc/chef/validation.pem', chef_cfg[key]) break # Create the chef config from template template_fn = cloud.get_template_filename('chef_client.rb') if template_fn: iid = str(cloud.datasource.get_instance_id()) params = { 'server_url': chef_cfg['server_url'], 'node_name': util.get_cfg_option_str(chef_cfg, 'node_name', iid), 'environment': util.get_cfg_option_str(chef_cfg, 'environment', '_default'), 'validation_name': chef_cfg['validation_name'] } templater.render_to_file(template_fn, '/etc/chef/client.rb', params) else: log.warn("No template found, not rendering to /etc/chef/client.rb") # set the firstboot json initial_json = {} if 'run_list' in chef_cfg: initial_json['run_list'] = chef_cfg['run_list'] if 'initial_attributes' in chef_cfg: initial_attributes = chef_cfg['initial_attributes'] for k in list(initial_attributes.keys()): initial_json[k] = initial_attributes[k] util.write_file('/etc/chef/firstboot.json', json.dumps(initial_json)) # If chef is not installed, we install chef based on 'install_type' if (not os.path.isfile('/usr/bin/chef-client') or util.get_cfg_option_bool(chef_cfg, 'force_install', default=False)): install_type = util.get_cfg_option_str(chef_cfg, 'install_type', 'packages') if install_type == "gems": # this will install and run the chef-client from gems chef_version = util.get_cfg_option_str(chef_cfg, 'version', None) ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version', RUBY_VERSION_DEFAULT) install_chef_from_gems(cloud.distro, ruby_version, chef_version) # and finally, run chef-client log.debug('Running chef-client') util.subp(['/usr/bin/chef-client', '-d', '-i', '1800', '-s', '20'], capture=False) elif install_type == 'packages': # this will install and run the chef-client from packages cloud.distro.install_packages(('chef',)) elif install_type == 'omnibus': url = util.get_cfg_option_str(chef_cfg, "omnibus_url", OMNIBUS_URL) content = url_helper.readurl(url=url, retries=5) with util.tempdir() as tmpd: # use tmpd over tmpfile to avoid 'Text file busy' on execute tmpf = "%s/chef-omnibus-install" % tmpd util.write_file(tmpf, str(content), mode=0700) util.subp([tmpf], capture=False) else: log.warn("Unknown chef install type %s", install_type)
def handle(name, cfg, cloud, log, _args): # If there isn't a chef key in the configuration don't do anything if 'chef' not in cfg: log.debug(("Skipping module named %s," " no 'chef' key in configuration"), name) return chef_cfg = cfg['chef'] # Ensure the chef directories we use exist for d in CHEF_DIRS: util.ensure_dir(d) # Set the validation key based on the presence of either 'validation_key' # or 'validation_cert'. In the case where both exist, 'validation_key' # takes precedence for key in ('validation_key', 'validation_cert'): if key in chef_cfg and chef_cfg[key]: util.write_file('/etc/chef/validation.pem', chef_cfg[key]) break # Create the chef config from template template_fn = cloud.get_template_filename('chef_client.rb') if template_fn: iid = str(cloud.datasource.get_instance_id()) params = { 'server_url': chef_cfg['server_url'], 'node_name': util.get_cfg_option_str(chef_cfg, 'node_name', iid), 'environment': util.get_cfg_option_str(chef_cfg, 'environment', '_default'), 'validation_name': chef_cfg['validation_name'] } templater.render_to_file(template_fn, '/etc/chef/client.rb', params) else: log.warn("No template found, not rendering to /etc/chef/client.rb") # set the firstboot json initial_json = {} if 'run_list' in chef_cfg: initial_json['run_list'] = chef_cfg['run_list'] if 'initial_attributes' in chef_cfg: initial_attributes = chef_cfg['initial_attributes'] for k in list(initial_attributes.keys()): initial_json[k] = initial_attributes[k] util.write_file('/etc/chef/firstboot.json', json.dumps(initial_json)) # If chef is not installed, we install chef based on 'install_type' if (not os.path.isfile('/usr/bin/chef-client') or util.get_cfg_option_bool( chef_cfg, 'force_install', default=False)): install_type = util.get_cfg_option_str(chef_cfg, 'install_type', 'packages') if install_type == "gems": # this will install and run the chef-client from gems chef_version = util.get_cfg_option_str(chef_cfg, 'version', None) ruby_version = util.get_cfg_option_str(chef_cfg, 'ruby_version', RUBY_VERSION_DEFAULT) install_chef_from_gems(cloud.distro, ruby_version, chef_version) # and finally, run chef-client log.debug('Running chef-client') util.subp(['/usr/bin/chef-client', '-d', '-i', '1800', '-s', '20'], capture=False) elif install_type == 'packages': # this will install and run the chef-client from packages cloud.distro.install_packages(('chef', )) elif install_type == 'omnibus': url = util.get_cfg_option_str(chef_cfg, "omnibus_url", OMNIBUS_URL) content = url_helper.readurl(url=url, retries=5) with util.tempdir() as tmpd: # use tmpd over tmpfile to avoid 'Text file busy' on execute tmpf = "%s/chef-omnibus-install" % tmpd util.write_file(tmpf, str(content), mode=0700) util.subp([tmpf], capture=False) else: log.warn("Unknown chef install type %s", install_type)