def run(args, output=sys.stdout, stdin=sys.stdin, stdin_buffer=sys.stdin.buffer): """Observe an Ethernet interface and print beaconing packets.""" # First, become a progress group leader, so that signals can be directed # to this process and its children; see p.u.twisted.terminateProcess. os.setpgrp() network_monitor = None if args.input_file is None: if args.interface is None: raise ActionScriptError("Required argument: interface") cmd = sudo([get_path("/usr/lib/maas/beacon-monitor"), args.interface]) network_monitor = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE) infile = network_monitor.stdout else: if args.input_file == '-': mode = os.fstat(stdin.fileno()).st_mode if not stat.S_ISFIFO(mode): raise ActionScriptError("Expected stdin to be a pipe.") infile = stdin_buffer else: infile = open(args.input_file, "rb") return_code = observe_beaconing_packets(input=infile, out=output) if return_code is not None: raise SystemExit(return_code) if network_monitor is not None: return_code = network_monitor.poll() if return_code is not None: raise SystemExit(return_code)
def run( args, output=sys.stdout, stdin=sys.stdin, stdin_buffer=sys.stdin.buffer ): """Observe an Ethernet interface and print DHCP packets.""" network_monitor = None if args.input_file is None: if args.interface is None: raise ActionScriptError("Required argument: interface") cmd = sudo([get_path("/usr/lib/maas/dhcp-monitor"), args.interface]) network_monitor = subprocess.Popen( cmd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, ) infile = network_monitor.stdout else: if args.input_file == "-": mode = os.fstat(stdin.fileno()).st_mode if not stat.S_ISFIFO(mode): raise ActionScriptError("Expected stdin to be a pipe.") infile = stdin_buffer else: infile = open(args.input_file, "rb") return_code = observe_dhcp_packets(input=infile, out=output) if return_code is not None: raise SystemExit(return_code) if network_monitor is not None: return_code = network_monitor.poll() if return_code is not None: raise SystemExit(return_code)
def _reader_from_avahi(): """Read from a newly spawned `avahi-browse` subprocess. :raises SystemExit: If `avahi-browse` exits non-zero. """ avahi_browse = subprocess.Popen( [ get_path("/usr/bin/avahi-browse"), "--all", "--resolve", "--no-db-lookup", "--parsable", "--no-fail", ], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, ) try: # Avahi says "All strings used in DNS-SD are UTF-8 strings". yield avahi_browse.stdout finally: # SIGINT or SIGTERM (see ActionScript.setup) has been received, # avahi-browse may have crashed or been terminated, or there may have # been an exception in this script. In any case we give the subprocess # a chance to exit cleanly if it has not done so already, and then we # report on that exit. if _terminate_process(avahi_browse) != 0: raise SystemExit(avahi_browse.returncode)
def update_targets_conf(snapshot): """Runs tgt-admin to update the new targets from "maas.tgt".""" # Ensure that tgt is running before tgt-admin is used. service_monitor.ensureService("tgt").wait(30) # Update the tgt config. targets_conf = os.path.join(snapshot, 'maas.tgt') # The targets_conf may not exist in the event the BootSource is broken # and images havn't been imported yet. This fixes LP:1655721 if not os.path.exists(targets_conf): return try: call_and_check( sudo([ get_path('/usr/sbin/tgt-admin'), '--conf', targets_conf, '--update', 'ALL', ])) except ExternalProcessError as e: msg = "Unable to update TGT config: %s" % e try_send_rack_event(EVENT_TYPES.RACK_IMPORT_WARNING, msg) maaslog.warning(msg)
def get_config_v4( template_name: str, global_dhcp_snippets: Sequence[dict], failover_peers: Sequence[dict], shared_networks: Sequence[dict], hosts: Sequence[dict], omapi_key: str, ) -> str: """Return a DHCP config file based on the supplied parameters. :param template_name: Template file name: `dhcpd.conf.template` for the IPv4 template. :return: A full configuration, as a string. """ platform_codename = lsb_release()["codename"] template = load_template("dhcp", template_name) dhcp_socket = get_maas_data_path("dhcpd.sock") # Helper functions to stuff into the template namespace. helpers = { "oneline": normalise_whitespace, "commalist": normalise_any_iterable_to_comma_list, "quoted_commalist": normalise_any_iterable_to_quoted_comma_list, "running_in_snap": snappy.running_in_snap(), } for shared_network in shared_networks: interface = shared_network.get("interface", None) for subnet in shared_network["subnets"]: rack_ip = get_rack_ip_for_subnet( 4, subnet["subnet_cidr"], interface ) if rack_ip is not None: subnet["next_server"] = rack_ip subnet["bootloader"] = compose_conditional_bootloader( False, rack_ip ) ntp_servers = subnet["ntp_servers"] # Is a list. ntp_servers_ipv4, ntp_servers_ipv6 = _get_addresses(*ntp_servers) subnet["ntp_servers_ipv4"] = ", ".join(ntp_servers_ipv4) subnet["ntp_servers_ipv6"] = ", ".join(ntp_servers_ipv6) try: return template.substitute( global_dhcp_snippets=global_dhcp_snippets, hosts=hosts, failover_peers=failover_peers, shared_networks=shared_networks, platform_codename=platform_codename, omapi_key=omapi_key, dhcp_helper=(get_path("/usr/sbin/maas-dhcp-helper")), dhcp_socket=dhcp_socket, **helpers ) except (KeyError, NameError) as error: raise DHCPConfigError( "Failed to render DHCP configuration." ) from error
def get_config_v4(template_name: str, global_dhcp_snippets: Sequence[dict], failover_peers: Sequence[dict], shared_networks: Sequence[dict], hosts: Sequence[dict], omapi_key: str) -> str: """Return a DHCP config file based on the supplied parameters. :param template_name: Template file name: `dhcpd.conf.template` for the IPv4 template. :return: A full configuration, as a string. """ platform_codename = linux_distribution()[2] template = load_template('dhcp', template_name) dhcp_socket = get_data_path('/var/lib/maas/dhcpd.sock') # Helper functions to stuff into the template namespace. helpers = { "oneline": normalise_whitespace, "commalist": normalise_any_iterable_to_comma_list, "quoted_commalist": normalise_any_iterable_to_quoted_comma_list, "running_in_snap": snappy.running_in_snap(), } rack_addrs = [ IPAddress(addr) for addr in net_utils.get_all_interface_addresses() ] for shared_network in shared_networks: for subnet in shared_network["subnets"]: cidr = IPNetwork(subnet['subnet_cidr']) rack_ips = [ str(rack_addr) for rack_addr in rack_addrs if rack_addr in cidr ] if len(rack_ips) > 0: subnet["next_server"] = rack_ips[0] subnet["bootloader"] = compose_conditional_bootloader( False, rack_ips[0]) ntp_servers = subnet["ntp_servers"] # Is a list. ntp_servers_ipv4, ntp_servers_ipv6 = _get_addresses(*ntp_servers) subnet["ntp_servers_ipv4"] = ", ".join(ntp_servers_ipv4) subnet["ntp_servers_ipv6"] = ", ".join(ntp_servers_ipv6) try: return template.substitute( global_dhcp_snippets=global_dhcp_snippets, hosts=hosts, failover_peers=failover_peers, shared_networks=shared_networks, platform_codename=platform_codename, omapi_key=omapi_key, dhcp_helper=(get_path('/usr/sbin/maas-dhcp-helper')), dhcp_socket=dhcp_socket, **helpers) except (KeyError, NameError) as error: raise DHCPConfigError( "Failed to render DHCP configuration.") from error
def get_maas_common_command(): """Return path to the maas-rack command. In production mode this will just return 'maas-rack', but in development mode it will return the path for the current development environment. """ # Avoid circular imports. from provisioningserver.config import is_dev_environment if is_dev_environment(): from maastesting import root return os.path.join(root, "bin", "maas-common") else: return os.path.join(get_path("/usr/lib/maas"), "maas-common")
def get_maas_common_command(): """Return path to the maas-rack command. In production mode this will just return 'maas-rack', but in development mode it will return the path for the current development environment. """ # Avoid circular imports. from provisioningserver.config import is_dev_environment if is_dev_environment(): from maastesting import root return os.path.join(root, 'bin/maas-common') elif snappy.running_in_snap(): # there's no maas-common in the snap as maas-rack is always present return os.path.join(snappy.get_snap_path(), 'bin/maas-rack') else: return get_path('usr/lib/maas/maas-common')
def get_library_script_path(name): """Return path to a "library script". By convention (here) scripts are always installed to ``/usr/lib/maas`` on the target machine. The FHS (Filesystem Hierarchy Standard) defines ``/usr/lib/`` as the location for libraries used by binaries in ``/usr/bin`` and ``/usr/sbin``, hence the term "library script". In production mode this will return ``/usr/lib/maas/$name``, but in development mode it will return ``$root/scripts/$name``. """ # Avoid circular imports. from provisioningserver.config import is_dev_environment if is_dev_environment(): from maastesting import root return os.path.join(root, "scripts", name) else: return os.path.join(get_path("/usr/lib/maas"), name)