Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 53 additions & 14 deletions cmd/climc/shell/compute/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"path"
"strings"

"github.com/ghodss/yaml"
Expand All @@ -31,6 +32,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
options "yunion.io/x/onecloud/pkg/mcclient/options/compute"
"yunion.io/x/onecloud/pkg/util/fileutils2"
"yunion.io/x/onecloud/pkg/util/pod/stream/cp"
)

Expand Down Expand Up @@ -137,38 +139,43 @@ func init() {
return nil
})

R(new(options.ContainerCopyOptions), "container-cp", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyOptions) error {
parts := strings.Split(opts.CONTAINER_ID_FILE, ":")
copyToContainer := func(s *mcclient.ClientSession, src, dst string, rawFile bool) error {
parts := strings.Split(dst, ":")
if len(parts) != 2 {
return fmt.Errorf("invalid container id: %s", opts.CONTAINER_ID_FILE)
return fmt.Errorf("invalid container id: %s", dst)
}
if opts.RawFile {
fr, err := os.Open(opts.SRC_FILE)
if rawFile {
if fileutils2.IsDir(src) {
return fmt.Errorf("source path cannot be a directory when raw file is true: %s", src)
}
fr, err := os.Open(src)
if err != nil {
return errors.Wrapf(err, "open file: %v", opts.SRC_FILE)
return errors.Wrapf(err, "open file: %v", src)
}
defer fr.Close()
if err := modules.Containers.CopyTo(s, parts[0], parts[1], fr); err != nil {
return errors.Wrapf(err, "copy file to container")
}
return nil
} else {
return cp.NewCopy().CopyToContainer(s, opts.SRC_FILE, cp.ContainerFileOpt{
return cp.NewCopy().CopyToContainer(s, src, cp.ContainerFileOpt{
ContainerId: parts[0],
File: parts[1],
})
}
})

R(new(options.ContainerCopyOptions), "container-cp-from", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyOptions) error {
parts := strings.Split(opts.SRC_FILE, ":")
}
copyFromContainer := func(s *mcclient.ClientSession, src, dst string, rawFile bool) error {
parts := strings.Split(src, ":")
if len(parts) != 2 {
return fmt.Errorf("invalid container id: %s", opts.CONTAINER_ID_FILE)
return fmt.Errorf("invalid container id: %s", src)
}
ctrId := parts[0]
ctrFile := parts[1]
destFile := opts.CONTAINER_ID_FILE
if opts.RawFile {
destFile := dst
if fileutils2.IsDir(destFile) {
destFile = path.Join(destFile, path.Base(ctrFile))
}
if rawFile {
fw, err := os.Create(destFile)
if err != nil {
return errors.Wrapf(err, "open file: %v", destFile)
Expand All @@ -184,5 +191,37 @@ func init() {
File: ctrFile,
}, destFile)
}
}

R(new(options.ContainerCopyOptions), "container-cp", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyOptions) error {
if strings.Contains(opts.SRC, ":") && !strings.Contains(opts.DST, ":") {
// copy from container to host
err := copyFromContainer(s, opts.SRC, opts.DST, opts.RawFile)
if err != nil {
return errors.Wrapf(err, "copy from container to host")
}
return nil
} else if !strings.Contains(opts.SRC, ":") && strings.Contains(opts.DST, ":") {
// copy from host to container
err := copyToContainer(s, opts.SRC, opts.DST, opts.RawFile)
if err != nil {
return errors.Wrapf(err, "copy to container")
}
return nil
} else if strings.Contains(opts.SRC, ":") && strings.Contains(opts.DST, ":") {
// copy from container to container
return fmt.Errorf("copy from container to container is not supported")
} else {
return fmt.Errorf("copy between local files is not supported")
}

})

R(new(options.ContainerCopyFromOptions), "container-cp-from", "Container copy", func(s *mcclient.ClientSession, opts *options.ContainerCopyFromOptions) error {
err := copyFromContainer(s, opts.CONTAINER_ID_PATH, opts.DST_PATH, opts.RawFile)
if err != nil {
return errors.Wrapf(err, "copy from container to host")
}
return nil
})
}
2 changes: 1 addition & 1 deletion pkg/mcclient/modules/compute/mod_containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var (
func init() {
Containers = ContainerManager{
modules.NewComputeManager("container", "containers",
[]string{"ID", "Name", "Guest_ID", "Status", "Started_At", "Last_Finished_At", "Restart_Count", "Spec"},
[]string{"ID", "Name", "Guest_ID", "Status", "Started_At", "Last_Finished_At", "Restart_Count"},
[]string{}),
}
modules.RegisterCompute(&Containers)
Expand Down
18 changes: 12 additions & 6 deletions pkg/mcclient/options/compute/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type ContainerCreateCommonOptions struct {
WorkingDir string `help:"Current working directory of the command" json:"working_dir"`
Env []string `help:"List of environment variable to set in the container and the format is: <key>=<value>"`
RootFs string `help:"Root filesystem of the container, e.g.: disk_index=<disk_number>,disk_id=<disk_id>"`
VolumeMount []string `help:"Volume mount of the container and the format is: name=<val>,mount=<container_path>,readonly=<true_or_false>,case_insensitive_paths=p1,p2,disk_index=<disk_number>,disk_id=<disk_id>"`
VolumeMount []string `help:"Volume mount of the container and the format is: name=<val>,mount_path=<container_path>,readonly=<true_or_false>,case_insensitive_paths=p1,p2,disk_index=<disk_number>,disk_id=<disk_id>"`
Device []string `help:"Host device: <host_path>:<container_path>:<permissions>, e.g.: /dev/snd:/dev/snd:rwm"`
Privileged bool `help:"Privileged mode"`
Caps string `help:"Container capabilities, e.g.: SETPCAP,AUDIT_WRITE,SYS_CHROOT,CHOWN,DAC_OVERRIDE,FOWNER,SETGID,SETUID,SYSLOG,SYS_ADMIN,WAKE_ALARM,SYS_PTRACE,BLOCK_SUSPEND,MKNOD,KILL,SYS_RESOURCE,NET_RAW,NET_ADMIN,NET_BIND_SERVICE,SYS_NICE"`
Expand Down Expand Up @@ -240,7 +240,7 @@ func parseContainerVolumeMount(vmStr string) (*apis.ContainerVolumeMount, error)
}
gId64 := int64(gId)
vm.FsGroup = &gId64
case "mount_path":
case "mount_path", "mount":
vm.MountPath = val
case "host_path":
if vm.HostPath == nil {
Expand Down Expand Up @@ -473,7 +473,7 @@ func (o *ContainerLogOptions) ToAPIInput() (*computeapi.PodLogOptions, error) {
if len(o.Since) > 0 {
dur, err := time.ParseDuration(o.Since)
if err != nil {
return nil, errors.Wrapf(err, "parse duration %s", o.Since)
return nil, errors.Wrapf(err, "invalid time duration: %s, shoud like 300ms, 1.5h or 2h45m", o.Since)
}
sec := int64(dur.Round(time.Second).Seconds())
opt.SinceSeconds = &sec
Expand Down Expand Up @@ -569,7 +569,13 @@ func (o *ContainerRemoveVolumeMountPostOverlayOptions) Params() (jsonutils.JSONO
}

type ContainerCopyOptions struct {
SRC_FILE string
CONTAINER_ID_FILE string
RawFile bool
SRC string `help:"Local path or file name, or cotnainer:path, e.g. /etc/hots or ctr-0:/etc/hosts"`
DST string `help:"Local path or file name, or cotnainer:path, e.g. /etc/hots or ctr-0:/etc/hosts"`
RawFile bool `help:"copy the file as raw data, if false, requires tar in executive path in container and host"`
}

type ContainerCopyFromOptions struct {
CONTAINER_ID_PATH string `help:"container id and the file path in the container, separated by ':', e.g. ctr-0:/etc/hosts"`
DST_PATH string `help:"Local destination path or file name"`
RawFile bool `help:"copy the file as raw data, if false, requires tar in executive path in container and host"`
}
10 changes: 5 additions & 5 deletions pkg/mcclient/options/compute/server_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import (
)

type PodCreateOptions struct {
NAME string `help:"Name of server pod" json:"-"`
ServerCreateCommonConfig
MEM string `help:"Memory size MB" metavar:"MEM" json:"-"`
VcpuCount int `help:"#CPU cores of VM server, default 1" default:"1" metavar:"<SERVER_CPU_COUNT>" json:"vcpu_count" token:"ncpu"`
AllowDelete *bool `help:"Unlock server to allow deleting" json:"-"`
NAME string `help:"Name of server pod" json:"-"`
ServerCreateCommonConfig `"disk->nargs":"*"`
MEM string `help:"Memory size MB" metavar:"MEM" json:"-"`
VcpuCount int `help:"#CPU cores of VM server, default 1" default:"1" metavar:"<SERVER_CPU_COUNT>" json:"vcpu_count" token:"ncpu"`
AllowDelete *bool `help:"Unlock server to allow deleting" json:"-"`
//PortMapping []string `help:"Port mapping of the pod and the format is: host_port=8080,port=80,protocol=<tcp|udp>,host_port_range=<int>-<int>" short-token:"p"`
Arch string `help:"image arch" choices:"aarch64|x86_64"`
AutoStart bool `help:"Auto start server after it is created"`
Expand Down
Loading