def add_bootstrap_to_no_proxy(self): """Finds bootstrap node IP and adds it to the current setting of no-proxy in the juju env. """ out = utils.get_command_output( "{0} juju status".format( self.config.juju_home()), timeout=None, user_sudo=True) if out['status'] != 0: log.debug("error from status: {}".format(out)) raise Exception("Problem with juju status.") try: status = yaml.load(out['output']) bootstrap_dns_name = status['machines']['0']['dns-name'] except: utils.pollinate(self.session_id, 'EJ') log.exception("Error parsing yaml from juju status") raise Exception("Problem getting bootstrap machine DNS name") # first attempt to get directly, then use juju run: try: bootstrap_ip = socket.gethostbyname(bootstrap_dns_name) except socket.gaierror as e: log.error("Failed to get ip directly: {}".format(e)) out = utils.get_command_output( "{} juju run --machine 0 " "'ip -o -4 address show dev juju-br0'".format( self.config.juju_home())) if out['status'] != 0: log.error("Failed to get ip: {}".format(out)) raise Exception("Failed to get IP of bootstrap node") regex = re.compile("inet\s+(\d+\.\d+\.\d+\.\d+)\/") match = re.search(regex, out['output'].rstrip()) if match: bootstrap_ip = match.group(1) bootstrap_ip = get_ip_set("{}/24".format(bootstrap_ip)) else: log.error("Failed to get ip: {}".format(out)) raise Exception("Failed to get IP of bootstrap node") out = utils.get_command_output( "{} juju get-env no-proxy".format(self.config.juju_home()), timeout=None, user_sudo=True) if out['status'] != 0: log.debug("error from get-env: {}".format(out)) raise Exception("Problem getting existing no-proxy setting") no_proxy = "{},{}".format( out['output'].rstrip(), bootstrap_ip) out = utils.get_command_output( "{} juju set-env no-proxy={}".format(self.config.juju_home(), no_proxy), timeout=None, user_sudo=True) if out['status'] != 0: log.debug("error from set-env: {}".format(out)) raise Exception("Problem setting no-proxy environment")
def test_get_command_output_timeout(self, mock_Popen, mock_env): mock_env.copy.return_value = {'FOO': 'bazbot'} mock_Popen.return_value.communicate.return_value = (bytes(), bytes()) get_command_output("fake", timeout=20) mock_Popen.assert_called_with("timeout 20s fake", shell=True, stdout=PIPE, stderr=PIPE, bufsize=-1, env={'LC_ALL': 'C', 'FOO': 'bazbot'}, close_fds=True)
def test_get_command_output_raises(self, mock_Popen, mock_env): err = OSError() err.errno = errno.ENOENT mock_Popen.side_effect = err rv = get_command_output('foo') self.assertEqual(rv, dict(ret=127, output="", err="")) mock_Popen.side_effect = OSError() with self.assertRaises(OSError): get_command_output('foo')
def login_to_maas(self, apikey): cmd = ("maas login maas {} {}".format(self.LOCAL_MAAS_URL, apikey)) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("failed to login to maas: {}".format(out)) # Remove maascli.db that gets created regardless of # status of login utils.get_command_output('rm -f {}'.format( os.path.join(utils.install_home(), '.maascli.db'))) raise MaasInstallError("Couldn't log in")
def set_perms(self): """ sets permissions """ try: log.info("Setting permissions for user {}".format(utils.install_user())) utils.chown(self.config.cfg_path, utils.install_user(), utils.install_user(), recursive=True) utils.get_command_output("sudo chmod 777 {}".format(self.config.cfg_path)) utils.get_command_output("sudo chmod 777 -R {}/*".format(self.config.cfg_path)) except: msg = "Error setting ownership for " "{}".format(self.config.cfg_path) log.exception(msg) raise Exception(msg)
def create_maas_bridge(self, target_iface): """Creates br0 bridge using existing config for 'target_iface'. Bridge is defined in /etc/network/interfaces.d/openstack.cfg. Existing config for either an existing br0 bridge or the specified target_iface will be commented out. """ utils.get_command_output('ifdown {} br0'.format(target_iface)) cfgfilenames = ['/etc/network/interfaces'] cfgfilenames += glob.glob('/etc/network/interfaces.d/*.cfg') new_bridgefilename = os.path.join(self.tempdir.name, 'bridge.cfg') num_bridges = 0 for cfn in [c for c in cfgfilenames if os.path.exists(c)]: created = self.create_bridge_if_exists(target_iface, new_bridgefilename, cfn) num_bridges += (1 if created else 0) if num_bridges > 1: log.warning("found multiple instances of {}, " "network configuration may " "be wrong".format(target_iface)) with open('/etc/network/interfaces', 'r+') as e_n_i_file: contents = "".join(e_n_i_file.readlines()) if not re.match('\s*source /etc/network/interfaces.d/\*.cfg', contents): e_n_i_file.write("\nsource /etc/network/interfaces.d/*.cfg") cloudinst_cfgfilename = "/etc/network/interfaces.d/openstack.cfg" with open(new_bridgefilename, 'r') as new_bridge: with open(cloudinst_cfgfilename, 'w') as cloudinstall_cfgfile: bridge_config = "".join(new_bridge.readlines()) cloudinstall_cfgfile.write("auto {}\n" "iface {} inet manual\n\n" "auto br0\n" "{}\n" "bridge_ports " "{}".format(target_iface, target_iface, bridge_config, target_iface)) res = utils.get_command_output('ifup {} br0'.format(target_iface)) if res['status'] != 0: log.debug("'ifup {} br0' failed. out={}".format(target_iface, res)) raise MaasInstallError("Failure in bridge creation")
def set_perms(self): """ sets permissions """ try: utils.chown(self.config.cfg_path, utils.install_user(), utils.install_user(), recursive=True) utils.get_command_output("sudo chmod 700 {}".format( self.config.cfg_path)) utils.get_command_output("sudo chmod 600 -R {}/*".format( self.config.cfg_path)) except: raise SingleInstallException( "Unable to set ownership for {}".format(self.config.cfg_path))
def post_proc(self): """ post processing for nova-cloud-controller """ super(CharmNovaCloudController, self).post_proc() svc = self.juju_state.service(self.charm_name) unit = svc.unit(self.charm_name) k_svc = self.juju_state.service('keystone') keystone = k_svc.unit('keystone') openstack_password = self.config.getopt('openstack_password') public_address = keystone.public_address if is_ipv6(public_address): public_address = "[%s]".format(public_address) log.debug("Found ipv6 address, {}".format(public_address)) if unit.machine_id == '-1': return True for u in ['admin', 'ubuntu']: env = self._openstack_env(u, openstack_password, u, public_address) self._openstack_env_save(u, env) setup_script_path = self.render_setup_script() cmds = ("bash {script} " "\"{password}\" \"{install_type}\" " "> {cfg_home}/script.log 2>&1".format( script=setup_script_path, password=openstack_password, cfg_home=self.config.cfg_path, install_type=self.config.getopt('install_type') )) err = utils.get_command_output(cmds) if err['status'] != 0: raise CharmPostProcessException(err)
def test_bootstrap_succeeded(self): """ Verifies a local bootstrap happened """ cmd = ("openstack-juju stat --format yaml") out = utils.get_command_output(cmd) out = out['output'] assert ('environment: local' in out)
def run_configure_script(self): "runs configure-landscape, returns output (LDS hostname)" ldscreds = self.config.getopt('landscapecreds') args = { "bin": self.lscape_configure_bin, "admin_email": shlex.quote(ldscreds['admin_email']), "admin_name": shlex.quote(ldscreds['admin_name']), "sys_email": shlex.quote(ldscreds['system_email']), "maas_host": shlex.quote(self.config.getopt('maascreds')['api_host']) } cmd = ("{bin} --admin-email {admin_email} " "--admin-name {admin_name} " "--system-email {sys_email} " "--maas-host {maas_host}".format(**args)) log.debug("Running landscape configure: {}".format(cmd)) out = utils.get_command_output(cmd, timeout=None) if out['status']: utils.pollinate(self.session_id, 'ET') log.error("Problem with configuring Landscape: {}.".format(out)) raise Exception("Error configuring Landscape.") utils.pollinate(self.session_id, 'DL') return out['output'].strip()
def detect_existing_dhcp(self, interface): """return True if an existing DHCP server is running on interface.""" cmd = "nmap --script broadcast-dhcp-discover -e {}".format(interface) out = utils.get_command_output(cmd) if "DHCPOFFER" in out['output']: return True return False
def add_config_entries(cls, name, configlines): raw_lxc_config = "\n".join(configlines) out = utils.get_command_output('lxc config set {} raw.lxc ' '"{}"'.format(name, raw_lxc_config), user_sudo=True) if out['status'] > 0: raise Exception("couldn't set container config")
def deploy(self, charm, settings): """ Deploy a charm to an instance :param str charm: charm to deploy :param str machine_id: (optional) machine id :param str instances: (optional) number of instances to deploy :param dict constraints: (optional) machine constraints """ cmd = "juju deploy" if 'machine_id' in settings and settings['machine_id']: cmd += " --to {mid}".format(mid=settings['machine_id']) if 'instances' in settings: cmd += " -n {instances}".format(instances=settings['instances']) if 'configfile' in settings: cmd += " --config {file}".format(file=settings['configfile']) if 'constraints' in settings: opts = [] for k, v in settings['constraints'].items(): opts.append("{k}={v}".format(k=k, v=v)) if opts: cmd += " --constraints \"{opts}\"".format(opts=" ".join(opts)) cmd += " {charm}".format(charm=charm) log.debug("Deploying {charm} -> {cmd}".format(charm=charm, cmd=cmd)) cmd_ = get_command_output(cmd) log.debug("Deploy result: {out}".format(out=cmd_['stdout'])) if cmd_['ret']: log.warning("Deploy error ({cmd}): " "{out}".format(cmd=cmd, out=cmd_['stdout']))
def test_bootstrap_succeeded(self): """ Verifies a local bootstrap happened """ cmd = ("openstack-juju stat --format yaml") out = utils.get_command_output(cmd) out = out['output'] assert('environment: local' in out)
def post_proc(self): """ post processing for nova-cloud-controller """ super(CharmNovaCloudController, self).post_proc() svc = self.juju_state.service(self.charm_name) unit = svc.unit(self.charm_name) k_svc = self.juju_state.service('keystone') keystone = k_svc.unit('keystone') openstack_password = self.config.getopt('openstack_password') public_address = keystone.public_address if is_ipv6(public_address): public_address = "[%s]".format(public_address) log.debug("Found ipv6 address, {}".format(public_address)) if unit.machine_id == '-1': return True for u in ['admin', 'ubuntu']: env = self._openstack_env(u, openstack_password, u, public_address) self._openstack_env_save(u, env) setup_script_path = self.render_setup_script() cmds = ("bash {script} " "\"{password}\" \"{install_type}\" " "> {cfg_home}/script.log 2>&1".format( script=setup_script_path, password=openstack_password, cfg_home=self.config.cfg_path, install_type=self.config.getopt('install_type'))) err = utils.get_command_output(cmds) if err['status'] != 0: raise CharmPostProcessException(err)
def run_configure_script(self): "runs configure-landscape, returns output (LDS hostname)" ldscreds = self.config.getopt('landscapecreds') args = {"bin": self.lscape_configure_bin, "admin_email": shlex.quote(ldscreds['admin_email']), "admin_name": shlex.quote(ldscreds['admin_name']), "sys_email": shlex.quote(ldscreds['system_email']), "maas_host": shlex.quote( self.config.getopt('maascreds')['api_host'])} cmd = ("{bin} --admin-email {admin_email} " "--admin-name {admin_name} " "--system-email {sys_email} " "--maas-host {maas_host}".format(**args)) log.debug("Running landscape configure: {}".format(cmd)) out = utils.get_command_output(cmd, timeout=None) if out['status']: log.error("Problem with configuring Landscape: {}.".format(out)) raise Exception("Error configuring Landscape.") return out['output'].strip()
def poll_state(): """ Polls current state of Juju and MAAS :returns: list of Machine() and the Juju state :rtype: tuple (JujuState(), MaasState()) """ # Capture Juju state cmd = utils.get_command_output('juju status', combine_output=False) if cmd['ret']: raise SystemExit("Error connecting to juju: stderr: {e}".format( e=cmd['stderr'])) juju = JujuState(cmd['stdout']) maas = None if MULTI_SYSTEM: # Login to MAAS auth = MaasAuth() auth.get_api_key('root') # auth.login() # Load Client routines c = MaasClient(auth) # Capture Maas state maas = MaasState(c.nodes) c.tag_fpi(maas) c.nodes_accept_all() c.tag_name(maas) update_machine_info(juju, maas) return (juju, maas)
def create(cls, name, userdata): """ creates a container from an image with the alias 'ubuntu' """ imgname = os.getenv("LXD_IMAGE_NAME", "ubuntu") out = utils.get_command_output('lxc image list | ' 'grep {}'.format(imgname), user_sudo=True) if len(out['output']) == 0: m = ("LXD: No image named '{}' found. " "Please import an image or set an alias.".format(imgname)) raise Exception(m) out = utils.get_command_output('lxc init {} {}'.format(imgname, name), user_sudo=True) if out['status'] > 0: raise Exception("Unable to create container: " + out['output'] + "\nERR:\n" + out['err']) out = utils.get_command_output('lxc config show ' + name, user_sudo=True) if out['status'] > 0: raise Exception("Unable to get container config: " + out['output'] + "\nERR:\n" + out['err']) cfgyaml = yaml.load(out['output']) with open(userdata, 'r') as uf: if 'user.user_data' in cfgyaml['config']: raise Exception("Container config already has userdata") cfgyaml['config']['user.user-data'] = "".join(uf.readlines()) cfgyaml['config']['security.privileged'] = True with tempfile.NamedTemporaryFile(delete=False) as cfgtmp: cfgtmp.write(yaml.dump(cfgyaml).encode()) cfgtmp.flush() os.chmod(cfgtmp.name, stat.S_IROTH | stat.S_IRWXU) cmd = 'cat {} | lxc config edit {}'.format(cfgtmp.name, name) out = utils.get_command_output(cmd, user_sudo=True) if out['status'] > 0: raise Exception("Unable to set userdata config: " + out['output'] + "ERR" + out['err']) return 0
def wait(cls, name): """ waits for the container to be in a RUNNING state :param str name: name of container """ out = utils.get_command_output( 'sudo lxc-wait -n {0} -s RUNNING'.format(name)) return out['status']
def get_apikey(self): credcmd = ("maas-region-admin apikey " "--username root") out = utils.get_command_output(credcmd) if out['status'] != 0: log.debug("failed to get apikey: {}".format(out)) raise MaasInstallError("Couldn't get apikey") apikey = out['output'].strip() return apikey
def login_to_maas(self, apikey): cmd = ("maas login maas {} {}".format(self.LOCAL_MAAS_URL, apikey)) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("failed to login to maas: {}".format(out)) raise MaasInstallError("Couldn't log in")
def add_relation(self, endpoint_a, endpoint_b): """ Add relation between services """ cmd = "juju add-relation {a} {b}".format(a=endpoint_a, b=endpoint_b) log.debug("Adding relation {a} <-> {b}".format(a=endpoint_a, b=endpoint_b)) ret, out, _, _ = get_command_output(cmd) return out
def add_devices(cls, name, devices): for dname, dtype, keyvalstr in devices: cmd = 'lxc config device add {} {} {} {}'.format( name, dname, dtype, keyvalstr) out = utils.get_command_output(cmd, user_sudo=True) if out['status'] > 0: raise Exception("couldn't add device:" "out:{}\nerr{}".format(out['output'], out['err']))
def get_log_text(self, unit_name): name = "-".join(unit_name.split("/")) cmd = "sudo grep {unit} /var/log/juju-ubuntu-local/all-machines.log " " | tail -n 2" cmd = cmd.format(unit=name) out = utils.get_command_output(cmd) if out["status"] == 0 and len(out["output"]) > 0: return out["output"] else: return "No log matches for {}".format(name)
def cloud_init_finished(self): """ checks the log to see if cloud-init finished """ log_file = os.path.join(self.container_abspath, 'rootfs/var/log/cloud-init-output.log') out = utils.get_command_output('sudo tail -n1 {0}'.format(log_file)) if 'finished at' in out['output']: return True return False
def add_devices(cls, name, devices): for dname, dtype, keyvalstr in devices: cmd = 'lxc config device add {} {} {} {}'.format(name, dname, dtype, keyvalstr) out = utils.get_command_output(cmd, user_sudo=True) if out['status'] > 0: raise Exception("couldn't add device:" "out:{}\nerr{}".format(out['output'], out['err']))
def configure_maas_networking(self, cluster_uuid, interface, gateway, dhcp_range, static_range): """ set up or update the node-group-interface. dhcp_range is a tuple of ip addresses as strings: (low, high) """ maas_query_cmd = ('maas maas node-group-interfaces' ' list {}'.format(cluster_uuid)) out = utils.get_command_output(maas_query_cmd) interfaces = json.loads(out['output']) nmatching = len([i for i in interfaces if i['interface'] == interface]) interface_exists = nmatching == 1 paramstr = ('ip={address} interface={interface} ' 'management=2 subnet_mask={netmask} ' 'broadcast_ip={bcast} router_ip={gateway} ' 'ip_range_low={ip_range_low} ' 'ip_range_high={ip_range_high} ' 'static_ip_range_low={static_ip_range_low} ' 'static_ip_range_high={static_ip_range_high}') args = dict(uuid=cluster_uuid, interface=interface, address=get_ip_addr(interface), netmask=get_netmask(interface), bcast=get_bcast_addr(interface), gateway=gateway, ip_range_low=dhcp_range[0], ip_range_high=dhcp_range[1], static_ip_range_low=static_range[0], static_ip_range_high=static_range[1]) if interface_exists: cmd = ('maas maas node-group-interface update {uuid} {interface} ' + paramstr).format(**args) else: cmd = ('maas maas node-group-interfaces new {uuid} ' + paramstr).format(**args) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("cmd failed: {}\n - output" "={}".format(cmd, out)) raise MaasInstallError("unable to create or update network")
def get_log_text(self, unit_name): name = '-'.join(unit_name.split('/')) cmd = ("sudo grep {unit} /var/log/juju-ubuntu-local/all-machines.log " " | tail -n 2") cmd = cmd.format(unit=name) out = utils.get_command_output(cmd) if out['status'] == 0 and len(out['output']) > 0: return out['output'] else: return "No log matches for {}".format(name)
def create_superuser(self): pw = shlex.quote(self.config.getopt('openstack_password')) cmd = ("maas-region-admin createadmin " "--username root --password {} " "--email [email protected]".format(pw)) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("failed to create maas admin. output" "={}".format(out)) raise MaasInstallError("Couldn't create admin")
def set_perms(self): """ sets permissions """ try: log.info("Setting permissions for user {}".format( utils.install_user())) utils.chown(self.config.cfg_path, utils.install_user(), utils.install_user(), recursive=True) utils.get_command_output("sudo chmod 777 {}".format( self.config.cfg_path)) utils.get_command_output("sudo chmod 777 -R {}/*".format( self.config.cfg_path)) except: msg = ("Error setting ownership for " "{}".format(self.config.cfg_path)) log.exception(msg) raise Exception(msg)
def configure_maas_networking(self, cluster_uuid, interface, gateway, dhcp_range, static_range): """ set up or update the node-group-interface. dhcp_range is a tuple of ip addresses as strings: (low, high) """ maas_query_cmd = ('maas maas node-group-interfaces' ' list {}'.format(cluster_uuid)) out = utils.get_command_output(maas_query_cmd) interfaces = json.loads(out['output']) nmatching = len([i for i in interfaces if i['interface'] == interface]) interface_exists = nmatching == 1 paramstr = ('ip={address} interface={interface} ' 'management=2 subnet_mask={netmask} ' 'broadcast_ip={bcast} router_ip={gateway} ' 'ip_range_low={ip_range_low} ' 'ip_range_high={ip_range_high} ' 'static_ip_range_low={static_ip_range_low} ' 'static_ip_range_high={static_ip_range_high}') args = dict(uuid=cluster_uuid, interface=interface, address=get_ip_addr(interface), netmask=get_netmask(interface), bcast=get_bcast_addr(interface), gateway=gateway, ip_range_low=dhcp_range[0], ip_range_high=dhcp_range[1], static_ip_range_low=static_range[0], static_ip_range_high=static_range[1]) if interface_exists: cmd = ('maas maas node-group-interface update ' '{uuid} {interface} paramstr').format(**args) else: cmd = ('maas maas node-group-interfaces new {uuid} ' + paramstr).format(**args) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("cmd failed: {}\n - output" "={}".format(cmd, out)) raise MaasInstallError("unable to create or update network")
def configure_nat(self, network): cmd = ('iptables -t nat -a POSTROUTING ' '-s {} ! -d {} -j MASQUERADE'.format(network, network)) utils.get_command_output(cmd) utils.spew('/etc/network/iptables.rules', "*nat\n" ":PREROUTING ACCEPT [0:0]\n" ":INPUT ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":POSTROUTING ACCEPT [0:0]\n" "-A POSTROUTING -s {} ! -d {} -j MASQUERADE\n" "COMMIT\n".format(network, network)) utils.get_command_output('chmod 0600 /etc/network/iptables.rules') cmd = ("sed -e '/^iface lo inet loopback$/a\ " "pre-up iptables-restore < /etc/network/iptables.rules' " "-i /etc/network/interfaces") res = utils.get_command_output(cmd) if res['status'] != 0: log.debug("error editing /etc/network/interfaces: {}".format(res))
def start(cls, name, lxc_logfile): """ starts lxc container :param str name: name of container """ out = utils.get_command_output('lxc start ' + name, user_sudo=True) if out['status'] > 0: raise Exception("Unable to start container: " "out:{}\nerr{}".format(out['output'], out['err'])) return out['status']
def create_superuser(self): pw = self.config.openstack_password cmd = ("maas-region-admin createadmin " "--username root --password {} " "--email [email protected]".format(pw)) out = utils.get_command_output(cmd) if out['status'] != 0: log.debug("failed to create maas admin. output" "={}".format(out)) raise MaasInstallError("Couldn't create admin")
def add_relation(self, endpoint_a, endpoint_b): """ Add relation between services """ cmd = "juju add-relation {a} {b}".format(a=endpoint_a, b=endpoint_b) cmd_ = get_command_output(cmd, combine_output=True) log.debug("Adding relation ({a},{b}) ".format(a=endpoint_a, b=endpoint_b)) if cmd_['ret']: log.error("Result: {r}".format(r=cmd_['stdout'])) return True return False
def configure_nat(self, network): cmd = ('iptables -t nat -a POSTROUTING ' '-s {} ! -d {} -j MASQUERADE'.format(network, network)) utils.get_command_output(cmd) utils.spew( '/etc/network/iptables.rules', "*nat\n" ":PREROUTING ACCEPT [0:0]\n" ":INPUT ACCEPT [0:0]\n" ":OUTPUT ACCEPT [0:0]\n" ":POSTROUTING ACCEPT [0:0]\n" "-A POSTROUTING -s {} ! -d {} -j MASQUERADE\n" "COMMIT\n".format(network, network)) utils.get_command_output('chmod 0600 /etc/network/iptables.rules') cmd = ("sed -e '/^iface lo inet loopback$/a\ " "pre-up iptables-restore < /etc/network/iptables.rules' " "-i /etc/network/interfaces") res = utils.get_command_output(cmd) if res['status'] != 0: log.debug("error editing /etc/network/interfaces: {}".format(res))
def destroy(cls, name): """ destroys lxc container :param str name: name of container """ out = utils.get_command_output('lxc delete ' + name, user_sudo=True) if out['status'] > 0: raise Exception("Unable to delete container: " "{0}".format(out['output'])) return out['status']
def stop(cls, name): """ stops lxc container :param str name: name of container """ out = utils.get_command_output('lxc stop ' + name, user_sudo=True) if out['status'] > 0: raise Exception("Unable to stop container: " "{}".format(out['output'])) return out['status']
def start(cls, name, lxc_logfile): """ starts lxc container :param str name: name of container """ out = utils.get_command_output( 'sudo lxc-start -n {0} -d -o {1}'.format(name, lxc_logfile)) if out['status'] > 0: raise Exception("Unable to start container: " "{0}".format(out['output'])) return out['status']
def destroy(cls, name): """ destroys lxc container :param str name: name of container """ out = utils.get_command_output('sudo lxc-destroy -n {0}'.format(name)) if out['status'] > 0: raise Exception("Unable to destroy container: " "{0}".format(out['output'])) return out['status']
def add_static_route(self, lxc_net): """ Adds static route to host system """ # Store container IP in config ip = Container.ip(self.container_name) self.config.setopt("container_ip", ip) log.info("Adding static route for {} via {}".format(lxc_net, ip)) out = utils.get_command_output("ip route add {} via {} dev lxcbr0".format(lxc_net, ip)) if out["status"] != 0: raise Exception("Could not add static route for {}" " network: {}".format(lxc_net, out["output"]))
def wait_checked(cls, name, check_logfile, interval=20): """waits for container to be in RUNNING state, checking 'check_logfile' every 'interval' seconds for error messages. Intended to be used with container_start, which uses 'lxc-start -d', which returns 0 immediately and does not detect errors. returns when the container 'name' is in RUNNING state. raises an exception if errors are detected. """ while True: out = utils.get_command_output('sudo lxc-wait -n {} -s RUNNING ' '-t {}'.format(name, interval)) if out['status'] == 0: return log.debug("{} not RUNNING after {} seconds, " "checking '{}' for errors".format( name, interval, check_logfile)) grepout = utils.get_command_output( 'grep -q ERROR {}'.format(check_logfile)) if grepout['status'] == 0: raise Exception("Error detected starting container. See {} " "for details.".format(check_logfile))
def add_static_route(self, lxc_net): """ Adds static route to host system """ # Store container IP in config ip = Container.ip(self.container_name) self.config.setopt('container_ip', ip) log.info("Adding static route for {} via {}".format(lxc_net, ip)) out = utils.get_command_output( 'ip route add {} via {} dev lxcbr0'.format(lxc_net, ip)) if out['status'] != 0: raise Exception("Could not add static route for {}" " network: {}".format(lxc_net, out['output']))
def configure_dns(self): with open('/etc/bind/named.conf.options', 'w') as nco_file: with open('/etc/resolv.conf', 'r') as resolv_conf_file: forwarders = "".join([ "\t\t{};\n".format(l.split()[1]) for l in resolv_conf_file.readlines() if l.startswith('nameserver') ]) nco_file.write(DNS_CONF_TEMPLATE.format(forwarders)) utils.get_command_output('service bind9 restart') utils.get_command_output("sed -e '/^iface lo inet loopback$/a" "\\n#added by openstack-install\\n" "dns-nameservers 127.0.0.1' " " -i /etc/network/interfaces") utils.get_command_output('ifdown lo') utils.get_command_output('ifup lo')
def cp(cls, name, src, dst): """ copy file to container :param str name: name of container :param str src: file to copy to container :param str dst: destination full path """ cmd = ("lxc file push {src} {name}/{dst} ".format(dst=dst, name=name, src=src)) ret = utils.get_command_output(cmd) if ret['status'] > 0: raise Exception("There was a problem copying ({0}) to the " "container ({1}): out:'{2}'\nerr:{3}" "\ncmd:{4}".format(src, name, ret['output'], ret['err'], cmd))
def wait_checked(cls, name, check_logfile, interval=20): """waits for container to be in RUNNING state. Ignores check_logfile. returns when the container 'name' is in RUNNING state. raises an exception if errors are detected. """ while True: cmd = 'lxc info {} | grep Status'.format(name) out = utils.get_command_output(cmd, user_sudo=True) if out['status'] != 0: raise Exception("Error getting container info {}".format(out)) outstr = out['output'].strip() if outstr == "Status: Running": return time.sleep(4)
def test_get_command_output_user_sudo(self, mock_Popen, mock_env): mock_env.copy.return_value = {'FOO': 'bazbot'} outb, errb = bytes('out', 'utf-8'), bytes('err', 'utf-8') mock_Popen.return_value.communicate.return_value = (outb, errb) mock_Popen.return_value.returncode = 4747 with patch('cloudinstall.utils.install_user') as mock_install_user: mock_install_user.return_value = 'fakeuser' rv = get_command_output("fake", user_sudo=True) self.assertEqual(rv, dict(output='out', err='err', status=4747)) mock_Popen.assert_called_with("sudo -E -H -u fakeuser fake", shell=True, stdout=PIPE, stderr=PIPE, bufsize=-1, env={'LC_ALL': 'C', 'FOO': 'bazbot'}, close_fds=True)