feat(osctl): add df command (#569)
Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
This commit is contained in:
parent
50c51ac717
commit
a8fa1f5cd1
42
cmd/osctl/cmd/df.go
Normal file
42
cmd/osctl/cmd/df.go
Normal file
@ -0,0 +1,42 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// nolint: dupl,golint
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
|
||||
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
|
||||
"github.com/talos-systems/talos/internal/pkg/constants"
|
||||
)
|
||||
|
||||
// dfCmd represents the df command.
|
||||
var dfCmd = &cobra.Command{
|
||||
Use: "df",
|
||||
Short: "List disk usage",
|
||||
Long: ``,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
creds, err := client.NewDefaultClientCredentials(talosconfig)
|
||||
if err != nil {
|
||||
helpers.Fatalf("error getting client credentials: %s", err)
|
||||
}
|
||||
if target != "" {
|
||||
creds.Target = target
|
||||
}
|
||||
c, err := client.NewClient(constants.OsdPort, creds)
|
||||
if err != nil {
|
||||
helpers.Fatalf("error constructing client: %s", err)
|
||||
}
|
||||
|
||||
if err := c.DF(); err != nil {
|
||||
helpers.Fatalf("error getting df: %s", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
dfCmd.Flags().StringVarP(&target, "target", "t", "", "target the specificed node")
|
||||
rootCmd.AddCommand(dfCmd)
|
||||
}
|
@ -13,6 +13,7 @@ import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
@ -271,3 +272,28 @@ func (c *Client) Top() (pl []proc.ProcessList, err error) {
|
||||
err = dec.Decode(&pl)
|
||||
return
|
||||
}
|
||||
|
||||
// DF implements the proto.OSDClient interface.
|
||||
func (c *Client) DF() (err error) {
|
||||
ctx := context.Background()
|
||||
reply, err := c.client.DF(ctx, &empty.Empty{})
|
||||
if err != nil {
|
||||
fmt.Printf("one or more error encountered: %+v", err)
|
||||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
fmt.Fprintln(w, "FILESYSTEM\tSIZE(GB)\tUSED(GB)\tAVAILABLE(GB)\tPERCENT USED\tMOUNTED ON")
|
||||
for _, r := range reply.Stats {
|
||||
percentAvailable := 100.0 - 100.0*(float64(r.Available)/float64(r.Size))
|
||||
|
||||
if math.IsNaN(percentAvailable) {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s\t%.02f\t%.02f\t%.02f\t%.02f%%\t%s\n", r.Filesystem, float64(r.Size)*1e-9, float64(r.Size-r.Available)*1e-9, float64(r.Available)*1e-9, percentAvailable, r.MountedOn)
|
||||
}
|
||||
if err := w.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -5,12 +5,14 @@
|
||||
package reg
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/cgroups"
|
||||
"github.com/containerd/containerd"
|
||||
@ -19,6 +21,7 @@ import (
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/talos-systems/talos/internal/app/init/pkg/system/events"
|
||||
@ -399,3 +402,68 @@ func (r *Registrator) Top(ctx context.Context, in *empty.Empty) (reply *proto.To
|
||||
reply = &proto.TopReply{ProcessList: p}
|
||||
return
|
||||
}
|
||||
|
||||
// DF implements the proto.OSDServer interface.
|
||||
func (r *Registrator) DF(ctx context.Context, in *empty.Empty) (reply *proto.DFReply, err error) {
|
||||
file, err := os.Open("/proc/mounts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// nolint: errcheck
|
||||
defer file.Close()
|
||||
|
||||
var (
|
||||
stat unix.Statfs_t
|
||||
multiErr *multierror.Error
|
||||
)
|
||||
|
||||
stats := []*proto.DFStat{}
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
fields := strings.Fields(scanner.Text())
|
||||
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
filesystem := fields[0]
|
||||
mountpoint := fields[1]
|
||||
|
||||
f, err := os.Stat(mountpoint)
|
||||
if err != nil {
|
||||
multiErr = multierror.Append(multiErr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if mode := f.Mode(); !mode.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := unix.Statfs(mountpoint, &stat); err != nil {
|
||||
multiErr = multierror.Append(multiErr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
totalSize := uint64(stat.Bsize) * stat.Blocks
|
||||
totalAvail := uint64(stat.Bsize) * stat.Bavail
|
||||
|
||||
stat := &proto.DFStat{
|
||||
Filesystem: filesystem,
|
||||
Size: totalSize,
|
||||
Available: totalAvail,
|
||||
MountedOn: mountpoint,
|
||||
}
|
||||
|
||||
stats = append(stats, stat)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
multiErr = multierror.Append(multiErr, err)
|
||||
}
|
||||
|
||||
reply = &proto.DFReply{
|
||||
Stats: stats,
|
||||
}
|
||||
|
||||
return reply, multiErr.ErrorOrNil()
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ service OSD {
|
||||
rpc Routes(google.protobuf.Empty) returns (RoutesReply) {}
|
||||
rpc Stats(StatsRequest) returns (StatsReply) {}
|
||||
rpc Top(google.protobuf.Empty) returns (TopReply) {}
|
||||
rpc DF(google.protobuf.Empty) returns (DFReply) {}
|
||||
rpc Version(google.protobuf.Empty) returns (Data) {}
|
||||
}
|
||||
|
||||
@ -89,3 +90,14 @@ message TopRequest {}
|
||||
message TopReply { ProcessList process_list = 1; }
|
||||
|
||||
message ProcessList { bytes bytes = 1; }
|
||||
|
||||
// The response message containing the requested df stats.
|
||||
message DFReply { repeated DFStat stats = 1; }
|
||||
|
||||
// The response message containing the requested processes.
|
||||
message DFStat {
|
||||
string filesystem = 1;
|
||||
uint64 size = 2;
|
||||
uint64 available = 3;
|
||||
string mounted_on = 4;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user