github.com/mfpierre/corectl@v0.5.6/ps.go (about)

     1  // Copyright 2015 - António Meireles  <antonio.meireles@reformi.st>
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package main
    17  
    18  import (
    19  	"encoding/json"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"log"
    23  	"os"
    24  	"path/filepath"
    25  	"strconv"
    26  	"text/tabwriter"
    27  	"time"
    28  
    29  	"github.com/spf13/cobra"
    30  )
    31  
    32  var (
    33  	psCmd = &cobra.Command{
    34  		Use:     "ps",
    35  		Aliases: []string{"status"},
    36  		Short:   "Lists running CoreOS instances",
    37  		PreRunE: defaultPreRunE,
    38  		RunE:    psCommand,
    39  	}
    40  	queryCmd = &cobra.Command{
    41  		Use:     "query [VMids]",
    42  		Aliases: []string{"q"},
    43  		Short:   "Display information about the running CoreOS instances",
    44  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
    45  			engine.rawArgs.BindPFlags(cmd.Flags())
    46  			if engine.rawArgs.GetBool("ip") && len(args) != 1 {
    47  				err = fmt.Errorf(" -i, --ip is only allowed when there's one " +
    48  					"and only one argument (a VM's name or UUID).")
    49  			}
    50  			return err
    51  		},
    52  		RunE: queryCommand,
    53  	}
    54  )
    55  
    56  func queryCommand(cmd *cobra.Command, args []string) (err error) {
    57  	var (
    58  		pp                []byte
    59  		running, selected []VMInfo
    60  		vm                VMInfo
    61  		tabP              = func(selected []VMInfo) {
    62  			w := new(tabwriter.Writer)
    63  			w.Init(os.Stdout, 5, 0, 1, ' ', 0)
    64  			fmt.Fprintf(w, "name\tchannel/version\tip\tcpu(s)\tram\tuuid\tpid"+
    65  				"\tuptime\tvols\n")
    66  			for _, vm = range selected {
    67  				fmt.Fprintf(w, "%v\t%v/%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
    68  					vm.Name, vm.Channel, vm.Version, vm.PublicIP, vm.Cpus,
    69  					vm.Memory, vm.UUID, vm.Pid, time.Now().Sub(vm.CreatedAt),
    70  					len(vm.Storage.HardDrives))
    71  			}
    72  			w.Flush()
    73  		}
    74  	)
    75  	if running, err = allRunningInstances(); err != nil {
    76  		return
    77  	}
    78  	if len(args) == 0 {
    79  		if engine.rawArgs.GetBool("json") {
    80  			if pp, err = json.MarshalIndent(running, "", "    "); err == nil {
    81  				fmt.Println(string(pp))
    82  			}
    83  			return
    84  		}
    85  		if engine.rawArgs.GetBool("all") {
    86  			tabP(running)
    87  			return
    88  		}
    89  		for _, vm := range running {
    90  			fmt.Println(vm.Name)
    91  		}
    92  		return
    93  	}
    94  	if len(args) == 1 && engine.rawArgs.GetBool("ip") {
    95  		if vm, err = vmInfo(args[0]); err != nil {
    96  			return
    97  		}
    98  		fmt.Println(vm.PublicIP)
    99  		return
   100  	}
   101  	for _, target := range args {
   102  		if vm, err = vmInfo(target); err != nil {
   103  			return
   104  		}
   105  		selected = append(selected, vm)
   106  	}
   107  	if engine.rawArgs.GetBool("json") {
   108  		if pp, err = json.MarshalIndent(selected, "", "    "); err == nil {
   109  			fmt.Println(string(pp))
   110  		}
   111  		return
   112  	}
   113  	if engine.rawArgs.GetBool("all") {
   114  		tabP(selected)
   115  		return
   116  	}
   117  	for _, vm := range selected {
   118  		fmt.Println(vm.Name)
   119  	}
   120  	return
   121  }
   122  
   123  func psCommand(cmd *cobra.Command, args []string) (err error) {
   124  	var (
   125  		pp      []byte
   126  		running []VMInfo
   127  	)
   128  
   129  	if running, err = allRunningInstances(); err != nil {
   130  		return
   131  	}
   132  	if engine.rawArgs.GetBool("json") {
   133  		if pp, err = json.MarshalIndent(running, "", "    "); err == nil {
   134  			fmt.Println(string(pp))
   135  		}
   136  		return
   137  	}
   138  	totalV, totalM, totalC := len(running), 0, 0
   139  	for _, vm := range running {
   140  		totalC, totalM = totalC+vm.Cpus, totalM+vm.Memory
   141  	}
   142  	log.Printf("found %v running VMs, summing %v vCPUs and %vMB in use.\n",
   143  		totalV, totalC, totalM)
   144  	for _, vm := range running {
   145  		vm.pp(engine.rawArgs.GetBool("all"))
   146  	}
   147  	return
   148  }
   149  
   150  func allRunningInstances() (alive []VMInfo, err error) {
   151  	var ls []os.FileInfo
   152  
   153  	if ls, err = ioutil.ReadDir(engine.runDir); err != nil {
   154  		return
   155  	}
   156  	for _, d := range ls {
   157  		if r, e := runningConfig(d.Name()); e == nil {
   158  			alive = append(alive, r)
   159  		}
   160  	}
   161  	return
   162  }
   163  
   164  func (vm *VMInfo) pp(extended bool) {
   165  	fmt.Printf("- %v, %v/%v, PID %v (detached=%v), up %v\n",
   166  		vm.Name, vm.Channel, vm.Version, vm.Pid, vm.Detached,
   167  		time.Now().Sub(vm.CreatedAt))
   168  	fmt.Printf("  - %v vCPU(s), %v RAM\n", vm.Cpus, vm.Memory)
   169  	if vm.CloudConfig != "" {
   170  		fmt.Printf("  - cloud-config: %v\n", vm.CloudConfig)
   171  	}
   172  	fmt.Println("  - Network Interfaces:")
   173  	fmt.Printf("    - eth0 (public interface) %v\n", vm.PublicIP)
   174  	if len(vm.Ethernet) > 1 {
   175  		fmt.Printf("    - eth1 (private interface/%v on host)\n", vm.Ethernet[1].Path)
   176  	}
   177  	vm.Storage.pp(vm.Root)
   178  	if extended {
   179  		fmt.Printf("  - UUID: %v\n", vm.UUID)
   180  		if vm.SSHkey != "" {
   181  			fmt.Printf("  - ssh key: %v\n", vm.SSHkey)
   182  		}
   183  		if vm.Extra != "" {
   184  			fmt.Printf("  - custom args to xhyve: %v\n", vm.Extra)
   185  		}
   186  	}
   187  }
   188  
   189  func (volumes *storageAssets) pp(root int) {
   190  	if len(volumes.CDDrives)+len(volumes.HardDrives) > 0 {
   191  		fmt.Println("  - Volumes:")
   192  		for a, b := range volumes.CDDrives {
   193  			fmt.Printf("    - /dev/cdrom%v (%s)\n", a, b.Path)
   194  		}
   195  		for a, b := range volumes.HardDrives {
   196  			i, _ := strconv.Atoi(a)
   197  			if i != root {
   198  				fmt.Printf("    - /dev/vd%v (%s)\n", string(i+'a'), b.Path)
   199  			} else {
   200  				fmt.Printf("    - /,/dev/vd%v (%s)\n", string(i+'a'), b.Path)
   201  			}
   202  		}
   203  	}
   204  }
   205  
   206  func runningConfig(uuid string) (vm VMInfo, err error) {
   207  	var buf []byte
   208  	if buf, err =
   209  		ioutil.ReadFile(filepath.Join(engine.runDir,
   210  			uuid, "/config")); err != nil {
   211  		return
   212  	}
   213  	json.Unmarshal(buf, &vm)
   214  	if !vm.isActive() {
   215  		return vm, fmt.Errorf("dead")
   216  	}
   217  	return
   218  }
   219  
   220  func init() {
   221  	psCmd.Flags().BoolP("all", "a", false,
   222  		"shows extended information about running CoreOS instances")
   223  	psCmd.Flags().BoolP("json", "j", false,
   224  		"outputs in JSON for easy 3rd party integration")
   225  	RootCmd.AddCommand(psCmd)
   226  
   227  	queryCmd.Flags().BoolP("json", "j", false,
   228  		"outputs in JSON for easy 3rd party integration")
   229  	queryCmd.Flags().BoolP("all", "a", false,
   230  		"display extended information about a running CoreOS instance")
   231  	queryCmd.Flags().BoolP("ip", "i", false,
   232  		"displays given instance IP address")
   233  	RootCmd.AddCommand(queryCmd)
   234  }