From 3fbe8a1642c9e80a97cb405c4a4fc4c9aa482a2a Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Tue, 29 Mar 2016 12:36:24 -0700 Subject: [PATCH] node-status -self command and docs --- command/alloc_status.go | 1 - command/node_status.go | 39 +++++- command/node_status_test.go | 51 +++++++ .../docs/commands/alloc-status.html.md.erb | 126 +++++++++++------- .../docs/commands/node-status.html.md.erb | 117 +++++++++++++--- 5 files changed, 260 insertions(+), 74 deletions(-) diff --git a/command/alloc_status.go b/command/alloc_status.go index fdd3879d9..7e0e97bb2 100644 --- a/command/alloc_status.go +++ b/command/alloc_status.go @@ -164,7 +164,6 @@ func (c *AllocStatusCommand) shortTaskStatus(alloc *api.Allocation) { tasks := make([]string, 0, len(alloc.TaskStates)+1) tasks = append(tasks, "Name|State|Last Event|Time") for task := range c.sortedTaskStateIterator(alloc.TaskStates) { - fmt.Println(task) state := alloc.TaskStates[task] lastState := state.State var lastEvent, lastTime string diff --git a/command/node_status.go b/command/node_status.go index 57c14821d..e15eee8ed 100644 --- a/command/node_status.go +++ b/command/node_status.go @@ -22,7 +22,8 @@ Usage: nomad node-status [options] If a node ID is passed, information for that specific node will be displayed. If no node ID's are passed, then a short-hand - list of all nodes will be displayed. + list of all nodes will be displayed. The -self flag is useful to + quickly access the status of the local node. General Options: @@ -37,6 +38,9 @@ Node Status Options: -verbose Display full information. + -self + Query the status of the local node. + -allocs Display a count of running allocations for each node. ` @@ -48,13 +52,14 @@ func (c *NodeStatusCommand) Synopsis() string { } func (c *NodeStatusCommand) Run(args []string) int { - var short, verbose, list_allocs bool + var short, verbose, list_allocs, self bool flags := c.Meta.FlagSet("node-status", FlagSetClient) flags.Usage = func() { c.Ui.Output(c.Help()) } flags.BoolVar(&short, "short", false, "") flags.BoolVar(&verbose, "verbose", false, "") flags.BoolVar(&list_allocs, "allocs", false, "") + flags.BoolVar(&self, "self", false, "") if err := flags.Parse(args); err != nil { return 1 @@ -80,8 +85,32 @@ func (c *NodeStatusCommand) Run(args []string) int { return 1 } + // If -self flag is set then determine the current node. + nodeID := "" + if self { + info, err := client.Agent().Self() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error querying agent info: %s", err)) + return 1 + } + var stats map[string]interface{} + stats, _ = info["stats"] + clientStats, ok := stats["client"].(map[string]interface{}) + if !ok { + c.Ui.Error("Nomad not running in client mode") + return 1 + } + + nodeID, ok = clientStats["node_id"].(string) + if !ok { + c.Ui.Error("Failed to determine node ID") + return 1 + } + + } + // Use list mode if no node name was provided - if len(args) == 0 { + if len(args) == 0 && !self { // Query the node info nodes, _, err := client.Nodes().List(nil) if err != nil { @@ -133,7 +162,9 @@ func (c *NodeStatusCommand) Run(args []string) int { } // Query the specific node - nodeID := args[0] + if !self { + nodeID = args[0] + } if len(nodeID) == 1 { c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters.")) return 1 diff --git a/command/node_status_test.go b/command/node_status_test.go index e4924d9c8..604b3625c 100644 --- a/command/node_status_test.go +++ b/command/node_status_test.go @@ -13,6 +13,57 @@ func TestNodeStatusCommand_Implements(t *testing.T) { var _ cli.Command = &NodeStatusCommand{} } +func TestNodeStatusCommand_Self(t *testing.T) { + // Start in dev mode so we get a node registration + srv, client, url := testServer(t, func(c *testutil.TestServerConfig) { + c.DevMode = true + c.NodeName = "mynode" + }) + defer srv.Stop() + + ui := new(cli.MockUi) + cmd := &NodeStatusCommand{Meta: Meta{Ui: ui}} + + // Wait for a node to appear + var nodeID string + testutil.WaitForResult(func() (bool, error) { + nodes, _, err := client.Nodes().List(nil) + if err != nil { + return false, err + } + if len(nodes) == 0 { + return false, fmt.Errorf("missing node") + } + nodeID = nodes[0].ID + return true, nil + }, func(err error) { + t.Fatalf("err: %s", err) + }) + + // Query self node + if code := cmd.Run([]string{"-address=" + url, "-self"}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out := ui.OutputWriter.String() + if !strings.Contains(out, "mynode") { + t.Fatalf("expect to find mynode, got: %s", out) + } + if strings.Contains(out, "Allocations") { + t.Fatalf("should not dump allocations") + } + ui.OutputWriter.Reset() + + // Request full id output + if code := cmd.Run([]string{"-address=" + url, "-self", "-verbose"}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out = ui.OutputWriter.String() + if !strings.Contains(out, nodeID) { + t.Fatalf("expected full node id %q, got: %s", nodeID, out) + } + ui.OutputWriter.Reset() +} + func TestNodeStatusCommand_Run(t *testing.T) { // Start in dev mode so we get a node registration srv, client, url := testServer(t, func(c *testutil.TestServerConfig) { diff --git a/website/source/docs/commands/alloc-status.html.md.erb b/website/source/docs/commands/alloc-status.html.md.erb index 65168799e..f6051ce43 100644 --- a/website/source/docs/commands/alloc-status.html.md.erb +++ b/website/source/docs/commands/alloc-status.html.md.erb @@ -37,70 +37,96 @@ allocations and information will be displayed. Short status of an alloc: ``` -$ nomad alloc-status --short a7365fe4 -ID = a7365fe4 -EvalID = 44c2d9ed -Name = example.cache[0] -NodeID = e55859b1 -JobID = example -ClientStatus = running -NodesEvaluated = 1 -NodesFiltered = 0 -NodesExhausted = 0 -AllocationTime = 911.026µs -CoalescedFailures = 0 -redis -web +$ nomad alloc-status --short 13901f26 +ID = 13901f26 +Eval ID = c3c9a1db +Name = example.cache[0] +Node ID = 1f029d38 +Job ID = example +Client Status = running ==> Tasks -Name State LastEvent Time -redis running Started 02:29:40 11/17/15 -web running Started 02:30:41 11/17/15 - -==> Status -Allocation "a7365fe4" status "running" (0/1 nodes filtered) - * Score "e55859b1.binpack" = 10.334026 +Name State Last Event Time +redis running Started 29/03/16 03:04:53 UTC +web running Started 29/03/16 03:04:53 UTC ``` Full status of an alloc, which shows one of the tasks dying and then being restarted: ``` $ nomad alloc-status a7365fe4 -ID = a7365fe4 -EvalID = 44c2d9ed -Name = example.cache[0] -NodeID = e55859b1 -JobID = example -ClientStatus = running -NodesEvaluated = 1 -NodesFiltered = 0 -NodesExhausted = 0 -AllocationTime = 911.026µs -CoalescedFailures = 0 - -==> Task "redis" is "running" -Recent Events: -Time Type Description -02:29:40 11/17/15 Started - -==> Task "web" is "running" -Recent Events: -Time Type Description -02:30:41 11/17/15 Started -02:30:02 11/17/15 Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137" -02:29:40 11/17/15 Started - -==> Status -Allocation "a7365fe4" status "running" (0/1 nodes filtered) -* Score "e55859b1.binpack" = 10.334026 +ID = a7365fe4 +Eval ID = c3c9a1db +Name = example.cache[0] +Node ID = 1f029d38 +Job ID = example +Client Status = running ==> Task Resources Task: "redis" CPU Memory MB Disk MB IOPS Addresses -500 256 300 0 db: 127.0.0.1:52004 +500 256 300 0 db: 127.0.0.1:46321 Task: "web" CPU Memory MB Disk MB IOPS Addresses -500 256 300 0 http: 127.0.0.1:52007 +500 256 300 0 db: 127.0.0.1:38537 + +==> Task "redis" is "running" +Recent Events: +Time Type Description +29/03/16 03:04:53 UTC Started Task started by client +29/03/16 03:04:51 UTC Received Task received by client + +==> Task "web" is "pending" +Recent Events: +Time Type Description +29/03/16 03:07:18 UTC Restarting Task restarting in 18.580059474s +29/03/16 03:07:18 UTC Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137" +29/03/16 03:04:53 UTC Started Task started by client +29/03/16 03:04:51 UTC Received Task received by client +``` + +Verbose status can also be accessed: ``` +$ nomad alloc-status a7365fe4 +ID = a7365fe4-cb28-a6e9-f3d4-f99e49c89776 +Eval ID = c3c9a1db-dbeb-8afa-0a83-4f1b8b5a03f5 +Name = example.cache[0] +Node ID = 1f029d38-8d4b-a552-261f-e457b60f9b4b +Job ID = example +Client Status = running +Evaluated Nodes = 1 +Filtered Nodes = 0 +Exhausted Nodes = 0 +Allocation Time = 1.085001ms +Failures = 0 + +==> Task Resources +Task: "web" +CPU Memory MB Disk MB IOPS Addresses +500 256 300 0 db: 127.0.0.1:38537 + +Task: "redis" +CPU Memory MB Disk MB IOPS Addresses +500 256 300 0 db: 127.0.0.1:46321 + +==> Task "redis" is "running" +Recent Events: +Time Type Description +29/03/16 03:04:53 UTC Started Task started by client +29/03/16 03:04:51 UTC Received Task received by client + +==> Task "web" is "running" +Recent Events: +Time Type Description +29/03/16 03:07:38 UTC Started Task started by client +29/03/16 03:07:18 UTC Restarting Task restarting in 18.580059474s +29/03/16 03:07:18 UTC Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137" +29/03/16 03:04:53 UTC Started Task started by client +29/03/16 03:04:51 UTC Received Task received by client + +==> Status +Allocation "13901f26-cb28-a6e9-f3d4-f99e49c89776" status "running" (0/1 nodes filtered) + * Score "1f029d38-8d4b-a552-261f-e457b60f9b4b.binpack" = 10.334026 +``` diff --git a/website/source/docs/commands/node-status.html.md.erb b/website/source/docs/commands/node-status.html.md.erb index f98602aa7..d684ff1b7 100644 --- a/website/source/docs/commands/node-status.html.md.erb +++ b/website/source/docs/commands/node-status.html.md.erb @@ -24,7 +24,9 @@ but is a good way to get a bird's-eye view of things. If there is an exact match based on the provided node ID or prefix, then that particular node will be queried, and detailed information will be displayed. -Otherwise, a list of matching nodes and information will be displayed. +Otherwise, a list of matching nodes and information will be displayed. If +running the command on a Nomad Client, the -self flag is useful to quickly +access the status of the local node. ## General Options @@ -32,10 +34,10 @@ Otherwise, a list of matching nodes and information will be displayed. ## Node Status Options -* `-short`: Display short output. Used only when querying a single node. Drops - verbose information about node allocations. +* `-short`: Display short output. Used only when querying a single node. * `-verbose`: Show full information. -* `-allocs`: Show running allocations per node +* `-allocs`: Show running allocations per node. +* `-self`: Query the status of the local node. ## Examples @@ -61,26 +63,103 @@ Single-node view in short mode: ``` $ nomad node-status -short 1f3f03ea -ID = 1f3f03ea -Name = node2 -Class = -Datacenter = dc1 -Drain = false -Status = ready +ID = c754da1f +Name = nomad +Class = +DC = dc1 +Drain = false +Status = ready ``` Full output for a single node: ``` $ nomad node-status 1f3f03ea -ID = 1f3f03ea -Name = node2 -Class = -Datacenter = dc1 -Drain = false -Status = ready +ID = c754da1f +Name = nomad +Class = +DC = dc1 +Drain = false +Status = ready -### Allocations -ID EvalID JobID TaskGroup DesiredStatus ClientStatus -678c51dc 193229c4 job8 grp8 failed failed +==> Resource Utilization +CPU Memory MB Disk MB IOPS +0/2600 0/1997 0/34374 0/0 + +==> Allocations +ID Eval ID Job ID Task Group Desired Status Client Status +3d743cff 2fb686da example cache run complete +``` + +Using `-self` when on a Nomad Client: + +``` +$ nomad node-status -self +ID = c754da1f +Name = nomad +Class = +DC = dc1 +Drain = false +Status = ready + +==> Resource Utilization +CPU Memory MB Disk MB IOPS +0/2600 0/1997 0/34374 0/0 + +==> Allocations +ID Eval ID Job ID Task Group Desired Status Client Status +3d743cff 2fb686da example cache run complete +``` + +To view verbose information about the node: + +``` +$ nomad node-status -verbose c754da1f +ID = c754da1f-6337-b86d-47dc-2ef4c71aca14 +Name = nomad +Class = +DC = dc1 +Drain = false +Status = ready + +==> Resource Utilization +CPU Memory MB Disk MB IOPS +0/2600 0/1997 0/34374 0/0 + +==> Allocations +ID Eval ID Job ID Task Group Desired Status Client Status +3d743cff-8d57-18c3-2260-a41d3f6c5204 2fb686da-b2b0-f8c2-5d57-2be5600435bd example cache run complete + +==> Attributes +arch = amd64 +cpu.frequency = 1300.000000 +cpu.modelname = Intel(R) Core(TM) M-5Y71 CPU @ 1.20GHz +cpu.numcores = 2 +cpu.totalcompute = 2600.000000 +driver.docker = 1 +driver.docker.version = 1.10.3 +driver.exec = 1 +driver.java = 1 +driver.java.runtime = OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-0ubuntu0.14.04.2) +driver.java.version = 1.7.0_95 +driver.java.vm = OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode) +driver.qemu = 1 +driver.qemu.version = 2.0.0 +driver.raw_exec = 1 +driver.rkt = 1 +driver.rkt.appc.version = 0.7.4 +driver.rkt.version = 1.2.0 +hostname = nomad +kernel.name = linux +kernel.version = 3.19.0-25-generic +memory.totalbytes = 2094473216 +nomad.revision = '270da7a60ccbf39eeeadc4064a59ca06bf9ac6fc+CHANGES' +nomad.version = 0.3.2dev +os.name = ubuntu +os.version = 14.04 +unique.cgroup.mountpoint = /sys/fs/cgroup +unique.network.ip-address = 127.0.0.1 +unique.storage.bytesfree = 36044333056 +unique.storage.bytestotal = 41092214784 +unique.storage.volume = /dev/mapper/ubuntu--14--vg-root ```