def start(self, nameserver=False, localhost_only=False): if self._started: raise RuntimeError("already started") try: ip.ipv4_enable_forwarding() self.vpn.start() self.router.start() if nameserver: for e in self._get_nameserver_entries(): self.registry.nameserver.assert_record(**e) basedir = self._basedir / UvnDefaults["nameserver"]["run_dir"] self.registry.nameserver.start(basedir, localhost_only=localhost_only) self.participant.start() self._started = True self._ts_started = Timestamp.now() self._proc = AgentProc(self) self._proc.start() logger.info("[started] UVN agent: {}", self.agent_id()) libuno.log.global_prefix(self.agent_id(brief=True)) except Exception as e: logger.exception(e) logger.error("failed to start agent") # Try to reset state self.stop() raise e
def _load(self): (self._vpn_cls, self._vpn_extra) = self._get_vpn_class() (self._router_cls, self._router_extra) = self._get_router_class() (self._participant_cls, self._participant_extra,) = self._get_participant_class() self._connection_test_peers = self._get_connection_test_peers() self.vpn = self._create_vpn(self._vpn_cls, self._vpn_extra) self.router = self._create_router(self._router_cls, self._router_extra) self.participant = self._create_participant( self._participant_cls, self._participant_extra) self.connection_test = self._create_connection_test( self._connection_test_peers) # register agent as the nameserver's listener self.registry.nameserver.listener = self # Determine default gateway self._default_gw = ip.ipv4_default_gateway() # Read network interfaces to determine the list of networks to which # the agent is attached self._local_sites = self._list_local_sites() # Determine list of private addresses on which to listen self._private_ports = {n["address"] for n in self._local_sites} self._loaded = True self._ts_loaded = Timestamp.now() logger.info("[loaded] UVN agent: {}", self.agent_id()) if self.registry.packaged: if not self.registry.bootstrapped: logger.warning("no deployment loaded") elif not self.registry.deployed_cell_config: raise UvnException(f"configuration not found: {self.registry.deployed_cell.id.name}@{self.registry.deployment_id}")
def _list_handshakes(self): result = exec_command(["wg", "show", str(self.interface), "latest-handshakes"], quiet=True, root=True, fail_msg="failed to get latest handshakes for interface: {}".format(self.interface), exception=WireGuardError) handshakes = {} for line in decode_output(result.stdout): l_split = list(filter(len, line.split())) handshakes[l_split[0]] = Timestamp.unix(l_split[1]) logger.trace("current handshakes [{}]: {}", self.interface, handshakes) return handshakes
def _tracepath_test(self, peer_count, peer_i, p_name, p_rec): ts_check = Timestamp.now() result = exec_command( ["tracepath", "-c", str(self._ping_count), str(p_rec["address"])], fail_msg="failed to ping peer: {} [{}]".format(p_name, p_rec["address"]), # don't throw an exception on error noexcept=True, # don't print any error message quiet=True) peer_ok = result.returncode == 0 if not peer_ok: unavail_peers.add(p_name) self._update_and_notify(peer_i, peer_count, p_name, peer_ok, ts_check)
def __init__(self, registry, assert_period, keep=False, daemon=False, interfaces=[], basedir=UvnDefaults["registry"]["agent"]["basedir"], logfile=UvnDefaults["registry"]["agent"]["log_file"]): # Try to create and lock a pid file to guarantee that only one # uvn agent is running on the system self.registry = registry self._basedir = pathlib.Path(basedir) self._logfile = self._basedir / logfile self._daemon = daemon if not daemon: libuno.log.output_file(self._logfile) self._interfaces = list(interfaces) self._keep = keep self._loaded = False self._started = False self._sem_wait = threading.Semaphore() self._sem_wait.acquire() self._sem_reload = threading.Semaphore() self._sem_reload.acquire() self._sem_deploy = threading.Semaphore() self._sem_deploy.acquire() self._sem_exit = threading.Semaphore() self._sem_exit.acquire() self._lock = threading.RLock() self._ts_created = Timestamp.now() self._ts_loaded = None self._ts_started = None self.vpn = None self.connection_test = None self.router = None self.participant = None self._rs = None self._peers = UvnPeerManager(listener=self) self._reload_queue = [] self._deploy_queue = [] self._status = PeerStatus.CREATED self._local_sites = [] self._private_ports = set() self._proc = None self._assert_period = assert_period self._default_gw = None logger.debug("loading uvn agent") self._load()
def deploy(self, strategy=None): if (strategy is None): strategy = DeploymentStrategy.strategies()[0] elif (isinstance(strategy, str)): strategy = DeploymentStrategy.by_name(strategy) strategy = strategy() (cells, psks, deployed_cells, address_range) = deploy_backbone(self, strategy) deploy_time = Timestamp.now() deployment = UvnDeployment(strategy=strategy, deploy_time=deploy_time, address_range=address_range, cells=cells, deployed_cells=deployed_cells, psks=psks, registry=self) self.deployments.append(deployment) self.dirty = True return deployment
def _registry_metadata(registry, dev=False): if registry.packaged: pkg_cell = registry.cell(registry.pkg_cell) component = pkg_cell.id.name component_type = "cell" image_tag = registry.deployment_id image_name = UvnDefaults["docker"]["image_name_fmt"][ "cell"].format(registry.address, component) component_labels = { "uvn.cell.name": pkg_cell.id.name, "uvn.cell.address": pkg_cell.id.address, "uvn.cell.admin": pkg_cell.id.admin, "uvn.deployment": registry.deployment_id } else: component = registry.address component_type = "registry" image_tag = Timestamp.now().format() image_name = UvnDefaults["docker"]["image_name_fmt"][ "root"].format(registry.address) component_labels = {"uvn.version": image_tag} image_labels = { "uvn.address": registry.address, "uvn.admin": registry.admin, "uvn.component": component_type } image_labels.update(component_labels) image_args = {} if dev: dockerfile_pfx = "-dev" else: dockerfile_pfx = "" dockerfile = f"{component_type}{dockerfile_pfx}.dockerfile" base_image_name = UvnDefaults["docker"]["base_image"] base_image_tag = libuno.__version__ base_image_labels = {} base_image_args = image_args base_dockerfile = f"{base_image_name}{dockerfile_pfx}.dockerfile" container_name = image_name container_labels = image_labels container_volumes = { str(registry.paths.basedir): { "bind": UvnDefaults["docker"]["volumes"]["uvn"], "mode": "rw" } } (os_system, os_node, os_release, os_version, container_arch, os_processor) = platform.uname() return (component, component_type, image_name, image_tag, image_labels, image_args, dockerfile, base_image_name, base_image_tag, base_image_labels, base_image_args, base_dockerfile, container_name, container_labels, container_volumes, container_arch)