reboot_node
Restart a specific node within a CloudLab experiment to resolve issues or apply configuration changes. Specify the experiment ID and node identifier to initiate the reboot process.
Instructions
Reboot a specific node in an experiment
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| experiment_id | Yes | Experiment UUID (from list_experiments) | |
| node | Yes | Node client_id (e.g., 'node0') |
Implementation Reference
- src/index.ts:315-332 (handler)The handler function for the 'reboot_node' tool. It extracts experiment_id and node from arguments, makes a POST request to the CloudLab API endpoint `/experiments/{experiment_id}/node/{node}/reboot`, and returns the result.case "reboot_node": { const { experiment_id, node } = args as { experiment_id: string; node: string; }; const result = await cloudlabRequest( `/experiments/${experiment_id}/node/${node}/reboot`, "POST" ); return { content: [ { type: "text", text: `Reboot initiated for node ${node}: ${JSON.stringify(result, null, 2)}`, }, ], }; }
- src/index.ts:153-170 (schema)The input schema definition for the 'reboot_node' tool, returned in the list_tools response. Requires experiment_id and node.{ name: "reboot_node", description: "Reboot a specific node in an experiment", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, node: { type: "string", description: "Node client_id (e.g., 'node0')", }, }, required: ["experiment_id", "node"], }, },
- src/index.ts:97-255 (registration)The ListToolsRequestHandler registers all tools including 'reboot_node' by returning their schemas.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "list_experiments", description: "List all your CloudLab experiments", inputSchema: { type: "object", properties: {}, required: [], }, }, { name: "create_experiment", description: "Create a new CloudLab experiment from a profile", inputSchema: { type: "object", properties: { project: { type: "string", description: "Project name (e.g., 'UCY-CS499-DC')", }, profile_name: { type: "string", description: "Profile name (e.g., 'small-lan')", }, profile_project: { type: "string", description: "Project that owns the profile (e.g., 'PortalProfiles')", }, name: { type: "string", description: "Optional experiment name (auto-generated if not provided)", }, bindings: { type: "object", description: "Optional profile parameter bindings (e.g., {nodeCount: '2', phystype: 'c220g1'})", }, }, required: ["project", "profile_name", "profile_project"], }, }, { name: "get_experiment", description: "Get detailed status of a specific experiment including node states", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, }, required: ["experiment_id"], }, }, { name: "reboot_node", description: "Reboot a specific node in an experiment", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, node: { type: "string", description: "Node client_id (e.g., 'node0')", }, }, required: ["experiment_id", "node"], }, }, { name: "reboot_all_nodes", description: "Reboot all nodes in an experiment", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, }, required: ["experiment_id"], }, }, { name: "reload_node", description: "Reload/reimage a node with its disk image", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, node: { type: "string", description: "Node client_id", }, }, required: ["experiment_id", "node"], }, }, { name: "powercycle_node", description: "Power cycle a node (hard reboot)", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, node: { type: "string", description: "Node client_id", }, }, required: ["experiment_id", "node"], }, }, { name: "extend_experiment", description: "Extend the expiration time of an experiment", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, hours: { type: "number", description: "Number of hours to extend", }, }, required: ["experiment_id", "hours"], }, }, { name: "terminate_experiment", description: "Terminate an experiment (WARNING: destroys all data)", inputSchema: { type: "object", properties: { experiment_id: { type: "string", description: "Experiment UUID (from list_experiments)", }, }, required: ["experiment_id"], }, }, ], }; });
- src/index.ts:258-438 (registration)The CallToolRequestHandler registers the execution logic for all tools via the switch statement on tool name.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "list_experiments": { const result = await cloudlabRequest("/experiments"); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "create_experiment": { const { project, profile_name, profile_project, name, bindings } = args as { project: string; profile_name: string; profile_project: string; name?: string; bindings?: Record<string, string>; }; const body: Record<string, any> = { project, profile_name, profile_project, }; if (name) body.name = name; if (bindings) body.bindings = bindings; const result = await cloudlabRequest("/experiments", "POST", body); return { content: [ { type: "text", text: `Experiment created: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "get_experiment": { const { experiment_id } = args as { experiment_id: string }; const result = await cloudlabRequest(`/experiments/${experiment_id}`); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } case "reboot_node": { const { experiment_id, node } = args as { experiment_id: string; node: string; }; const result = await cloudlabRequest( `/experiments/${experiment_id}/node/${node}/reboot`, "POST" ); return { content: [ { type: "text", text: `Reboot initiated for node ${node}: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "reboot_all_nodes": { const { experiment_id } = args as { experiment_id: string }; const result = await cloudlabRequest( `/experiments/${experiment_id}/nodes/reboot`, "POST" ); return { content: [ { type: "text", text: `Reboot initiated for all nodes: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "reload_node": { const { experiment_id, node } = args as { experiment_id: string; node: string; }; const result = await cloudlabRequest( `/experiments/${experiment_id}/node/${node}/reload`, "POST" ); return { content: [ { type: "text", text: `Reload initiated for node ${node}: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "powercycle_node": { const { experiment_id, node } = args as { experiment_id: string; node: string; }; const result = await cloudlabRequest( `/experiments/${experiment_id}/node/${node}/powercycle`, "POST" ); return { content: [ { type: "text", text: `Power cycle initiated for node ${node}: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "extend_experiment": { const { experiment_id, hours } = args as { experiment_id: string; hours: number; }; const result = await cloudlabRequest( `/experiments/${experiment_id}`, "PUT", { extend_by: hours } ); return { content: [ { type: "text", text: `Extension requested: ${JSON.stringify(result, null, 2)}`, }, ], }; } case "terminate_experiment": { const { experiment_id } = args as { experiment_id: string }; const result = await cloudlabRequest( `/experiments/${experiment_id}`, "DELETE" ); return { content: [ { type: "text", text: `Experiment termination initiated: ${JSON.stringify(result, null, 2)}`, }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } });
- src/index.ts:47-81 (helper)Helper function used by all tools, including reboot_node, to make authenticated requests to the CloudLab API.async function cloudlabRequest( endpoint: string, method: string = "GET", body?: object ): Promise<any> { const token = loadToken(); const url = `${CLOUDLAB_API_BASE}${endpoint}`; const headers: Record<string, string> = { "X-Api-Token": token, "Accept": "application/json", }; if (body) { headers["Content-Type"] = "application/json"; } const response = await fetch(url, { method, headers, body: body ? JSON.stringify(body) : undefined, redirect: "follow", }); if (!response.ok) { const text = await response.text(); throw new Error(`CloudLab API error (${response.status}): ${text}`); } const contentType = response.headers.get("content-type"); if (contentType?.includes("application/json")) { return response.json(); } return response.text(); }