Skip to content

Commit a4a2af6

Browse files
Port forwarding test between apps connected to different network instances (#576)
* Port forwarding between apps connected to different network instances - Qemu Signed-off-by: gkodali-zededa <[email protected]> * Port forwarding with apps connected to different network instnaces - VBox Signed-off-by: GopiKrishna Kodali <[email protected]> * Add runtime OS knob to eden test parsing Signed-off-by: GopiKrishna Kodali <[email protected]> * Clean up some hard coding Signed-off-by: GopiKrishna Kodali <[email protected]> * Reintroduce some deleted checks Signed-off-by: GopiKrishna Kodali <[email protected]> * spilt pkg/eden.go into hypervisor specific files Signed-off-by: GopiKrishna Kodali <[email protected]> * Only allow port map testing with Qemu and Virtual Box Signed-off-by: GopiKrishna Kodali <[email protected]>
1 parent 95bf500 commit a4a2af6

File tree

19 files changed

+601
-317
lines changed

19 files changed

+601
-317
lines changed

cmd/edenNetwork.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
var (
1616
networkType string
1717
networkName string
18+
uplinkAdapter string
1819
)
1920

2021
var networkCmd = &cobra.Command{
@@ -125,7 +126,7 @@ var networkCreateCmd = &cobra.Command{
125126
log.Fatalf("getControllerAndDev: %s", err)
126127
}
127128
var opts []expect.ExpectationOption
128-
opts = append(opts, expect.AddNetInstanceAndPortPublish(subnet, networkType, networkName, nil))
129+
opts = append(opts, expect.AddNetInstanceAndPortPublish(subnet, networkType, networkName, nil, uplinkAdapter))
129130
expectation := expect.AppExpectationFromURL(ctrl, dev, defaults.DefaultDummyExpect, podName, opts...)
130131
netInstancesConfigs := expectation.NetworkInstances()
131132
mainloop:
@@ -151,4 +152,5 @@ func networkInit() {
151152
networkCmd.AddCommand(networkCreateCmd)
152153
networkCreateCmd.Flags().StringVar(&networkType, "type", "local", "Type of network: local or switch")
153154
networkCreateCmd.Flags().StringVarP(&networkName, "name", "n", "", "Name of network (empty for auto generation)")
155+
networkCreateCmd.Flags().StringVarP(&uplinkAdapter, "uplink", "u", "eth0", "Name of uplink adapter")
154156
}

cmd/edenStart.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package cmd
33
import (
44
"fmt"
55
"github.com/lf-edge/eden/pkg/eden"
6+
"github.com/lf-edge/eden/pkg/eve"
7+
"net"
68
"os"
79
"path/filepath"
810
"runtime"
@@ -107,7 +109,7 @@ var startCmd = &cobra.Command{
107109
log.Infof("EVE is starting in Parallels")
108110
}
109111
} else if devModel == defaults.DefaultVBoxModel {
110-
if err := eden.StartEVEVBox(vmName, eveImageFile, cpus, mem, hostFwd); err != nil {
112+
if err := eden.StartEVEVBox(vmName, eveImageFile, cpus, mem, hostFwd, getUplinkPortIPMap()); err != nil {
111113
log.Errorf("cannot start eve: %s", err)
112114
} else {
113115
log.Infof("EVE is starting in Virtual Box")
@@ -122,6 +124,30 @@ var startCmd = &cobra.Command{
122124
},
123125
}
124126

127+
func getUplinkPortIPMap() map[string]net.IP {
128+
ipMap := make(map[string]net.IP)
129+
changer := &adamChanger{}
130+
ctrl, dev, err := changer.getControllerAndDev()
131+
if err != nil {
132+
log.Debugf("getControllerAndDev: %s", err)
133+
fmt.Printf("%s EVE status: undefined (no onboarded EVE)\n", statusWarn())
134+
} else {
135+
eveState := eve.Init(ctrl, dev)
136+
if err = ctrl.InfoLastCallback(dev.GetID(), nil, eveState.InfoCallback()); err != nil {
137+
log.Fatalf("Fail in get InfoLastCallback: %s", err)
138+
}
139+
if err = ctrl.MetricLastCallback(dev.GetID(), nil, eveState.MetricCallback()); err != nil {
140+
log.Fatalf("Fail in get InfoLastCallback: %s", err)
141+
}
142+
if lastDInfo := eveState.InfoAndMetrics().GetDinfo(); lastDInfo != nil {
143+
for _, nw := range lastDInfo.Network {
144+
ipMap[nw.DevName] = net.ParseIP(nw.IPAddrs[0])
145+
}
146+
}
147+
}
148+
return ipMap
149+
}
150+
125151
func startInit() {
126152
currentPath, err := os.Getwd()
127153
if err != nil {

cmd/eve.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ var startEveCmd = &cobra.Command{
7171
}
7272

7373
if devModel == defaults.DefaultVBoxModel {
74-
if err := eden.StartEVEVBox(vmName, eveImageFile, cpus, mem, hostFwd); err != nil {
74+
if err := eden.StartEVEVBox(vmName, eveImageFile, cpus, mem, hostFwd, getUplinkPortIPMap()); err != nil {
7575
log.Errorf("cannot start eve: %s", err)
7676
} else {
7777
log.Infof("EVE is starting in Virtual Box")

pkg/defaults/defaults.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ const (
121121

122122
DefaultVBoxModel = "VBox"
123123

124+
DefaultVBoxSubnet = "10.0.2.0/24"
125+
126+
DefaultPortMapOffset = 10
127+
124128
DefaultParallelsModel = "parallels"
125129

126130
DefaultGeneralModel = "general"

pkg/eden/eden.go

Lines changed: 0 additions & 286 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package eden
22

33
import (
4-
"bufio"
54
"bytes"
65
"crypto/tls"
76
"encoding/json"
@@ -360,291 +359,6 @@ func StatusEServer() (status string, err error) {
360359
return state, nil
361360
}
362361

363-
//StartEVEVBox function run EVE in VirtualBox
364-
func StartEVEVBox(vmName, eveImageFile string, cpus int, mem int, hostFwd map[string]string) (err error) {
365-
poweroff := false
366-
if out, _, err := utils.RunCommandAndWait("VBoxManage", strings.Fields(fmt.Sprintf("showvminfo %s --machinereadable", vmName))...); err != nil {
367-
log.Info("No VMs with eve_live name", err)
368-
commandArgsString := fmt.Sprintf("createvm --name %s --register", vmName)
369-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
370-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
371-
}
372-
commandArgsString = fmt.Sprintf("modifyvm %s --cpus %d --memory %d --vram 16 --nested-hw-virt on --ostype Ubuntu_64 --mouse usbtablet --graphicscontroller vmsvga --boot1 disk --boot2 net", vmName, cpus, mem)
373-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
374-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
375-
}
376-
377-
commandArgsString = fmt.Sprintf("storagectl %s --name \"SATA\" --add sata --bootable on --hostiocache on", vmName)
378-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
379-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
380-
}
381-
382-
commandArgsString = fmt.Sprintf("storageattach %s --storagectl \"SATA\" --port 0 --device 0 --type hdd --medium %s", vmName, eveImageFile)
383-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
384-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
385-
}
386-
387-
commandArgsString = fmt.Sprintf("modifyvm %s --nic1 nat --cableconnected1 on", vmName)
388-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
389-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
390-
}
391-
392-
for k, v := range hostFwd {
393-
commandArgsString = fmt.Sprintf("modifyvm %s --nic1 nat --cableconnected1 on --natpf1 ,tcp,,%s,,%s", vmName, k, v)
394-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
395-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
396-
}
397-
}
398-
399-
commandArgsString = fmt.Sprintf("startvm %s", vmName)
400-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
401-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
402-
}
403-
} else {
404-
scanner := bufio.NewScanner(bytes.NewReader([]byte(out)))
405-
for scanner.Scan() {
406-
line := strings.TrimSpace(scanner.Text())
407-
if strings.Contains(line, "VMState=\"poweroff\"") {
408-
poweroff = true
409-
continue
410-
}
411-
if !strings.HasPrefix(line, "Forwarding") {
412-
continue
413-
}
414-
if i := strings.IndexRune(line, '='); i != -1 {
415-
line = line[i+1:]
416-
}
417-
if s, err := strconv.Unquote(line); err == nil {
418-
line = s
419-
}
420-
// forwarding rule is in format "tcp_2222_22,tcp,,2222,,22", where
421-
v := strings.Split(line, ",")
422-
commandArgsString := fmt.Sprintf("modifyvm %s --natpf1 delete %s", vmName, v[0])
423-
if !poweroff {
424-
commandArgsString = fmt.Sprintf("controlvm %s natpf1 delete %s", vmName, v[0])
425-
}
426-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
427-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
428-
}
429-
}
430-
431-
for k, v := range hostFwd {
432-
commandArgsString := fmt.Sprintf("modifyvm %s --nic1 nat --cableconnected1 on --natpf1 ,tcp,,%s,,%s", vmName, k, v)
433-
if !poweroff {
434-
commandArgsString = fmt.Sprintf("controlvm %s nic1 nat natpf1 ,tcp,,%s,,%s", vmName, k, v)
435-
}
436-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
437-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
438-
}
439-
}
440-
if poweroff {
441-
commandArgsString := fmt.Sprintf("startvm %s", vmName)
442-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
443-
log.Fatalf("VBoxManage error for command %s %s", commandArgsString, err)
444-
}
445-
}
446-
}
447-
448-
return err
449-
}
450-
451-
//StartEVEQemu function run EVE in qemu
452-
func StartEVEQemu(qemuARCH, qemuOS, eveImageFile, qemuSMBIOSSerial string, eveTelnetPort int, qemuHostFwd map[string]string, qemuAccel bool, qemuConfigFile, logFile string, pidFile string, foregroud bool) (err error) {
453-
qemuCommand := ""
454-
qemuOptions := "-display none -nodefaults -no-user-config "
455-
qemuOptions += fmt.Sprintf("-serial chardev:char0 -chardev socket,id=char0,port=%d,host=localhost,server,nodelay,nowait,telnet,logfile=%s ", eveTelnetPort, logFile)
456-
if qemuSMBIOSSerial != "" {
457-
qemuOptions += fmt.Sprintf("-smbios type=1,serial=%s ", qemuSMBIOSSerial)
458-
}
459-
nets, err := utils.GetSubnetsNotUsed(2)
460-
if err != nil {
461-
return fmt.Errorf("StartEVEQemu: %s", err)
462-
}
463-
for ind, n := range nets {
464-
qemuOptions += fmt.Sprintf("-netdev user,id=eth%d,net=%s,dhcpstart=%s", ind, n.Subnet, n.FirstAddress)
465-
if ind == 0 {
466-
for k, v := range qemuHostFwd {
467-
qemuOptions += fmt.Sprintf(",hostfwd=tcp::%s-:%s", k, v)
468-
}
469-
}
470-
qemuOptions += fmt.Sprintf(" -device virtio-net-pci,netdev=eth%d ", ind)
471-
}
472-
if qemuOS == "" {
473-
qemuOS = runtime.GOOS
474-
} else {
475-
qemuOS = strings.ToLower(qemuOS)
476-
}
477-
if qemuOS != "linux" && qemuOS != "darwin" {
478-
return fmt.Errorf("StartEVEQemu: OS not supported: %s", qemuOS)
479-
}
480-
if qemuARCH == "" {
481-
qemuARCH = runtime.GOARCH
482-
} else {
483-
qemuARCH = strings.ToLower(qemuARCH)
484-
}
485-
switch qemuARCH {
486-
case "amd64":
487-
qemuCommand = "qemu-system-x86_64"
488-
if qemuAccel {
489-
if qemuOS == "darwin" {
490-
qemuOptions += defaults.DefaultQemuAccelDarwin
491-
} else {
492-
qemuOptions += defaults.DefaultQemuAccelLinuxAmd64
493-
}
494-
} else {
495-
qemuOptions += "--cpu SandyBridge "
496-
}
497-
case "arm64":
498-
qemuCommand = "qemu-system-aarch64"
499-
if qemuAccel {
500-
qemuOptions += defaults.DefaultQemuAccelLinuxArm64
501-
}
502-
default:
503-
return fmt.Errorf("StartEVEQemu: Arch not supported: %s", qemuARCH)
504-
}
505-
qemuOptions += fmt.Sprintf("-drive file=%s,format=qcow2 ", eveImageFile)
506-
if qemuConfigFile != "" {
507-
qemuOptions += fmt.Sprintf("-readconfig %s ", qemuConfigFile)
508-
}
509-
log.Infof("Start EVE: %s %s", qemuCommand, qemuOptions)
510-
if foregroud {
511-
if err := utils.RunCommandForeground(qemuCommand, strings.Fields(qemuOptions)...); err != nil {
512-
return fmt.Errorf("StartEVEQemu: %s", err)
513-
}
514-
} else {
515-
log.Infof("With pid: %s ; log: %s", pidFile, logFile)
516-
if err := utils.RunCommandNohup(qemuCommand, logFile, pidFile, strings.Fields(qemuOptions)...); err != nil {
517-
return fmt.Errorf("StartEVEQemu: %s", err)
518-
}
519-
}
520-
return nil
521-
}
522-
523-
//StopEVEQemu function stop EVE
524-
func StopEVEQemu(pidFile string) (err error) {
525-
return utils.StopCommandWithPid(pidFile)
526-
}
527-
528-
//StopEVEVBox function stop EVE in VirtualBox
529-
func StopEVEVBox(vmName string) (err error) {
530-
commandArgsString := fmt.Sprintf("controlvm %s poweroff", vmName)
531-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
532-
log.Errorf("VBoxManage error for command %s %s", commandArgsString, err)
533-
} else {
534-
for i := 0; i < 5; i++ {
535-
time.Sleep(defaults.DefaultRepeatTimeout)
536-
status, err := StatusEVEVBox(vmName)
537-
if err != nil {
538-
return err
539-
}
540-
if strings.Contains(status, "poweroff") {
541-
return nil
542-
}
543-
}
544-
}
545-
return err
546-
}
547-
548-
//DeleteEVEVBox function removes EVE from VirtualBox
549-
func DeleteEVEVBox(vmName string) (err error) {
550-
commandArgsString := fmt.Sprintf("unregistervm %s --delete", vmName)
551-
if err = utils.RunCommandWithLogAndWait("VBoxManage", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
552-
log.Errorf("VBoxManage error for command %s %s", commandArgsString, err)
553-
}
554-
return err
555-
}
556-
557-
//DeleteEVEParallels function removes EVE from parallels
558-
func DeleteEVEParallels(vmName string) (err error) {
559-
commandArgsString := fmt.Sprintf("delete %s", vmName)
560-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
561-
log.Errorf("prlctl error for command %s %s", commandArgsString, err)
562-
}
563-
return err
564-
}
565-
566-
//StatusEVEQemu function get status of EVE
567-
func StatusEVEQemu(pidFile string) (status string, err error) {
568-
return utils.StatusCommandWithPid(pidFile)
569-
}
570-
571-
//StartEVEParallels function run EVE in parallels
572-
func StartEVEParallels(vmName, eveImageFile string, parallelsCpus int, parallelsMem int, hostFwd map[string]string) (err error) {
573-
status, err := StatusEVEParallels(vmName)
574-
if err != nil {
575-
log.Fatal(err)
576-
}
577-
if strings.Contains(status, "running") {
578-
return nil
579-
}
580-
_ = StopEVEParallels(vmName)
581-
582-
commandArgsString := fmt.Sprintf("create %s --distribution ubuntu --no-hdd", vmName)
583-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
584-
log.Fatalf("prlctl error for command %s %s", commandArgsString, err)
585-
}
586-
commandArgsString = fmt.Sprintf("set %s --device-del net0 --cpus %d --memsize %d --nested-virt on --adaptive-hypervisor on --hypervisor-type parallels", vmName, parallelsCpus, parallelsMem)
587-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
588-
log.Fatalf("prlctl error for command %s %s", commandArgsString, err)
589-
}
590-
dirForParallels := strings.TrimRight(eveImageFile, filepath.Ext(eveImageFile))
591-
commandArgsString = fmt.Sprintf("set %s --device-add hdd --image %s", vmName, dirForParallels)
592-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
593-
log.Fatalf("prlctl error for command %s %s", commandArgsString, err)
594-
}
595-
commandArgsString = fmt.Sprintf("set %s --device-add net --type shared --adapter-type virtio --ipadd 192.168.1.0/24 --dhcp yes", vmName)
596-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
597-
log.Fatalf("prlctl error for command %s %s", commandArgsString, err)
598-
}
599-
commandArgsString = fmt.Sprintf("set %s --device-add net --type shared --adapter-type virtio --ipadd 192.168.2.0/24 --dhcp yes", vmName)
600-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
601-
log.Fatalf("prlctl error for command %s %s", commandArgsString, err)
602-
}
603-
for k, v := range hostFwd {
604-
commandArgsString = fmt.Sprintf("net set Shared --nat-tcp-add %s_%s,%s,%s,%s", k, v, k, vmName, v)
605-
if err = utils.RunCommandWithLogAndWait("prlsrvctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
606-
log.Fatalf("prlsrvctl error for command %s %s", commandArgsString, err)
607-
}
608-
}
609-
commandArgsString = fmt.Sprintf("start %s", vmName)
610-
return utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...)
611-
}
612-
613-
//StopEVEParallels function stop EVE and delete parallels VM
614-
func StopEVEParallels(vmName string) (err error) {
615-
commandArgsString := fmt.Sprintf("stop %s --kill", vmName)
616-
if err = utils.RunCommandWithLogAndWait("prlctl", defaults.DefaultLogLevelToPrint, strings.Fields(commandArgsString)...); err != nil {
617-
log.Errorf("prlctl error for command %s %s", commandArgsString, err)
618-
}
619-
return DeleteEVEParallels(vmName)
620-
}
621-
622-
//StatusEVEVBox function get status of EVE
623-
func StatusEVEVBox(vmName string) (status string, err error) {
624-
out, _, err := utils.RunCommandAndWait("VBoxManage", strings.Fields(fmt.Sprintf("showvminfo %s --machinereadable", vmName))...)
625-
if err != nil {
626-
return "", err
627-
}
628-
scanner := bufio.NewScanner(bytes.NewReader([]byte(out)))
629-
for scanner.Scan() {
630-
line := strings.TrimSpace(scanner.Text())
631-
if strings.Contains(line, "VMState=") {
632-
return strings.Split(line, "\"")[1], nil
633-
}
634-
}
635-
return "process doesn''t exist", nil
636-
}
637-
638-
//StatusEVEParallels function get status of EVE
639-
func StatusEVEParallels(vmName string) (status string, err error) {
640-
commandArgsString := fmt.Sprintf("status %s", vmName)
641-
statusEVE, _, err := utils.RunCommandAndWait("prlctl", strings.Fields(commandArgsString)...)
642-
if err != nil {
643-
return "process doesn''t exist", nil
644-
}
645-
statusEVE = strings.TrimLeft(statusEVE, fmt.Sprintf("VM %s exist ", vmName))
646-
return statusEVE, nil
647-
}
648362

649363
//GenerateEveCerts function generates certs for EVE
650364
func GenerateEveCerts(certsDir, domain, ip, eveIP, uuid, devModel, ssid, password string) (err error) {

0 commit comments

Comments
 (0)