Python How-to¶
Generated from eve-iac OpenAPI/semantics. Do not edit manually.
Recipes for combining operations. The API reference explains each call. Examples assume an authenticated client and a packed project: lab, manifest, yaml, and files.
Model¶
YAML is IaC intent: what you want the lab to be. planProject previews the difference. reconcileProject with to_eve makes EVE match that intent. reconcileProject with from_eve turns the current EVE UNL definition into new IaC intent. It is not a capture of transient runtime state, and it is not importProject. getProjectStatus is the lightweight live poll. inspectProject is the rich structural snapshot.
IaC intent
|
| plan / reconcile
v
EVE lab
|
+-> getProjectStatus
| lightweight live observation
|
+-> inspectProject
rich structural observation
to_eve
YAML intent -> EVE
from_eve
current EVE UNL definition -> new YAML intent
Workflows¶
- Observe a live lab
- Load the structural lab model
- Build a live UI or monitoring loop
- Plan changes without applying them
- Make EVE match IaC intent
- Make the current EVE lab definition the new intent
- Start, stop, and wipe lab nodes
- Execute console commands
- Apply runtime link quality
- Suspend and resume a link
- Capture traffic
- Use traffic filters
Observe a live lab¶
What this solves¶
Which nodes are alive right now, and which runtime link impairments are currently visible?
Mental model¶
What is alive right now?
Use these operations¶
Workflow¶
- Call getProjectStatus. Use inspectProject only when you need structure.
- If live is omitted, the project has no runtime lab.
- If live.available is false, the live read failed. nodes and netem are omitted. That is not an empty lab.
- If live.available is true, read live.nodes and live.netem. A missing netem side is effective delay 0, jitter 0, loss 0, bandwidth 0 and stays omitted.
Important semantics¶
- This is the lightweight poll. An empty nodes array on a successful read means the lab has no nodes.
- joined false means rows were read but they are not all mapped to IaC keys.
- The status call stays HTTP 200 when the live read fails, so project context is still usable.
CLI: eve-iac status
Example¶
from eveiac import GetProjectStatusRequest
status = client.get_project_status(GetProjectStatusRequest(lab=lab, manifest=manifest, yaml=yaml, files=files))
live = getattr(status, "live", None)
if live is None:
print("no runtime lab")
elif getattr(live, "available", None) is not True:
print(getattr(live, "error", None) or "runtime unavailable")
else:
for node in getattr(live, "nodes", None) or []:
print(f"{getattr(node, 'key', '')}: {getattr(node, 'state_label', '')}")
Related¶
Load the structural lab model¶
What this solves¶
What nodes, interfaces, and attachment points make up the current EVE lab?
Mental model¶
What does the current EVE lab look like?
Use these operations¶
Workflow¶
- Call inspectProject with refresh when you need a fresh structural snapshot.
- Read nodes and the interfaces on each node. Those interface names are the structural attachment points.
- Keep this snapshot. Do not repeat it as a live poll.
- For running or stopped state and runtime netem, switch to getProjectStatus.
Important semantics¶
- inspectProject is the rich structural observation. It is not the high-frequency poll.
- The canvas uses this snapshot to resolve node and interface identity, then overlays live state from getProjectStatus.
- A missing netem side on a later status poll is effective zero impairment and is omitted.
CLI: eve-iac inspect --refresh
Example¶
from eveiac import InspectProjectRequest
observed = client.inspect_project(InspectProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, refresh=True,
))
for node in getattr(observed, "nodes", None) or []:
names = [iface.name for iface in (getattr(node, "interfaces", None) or []) if getattr(iface, "name", None)]
print(f"{getattr(node, 'key', '')}: {','.join(names)}")
Related¶
Build a live UI or monitoring loop¶
What this solves¶
How do I keep a structural picture of the lab and refresh only what is alive?
Mental model¶
Snapshot the shape once. Poll what is alive.
Use these operations¶
Workflow¶
- Inspect once, with refresh, and keep nodes plus their interfaces.
- Poll getProjectStatus on an interval your application chooses.
- When live.available is true, overlay node state and netem onto the structural model by native id.
- Inspect again only when interface names are missing, the topology changed, or the user asked for a structural refresh.
inspectProject(refresh=true)
|
v
structural model
|
+----------------+
|
getProjectStatus
getProjectStatus
getProjectStatus
|
v
runtime overlay
Important semantics¶
- A failed live read keeps the previous overlay. Do not replace netem with an empty object.
- A missing netem side stays omitted. That means effective zero impairment.
- Suspend is not on this poll. Read it from a structural inspect when you need it.
CLI: eve-iac inspect --refresh, then eve-iac status
Example¶
from eveiac import GetProjectStatusRequest, InspectProjectRequest
structure = client.inspect_project(InspectProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, refresh=True,
))
by_id = {node.id: node for node in (getattr(structure, "nodes", None) or []) if getattr(node, "id", None)}
status = client.get_project_status(GetProjectStatusRequest(lab=lab, manifest=manifest, yaml=yaml, files=files))
live = getattr(status, "live", None)
if getattr(live, "available", None) is True:
for row in getattr(live, "nodes", None) or []:
node = by_id.get(getattr(row, "id", None))
if node is not None:
node.state_label = getattr(row, "state_label", None)
structure.netem = getattr(live, "netem", None)
Related¶
Plan changes without applying them¶
What this solves¶
What would change if I applied my current IaC intent?
Mental model¶
Preview the delta before mutation.
Use these operations¶
Workflow¶
- Call planProject. Omitted direction means to_eve.
- Read summary creates, updates, and deletes, and the action list.
- Keep plan_identity if a later to_eve confirm must stop nodes.
- Leave the plan as a preview. This call writes neither EVE nor the project files.
YAML intent
+
EVE current state
|
v
plan
Important semantics¶
- A plan identity belongs to one direction. Do not reuse a to_eve identity for from_eve.
- applicable is a summary. It does not authorize the change.
CLI: eve-iac plan
Example¶
from eveiac import PlanProjectRequest
plan = client.plan_project(PlanProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, direction="to_eve",
))
summary = getattr(plan, "summary", None)
changes = sum(getattr(summary, name, 0) or 0 for name in ("creates", "updates", "deletes"))
print(f"changes={changes}")
Related¶
Make EVE match IaC intent¶
What this solves¶
How do I apply the YAML intent to EVE?
Mental model¶
Make EVE match my IaC intent.
Use these operations¶
Workflow¶
- Plan with direction to_eve and read the actions.
- Reconcile with direction to_eve. Omitted confirm applies only live-safe work and does not stop nodes.
- If status is pending_stop, reconcile again with confirm true and the plan_identity from that same direction.
- An unsupported action means to_eve performs zero EVE mutations.
Important semantics¶
- A later confirm reuses the plan_identity from this same direction. A missing or mismatched identity is 409 plan_stale and stops nothing.
- Send direction to_eve on this recipe. from_eve is the other recipe.
CLI: eve-iac reconcile --direction to_eve
Example¶
from eveiac import PlanProjectRequest, ReconcileProjectRequest
plan = client.plan_project(PlanProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, direction="to_eve",
))
applied = client.reconcile_project(ReconcileProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, direction="to_eve",
))
if getattr(applied, "status", None) == "pending_stop" and getattr(plan, "plan_identity", None):
applied = client.reconcile_project(ReconcileProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files,
direction="to_eve", confirm=True, plan_identity=plan.plan_identity,
))
Related¶
Make the current EVE lab definition the new intent¶
What this solves¶
I changed the EVE lab and now want that definition to become my IaC YAML intent. What do I do?
Mental model¶
Make the current EVE UNL definition my new IaC intent.
Use these operations¶
Workflow¶
- Reconcile with direction from_eve.
- Read the returned YAML intent and persist it in the project. The agent does not rewrite your files.
- Do not read node run state or netem out of this result and copy them into YAML.
EVE UNL definition
-> Lab Object
-> YAML intent
Important semantics¶
- from_eve promotes the persisted EVE UNL definition. It is not a runtime capture.
- It is not importProject. Import clones a lab into a managed copy and leaves YAML intent alone.
- from_eve does not perform mutating EVE writes. confirm does not authorize a stop on this direction.
CLI: eve-iac reconcile --direction from_eve
Example¶
from eveiac import ReconcileProjectRequest, commit_pulled, should_persist_from_eve
pulled = client.reconcile_project(ReconcileProjectRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, direction="from_eve",
))
if should_persist_from_eve(pulled):
commit_pulled(root, pulled)
Related¶
Start, stop, and wipe lab nodes¶
What this solves¶
How do I control node power and disks from an SDK?
Mental model¶
Start, stop, or wipe these nodes.
Use these operations¶
Workflow¶
- Read getCapabilities and the lifecycle flags for the project mode: create, import, or load.
- Call execProject with action start, stop, or wipe.
- Omit node to select every node. Pass nodes or node to select IaC keys.
Important semantics¶
- Omitted stopmode is automatic. Explicit 0 is a graceful stop and is different from omitting the field.
- Wipe clears node data. Destroying the lab is destroyProject, not wipe.
CLI: eve-iac exec start|stop|wipe
Example¶
from eveiac import ExecProjectRequest
caps = client.get_capabilities()
modes = getattr(caps, "projectModes", None) or {}
create = modes.get("create") if isinstance(modes, dict) else None
life = getattr(create, "lifecycle", None)
if getattr(life, "start", None) is True:
client.exec_project(ExecProjectRequest(lab=lab, manifest=manifest, yaml=yaml, files=files, action="start"))
if getattr(life, "stop", None) is True:
client.exec_project(ExecProjectRequest(lab=lab, manifest=manifest, yaml=yaml, files=files, action="stop", node="n_1"))
if getattr(life, "wipe", None) is True:
client.exec_project(ExecProjectRequest(lab=lab, manifest=manifest, yaml=yaml, files=files, action="wipe", node="n_1"))
Related¶
Execute console commands¶
What this solves¶
How do I run commands against devices through EVE IaC?
Mental model¶
Talk to the node through the agent, not through a private console socket.
Use these operations¶
Workflow¶
- Use execConsole for one command on one node. The call returns when the prompt comes back.
- Use execConsoleMany when several nodes each get a command. One target's failure stays on that target.
- Use runConsole when the dialogue is an ordered expect and send. Use attachConsole and streamConsole for the live byte stream. A single show or ping stays on execConsole.
Important semantics¶
- The SDK is the automation surface. Do not dial the EVE console transport yourself.
- Omitted session joins or opens the console hub. A missing session is reopened once.
CLI: eve-iac console exec
Example¶
from eveiac import ConsoleTarget, ExecConsoleManyRequest, ExecConsoleRequest
one = client.exec_console(ExecConsoleRequest(lab=lab, node="n_1", command="show version"))
print(getattr(one, "output", "") or "")
client.exec_console_many(ExecConsoleManyRequest(
lab=lab,
targets=[
ConsoleTarget(node="n_1", command="show version"),
ConsoleTarget(node="n_2", command="show version"),
],
))
Related¶
Apply runtime link quality¶
What this solves¶
How do I temporarily change latency, jitter, loss, or bandwidth on a live link?
Mental model¶
Impair this live link, then look again.
Use these operations¶
Workflow¶
- Read getProjectStatus and live.netem. A missing side is effective zero and is not present in the object.
- Call applyLinkQuality with the public YAML endpoints. Omitted save changes the live link only.
- Read getProjectStatus again. The sides you set are present. Sides you did not need to report stay omitted.
Important semantics¶
- This is runtime interaction. It does not rewrite topology.yml.
- save true asks EVE to persist the impairment in the UNL. That is still not an edit of IaC intent.
- Omitted impairment on a side clears live netem on that side.
CLI: eve-iac link quality
Example¶
from eveiac import ApplyLinkQualityRequest, GetProjectStatusRequest, LinkImpairment, PublicLinkEndpoint, PublicLinkMatch
body = dict(lab=lab, manifest=manifest, yaml=yaml, files=files)
client.get_project_status(GetProjectStatusRequest(**body))
match = PublicLinkMatch(endpoints=[
PublicLinkEndpoint(node="n_1", interface="e0/0"),
PublicLinkEndpoint(node="n_2", interface="e0/1"),
])
client.apply_link_quality(ApplyLinkQualityRequest(
**body,
match=match,
source_impairment=LinkImpairment(delay=50),
))
after = client.get_project_status(GetProjectStatusRequest(**body))
live = getattr(after, "live", None)
print(getattr(live, "available", None) is True)
Related¶
Suspend and resume a link¶
What this solves¶
How do I temporarily interrupt a live link?
Mental model¶
Pause or resume this live link.
Use these operations¶
Workflow¶
- Identify the link by its public YAML endpoints.
- Call setLinkSuspend with suspended true to interrupt it, or false to resume it.
- Omitted side means both node endpoints.
Important semantics¶
- Suspend is runtime interaction. There is no topology.yml suspend field.
- getProjectStatus does not carry suspend. A structural inspect does.
CLI: eve-iac link suspend / eve-iac link resume
Example¶
from eveiac import PublicLinkEndpoint, PublicLinkMatch, SetLinkSuspendRequest
match = PublicLinkMatch(endpoints=[
PublicLinkEndpoint(node="n_1", interface="e0/0"),
PublicLinkEndpoint(node="n_2", interface="e0/1"),
])
client.set_link_suspend(SetLinkSuspendRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, match=match, suspended=True,
))
client.set_link_suspend(SetLinkSuspendRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, match=match, suspended=False,
))
Related¶
Capture traffic¶
What this solves¶
How do I start a packet capture from an SDK?
Mental model¶
Capture packets on this interface.
Use these operations¶
Workflow¶
- Call startCapture with the IaC node key and the interface name.
- Open the returned HTML5 URL.
- Closing the page leaves the capture container running. The API has no stop call.
Important semantics¶
- The URL is an HTML5 capture. evecapture:// is refused.
- LOAD mode is allowed, the same way other runtime interaction is allowed.
Example¶
from eveiac import StartCaptureRequest
capture = client.start_capture(StartCaptureRequest(
lab=lab, manifest=manifest, yaml=yaml, files=files, node="n_1", interface="e0/0",
))
print(capture.url)
Related¶
Use traffic filters¶
What this solves¶
How do I describe selected traffic in IaC intent and then watch that stream?
Mental model¶
Describe the filter in intent. Watch the stream through the agent.
Use these operations¶
Workflow¶
- Read or edit traffic_filters on IaC intent with getPublicProject and editProject. That is the filter definition, not a live packet API.
- Call attachTraffic to receive a one-time ticket. Native EVE ids stay on the agent.
- Upgrade that ticket with streamTraffic and read the translated stream.
Important semantics¶
- The filter is IaC intent, edited with editProject on section traffic_filters. The stream is runtime observation.
- The SDK is the stream surface. Native EVE traffic sockets stay on the agent.
Example¶
from eveiac import AttachTrafficRequest
attached = client.attach_traffic(AttachTrafficRequest(lab=lab, manifest=manifest, yaml=yaml, files=files))
ticket = attached.stream.rsplit("/", 1)[-1]
sock = client.stream_traffic(ticket)