github.com/containers/podman/v4@v4.9.4/pkg/machine/applehv/config.go (about) 1 //go:build darwin 2 // +build darwin 3 4 package applehv 5 6 import ( 7 "errors" 8 "fmt" 9 "io/fs" 10 "path/filepath" 11 "time" 12 13 "github.com/containers/podman/v4/pkg/machine" 14 "github.com/containers/podman/v4/pkg/machine/compression" 15 "github.com/containers/podman/v4/pkg/machine/define" 16 vfConfig "github.com/crc-org/vfkit/pkg/config" 17 "github.com/docker/go-units" 18 "golang.org/x/sys/unix" 19 ) 20 21 const ( 22 localhostURI = "http://localhost" 23 ignitionSocketName = "ignition.sock" 24 ) 25 26 type AppleHVVirtualization struct { 27 machine.Virtualization 28 } 29 30 type MMHardwareConfig struct { 31 CPUs uint16 32 DiskPath string 33 DiskSize uint64 34 Memory int32 35 } 36 37 func VirtualizationProvider() machine.VirtProvider { 38 return &AppleHVVirtualization{ 39 machine.NewVirtualization(define.AppleHV, compression.Xz, define.Raw, vmtype), 40 } 41 } 42 43 func (v AppleHVVirtualization) CheckExclusiveActiveVM() (bool, string, error) { 44 fsVms, err := getVMInfos() 45 if err != nil { 46 return false, "", err 47 } 48 for _, vm := range fsVms { 49 if vm.Running || vm.Starting { 50 return true, vm.Name, nil 51 } 52 } 53 54 return false, "", nil 55 } 56 57 func (v AppleHVVirtualization) IsValidVMName(name string) (bool, error) { 58 configDir, err := machine.GetConfDir(machine.AppleHvVirt) 59 if err != nil { 60 return false, err 61 } 62 fqName := filepath.Join(configDir, fmt.Sprintf("%s.json", name)) 63 if _, err := loadMacMachineFromJSON(fqName); err != nil { 64 return false, err 65 } 66 return true, nil 67 } 68 69 func (v AppleHVVirtualization) List(opts machine.ListOptions) ([]*machine.ListResponse, error) { 70 var ( 71 response []*machine.ListResponse 72 ) 73 74 mms, err := v.loadFromLocalJson() 75 if err != nil { 76 return nil, err 77 } 78 79 for _, mm := range mms { 80 vmState, err := mm.Vfkit.state() 81 if err != nil { 82 if errors.Is(err, unix.ECONNREFUSED) { 83 vmState = machine.Stopped 84 } else { 85 return nil, err 86 } 87 } 88 89 mlr := machine.ListResponse{ 90 Name: mm.Name, 91 CreatedAt: mm.Created, 92 LastUp: mm.LastUp, 93 Running: vmState == machine.Running, 94 Starting: vmState == machine.Starting, 95 Stream: mm.ImageStream, 96 VMType: machine.AppleHvVirt.String(), 97 CPUs: mm.CPUs, 98 Memory: mm.Memory * units.MiB, 99 DiskSize: mm.DiskSize * units.GiB, 100 Port: mm.Port, 101 RemoteUsername: mm.RemoteUsername, 102 IdentityPath: mm.IdentityPath, 103 } 104 response = append(response, &mlr) 105 } 106 return response, nil 107 } 108 109 func (v AppleHVVirtualization) LoadVMByName(name string) (machine.VM, error) { 110 m := MacMachine{Name: name} 111 return m.loadFromFile() 112 } 113 114 func (v AppleHVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM, error) { 115 m := MacMachine{Name: opts.Name} 116 117 if len(opts.USBs) > 0 { 118 return nil, fmt.Errorf("USB host passtrough not supported for applehv machines") 119 } 120 121 configDir, err := machine.GetConfDir(machine.AppleHvVirt) 122 if err != nil { 123 return nil, err 124 } 125 126 configPath, err := define.NewMachineFile(getVMConfigPath(configDir, opts.Name), nil) 127 if err != nil { 128 return nil, err 129 } 130 m.ConfigPath = *configPath 131 132 dataDir, err := machine.GetDataDir(machine.AppleHvVirt) 133 if err != nil { 134 return nil, err 135 } 136 137 if err := machine.SetIgnitionFile(&m.IgnitionFile, vmtype, m.Name); err != nil { 138 return nil, err 139 } 140 141 // Set creation time 142 m.Created = time.Now() 143 144 m.ResourceConfig = machine.ResourceConfig{ 145 CPUs: opts.CPUS, 146 DiskSize: opts.DiskSize, 147 // Diskpath will be needed 148 Memory: opts.Memory, 149 } 150 bl := vfConfig.NewEFIBootloader(fmt.Sprintf("%s/%ss", dataDir, opts.Name), true) 151 m.Vfkit.VirtualMachine = vfConfig.NewVirtualMachine(uint(opts.CPUS), opts.Memory, bl) 152 153 if err := m.writeConfig(); err != nil { 154 return nil, err 155 } 156 return m.loadFromFile() 157 } 158 159 func (v AppleHVVirtualization) RemoveAndCleanMachines() error { 160 // This can be implemented when host networking is completed. 161 return machine.ErrNotImplemented 162 } 163 164 func (v AppleHVVirtualization) VMType() machine.VMType { 165 return vmtype 166 } 167 168 func (v AppleHVVirtualization) loadFromLocalJson() ([]*MacMachine, error) { 169 var ( 170 jsonFiles []string 171 mms []*MacMachine 172 ) 173 configDir, err := machine.GetConfDir(v.VMType()) 174 if err != nil { 175 return nil, err 176 } 177 if err := filepath.WalkDir(configDir, func(input string, d fs.DirEntry, e error) error { 178 if e != nil { 179 return e 180 } 181 if filepath.Ext(d.Name()) == ".json" { 182 jsonFiles = append(jsonFiles, input) 183 } 184 return nil 185 }); err != nil { 186 return nil, err 187 } 188 189 for _, jsonFile := range jsonFiles { 190 mm, err := loadMacMachineFromJSON(jsonFile) 191 if err != nil { 192 return nil, err 193 } 194 if err != nil { 195 return nil, err 196 } 197 mms = append(mms, mm) 198 } 199 return mms, nil 200 }