Skip to content

Commit

Permalink
Merge pull request containers#13674 from baude/refactor1
Browse files Browse the repository at this point in the history
Machine refactor - part 1
  • Loading branch information
openshift-merge-robot authored Mar 28, 2022
2 parents b76d717 + 2ac897a commit 9cfa969
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 13 deletions.
8 changes: 7 additions & 1 deletion cmd/podman/machine/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ var (
now bool
)

// maxMachineNameSize is set to thirty to limit huge machine names primarily
// because macos has a much smaller file size limit.
const maxMachineNameSize = 30

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: initCmd,
Expand Down Expand Up @@ -111,10 +115,12 @@ func initMachine(cmd *cobra.Command, args []string) error {
vm machine.VM
err error
)

provider := getSystemDefaultProvider()
initOpts.Name = defaultMachineName
if len(args) > 0 {
if len(args[0]) > maxMachineNameSize {
return errors.New("machine name must be 30 characters or less")
}
initOpts.Name = args[0]
}
if _, err := provider.LoadVMByName(initOpts.Name); err == nil {
Expand Down
3 changes: 2 additions & 1 deletion pkg/machine/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type InitOptions struct {
Username string
ReExec bool
Rootful bool
// The numberical userid of the user that called machine
// The numerical userid of the user that called machine
UID string
}

Expand Down Expand Up @@ -128,6 +128,7 @@ type DistributionDownload interface {
}

func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url.URL {
//TODO Should this function have input verification?
userInfo := url.User(userName)
uri := url.URL{
Scheme: "ssh",
Expand Down
71 changes: 71 additions & 0 deletions pkg/machine/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package machine

import (
"net"
"net/url"
"reflect"
"testing"
)

func TestRemoteConnectionType_MakeSSHURL(t *testing.T) {
var (
host = "foobar"
path = "/path/to/socket"
rc = "ssh"
username = "core"
)
type args struct {
host string
path string
port string
userName string
}
tests := []struct {
name string
rc RemoteConnectionType
args args
want url.URL
}{
{
name: "Good no port",
rc: "ssh",
args: args{
host: host,
path: path,
port: "",
userName: username,
},
want: url.URL{
Scheme: rc,
User: url.User(username),
Host: host,
Path: path,
ForceQuery: false,
},
},
{
name: "Good with port",
rc: "ssh",
args: args{
host: host,
path: path,
port: "222",
userName: username,
},
want: url.URL{
Scheme: rc,
User: url.User(username),
Host: net.JoinHostPort(host, "222"),
Path: path,
ForceQuery: false,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.rc.MakeSSHURL(tt.args.host, tt.args.path, tt.args.port, tt.args.userName); !reflect.DeepEqual(got, tt.want) { //nolint: scopelint
t.Errorf("MakeSSHURL() = %v, want %v", got, tt.want) //nolint: scopelint
}
})
}
}
122 changes: 120 additions & 2 deletions pkg/machine/qemu/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,28 @@
package qemu

import (
"errors"
"os"
"time"

"github.com/sirupsen/logrus"
)

const (
// FCOS streams
// Testing FCOS stream
Testing string = "testing"
// Next FCOS stream
Next string = "next"
// Stable FCOS stream
Stable string = "stable"
)

type Provider struct{}

type MachineVM struct {
// Deprecated: MachineVMV1 is being deprecated in favor a more flexible and informative
// structure
type MachineVMV1 struct {
// CPUs to be assigned to the VM
CPUs uint64
// The command line representation of the qemu command
Expand Down Expand Up @@ -42,6 +58,74 @@ type MachineVM struct {
UID int
}

type MachineVM struct {
// The command line representation of the qemu command
CmdLine []string
// HostUser contains info about host user
HostUser
// ImageConfig describes the bootable image
ImageConfig
// Mounts is the list of remote filesystems to mount
Mounts []Mount
// Name of VM
Name string
// PidFilePath is the where the PID file lives
PidFilePath MachineFile
// QMPMonitor is the qemu monitor object for sending commands
QMPMonitor Monitor
// ReadySocket tells host when vm is booted
ReadySocket MachineFile
// ResourceConfig is physical attrs of the VM
ResourceConfig
// SSHConfig for accessing the remote vm
SSHConfig
}

// ImageConfig describes the bootable image for the VM
type ImageConfig struct {
IgnitionFilePath string
// ImageStream is the update stream for the image
ImageStream string
// ImagePath is the fq path to
ImagePath string
}

// HostUser describes the host user
type HostUser struct {
// Whether this machine should run in a rootful or rootless manner
Rootful bool
// UID is the numerical id of the user that called machine
UID int
}

// SSHConfig contains remote access information for SSH
type SSHConfig struct {
// IdentityPath is the fq path to the ssh priv key
IdentityPath string
// SSH port for user networking
Port int
// RemoteUsername of the vm user
RemoteUsername string
}

// ResourceConfig describes physical attributes of the machine
type ResourceConfig struct {
// CPUs to be assigned to the VM
CPUs uint64
// Memory in megabytes assigned to the vm
Memory uint64
// Disk size in gigabytes assigned to the vm
DiskSize uint64
}

type MachineFile struct {
// Path is the fully qualified path to a file
Path string
// Symlink is a shortened version of Path by using
// a symlink
Symlink *string
}

type Mount struct {
Type string
Tag string
Expand All @@ -52,7 +136,7 @@ type Mount struct {

type Monitor struct {
// Address portion of the qmp monitor (/tmp/tmp.sock)
Address string
Address MachineFile
// Network portion of the qmp monitor (unix)
Network string
// Timeout in seconds for qmp monitor transactions
Expand All @@ -64,3 +148,37 @@ var (
// qmp monitor interactions.
defaultQMPTimeout time.Duration = 2 * time.Second
)

// GetPath returns the working path for a machinefile. it returns
// the symlink unless one does not exist
func (m *MachineFile) GetPath() string {
if m.Symlink == nil {
return m.Path
}
return *m.Symlink
}

// Delete removes the machinefile symlink (if it exists) and
// the actual path
func (m *MachineFile) Delete() error {
if m.Symlink != nil {
if err := os.Remove(*m.Symlink); err != nil {
logrus.Errorf("unable to remove symlink %q", *m.Symlink)
}
}
return os.Remove(m.Path)
}

// NewMachineFile is a constructor for MachineFile
func NewMachineFile(path string, symlink *string) (*MachineFile, error) {
if len(path) < 1 {
return nil, errors.New("invalid machine file path")
}
if symlink != nil && len(*symlink) < 1 {
return nil, errors.New("invalid symlink path")
}
return &MachineFile{
Path: path,
Symlink: symlink,
}, nil
}
103 changes: 103 additions & 0 deletions pkg/machine/qemu/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package qemu

import (
"reflect"
"testing"
)

func TestMachineFile_GetPath(t *testing.T) {
path := "/var/tmp/podman/my.sock"
sym := "/tmp/podman/my.sock"
type fields struct {
Path string
Symlink *string
}
tests := []struct {
name string
fields fields
want string
}{
{
name: "Original path",
fields: fields{path, nil},
want: path,
},
{
name: "Symlink over path",
fields: fields{
Path: path,
Symlink: &sym,
},
want: sym,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := &MachineFile{
Path: tt.fields.Path, //nolint: scopelint
Symlink: tt.fields.Symlink, //nolint: scopelint
}
if got := m.GetPath(); got != tt.want { //nolint: scopelint
t.Errorf("GetPath() = %v, want %v", got, tt.want) //nolint: scopelint
}
})
}
}

func TestNewMachineFile(t *testing.T) {
p := "/var/tmp/podman/my.sock"
sym := "/tmp/podman/my.sock"
empty := ""

m := MachineFile{
Path: p,
Symlink: nil,
}
type args struct {
path string
symlink *string
}
tests := []struct {
name string
args args
want *MachineFile
wantErr bool
}{
{
name: "Good",
args: args{path: p},
want: &m,
wantErr: false,
},
{
name: "Good with Symlink",
args: args{p, &sym},
want: &MachineFile{p, &sym},
wantErr: false,
},
{
name: "Bad path name",
args: args{empty, nil},
want: nil,
wantErr: true,
},
{
name: "Bad symlink name",
args: args{p, &empty},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := NewMachineFile(tt.args.path, tt.args.symlink) //nolint: scopelint
if (err != nil) != tt.wantErr { //nolint: scopelint
t.Errorf("NewMachineFile() error = %v, wantErr %v", err, tt.wantErr) //nolint: scopelint
return
}
if !reflect.DeepEqual(got, tt.want) { //nolint: scopelint
t.Errorf("NewMachineFile() got = %v, want %v", got, tt.want) //nolint: scopelint
}
})
}
}
Loading

0 comments on commit 9cfa969

Please sign in to comment.