Skip to content

Commit

Permalink
Merge pull request containers#9885 from ashley-cui/machinels
Browse files Browse the repository at this point in the history
Add podman machine ls
  • Loading branch information
openshift-merge-robot authored Mar 30, 2021
2 parents bd07179 + ef4e91a commit a373e2f
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 5 deletions.
143 changes: 143 additions & 0 deletions cmd/podman/machine/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// +build amd64,linux arm64,linux amd64,darwin arm64,darwin

package machine

import (
"os"
"sort"
"text/tabwriter"
"text/template"
"time"

"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v3/cmd/podman/parse"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/machine"
"github.com/containers/podman/v3/pkg/machine/qemu"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var (
lsCmd = &cobra.Command{
Use: "list [options]",
Aliases: []string{"ls"},
Short: "List machines",
Long: "List Podman managed virtual machines.",
RunE: list,
Args: validate.NoArgs,
Example: `podman machine list,
podman machine ls`,
ValidArgsFunction: completion.AutocompleteNone,
}
listFlag = listFlagType{}
)

type listFlagType struct {
format string
noHeading bool
}

type machineReporter struct {
Name string
Created string
LastUp string
VMType string
}

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: lsCmd,
Parent: machineCmd,
})

flags := lsCmd.Flags()
formatFlagName := "format"
flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n", "Format volume output using Go template")
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone)
}

func list(cmd *cobra.Command, args []string) error {
var opts machine.ListOptions
// We only have qemu VM's for now
listResponse, err := qemu.List(opts)
if err != nil {
return errors.Wrap(err, "error listing vms")
}

// Sort by last run
sort.Slice(listResponse, func(i, j int) bool {
return listResponse[i].LastUp.After(listResponse[j].LastUp)
})
// Bring currently running machines to top
sort.Slice(listResponse, func(i, j int) bool {
return listResponse[i].Running
})
machineReporter, err := toHumanFormat(listResponse)
if err != nil {
return err
}

return outputTemplate(cmd, machineReporter)
}

func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
headers := report.Headers(machineReporter{}, map[string]string{
"LastUp": "LAST UP",
"VmType": "VM TYPE",
})

row := report.NormalizeFormat(listFlag.format)
format := parse.EnforceRange(row)

tmpl, err := template.New("list machines").Parse(format)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
defer w.Flush()

if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
listFlag.noHeading = true
}

if !listFlag.noHeading {
if err := tmpl.Execute(w, headers); err != nil {
return errors.Wrapf(err, "failed to write report column headers")
}
}
return tmpl.Execute(w, responses)
}

func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
cfg, err := config.ReadCustomConfig()
if err != nil {
return nil, err
}

humanResponses := make([]*machineReporter, 0, len(vms))
for _, vm := range vms {
response := new(machineReporter)
if vm.Name == cfg.Engine.ActiveService {
response.Name = vm.Name + "*"
} else {
response.Name = vm.Name
}
if vm.Running {
response.LastUp = "Currently running"
} else {
response.LastUp = units.HumanDuration(time.Since(vm.LastUp)) + " ago"
}
response.Created = units.HumanDuration(time.Since(vm.CreatedAt)) + " ago"
response.VMType = vm.VMType

humanResponses = append(humanResponses, response)
}
return humanResponses, nil
}
1 change: 1 addition & 0 deletions docs/source/machine.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Machine


:doc:`init <markdown/podman-machine-init.1>` Initialize a new virtual machine
:doc:`list <markdown/podman-machine-list.1>` List virtual machines
:doc:`rm <markdown/podman-machine-rm.1>` Remove a virtual machine
:doc:`ssh <markdown/podman-machine-ssh.1>` SSH into a virtual machine
:doc:`start <markdown/podman-machine-start.1>` Start a virtual machine
Expand Down
1 change: 1 addition & 0 deletions docs/source/markdown/links/podman-machine-ls.1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.so man1/podman-machine-list.1
50 changes: 50 additions & 0 deletions docs/source/markdown/podman-machine-list.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
% podman-machine-ls(1)

