plesty.server.model.agent ========================= .. py:module:: plesty.server.model.agent .. autoapi-nested-parse:: What this bench serves remote clients on: the agent's own settings. The agent had no configuration surface at all — endpoint, token and worker count came from ``plesty-server agent`` arguments and nowhere else, so a bench could only be made reachable from a command line, and was reachable only for as long as that command ran. These settings belong to the *bench*, not to a fleet and not to the packaged module: two benches on one network need different tokens, and the same bench keeps its endpoint across whatever fleet is open. They live in the bench home as ``agent.yaml``, beside the state the rest of the home holds. The bench's data path is kept here for the same reason: it is where this one bench writes on the lab's shared disk, set once per bench in *Server ▸ Configure…*, and the same whichever fleet is open. A fleet only names folders under it (a device's ``data_dir``). Attributes ---------- .. autoapisummary:: plesty.server.model.agent.DEFAULT_BIND plesty.server.model.agent.DEFAULT_WORKERS plesty.server.model.agent.TOKEN_BYTES plesty.server.model.agent.ROLE_MASTER plesty.server.model.agent.ROLE_NODE plesty.server.model.agent.ROLES plesty.server.model.agent.DEFAULT_ROLE plesty.server.model.agent.DATA_ROOT_VAR plesty.server.model.agent.DATA_PATH_VAR plesty.server.model.agent.DEFAULT_DATA_DIR plesty.server.model.agent.DATA_SHARE_VAR Classes ------- .. autoapisummary:: plesty.server.model.agent.AgentSettings Functions --------- .. autoapisummary:: plesty.server.model.agent.check_data_location plesty.server.model.agent.settings_file plesty.server.model.agent.load_agent_settings plesty.server.model.agent.save_agent_settings Module Contents --------------- .. py:data:: DEFAULT_BIND :value: 'tcp://*:5550' .. py:data:: DEFAULT_WORKERS :value: 4 .. py:data:: TOKEN_BYTES :value: 24 .. py:data:: ROLE_MASTER :value: 'master' .. py:data:: ROLE_NODE :value: 'node' .. py:data:: ROLES .. py:data:: DEFAULT_ROLE :value: 'node' .. py:data:: DATA_ROOT_VAR :value: 'DEVICE_DATA_ROOT' .. py:data:: DATA_PATH_VAR :value: 'DEVICE_DATA_PATH' .. py:data:: DEFAULT_DATA_DIR :value: 'tmp' .. py:data:: DATA_SHARE_VAR :value: 'PLESTY_DATA' .. py:class:: AgentSettings How the bench agent binds, whom it answers, and whether it drives others. :ivar bind: ZMQ endpoint to bind. :ivar token: Shared secret every ``exec``/``fetch`` must carry. Empty is legal and means no check — a bench on a network already trusted. :ivar workers: Requests served concurrently. :ivar role: ``master`` to drive other benches, ``node`` to serve only this one. One master to a group and no chaining, so the benches of a lab form a star: see :attr:`is_master`. :ivar data_share: The Plesty share — the lab's shared disk — as this machine mounts it (``Z:/xyz/plesty``, ``/Volumes/plesty``). Empty until set. :ivar data_folder: This bench's folder in the share, relative to it (``platform-a``, any depth); empty for the share itself. :ivar check_updates: Whether the console asks PyPI for a newer bench when it starts, at most once a day (#39). .. py:attribute:: bind :type: str :value: 'tcp://*:5550' .. py:attribute:: token :type: str :value: '' .. py:attribute:: workers :type: int :value: 4 .. py:attribute:: role :type: str :value: 'node' .. py:attribute:: data_share :type: str :value: '' .. py:attribute:: data_folder :type: str :value: '' .. py:attribute:: check_updates :type: bool :value: True .. py:property:: data_root :type: str its folder in the share, where every device it starts writes. Empty while no share is set. :type: The bench data path .. py:property:: guarded :type: bool Whether a token is checked (never the token itself). .. py:property:: is_master :type: bool Whether this bench declares nodes and drives their devices. A configuration convention rather than a permission: the agent checks one shared secret and knows no caller identity, so a node's token drives that node whoever holds it, and nothing here stops a second bench from declaring itself master of the same nodes. What the role decides is what *this* console does — a node keeps no peer list and offers nothing remote. .. py:method:: validate() -> AgentSettings Return self, having refused settings the agent could not bind. :raises FleetError: When the endpoint is empty or the worker count is not a positive number. .. py:method:: to_mapping() -> dict[str, Any] The document written to ``agent.yaml``. .. py:method:: from_mapping(raw: Any) -> AgentSettings :classmethod: Read a document, falling back to the defaults key by key. A settings file nobody can parse must not stop the console from opening: what is unreadable is replaced by its default rather than raised, since the operator can see and fix every value in the dialog. .. py:method:: with_new_token() -> AgentSettings These settings with a freshly generated token. .. py:method:: device_data_env(name: str, data_dir: str | None, fallback: pathlib.Path | None = None) -> dict[str, str] Where a device the bench starts may write, and where it writes by default. :param name: The device, whose own folder under ``tmp`` is its default. :param data_dir: Its folder under the bench data path, as its declaration names it; ``None`` for ``tmp/``. :param fallback: Where it writes while the bench has no share — a folder of the bench's own (#43). A device that must have a data path otherwise refused to start on a bench alone. :returns: ``DEVICE_DATA_ROOT``, ``DEVICE_DATA_PATH`` and ``PLESTY_DATA`` — the share, which the device reports its folders relative to. Without a share, the first two under *fallback* and no ``PLESTY_DATA``; nothing when there is no *fallback* either. .. py:method:: run_data_env() -> dict[str, str] ``PLESTY_DATA`` for a run the bench starts: where it reads its devices' files. .. py:function:: check_data_location(share: str, folder: str) -> tuple[str, str] Return *share* and *folder*, having made sure the bench can write in the folder. An empty share is legal and means unset. Otherwise the share is an absolute path to an existing folder — a relative one would follow whatever directory a server happens to start in — and the bench's folder is a path inside it, created when missing. :returns: The share, and the folder as ``a/b`` (empty for the share itself). :raises FleetError: Naming why the bench cannot write there. .. py:function:: settings_file(home: plesty.server.model.home.Home) -> pathlib.Path Where *home* keeps the agent settings. .. py:function:: load_agent_settings(home: plesty.server.model.home.Home) -> AgentSettings The agent settings of *home*, defaults when it has none. .. py:function:: save_agent_settings(home: plesty.server.model.home.Home, settings: AgentSettings) -> pathlib.Path Write *settings* to *home*; returns the path. The file holds a shared secret, so it is made readable by its owner alone. Windows ignores the mode — there the bench home's own ACL is the guard — which is why the token is a bench-network secret and not a credential. :raises FleetError: When the settings would not bind (see :meth:`AgentSettings.validate`).