github.com/containers/podman/v4@v4.9.4/pkg/machine/e2e/init_test.go (about) 1 package e2e_test 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/containers/podman/v4/pkg/machine" 12 "github.com/containers/podman/v4/utils" 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gexec" 16 "github.com/sirupsen/logrus" 17 ) 18 19 var _ = Describe("podman machine init", func() { 20 var ( 21 mb *machineTestBuilder 22 testDir string 23 ) 24 25 BeforeEach(func() { 26 testDir, mb = setup() 27 }) 28 AfterEach(func() { 29 teardown(originalHomeDir, testDir, mb) 30 }) 31 32 cpus := runtime.NumCPU() / 2 33 if cpus == 0 { 34 cpus = 1 35 } 36 37 It("bad init name", func() { 38 i := initMachine{} 39 reallyLongName := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 40 session, err := mb.setName(reallyLongName).setCmd(&i).run() 41 Expect(err).ToNot(HaveOccurred()) 42 Expect(session).To(Exit(125)) 43 44 reservedName := initMachine{} 45 reservedNameSession, err := mb.setName(testProvider.VMType().String()).setCmd(&reservedName).run() 46 Expect(err).ToNot(HaveOccurred()) 47 Expect(reservedNameSession).To(Exit(125)) 48 Expect(reservedNameSession.errorToString()).To(ContainSubstring(fmt.Sprintf("cannot use %q", testProvider.VMType().String()))) 49 50 badName := "foobar" 51 bm := basicMachine{} 52 sysConn, err := mb.setCmd(bm.withPodmanCommand([]string{"system", "connection", "add", badName, "tcp://localhost:8000"})).run() 53 Expect(err).ToNot(HaveOccurred()) 54 defer func() { 55 if _, rmErr := mb.setCmd(bm.withPodmanCommand([]string{"system", "connection", "rm", badName})).run(); rmErr != nil { 56 logrus.Error(rmErr) 57 } 58 }() 59 Expect(sysConn).To(Exit(0)) 60 61 bi := new(initMachine) 62 want := fmt.Sprintf("system connection \"%s\" already exists", badName) 63 badInit, berr := mb.setName(badName).setCmd(bi.withImagePath(mb.imagePath)).run() 64 Expect(berr).ToNot(HaveOccurred()) 65 Expect(badInit).To(Exit(125)) 66 Expect(badInit.errorToString()).To(ContainSubstring(want)) 67 68 }) 69 It("simple init", func() { 70 i := new(initMachine) 71 session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() 72 Expect(err).ToNot(HaveOccurred()) 73 Expect(session).To(Exit(0)) 74 75 inspectBefore, ec, err := mb.toQemuInspectInfo() 76 Expect(err).ToNot(HaveOccurred()) 77 Expect(ec).To(BeZero()) 78 Expect(inspectBefore).ToNot(BeEmpty()) 79 80 testMachine := inspectBefore[0] 81 Expect(testMachine.Name).To(Equal(mb.names[0])) 82 if testProvider.VMType() == machine.WSLVirt { // WSL hardware specs are hardcoded 83 Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus))) 84 Expect(testMachine.Resources.Memory).To(Equal(uint64(2048))) 85 } 86 }) 87 88 It("simple init with start", func() { 89 i := initMachine{} 90 session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() 91 Expect(err).ToNot(HaveOccurred()) 92 Expect(session).To(Exit(0)) 93 94 inspectBefore, ec, err := mb.toQemuInspectInfo() 95 Expect(ec).To(BeZero()) 96 Expect(inspectBefore).ToNot(BeEmpty()) 97 Expect(err).ToNot(HaveOccurred()) 98 Expect(inspectBefore).ToNot(BeEmpty()) 99 Expect(inspectBefore[0].Name).To(Equal(mb.names[0])) 100 101 s := startMachine{} 102 ssession, err := mb.setCmd(s).setTimeout(time.Minute * 10).run() 103 Expect(err).ToNot(HaveOccurred()) 104 Expect(ssession).Should(Exit(0)) 105 106 inspectAfter, ec, err := mb.toQemuInspectInfo() 107 Expect(err).ToNot(HaveOccurred()) 108 Expect(ec).To(BeZero()) 109 Expect(inspectBefore).ToNot(BeEmpty()) 110 Expect(inspectAfter).ToNot(BeEmpty()) 111 Expect(inspectAfter[0].State).To(Equal(machine.Running)) 112 113 if isWSL() { // WSL does not use FCOS 114 return 115 } 116 117 // check to see that zincati is masked 118 sshDisk := sshMachine{} 119 zincati, err := mb.setCmd(sshDisk.withSSHCommand([]string{"sudo", "systemctl", "is-enabled", "zincati"})).run() 120 Expect(err).ToNot(HaveOccurred()) 121 Expect(zincati.outputToString()).To(ContainSubstring("disabled")) 122 }) 123 124 It("simple init with username", func() { 125 i := new(initMachine) 126 remoteUsername := "remoteuser" 127 session, err := mb.setCmd(i.withImagePath(mb.imagePath).withUsername(remoteUsername)).run() 128 Expect(err).ToNot(HaveOccurred()) 129 Expect(session).To(Exit(0)) 130 131 inspectBefore, ec, err := mb.toQemuInspectInfo() 132 Expect(err).ToNot(HaveOccurred()) 133 Expect(ec).To(BeZero()) 134 135 Expect(inspectBefore).ToNot(BeEmpty()) 136 testMachine := inspectBefore[0] 137 Expect(testMachine.Name).To(Equal(mb.names[0])) 138 if testProvider.VMType() != machine.WSLVirt { // memory and cpus something we cannot set with WSL 139 Expect(testMachine.Resources.CPUs).To(Equal(uint64(cpus))) 140 Expect(testMachine.Resources.Memory).To(Equal(uint64(2048))) 141 } 142 Expect(testMachine.SSHConfig.RemoteUsername).To(Equal(remoteUsername)) 143 144 }) 145 146 It("machine init with cpus, disk size, memory, timezone", func() { 147 skipIfWSL("setting hardware resource numbers and timezone are not supported on WSL") 148 name := randomString() 149 i := new(initMachine) 150 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withCPUs(2).withDiskSize(102).withMemory(4096).withTimezone("Pacific/Honolulu")).run() 151 Expect(err).ToNot(HaveOccurred()) 152 Expect(session).To(Exit(0)) 153 154 s := new(startMachine) 155 startSession, err := mb.setCmd(s).run() 156 Expect(err).ToNot(HaveOccurred()) 157 Expect(startSession).To(Exit(0)) 158 159 sshCPU := sshMachine{} 160 CPUsession, err := mb.setName(name).setCmd(sshCPU.withSSHCommand([]string{"lscpu", "|", "grep", "\"CPU(s):\"", "|", "head", "-1"})).run() 161 Expect(err).ToNot(HaveOccurred()) 162 Expect(CPUsession).To(Exit(0)) 163 Expect(CPUsession.outputToString()).To(ContainSubstring("2")) 164 165 sshDisk := sshMachine{} 166 diskSession, err := mb.setName(name).setCmd(sshDisk.withSSHCommand([]string{"sudo", "fdisk", "-l", "|", "grep", "Disk"})).run() 167 Expect(err).ToNot(HaveOccurred()) 168 Expect(diskSession).To(Exit(0)) 169 Expect(diskSession.outputToString()).To(ContainSubstring("102 GiB")) 170 171 sshMemory := sshMachine{} 172 memorySession, err := mb.setName(name).setCmd(sshMemory.withSSHCommand([]string{"cat", "/proc/meminfo", "|", "grep", "-i", "'memtotal'", "|", "grep", "-o", "'[[:digit:]]*'"})).run() 173 Expect(err).ToNot(HaveOccurred()) 174 Expect(memorySession).To(Exit(0)) 175 foundMemory, err := strconv.Atoi(memorySession.outputToString()) 176 Expect(err).ToNot(HaveOccurred()) 177 Expect(foundMemory).To(BeNumerically(">", 3800000)) 178 Expect(foundMemory).To(BeNumerically("<", 4200000)) 179 180 sshTimezone := sshMachine{} 181 timezoneSession, err := mb.setName(name).setCmd(sshTimezone.withSSHCommand([]string{"date"})).run() 182 Expect(err).ToNot(HaveOccurred()) 183 Expect(timezoneSession).To(Exit(0)) 184 Expect(timezoneSession.outputToString()).To(ContainSubstring("HST")) 185 }) 186 187 It("machine init with volume", func() { 188 if testProvider.VMType() == machine.HyperVVirt { 189 Skip("volumes are not supported on hyperv yet") 190 } 191 skipIfWSL("WSL volumes are much different. This test will not pass as is") 192 193 tmpDir, err := os.MkdirTemp("", "") 194 Expect(err).ToNot(HaveOccurred()) 195 _, err = os.CreateTemp(tmpDir, "example") 196 Expect(err).ToNot(HaveOccurred()) 197 mount := tmpDir + ":/testmountdir" 198 defer func() { _ = utils.GuardedRemoveAll(tmpDir) }() 199 200 name := randomString() 201 i := new(initMachine) 202 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withVolume(mount).withNow()).run() 203 Expect(err).ToNot(HaveOccurred()) 204 Expect(session).To(Exit(0)) 205 206 ssh := sshMachine{} 207 sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"ls /testmountdir"})).run() 208 Expect(err).ToNot(HaveOccurred()) 209 Expect(sshSession).To(Exit(0)) 210 Expect(sshSession.outputToString()).To(ContainSubstring("example")) 211 }) 212 213 It("machine init rootless docker.sock check", func() { 214 i := initMachine{} 215 name := randomString() 216 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() 217 Expect(err).ToNot(HaveOccurred()) 218 Expect(session).To(Exit(0)) 219 220 s := startMachine{} 221 ssession, err := mb.setCmd(s).setTimeout(time.Minute * 10).run() 222 Expect(err).ToNot(HaveOccurred()) 223 Expect(ssession).Should(Exit(0)) 224 225 ssh2 := sshMachine{} 226 sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHCommand([]string{"readlink /var/run/docker.sock"})).run() 227 Expect(err).ToNot(HaveOccurred()) 228 Expect(sshSession2).To(Exit(0)) 229 230 output := strings.TrimSpace(sshSession2.outputToString()) 231 Expect(output).To(HavePrefix("/run/user")) 232 Expect(output).To(HaveSuffix("/podman/podman.sock")) 233 234 }) 235 236 It("machine init rootful with docker.sock check", func() { 237 i := initMachine{} 238 name := randomString() 239 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withRootful(true)).run() 240 Expect(err).ToNot(HaveOccurred()) 241 Expect(session).To(Exit(0)) 242 243 s := startMachine{} 244 ssession, err := mb.setCmd(s).setTimeout(time.Minute * 10).run() 245 Expect(err).ToNot(HaveOccurred()) 246 Expect(ssession).Should(Exit(0)) 247 248 inspect := new(inspectMachine) 249 inspect = inspect.withFormat("{{.Rootful}}") 250 inspectSession, err := mb.setName(name).setCmd(inspect).run() 251 Expect(err).ToNot(HaveOccurred()) 252 Expect(inspectSession).To(Exit(0)) 253 Expect(inspectSession.outputToString()).To(Equal("true")) 254 255 ssh2 := sshMachine{} 256 sshSession2, err := mb.setName(name).setCmd(ssh2.withSSHCommand([]string{"readlink /var/run/docker.sock"})).run() 257 Expect(err).ToNot(HaveOccurred()) 258 Expect(sshSession2).To(Exit(0)) 259 output := strings.TrimSpace(sshSession2.outputToString()) 260 Expect(output).To(Equal("/run/podman/podman.sock")) 261 }) 262 263 It("init with user mode networking", func() { 264 if testProvider.VMType() != machine.WSLVirt { 265 Skip("test is only supported by WSL") 266 } 267 i := new(initMachine) 268 name := randomString() 269 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withUserModeNetworking(true)).run() 270 Expect(err).ToNot(HaveOccurred()) 271 Expect(session).To(Exit(0)) 272 273 inspect := new(inspectMachine) 274 inspect = inspect.withFormat("{{.UserModeNetworking}}") 275 inspectSession, err := mb.setName(name).setCmd(inspect).run() 276 Expect(err).ToNot(HaveOccurred()) 277 Expect(inspectSession).To(Exit(0)) 278 Expect(inspectSession.outputToString()).To(Equal("true")) 279 }) 280 281 It("init should cleanup on failure", func() { 282 i := new(initMachine) 283 name := randomString() 284 session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() 285 286 Expect(err).ToNot(HaveOccurred()) 287 Expect(session).To(Exit(0)) 288 289 inspect := new(inspectMachine) 290 inspect = inspect.withFormat("{{.ConfigPath.Path}}") 291 inspectSession, err := mb.setCmd(inspect).run() 292 Expect(err).ToNot(HaveOccurred()) 293 cfgpth := inspectSession.outputToString() 294 295 inspect = inspect.withFormat("{{.Image.IgnitionFile.Path}}") 296 inspectSession, err = mb.setCmd(inspect).run() 297 Expect(err).ToNot(HaveOccurred()) 298 ign := inspectSession.outputToString() 299 300 inspect = inspect.withFormat("{{.Image.ImagePath.Path}}") 301 inspectSession, err = mb.setCmd(inspect).run() 302 Expect(err).ToNot(HaveOccurred()) 303 img := inspectSession.outputToString() 304 305 rm := rmMachine{} 306 removeSession, err := mb.setCmd(rm.withForce().withSaveKeys()).run() 307 Expect(err).ToNot(HaveOccurred()) 308 Expect(removeSession).To(Exit(0)) 309 310 // Inspecting a non-existent machine should fail 311 // which means it is gone 312 _, ec, err := mb.toQemuInspectInfo() 313 Expect(err).ToNot(HaveOccurred()) 314 Expect(ec).To(Equal(125)) 315 316 // Clashing keys - init fails 317 i = new(initMachine) 318 session, err = mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run() 319 Expect(err).ToNot(HaveOccurred()) 320 Expect(session).To(Exit(125)) 321 322 // ensure files created by init are cleaned up on init failure 323 _, err = os.Stat(img) 324 Expect(err).To(HaveOccurred()) 325 _, err = os.Stat(cfgpth) 326 Expect(err).To(HaveOccurred()) 327 328 // WSL does not use ignition 329 if testProvider.VMType() != machine.WSLVirt { 330 _, err = os.Stat(ign) 331 Expect(err).To(HaveOccurred()) 332 } 333 }) 334 })