## NAME
podman\-machine\-list - List virtual machines

## SYNOPSIS
**podman machine list** [*options*]

**podman machine ls** [*options*]

## DESCRIPTION

List Podman managed virtual machines.

Podman on macOS requires a virtual machine. This is because containers are Linux -
containers do not run on any other OS because containers' core functionality is
tied to the Linux kernel.

## OPTIONS

#### **\-\-format**=*format*

Format list output using a Go template.

Valid placeholders for the Go template are listed below:

| **Placeholder** | **Description** |
| --------------- | ------------------------------- |
| .Name | VM name |
| .Created | Time since VM creation |
| .LastUp | Time since the VM was last run |
| .VMType | VM type |

#### **\-\-help**

Print usage statement.

## EXAMPLES

```
$ podman machine list
$ podman machine ls --format {{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n
```

## SEE ALSO
podman-machine(1)

## HISTORY
March 2021, Originally compiled by Ashley Cui <[email protected]>
11 changes: 6 additions & 5 deletions docs/source/markdown/podman-machine.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ podman\-machine - Manage Podman's virtual machine
| Command | Man Page | Description |
| ------- | ------------------------------------------------------- | --------------------------------- |
| init | [podman-machine-init(1)](podman-machine-init.1.md) | Initialize a new virtual machine |
| rm | [podman-machine-rm(1)](podman-machine-rm.1.md)| Remove a virtual machine |
| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
| list | [podman-machine-list(1)](podman-machine-list.1.md) | List virtual machines |
| rm | [podman-machine-rm(1)](podman-machine-rm.1.md) | Remove a virtual machine |
| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |

## SEE ALSO
podman(1)
podman(1), podman-machine-init(1), podman-machine-list(1), podman-machine-rm(1), podman-machine-ssh(1), podman-machine-start(1), podman-machine-stop(1)

## HISTORY
March 2021, Originally compiled by Ashley Cui <[email protected]>
11 changes: 11 additions & 0 deletions pkg/machine/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/url"
"os"
"path/filepath"
"time"

"github.com/containers/storage/pkg/homedir"
"github.com/pkg/errors"
Expand Down Expand Up @@ -44,6 +45,16 @@ type Download struct {
VMName string
}

type ListOptions struct{}

type ListResponse struct {
Name string
CreatedAt time.Time
LastUp time.Time
Running bool
VMType string
}

type SSHOptions struct {
Execute bool
Args []string
Expand Down
50 changes: 50 additions & 0 deletions pkg/machine/qemu/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/containers/podman/v3/pkg/machine"
Expand Down Expand Up @@ -426,3 +427,52 @@ func getDiskSize(path string) (uint64, error) {
}
return tmpInfo.VirtualSize, nil
}

// List lists all vm's that use qemu virtualization
func List(opts machine.ListOptions) ([]*machine.ListResponse, error) {
vmConfigDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
}

var listed []*machine.ListResponse

if err = filepath.Walk(vmConfigDir, func(path string, info os.FileInfo, err error) error {
vm := new(MachineVM)
if strings.HasSuffix(info.Name(), ".json") {
fullPath := filepath.Join(vmConfigDir, info.Name())
b, err := ioutil.ReadFile(fullPath)
if err != nil {
return err
}
err = json.Unmarshal(b, vm)
if err != nil {
return err
}
listEntry := new(machine.ListResponse)

listEntry.Name = vm.Name
listEntry.VMType = "qemu"
fi, err := os.Stat(fullPath)
if err != nil {
return err
}
listEntry.CreatedAt = fi.ModTime()

fi, err = os.Stat(vm.ImagePath)
if err != nil {
return err
}
listEntry.LastUp = fi.ModTime()
if vm.isRunning() {
listEntry.Running = true
}

listed = append(listed, listEntry)
}
return nil
}); err != nil {
return nil, err
}
return listed, err
}

0 comments on commit a373e2f

Please sign in to comment.