Example #1
0
    def read_resource(self, ctx: HandlerContext, resource: Config) -> None:
        if resource.facts:
            return
        vyos = self.get_connection(ctx, resource.id.version, resource)
        current = self.get_config_dict(ctx, resource, vyos)

        cfg = current
        for key in resource.node.split(" "):
            if isinstance(cfg, str):
                cfg = {cfg: {}}
                break
            elif key in cfg:
                cfg = cfg[key]
            else:
                raise ResourcePurged()

        ctx.debug(
            "Comparing desired with current",
            desired=resource.config,
            current=cfg,
            node=resource.node,
            raw_current=current,
        )

        current_cfg = self._dict_to_path(resource.node, cfg)
        ctx.debug("Current paths", path=current_cfg)
        resource.config = current_cfg
Example #2
0
    def _execute_command(self,
                         ctx: HandlerContext,
                         vyos,
                         command,
                         terminator,
                         timeout=10):
        """Patch for wonky behavior of vymgmt, after exit it can no longer use the unique prompt"""
        conn = vyos._Router__conn

        conn.sendline(command)

        i = conn.expect([terminator, TIMEOUT], timeout=timeout)

        output = conn.before

        if isinstance(output, bytes):
            output = output.decode("utf-8")

        if not i == 0:
            ctx.debug("got raw result %(result)s",
                      result=conn.before.decode(),
                      cmd=command)
            raise vymgmt.VyOSError("Connection timed out")

        if not conn.prompt():
            ctx.debug("got raw result %(result)s",
                      result=conn.before.decode(),
                      cmd=command)
            raise vymgmt.VyOSError("Connection timed out")

        return output
Example #3
0
    def create_resource(self, ctx: HandlerContext, resource: Config) -> None:
        if resource.facts:
            return
        ctx.debug("Creating resource, invalidating cache")
        self._invalidate_cache(resource)

        self._execute(ctx, resource, delete=False)
        ctx.set_created()
Example #4
0
    def update_resource(self, ctx: HandlerContext, changes: dict,
                        resource: Config) -> None:
        if resource.facts:
            return
        ctx.debug("Updating resource, invalidating cache")
        self._invalidate_cache(resource)

        self._execute(ctx, resource, delete=True)
        ctx.set_updated()
Example #5
0
    def create_resource(self, ctx: HandlerContext, resource: Config) -> None:
        vyos = self.get_connection(ctx, resource.id.version, resource)

        # try old command first, new one hangs due to insufficient entropy
        cmd = "generate vpn rsa-key bits 2048 random /dev/urandom"
        result = vyos.run_op_mode_command(cmd)
        if "Invalid command:" in result:
            cmd = "generate vpn rsa-key bits 2048"
            result = vyos.run_op_mode_command(cmd)

        ctx.debug("got result %(result)s", result=result, cmd=cmd)

        assert "has been generated" in result
Example #6
0
    def _execute(self, ctx: handler.HandlerContext, events: dict,
                 cache: AgentCache) -> (bool, bool):
        """
            :param ctx The context to use during execution of this deploy
            :param events Possible events that are available for this resource
            :param cache The cache instance to use
            :return (success, send_event) Return whether the execution was successful and whether a change event should be sent
                                          to provides of this resource.
        """
        ctx.debug("Start deploy %(deploy_id)s of resource %(resource_id)s",
                  deploy_id=self.gid,
                  resource_id=self.resource_id)
        provider = None

        try:
            provider = handler.Commander.get_provider(cache,
                                                      self.scheduler.agent,
                                                      self.resource)
            provider.set_cache(cache)
        except Exception:
            if provider is not None:
                provider.close()

            cache.close_version(self.resource.id.version)
            ctx.set_status(const.ResourceState.unavailable)
            ctx.exception("Unable to find a handler for %(resource_id)s",
                          resource_id=str(self.resource.id))
            return False, False

        yield self.scheduler.agent.thread_pool.submit(provider.execute, ctx,
                                                      self.resource)

        send_event = (hasattr(self.resource, "send_event")
                      and self.resource.send_event)

        if ctx.status is not const.ResourceState.deployed:
            provider.close()
            cache.close_version(self.resource.id.version)
            return False, send_event

        if len(events) > 0 and provider.can_process_events():
            ctx.info(
                "Sending events to %(resource_id)s because of modified dependencies",
                resource_id=str(self.resource.id))
            yield self.scheduler.agent.thread_pool.submit(
                provider.process_events, ctx, self.resource, events)

        provider.close()
        cache.close_version(self.resource_id.version)

        return True, send_event
