summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/images/build.go17
-rw-r--r--cmd/podman/machine/init.go43
-rw-r--r--cmd/podman/machine/rm.go (renamed from cmd/podman/machine/remove.go)28
-rw-r--r--cmd/podman/machine/ssh.go12
-rw-r--r--cmd/podman/machine/start.go12
-rw-r--r--cmd/podman/machine/stop.go12
-rw-r--r--docs/source/machine.rst2
-rw-r--r--docs/source/markdown/podman-create.1.md2
-rw-r--r--docs/source/markdown/podman-machine-init.1.md4
-rw-r--r--docs/source/markdown/podman-machine-rm.1.md (renamed from docs/source/markdown/podman-machine-remove.1.md)10
-rw-r--r--docs/source/markdown/podman-machine-ssh.1.md2
-rw-r--r--docs/source/markdown/podman-machine-start.1.md2
-rw-r--r--docs/source/markdown/podman-machine-stop.1.md2
-rw-r--r--docs/source/markdown/podman-machine.1.md8
-rw-r--r--docs/source/markdown/podman-run.1.md2
-rw-r--r--libpod/container_internal_linux.go12
-rw-r--r--pkg/api/handlers/compat/images_build.go8
-rw-r--r--pkg/api/handlers/compat/images_remove.go35
-rw-r--r--pkg/api/handlers/libpod/pods.go12
-rw-r--r--pkg/machine/config.go14
-rw-r--r--pkg/machine/ignition.go51
-rw-r--r--pkg/machine/qemu/machine.go61
-rw-r--r--pkg/specgen/generate/kube/volume.go2
-rw-r--r--test/apiv2/40-pods.at6
-rw-r--r--test/e2e/play_kube_test.go1
25 files changed, 234 insertions, 126 deletions
diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go
index 7db927e55..da6d556b1 100644
--- a/cmd/podman/images/build.go
+++ b/cmd/podman/images/build.go
@@ -8,7 +8,6 @@ import (
"strings"
"time"
- "github.com/containers/buildah"
"github.com/containers/buildah/define"
buildahCLI "github.com/containers/buildah/pkg/cli"
"github.com/containers/buildah/pkg/parse"
@@ -159,11 +158,11 @@ func buildFlags(cmd *cobra.Command) {
flags.SetNormalizeFunc(buildahCLI.AliasFlags)
if registry.IsRemote() {
flag = flags.Lookup("isolation")
- buildOpts.Isolation = buildah.OCI
- if err := flag.Value.Set(buildah.OCI); err != nil {
- logrus.Errorf("unable to set --isolation to %v: %v", buildah.OCI, err)
+ buildOpts.Isolation = define.OCI
+ if err := flag.Value.Set(define.OCI); err != nil {
+ logrus.Errorf("unable to set --isolation to %v: %v", define.OCI, err)
}
- flag.DefValue = buildah.OCI
+ flag.DefValue = define.OCI
_ = flags.MarkHidden("disable-content-trust")
_ = flags.MarkHidden("cache-from")
_ = flags.MarkHidden("sign-by")
@@ -427,10 +426,10 @@ func buildFlagsWrapperToOptions(c *cobra.Command, contextDir string, flags *buil
format := ""
flags.Format = strings.ToLower(flags.Format)
switch {
- case strings.HasPrefix(flags.Format, buildah.OCI):
- format = buildah.OCIv1ImageManifest
- case strings.HasPrefix(flags.Format, buildah.DOCKER):
- format = buildah.Dockerv2ImageManifest
+ case strings.HasPrefix(flags.Format, define.OCI):
+ format = define.OCIv1ImageManifest
+ case strings.HasPrefix(flags.Format, define.DOCKER):
+ format = define.Dockerv2ImageManifest
default:
return nil, errors.Errorf("unrecognized image type %q", flags.Format)
}
diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index 900f67e2f..05474fd89 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -8,6 +8,7 @@ import (
"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/pkg/errors"
"github.com/spf13/cobra"
)
@@ -23,17 +24,8 @@ var (
}
)
-type InitCLIOptions struct {
- CPUS uint64
- Memory uint64
- Devices []string
- ImagePath string
- IgnitionPath string
- Name string
-}
-
var (
- initOpts = InitCLIOptions{}
+ initOpts = machine.InitOptions{}
defaultMachineName string = "podman-machine-default"
)
@@ -53,6 +45,15 @@ func init() {
)
_ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
+ diskSizeFlagName := "disk-size"
+ flags.Uint64Var(
+ &initOpts.DiskSize,
+ diskSizeFlagName, 10,
+ "Disk size in GB",
+ )
+
+ _ = initCmd.RegisterFlagCompletionFunc(diskSizeFlagName, completion.AutocompleteNone)
+
memoryFlagName := "memory"
flags.Uint64VarP(
&initOpts.Memory,
@@ -72,28 +73,24 @@ func init() {
// TODO should we allow for a users to append to the qemu cmdline?
func initMachine(cmd *cobra.Command, args []string) error {
- initOpts.Name = defaultMachineName
- if len(args) > 0 {
- initOpts.Name = args[0]
- }
- vmOpts := machine.InitOptions{
- CPUS: initOpts.CPUS,
- Memory: initOpts.Memory,
- IgnitionPath: initOpts.IgnitionPath,
- ImagePath: initOpts.ImagePath,
- Name: initOpts.Name,
- }
var (
vm machine.VM
vmType string
err error
)
+ initOpts.Name = defaultMachineName
+ if len(args) > 0 {
+ initOpts.Name = args[0]
+ }
switch vmType {
default: // qemu is the default
- vm, err = qemu.NewMachine(vmOpts)
+ if _, err := qemu.LoadVMByName(initOpts.Name); err == nil {
+ return errors.Wrap(machine.ErrVMAlreadyExists, initOpts.Name)
+ }
+ vm, err = qemu.NewMachine(initOpts)
}
if err != nil {
return err
}
- return vm.Init(vmOpts)
+ return vm.Init(initOpts)
}
diff --git a/cmd/podman/machine/remove.go b/cmd/podman/machine/rm.go
index f6ce9e326..cd2cc84f2 100644
--- a/cmd/podman/machine/remove.go
+++ b/cmd/podman/machine/rm.go
@@ -17,13 +17,13 @@ import (
)
var (
- removeCmd = &cobra.Command{
- Use: "remove [options] NAME",
+ rmCmd = &cobra.Command{
+ Use: "rm [options] [NAME]",
Short: "Remove an existing machine",
Long: "Remove an existing machine ",
- RunE: remove,
- Args: cobra.ExactArgs(1),
- Example: `podman machine remove myvm`,
+ RunE: rm,
+ Args: cobra.MaximumNArgs(1),
+ Example: `podman machine rm myvm`,
ValidArgsFunction: completion.AutocompleteNone,
}
)
@@ -35,13 +35,13 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
- Command: removeCmd,
+ Command: rmCmd,
Parent: machineCmd,
})
- flags := removeCmd.Flags()
+ flags := rmCmd.Flags()
formatFlagName := "force"
- flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before removeing")
+ flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before rming")
keysFlagName := "save-keys"
flags.BoolVar(&destoryOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys")
@@ -53,20 +53,24 @@ func init() {
flags.BoolVar(&destoryOptions.SaveImage, imageFlagName, false, "Do not delete the image file")
}
-func remove(cmd *cobra.Command, args []string) error {
+func rm(cmd *cobra.Command, args []string) error {
var (
err error
vm machine.VM
vmType string
)
+ vmName := defaultMachineName
+ if len(args) > 0 && len(args[0]) > 0 {
+ vmName = args[0]
+ }
switch vmType {
default:
- vm, err = qemu.LoadVMByName(args[0])
+ vm, err = qemu.LoadVMByName(vmName)
}
if err != nil {
return err
}
- confirmationMessage, doIt, err := vm.Remove(args[0], machine.RemoveOptions{})
+ confirmationMessage, remove, err := vm.Remove(vmName, machine.RemoveOptions{})
if err != nil {
return err
}
@@ -84,5 +88,5 @@ func remove(cmd *cobra.Command, args []string) error {
return nil
}
}
- return doIt()
+ return remove()
}
diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go
index a7111a195..879122a14 100644
--- a/cmd/podman/machine/ssh.go
+++ b/cmd/podman/machine/ssh.go
@@ -14,11 +14,11 @@ import (
var (
sshCmd = &cobra.Command{
- Use: "ssh [options] NAME [COMMAND [ARG ...]]",
+ Use: "ssh [options] [NAME] [COMMAND [ARG ...]]",
Short: "SSH into a virtual machine",
Long: "SSH into a virtual machine ",
RunE: ssh,
- Args: cobra.MinimumNArgs(1),
+ Args: cobra.MaximumNArgs(1),
Example: `podman machine ssh myvm
podman machine ssh -e myvm echo hello`,
@@ -48,6 +48,10 @@ func ssh(cmd *cobra.Command, args []string) error {
vm machine.VM
vmType string
)
+ vmName := defaultMachineName
+ if len(args) > 0 && len(args[0]) > 1 {
+ vmName = args[0]
+ }
sshOpts.Args = args[1:]
// Error if no execute but args given
@@ -61,10 +65,10 @@ func ssh(cmd *cobra.Command, args []string) error {
switch vmType {
default:
- vm, err = qemu.LoadVMByName(args[0])
+ vm, err = qemu.LoadVMByName(vmName)
}
if err != nil {
return errors.Wrapf(err, "vm %s not found", args[0])
}
- return vm.SSH(args[0], sshOpts)
+ return vm.SSH(vmName, sshOpts)
}
diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go
index 44ade2850..80fd77102 100644
--- a/cmd/podman/machine/start.go
+++ b/cmd/podman/machine/start.go
@@ -13,11 +13,11 @@ import (
var (
startCmd = &cobra.Command{
- Use: "start NAME",
+ Use: "start [NAME]",
Short: "Start an existing machine",
Long: "Start an existing machine ",
RunE: start,
- Args: cobra.ExactArgs(1),
+ Args: cobra.MaximumNArgs(1),
Example: `podman machine start myvm`,
ValidArgsFunction: completion.AutocompleteNone,
}
@@ -37,12 +37,16 @@ func start(cmd *cobra.Command, args []string) error {
vm machine.VM
vmType string
)
+ vmName := defaultMachineName
+ if len(args) > 0 && len(args[0]) > 0 {
+ vmName = args[0]
+ }
switch vmType {
default:
- vm, err = qemu.LoadVMByName(args[0])
+ vm, err = qemu.LoadVMByName(vmName)
}
if err != nil {
return err
}
- return vm.Start(args[0], machine.StartOptions{})
+ return vm.Start(vmName, machine.StartOptions{})
}
diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go
index 35fd4ff95..4fcb065a3 100644
--- a/cmd/podman/machine/stop.go
+++ b/cmd/podman/machine/stop.go
@@ -13,11 +13,11 @@ import (
var (
stopCmd = &cobra.Command{
- Use: "stop NAME",
+ Use: "stop [NAME]",
Short: "Stop an existing machine",
Long: "Stop an existing machine ",
RunE: stop,
- Args: cobra.ExactArgs(1),
+ Args: cobra.MaximumNArgs(1),
Example: `podman machine stop myvm`,
ValidArgsFunction: completion.AutocompleteNone,
}
@@ -38,12 +38,16 @@ func stop(cmd *cobra.Command, args []string) error {
vm machine.VM
vmType string
)
+ vmName := defaultMachineName
+ if len(args) > 0 && len(args[0]) > 0 {
+ vmName = args[0]
+ }
switch vmType {
default:
- vm, err = qemu.LoadVMByName(args[0])
+ vm, err = qemu.LoadVMByName(vmName)
}
if err != nil {
return err
}
- return vm.Stop(args[0], machine.StopOptions{})
+ return vm.Stop(vmName, machine.StopOptions{})
}
diff --git a/docs/source/machine.rst b/docs/source/machine.rst
index 55df29667..be9ef1e95 100644
--- a/docs/source/machine.rst
+++ b/docs/source/machine.rst
@@ -3,7 +3,7 @@ Machine
:doc:`init <markdown/podman-machine-init.1>` Initialize a new virtual machine
-:doc:`remove <markdown/podman-machine-remove.1>` Remove a virtual machine
+: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
:doc:`stop <markdown/podman-machine-stop.1>` Stop a virtual machine
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 5c53f8601..7a7e5cfff 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -821,7 +821,7 @@ for the case where some other process above Podman uses NOTIFY_SOCKET and Podman
#### **--seccomp-policy**=*policy*
-Specify the policy to select the seccomp profile. If set to *image*, Podman will look for a "io.podman.seccomp.profile" label in the container-image config and use its value as a seccomp profile. Otherwise, Podman will follow the *default* policy by applying the default profile unless specified otherwise via *--security-opt seccomp* as described below.
+Specify the policy to select the seccomp profile. If set to *image*, Podman will look for a "io.containers.seccomp.profile" label in the container-image config and use its value as a seccomp profile. Otherwise, Podman will follow the *default* policy by applying the default profile unless specified otherwise via *--security-opt seccomp* as described below.
Note that this feature is experimental and may change in the future.
diff --git a/docs/source/markdown/podman-machine-init.1.md b/docs/source/markdown/podman-machine-init.1.md
index 5ff07de03..be07a7bd5 100644
--- a/docs/source/markdown/podman-machine-init.1.md
+++ b/docs/source/markdown/podman-machine-init.1.md
@@ -22,6 +22,10 @@ tied to the Linux kernel.
Number of CPUs.
+#### **--disk-size**=*number*
+
+Size of the disk for the guest VM in GB.
+
#### **--ignition-path**
Fully qualified path of the ignition file
diff --git a/docs/source/markdown/podman-machine-remove.1.md b/docs/source/markdown/podman-machine-rm.1.md
index 07763741d..4da17fdcb 100644
--- a/docs/source/markdown/podman-machine-remove.1.md
+++ b/docs/source/markdown/podman-machine-rm.1.md
@@ -1,17 +1,17 @@
-% podman-machine-remove(1)
+% podman-machine-rm(1)
## NAME
-podman\-machine\-remove - Remove a virtual machine
+podman\-machine\-rm - Remove a virtual machine
## SYNOPSIS
-**podman machine remove** [*options*] *name*
+**podman machine rm** [*options*] [*name*]
## DESCRIPTION
Remove a virtual machine and its related files. What is actually deleted
depends on the virtual machine type. For all virtual machines, the generated
SSH keys and the podman system connection are deleted. The ignition files
-generated for that VM are also removeed as is its image file on the filesystem.
+generated for that VM are also removed as is its image file on the filesystem.
Users get a display of what will be deleted and are required to confirm unless the option `--force`
is used.
@@ -45,7 +45,7 @@ deleted.
Remove a VM named "test1"
```
-$ podman machine remove test1
+$ podman machine rm test1
The following files will be deleted:
diff --git a/docs/source/markdown/podman-machine-ssh.1.md b/docs/source/markdown/podman-machine-ssh.1.md
index bcecd1010..01cec1f57 100644
--- a/docs/source/markdown/podman-machine-ssh.1.md
+++ b/docs/source/markdown/podman-machine-ssh.1.md
@@ -4,7 +4,7 @@
podman\-machine\-ssh - SSH into a virtual machine
## SYNOPSIS
-**podman machine ssh** [*options*] *name* [*command* [*arg* ...]]
+**podman machine ssh** [*options*] [*name*] [*command* [*arg* ...]]
## DESCRIPTION
diff --git a/docs/source/markdown/podman-machine-start.1.md b/docs/source/markdown/podman-machine-start.1.md
index 511296b11..7f3a9f592 100644
--- a/docs/source/markdown/podman-machine-start.1.md
+++ b/docs/source/markdown/podman-machine-start.1.md
@@ -4,7 +4,7 @@
podman\-machine\-start - Start a virtual machine
## SYNOPSIS
-**podman machine start** *name*
+**podman machine start** [*name*]
## DESCRIPTION
diff --git a/docs/source/markdown/podman-machine-stop.1.md b/docs/source/markdown/podman-machine-stop.1.md
index 62439cbb1..f4be54511 100644
--- a/docs/source/markdown/podman-machine-stop.1.md
+++ b/docs/source/markdown/podman-machine-stop.1.md
@@ -4,7 +4,7 @@
podman\-machine\-stop - Stop a virtual machine
## SYNOPSIS
-**podman machine stop** *name*
+**podman machine stop** [*name*]
## DESCRIPTION
diff --git a/docs/source/markdown/podman-machine.1.md b/docs/source/markdown/podman-machine.1.md
index 0e3c1ca34..a5d3b78df 100644
--- a/docs/source/markdown/podman-machine.1.md
+++ b/docs/source/markdown/podman-machine.1.md
@@ -14,10 +14,10 @@ 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 |
-| remove | [podman-machine-remove(1)](podman-machine-remove.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 |
+| 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)
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index f61344099..adc0a5ff8 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -873,7 +873,7 @@ for the case where some other process above Podman uses NOTIFY_SOCKET and Podman
#### **--seccomp-policy**=*policy*
-Specify the policy to select the seccomp profile. If set to *image*, Podman will look for a "io.podman.seccomp.profile" label in the container-image config and use its value as a seccomp profile. Otherwise, Podman will follow the *default* policy by applying the default profile unless specified otherwise via *--security-opt seccomp* as described below.
+Specify the policy to select the seccomp profile. If set to *image*, Podman will look for a "io.containers.seccomp.profile" label in the container-image config and use its value as a seccomp profile. Otherwise, Podman will follow the *default* policy by applying the default profile unless specified otherwise via *--security-opt seccomp* as described below.
Note that this feature is experimental and may change in the future.
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 94c6c3840..a136fb72d 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -607,10 +607,16 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps()
if err != nil {
- return nil, err
+ if os.IsNotExist(err) {
+ // The kernel-provided files only exist if user namespaces are supported
+ logrus.Debugf("user or group ID mappings not available: %s", err)
+ } else {
+ return nil, err
+ }
+ } else {
+ g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
+ g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
}
- g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
- g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
// Hostname handling:
// If we have a UTS namespace, set Hostname in the OCI spec.
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 20331600d..36785a362 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -201,13 +201,9 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}
format := buildah.Dockerv2ImageManifest
registry := query.Registry
- isolation := buildah.IsolationChroot
- /*
- // FIXME, This is very broken. Buildah will only work with chroot
- isolation := buildah.IsolationDefault
- */
+ isolation := buildah.IsolationDefault
if utils.IsLibpodRequest(r) {
- // isolation = parseLibPodIsolation(query.Isolation)
+ isolation = parseLibPodIsolation(query.Isolation)
registry = ""
format = query.OutputFormat
} else {
diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go
index 874c57f16..e89558a86 100644
--- a/pkg/api/handlers/compat/images_remove.go
+++ b/pkg/api/handlers/compat/images_remove.go
@@ -4,7 +4,10 @@ import (
"net/http"
"github.com/containers/podman/v3/libpod"
+ "github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
@@ -30,28 +33,32 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
}
}
name := utils.GetName(r)
- newImage, err := runtime.ImageRuntime().NewFromLocal(name)
- if err != nil {
- utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
- return
+ imageEngine := abi.ImageEngine{Libpod: runtime}
+
+ options := entities.ImageRemoveOptions{
+ Force: query.Force,
}
+ report, rmerrors := imageEngine.Remove(r.Context(), []string{name}, options)
+ if len(rmerrors) > 0 && rmerrors[0] != nil {
+ err := rmerrors[0]
+ if errors.Cause(err) == define.ErrNoSuchImage {
+ utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
+ return
+ }
- results, err := runtime.RemoveImage(r.Context(), newImage, query.Force)
- if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
return
}
-
- response := make([]map[string]string, 0, len(results.Untagged)+1)
- deleted := make(map[string]string, 1)
- deleted["Deleted"] = results.Deleted
- response = append(response, deleted)
-
- for _, u := range results.Untagged {
+ response := make([]map[string]string, 0, len(report.Untagged)+1)
+ for _, d := range report.Deleted {
+ deleted := make(map[string]string, 1)
+ deleted["Deleted"] = d
+ response = append(response, deleted)
+ }
+ for _, u := range report.Untagged {
untagged := make(map[string]string, 1)
untagged["Untagged"] = u
response = append(response, untagged)
}
-
utils.WriteResponse(w, http.StatusOK, response)
}
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 89a4a451f..4dc8740e2 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -44,13 +44,9 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
func Pods(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- query := struct {
- Filters map[string][]string `schema:"filters"`
- }{
- // override any golang type defaults
- }
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+
+ filterMap, err := util.PrepareFilters(r)
+ if err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
@@ -58,7 +54,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
containerEngine := abi.ContainerEngine{Libpod: runtime}
podPSOptions := entities.PodPSOptions{
- Filters: query.Filters,
+ Filters: *filterMap,
}
pods, err := containerEngine.PodPs(r.Context(), podPSOptions)
if err != nil {
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index 4933deee8..273deca00 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -7,19 +7,19 @@ import (
"path/filepath"
"github.com/containers/storage/pkg/homedir"
+ "github.com/pkg/errors"
)
type InitOptions struct {
- Name string
CPUS uint64
- Memory uint64
+ DiskSize uint64
IgnitionPath string
ImagePath string
- Username string
- URI url.URL
IsDefault bool
- //KernelPath string
- //Devices []VMDevices
+ Memory uint64
+ Name string
+ URI url.URL
+ Username string
}
type RemoteConnectionType string
@@ -27,6 +27,8 @@ type RemoteConnectionType string
var (
SSHRemoteConnection RemoteConnectionType = "ssh"
DefaultIgnitionUserName = "core"
+ ErrNoSuchVM = errors.New("VM does not exist")
+ ErrVMAlreadyExists = errors.New("VM already exists")
)
type Download struct {
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index ff79d5afb..a68d68ac3 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -2,6 +2,7 @@ package machine
import (
"encoding/json"
+ "fmt"
"io/ioutil"
)
@@ -37,10 +38,17 @@ func getNodeGrp(grpName string) NodeGroup {
return NodeGroup{Name: &grpName}
}
+type DynamicIgnition struct {
+ Name string
+ Key string
+ VMName string
+ WritePath string
+}
+
// NewIgnitionFile
-func NewIgnitionFile(name, key, writePath string) error {
- if len(name) < 1 {
- name = DefaultIgnitionUserName
+func NewIgnitionFile(ign DynamicIgnition) error {
+ if len(ign.Name) < 1 {
+ ign.Name = DefaultIgnitionUserName
}
ignVersion := Ignition{
Version: "3.2.0",
@@ -48,23 +56,44 @@ func NewIgnitionFile(name, key, writePath string) error {
ignPassword := Passwd{
Users: []PasswdUser{{
- Name: name,
- SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(key)},
+ Name: ign.Name,
+ SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
}},
}
ignStorage := Storage{
- Directories: getDirs(name),
- Files: getFiles(name),
- Links: getLinks(name),
+ Directories: getDirs(ign.Name),
+ Files: getFiles(ign.Name),
+ Links: getLinks(ign.Name),
}
+
+ // ready is a unit file that sets up the virtual serial device
+ // where when the VM is done configuring, it will send an ack
+ // so a listening host knows it can being interacting with it
+ ready := `[Unit]
+Requires=dev-virtio\\x2dports-%s.device
+OnFailure=emergency.target
+OnFailureJobMode=isolate
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/bin/sh -c '/usr/bin/echo Ready >/dev/%s'
+[Install]
+RequiredBy=multi-user.target
+`
+ _ = ready
ignSystemd := Systemd{
Units: []Unit{
{
Enabled: boolToPtr(true),
Name: "podman.socket",
- }}}
-
+ },
+ {
+ Enabled: boolToPtr(true),
+ Name: "ready.service",
+ Contents: strToPtr(fmt.Sprintf(ready, "vport1p1", "vport1p1")),
+ },
+ }}
ignConfig := Config{
Ignition: ignVersion,
Passwd: ignPassword,
@@ -75,7 +104,7 @@ func NewIgnitionFile(name, key, writePath string) error {
if err != nil {
return err
}
- return ioutil.WriteFile(writePath, b, 0644)
+ return ioutil.WriteFile(ign.WritePath, b, 0644)
}
func getDirs(usrName string) []Directory {
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index b97eb991a..fe155750f 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -1,9 +1,11 @@
package qemu
import (
+ "bufio"
"encoding/json"
"fmt"
"io/ioutil"
+ "net"
"os"
"os/exec"
"path/filepath"
@@ -22,9 +24,6 @@ import (
var (
// vmtype refers to qemu (vs libvirt, krun, etc)
vmtype = "qemu"
- // qemuCommon are the common command line arguments between the arches
- //qemuCommon = []string{"-cpu", "host", "-qmp", "unix://tmp/qmp.sock,server,nowait"}
- //qemuCommon = []string{"-cpu", "host", "-qmp", "tcp:localhost:4444,server,nowait"}
)
// NewMachine initializes an instance of a virtual machine based on the qemu
@@ -89,6 +88,16 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
// Add network
cmd = append(cmd, "-nic", "user,model=virtio,hostfwd=tcp::"+strconv.Itoa(vm.Port)+"-:22")
+ socketPath, err := getSocketDir()
+ if err != nil {
+ return nil, err
+ }
+ virtualSocketPath := filepath.Join(socketPath, "podman", vm.Name+"_ready.sock")
+ // Add serial port for readiness
+ cmd = append(cmd, []string{
+ "-device", "virtio-serial",
+ "-chardev", "socket,path=" + virtualSocketPath + ",server,nowait,id=" + vm.Name + "_ready",
+ "-device", "virtserialport,chardev=" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0"}...)
vm.CmdLine = cmd
return vm, nil
}
@@ -96,13 +105,15 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
// LoadByName reads a json file that describes a known qemu vm
// and returns a vm instance
func LoadVMByName(name string) (machine.VM, error) {
- // TODO need to define an error relating to ErrMachineNotFound
vm := new(MachineVM)
vmConfigDir, err := machine.GetConfDir(vmtype)
if err != nil {
return nil, err
}
b, err := ioutil.ReadFile(filepath.Join(vmConfigDir, name+".json"))
+ if os.IsNotExist(err) {
+ return nil, errors.Wrap(machine.ErrNoSuchVM, name)
+ }
if err != nil {
return nil, err
}
@@ -159,14 +170,28 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
if err := v.prepare(); err != nil {
return err
}
+
+ // Resize the disk image to input disk size
+ resize := exec.Command("qemu-img", []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
+ if err := resize.Run(); err != nil {
+ return errors.Errorf("error resizing image: %q", err)
+ }
// Write the ignition file
- return machine.NewIgnitionFile(opts.Username, key, v.IgnitionFilePath)
+ ign := machine.DynamicIgnition{
+ Name: opts.Username,
+ Key: key,
+ VMName: v.Name,
+ WritePath: v.IgnitionFilePath,
+ }
+ return machine.NewIgnitionFile(ign)
}
// Start executes the qemu command line and forks it
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
var (
- err error
+ conn net.Conn
+ err error
+ wait time.Duration = time.Millisecond * 500
)
attr := new(os.ProcAttr)
files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
@@ -181,6 +206,30 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
}
_, err = os.StartProcess(v.CmdLine[0], cmd, attr)
+ if err != nil {
+ return err
+ }
+ fmt.Println("Waiting for VM ...")
+ socketPath, err := getSocketDir()
+ if err != nil {
+ return err
+ }
+
+ // The socket is not made until the qemu process is running so here
+ // we do a backoff waiting for it. Once we have a conn, we break and
+ // then wait to read it.
+ for i := 0; i < 6; i++ {
+ conn, err = net.Dial("unix", filepath.Join(socketPath, "podman", v.Name+"_ready.sock"))
+ if err == nil {
+ break
+ }
+ time.Sleep(wait)
+ wait++
+ }
+ if err != nil {
+ return err
+ }
+ _, err = bufio.NewReader(conn).ReadString('\n')
return err
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index e4f3eb196..a8042b532 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -116,7 +116,7 @@ func InitializeVolumes(specVolumes []v1.Volume) (map[string]*KubeVolume, error)
for _, specVolume := range specVolumes {
volume, err := VolumeFromSource(specVolume.VolumeSource)
if err != nil {
- return nil, err
+ return nil, errors.Wrapf(err, "failed to create volume %q", specVolume.Name)
}
volumes[specVolume.Name] = volume
diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at
index f3272c41e..94c72dbaa 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -116,6 +116,12 @@ t GET libpod/pods/foo/top?ps_args=args,pid 200 \
.Titles[0]="COMMAND" \
.Titles[1]="PID" \
+#api list pods sanity checks
+t GET libpod/pods/json?filters='garb1age}' 400 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET libpod/pods/json?filters='{"label":["testl' 400 \
+ .cause="unexpected end of JSON input"
+
# FIXME: I'm not sure what 'prune' is supposed to do; as of 20200224 it
# just returns 200 (ok) with empty result list.
#t POST libpod/pods/prune 200 # FIXME: 2020-02-24 returns 200 {}
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index cc4450379..a4c738f17 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -1449,6 +1449,7 @@ spec:
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).NotTo(Equal(0))
+ Expect(kube.ErrorToString()).To(ContainSubstring(defaultVolName))
})
It("podman play kube test with empty HostPath type volume", func() {