Example #7
0
 def facts(self, ctx: HandlerContext, resource: Config) -> None:
     vyos = self.get_connection(ctx, resource.id.version, resource)
     orig = current = self.get_config_dict(ctx, resource, vyos)
     path = resource.node.split(" ")
     for el in path:
         if el in current:
             current = current[el]
         else:
             ctx.debug("No value found",
                       error=current,
                       path=path,
                       orig=orig)
             return {}
     return {"value": current}
Example #8
0
    def delete_resource(self, ctx: HandlerContext, resource: Config) -> None:
        if resource.facts:
            return
        ctx.debug("Deleting resource, invalidating cache")
        self._invalidate_cache(resource)

        vyos = self.get_connection(ctx, resource.id.version, resource)
        vyos.configure()
        vyos.delete(resource.node)
        vyos.commit()
        if resource.save:
            vyos.save()
        vyos.exit(force=True)
        ctx.set_purged()
Example #9
0
    def facts(self, ctx: HandlerContext, resource: IpFact) -> None:
        # example output
        # vyos@vyos:~$ show interfaces
        # Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
        # Interface        IP Address                        S/L  Description
        # ---------        ----------                        ---  -----------
        # eth0             10.0.0.7/24                       u/u
        # eth1             10.1.0.15/24                      u/u
        # lo               127.0.0.1/8                       u/u
        #                  ::1/128
        try:

            vyos = self.get_connection(ctx, resource.id.version, resource)
            cmd = "show interfaces"
            interface = resource.interface
            result = vyos.run_op_mode_command(cmd).replace("\r", "")
            ctx.debug("got result %(result)s", result=result, cmd=cmd)

            parsed_lines = [
                self.parse_line(line) for line in result.split("\n")
            ]
            parsed_lines = [line for line in parsed_lines if line is not None]

            # find right lines
            ips = itertools.dropwhile(lambda x: x[0] != interface,
                                      parsed_lines)
            ips = list(
                itertools.takewhile(lambda x: x[0] == interface or not x[0],
                                    ips))

            ctx.debug("got ips %(ips)s", ips=ips)

            ips = [ip[1] for ip in ips]

            if not ips:
                return {}

            if len(ips) == 1:
                return {"ip_address": ips[0]}
            else:
                ips = sorted(ips)
                out = {"ip_address": ips[0]}
                for i, addr in enumerate(ips):
                    out[f"ip_address_{i}"] = addr
                return out
        finally:
            self.post(ctx, resource)
Example #10
0
    def get_pubkey(self, ctx: HandlerContext, resource: Config) -> str:
        vyos = self.get_connection(ctx, resource.id.version, resource)
        cmd = "TERM=ansi show vpn ike rsa-keys"
        try:
            result = re.sub(
                "\x1b\\[[0-9]?[a-zA-Z]",
                "",
                vyos.run_op_mode_command(cmd).replace("\r", ""),
            )
        except vymgmt.router.VyOSError:
            ctx.debug(
                "got raw raw result %(result)s",
                result=vyos._Router__conn.before.decode("utf-8"),
                cmd=cmd,
            )
            raise
        ctx.debug("got raw result %(result)s", result=result, cmd=cmd)

        marker = "Local public key (/config/ipsec.d/rsa-keys/localhost.key):"

        if marker in result:
            idx = result.find(marker)
            result = result[idx + len(marker):]
            if "====" in result:
                idx = result.find("====")
                result = result[:idx]
            ctx.debug("got result %(result)s", result=result, cmd=cmd)
            result = result.strip()
        else:
            raise ResourcePurged()
        return result
Example #11
0
    def _execute(self, ctx: HandlerContext, resource: Config,
                 delete: bool) -> None:
        commands = [x for x in resource.config.split("\n") if len(x) > 0]
        vyos = self.get_connection(ctx, resource.id.version, resource)
        try:
            vyos.configure()
            if delete and not resource.never_delete:
                ctx.debug("Deleting %(node)s", node=resource.node)
                vyos.delete(resource.node)

            for cmd in commands:
                ctx.debug("Setting %(cmd)s", cmd=cmd)
                if delete and resource.never_delete:
                    try:
                        vyos.delete(cmd)
                    except vymgmt.ConfigError:
                        pass
                vyos.set(cmd)

            vyos.commit()
            if resource.save:
                vyos.save()
            vyos.exit(force=True)
        except vymgmt.router.VyOSError:
            ctx.debug(
                "got raw raw result %(result)s",
                result=vyos._Router__conn.before.decode("utf-8"),
                cmd=cmd,
            )
            raise