mirror of
				https://github.com/linuxkit/linuxkit.git
				synced 2025-10-31 05:12:03 +00:00 
			
		
		
		
	Merge pull request #1438 from rneugeba/moby
Support multiple "run" backends for the CLI
This commit is contained in:
		| @@ -4,73 +4,42 @@ import ( | ||||
| 	"archive/tar" | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/moby/src/initrd" | ||||
| ) | ||||
|  | ||||
| func untarKernel(buf *bytes.Buffer, bzimageName, ktarName string) (*bytes.Buffer, *bytes.Buffer, error) { | ||||
| 	tr := tar.NewReader(buf) | ||||
|  | ||||
| 	var bzimage, ktar *bytes.Buffer | ||||
|  | ||||
| 	for { | ||||
| 		hdr, err := tr.Next() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			log.Fatalln(err) | ||||
| 		} | ||||
| 		switch hdr.Name { | ||||
| 		case bzimageName: | ||||
| 			bzimage = new(bytes.Buffer) | ||||
| 			_, err := io.Copy(bzimage, tr) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
| 		case ktarName: | ||||
| 			ktar = new(bytes.Buffer) | ||||
| 			_, err := io.Copy(bzimage, tr) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
| 		default: | ||||
| 			continue | ||||
| 		} | ||||
| // Process the build arguments and execute build | ||||
| func build(args []string) { | ||||
| 	buildCmd := flag.NewFlagSet("build", flag.ExitOnError) | ||||
| 	buildCmd.Usage = func() { | ||||
| 		fmt.Printf("USAGE: %s build [options] [file.yml]\n\n", os.Args[0]) | ||||
| 		fmt.Printf("'file.yml' defaults to 'moby.yml' if not specified.\n\n") | ||||
| 		fmt.Printf("Options:\n") | ||||
| 		buildCmd.PrintDefaults() | ||||
| 	} | ||||
| 	buildName := buildCmd.String("name", "", "Name to use for output files") | ||||
| 	buildPull := buildCmd.Bool("pull", false, "Always pull images") | ||||
|  | ||||
| 	if ktar == nil || bzimage == nil { | ||||
| 		return nil, nil, errors.New("did not find bzImage and kernel.tar in tarball") | ||||
| 	} | ||||
| 	buildCmd.Parse(args) | ||||
| 	remArgs := buildCmd.Args() | ||||
|  | ||||
| 	return bzimage, ktar, nil | ||||
| } | ||||
|  | ||||
| func containersInitrd(containers []*bytes.Buffer) (*bytes.Buffer, error) { | ||||
| 	w := new(bytes.Buffer) | ||||
| 	iw := initrd.NewWriter(w) | ||||
| 	defer iw.Close() | ||||
| 	for _, file := range containers { | ||||
| 		_, err := initrd.Copy(iw, file) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return w, nil | ||||
| } | ||||
|  | ||||
| func build(name string, pull bool, args []string) { | ||||
| 	conf := "moby.yml" | ||||
| 	if len(args) > 0 { | ||||
| 		conf = args[0] | ||||
| 	if len(remArgs) > 0 { | ||||
| 		conf = remArgs[0] | ||||
| 	} | ||||
|  | ||||
| 	buildInternal(*buildName, *buildPull, conf) | ||||
| } | ||||
|  | ||||
| // Perform the actual build process | ||||
| func buildInternal(name string, pull bool, conf string) { | ||||
| 	if name == "" { | ||||
| 		name = filepath.Base(conf) | ||||
| 		ext := filepath.Ext(conf) | ||||
| @@ -198,3 +167,55 @@ func build(name string, pull bool, args []string) { | ||||
| 		log.Fatalf("Error writing outputs: %v", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func untarKernel(buf *bytes.Buffer, bzimageName, ktarName string) (*bytes.Buffer, *bytes.Buffer, error) { | ||||
| 	tr := tar.NewReader(buf) | ||||
|  | ||||
| 	var bzimage, ktar *bytes.Buffer | ||||
|  | ||||
| 	for { | ||||
| 		hdr, err := tr.Next() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			log.Fatalln(err) | ||||
| 		} | ||||
| 		switch hdr.Name { | ||||
| 		case bzimageName: | ||||
| 			bzimage = new(bytes.Buffer) | ||||
| 			_, err := io.Copy(bzimage, tr) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
| 		case ktarName: | ||||
| 			ktar = new(bytes.Buffer) | ||||
| 			_, err := io.Copy(bzimage, tr) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
| 		default: | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if ktar == nil || bzimage == nil { | ||||
| 		return nil, nil, errors.New("did not find bzImage and kernel.tar in tarball") | ||||
| 	} | ||||
|  | ||||
| 	return bzimage, ktar, nil | ||||
| } | ||||
|  | ||||
| func containersInitrd(containers []*bytes.Buffer) (*bytes.Buffer, error) { | ||||
| 	w := new(bytes.Buffer) | ||||
| 	iw := initrd.NewWriter(w) | ||||
| 	defer iw.Close() | ||||
| 	for _, file := range containers { | ||||
| 		_, err := initrd.Copy(iw, file) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return w, nil | ||||
| } | ||||
|   | ||||
| @@ -40,33 +40,6 @@ func main() { | ||||
| 	flagQuiet := flag.Bool("q", false, "Quiet execution") | ||||
| 	flagVerbose := flag.Bool("v", false, "Verbose execution") | ||||
|  | ||||
| 	buildCmd := flag.NewFlagSet("build", flag.ExitOnError) | ||||
| 	buildCmd.Usage = func() { | ||||
| 		fmt.Printf("USAGE: %s build [options] [file.yml]\n\n", os.Args[0]) | ||||
| 		fmt.Printf("'file.yml' defaults to 'moby.yml' if not specified.\n\n") | ||||
| 		fmt.Printf("Options:\n") | ||||
| 		buildCmd.PrintDefaults() | ||||
| 	} | ||||
| 	buildName := buildCmd.String("name", "", "Name to use for output files") | ||||
| 	buildPull := buildCmd.Bool("pull", false, "Always pull images") | ||||
|  | ||||
| 	runCmd := flag.NewFlagSet("run", flag.ExitOnError) | ||||
| 	runCmd.Usage = func() { | ||||
| 		fmt.Printf("USAGE: %s run [options] [prefix]\n\n", os.Args[0]) | ||||
| 		fmt.Printf("'prefix' specifies the path to the VM image.\n") | ||||
| 		fmt.Printf("It defaults to './moby'.\n") | ||||
| 		fmt.Printf("\n") | ||||
| 		fmt.Printf("Options:\n") | ||||
| 		runCmd.PrintDefaults() | ||||
| 		fmt.Printf("\n") | ||||
| 		fmt.Printf("If 'data' is supplied or if 'background' is selected\n") | ||||
| 		fmt.Printf("some per VM state is kept in a sub-directory in the ~/.moby\n") | ||||
| 	} | ||||
| 	runCPUs := runCmd.Int("cpus", 1, "Number of CPUs") | ||||
| 	runMem := runCmd.Int("mem", 1024, "Amount of memory in MB") | ||||
| 	runDiskSz := runCmd.Int("disk-size", 0, "Size of Disk in MB") | ||||
| 	runDisk := runCmd.String("disk", "", "Path to disk image to used") | ||||
|  | ||||
| 	// Set up logging | ||||
| 	log.SetFormatter(new(infoFormatter)) | ||||
| 	log.SetLevel(log.InfoLevel) | ||||
| @@ -93,11 +66,9 @@ func main() { | ||||
|  | ||||
| 	switch args[0] { | ||||
| 	case "build": | ||||
| 		buildCmd.Parse(args[1:]) | ||||
| 		build(*buildName, *buildPull, buildCmd.Args()) | ||||
| 		build(args[1:]) | ||||
| 	case "run": | ||||
| 		runCmd.Parse(args[1:]) | ||||
| 		run(*runCPUs, *runMem, *runDiskSz, *runDisk, runCmd.Args()) | ||||
| 		run(args[1:]) | ||||
| 	case "help": | ||||
| 		flag.Usage() | ||||
| 	default: | ||||
|   | ||||
							
								
								
									
										45
									
								
								src/cmd/moby/run.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/cmd/moby/run.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"runtime" | ||||
|  | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| func runUsage() { | ||||
| 	fmt.Printf("USAGE: %s run [backend] [options] [prefix]\n\n", os.Args[0]) | ||||
|  | ||||
| 	fmt.Printf("'backend' specifies the run backend.\n") | ||||
| 	fmt.Printf("If not specified the platform specific default will be used\n") | ||||
| 	fmt.Printf("Supported backends are (default platform in brackets):\n") | ||||
| 	fmt.Printf("  hyperkit [macOS]\n") | ||||
| 	fmt.Printf("\n") | ||||
| 	fmt.Printf("'options' are the backend specific options.\n") | ||||
| 	fmt.Printf("See 'moby run [backend] --help' for details.\n\n") | ||||
| 	fmt.Printf("'prefix' specifies the path to the VM image.\n") | ||||
| 	fmt.Printf("It defaults to './moby'.\n") | ||||
| } | ||||
|  | ||||
| func run(args []string) { | ||||
| 	if len(args) < 1 { | ||||
| 		runUsage() | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	switch args[0] { | ||||
| 	case "help", "-h", "-help", "--help": | ||||
| 		runUsage() | ||||
| 		os.Exit(0) | ||||
| 	case "hyperkit": | ||||
| 		runHyperKit(args[1:]) | ||||
| 	default: | ||||
| 		switch runtime.GOOS { | ||||
| 		case "darwin": | ||||
| 			runHyperKit(args) | ||||
| 		default: | ||||
| 			log.Errorf("There currently is no default 'run' backend for your platform.") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| // +build darwin | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/user" | ||||
|  | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/hyperkit/go" | ||||
| ) | ||||
|  | ||||
| func run(cpus, mem, diskSz int, disk string, args []string) { | ||||
| 	prefix := "moby" | ||||
| 	if len(args) > 0 { | ||||
| 		prefix = args[0] | ||||
| 	} | ||||
|  | ||||
| 	cmdline, err := ioutil.ReadFile(prefix + "-cmdline") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Cannot open cmdline file: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if diskSz != 0 && disk == "" { | ||||
| 		disk = prefix + "-disk.img" | ||||
| 	} | ||||
|  | ||||
| 	h, err := hyperkit.New("", "", "auto", disk) | ||||
| 	if err != nil { | ||||
| 		log.Fatalln("Error creating hyperkit: ", err) | ||||
| 	} | ||||
|  | ||||
| 	h.Kernel = prefix + "-bzImage" | ||||
| 	h.Initrd = prefix + "-initrd.img" | ||||
| 	h.CPUs = cpus | ||||
| 	h.Memory = mem | ||||
| 	h.DiskSize = diskSz | ||||
|  | ||||
| 	err = h.Run(string(cmdline)) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Cannot run hyperkit: %v", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func getHome() string { | ||||
| 	if usr, err := user.Current(); err == nil { | ||||
| 		return usr.HomeDir | ||||
| 	} | ||||
| 	return os.Getenv("HOME") | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| // +build !darwin | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| func run(cpus, mem, diskSz int, userData string, args []string) { | ||||
| 	log.Fatalf("'run' is not supported yet on your OS") | ||||
| } | ||||
							
								
								
									
										65
									
								
								src/cmd/moby/run_hyperkit.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/cmd/moby/run_hyperkit.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
|  | ||||
| 	log "github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/hyperkit/go" | ||||
| ) | ||||
|  | ||||
| // Process the run arguments and execute run | ||||
| func runHyperKit(args []string) { | ||||
| 	hyperkitCmd := flag.NewFlagSet("hyperkit", flag.ExitOnError) | ||||
| 	hyperkitCmd.Usage = func() { | ||||
| 		fmt.Printf("USAGE: %s run hyperkit [options] [prefix]\n\n", os.Args[0]) | ||||
| 		fmt.Printf("'prefix' specifies the path to the VM image.\n") | ||||
| 		fmt.Printf("It defaults to './moby'.\n") | ||||
| 		fmt.Printf("\n") | ||||
| 		fmt.Printf("Options:\n") | ||||
| 		hyperkitCmd.PrintDefaults() | ||||
| 	} | ||||
| 	runCPUs := hyperkitCmd.Int("cpus", 1, "Number of CPUs") | ||||
| 	runMem := hyperkitCmd.Int("mem", 1024, "Amount of memory in MB") | ||||
| 	runDiskSz := hyperkitCmd.Int("disk-size", 0, "Size of Disk in MB") | ||||
| 	runDisk := hyperkitCmd.String("disk", "", "Path to disk image to used") | ||||
|  | ||||
| 	hyperkitCmd.Parse(args) | ||||
| 	remArgs := hyperkitCmd.Args() | ||||
|  | ||||
| 	prefix := "moby" | ||||
| 	if len(remArgs) > 0 { | ||||
| 		prefix = remArgs[0] | ||||
| 	} | ||||
|  | ||||
| 	runHyperKitInternal(*runCPUs, *runMem, *runDiskSz, *runDisk, prefix) | ||||
| } | ||||
|  | ||||
| func runHyperKitInternal(cpus, mem, diskSz int, disk, prefix string) { | ||||
| 	cmdline, err := ioutil.ReadFile(prefix + "-cmdline") | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Cannot open cmdline file: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	if diskSz != 0 && disk == "" { | ||||
| 		disk = prefix + "-disk.img" | ||||
| 	} | ||||
|  | ||||
| 	h, err := hyperkit.New("", "", "auto", disk) | ||||
| 	if err != nil { | ||||
| 		log.Fatalln("Error creating hyperkit: ", err) | ||||
| 	} | ||||
|  | ||||
| 	h.Kernel = prefix + "-bzImage" | ||||
| 	h.Initrd = prefix + "-initrd.img" | ||||
| 	h.CPUs = cpus | ||||
| 	h.Memory = mem | ||||
| 	h.DiskSize = diskSz | ||||
|  | ||||
| 	err = h.Run(string(cmdline)) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Cannot run hyperkit: %v", err) | ||||
| 	} | ||||
| } | ||||
| @@ -1,4 +1,4 @@ | ||||
| github.com/docker/hyperkit/go 874e68dbb7a2a7a2794dbd8648c2f4be1e7a8bb3 | ||||
| github.com/docker/hyperkit/go 57e91c5bb6655514aa71d00dd1949db891903d34 | ||||
| github.com/googleapis/gax-go 8c5154c0fe5bf18cf649634d4c6df50897a32751 | ||||
| github.com/golang/protobuf/proto c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 | ||||
| github.com/Masterminds/semver 312afcd0e81e5cf81fdc3cfd0e8504ae031521c8 | ||||
|   | ||||
							
								
								
									
										14
									
								
								vendor/github.com/docker/hyperkit/go/hyperkit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/docker/hyperkit/go/hyperkit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,5 +1,3 @@ | ||||
| // +build darwin | ||||
|  | ||||
| // Package hyperkit provides a Go wrapper around the hyperkit | ||||
| // command. It currently shells out to start hyperkit with the | ||||
| // provided configuration. | ||||
| @@ -75,6 +73,8 @@ type HyperKit struct { | ||||
| 	DiskImage string `json:"disk"` | ||||
| 	// ISOImage is the (optional) path to a ISO image to attach | ||||
| 	ISOImage string `json:"iso"` | ||||
| 	// VSock enables the virtio-socket device and exposes it on the host | ||||
| 	VSock bool `json:"vsock"` | ||||
|  | ||||
| 	// Kernel is the path to the kernel image to boot | ||||
| 	Kernel string `json:"kernel"` | ||||
| @@ -195,7 +195,7 @@ func (h *HyperKit) execute(cmdline string) error { | ||||
| 	var err error | ||||
| 	// Sanity checks on configuration | ||||
| 	if h.Console == ConsoleFile && h.StateDir == "" { | ||||
| 		return fmt.Errorf("If ConsoleFile is set, StateDir was be specified") | ||||
| 		return fmt.Errorf("If ConsoleFile is set, StateDir must be specified") | ||||
| 	} | ||||
| 	if h.UserData != "" && h.ISOImage != "" { | ||||
| 		return fmt.Errorf("If UserData is supplied, ISOImage must not be set") | ||||
| @@ -205,8 +205,11 @@ func (h *HyperKit) execute(cmdline string) error { | ||||
| 			return fmt.Errorf("ISO %s does not exist", h.ISOImage) | ||||
| 		} | ||||
| 	} | ||||
| 	if h.VSock && h.StateDir == "" { | ||||
| 		return fmt.Errorf("If virtio-sockets are enabled, StateDir must be specified") | ||||
| 	} | ||||
| 	if h.UserData != "" && h.StateDir == "" { | ||||
| 		return fmt.Errorf("If UserData is supplied, StateDir was be specified") | ||||
| 		return fmt.Errorf("If UserData is supplied, StateDir must be specified") | ||||
| 	} | ||||
| 	if _, err = os.Stat(h.Kernel); os.IsNotExist(err) { | ||||
| 		return fmt.Errorf("Kernel %s does not exist", h.Kernel) | ||||
| @@ -355,6 +358,9 @@ func (h *HyperKit) buildArgs(cmdline string) { | ||||
| 	if h.DiskImage != "" { | ||||
| 		a = append(a, "-s", fmt.Sprintf("2:0,virtio-blk,%s", h.DiskImage)) | ||||
| 	} | ||||
| 	if h.VSock { | ||||
| 		a = append(a, "-s", fmt.Sprintf("3,virtio-sock,guest_cid=3,path=%s", h.StateDir)) | ||||
| 	} | ||||
| 	if h.ISOImage != "" { | ||||
| 		a = append(a, "-s", fmt.Sprintf("4,ahci-cd,%s", h.ISOImage)) | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/docker/hyperkit/src/include/xhyve/xhyve.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/docker/hyperkit/src/include/xhyve/xhyve.h
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -41,7 +41,6 @@ | ||||
| #define	VMEXIT_ABORT (-1) | ||||
|  | ||||
| extern int guest_ncpus; | ||||
| extern int print_mac; | ||||
| extern char *guest_uuid_str; | ||||
| extern char *vmname; | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/docker/hyperkit/src/lib/acpitbl.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/docker/hyperkit/src/lib/acpitbl.c
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -737,7 +737,7 @@ void dsdt_fixup(int bus, uint16_t iobase, uint16_t iolimit, uint32_t membase32, | ||||
| { | ||||
| 	if (bus != 0) { | ||||
| 		fprintf(stderr, "DSDT, unsupported PCI bus (%d)\n", bus); | ||||
| 		exit(-1); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	acpitbl_write16(dsdt, 0xb6, iobase); | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/docker/hyperkit/src/lib/mevent.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/docker/hyperkit/src/lib/mevent.c
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -408,7 +408,7 @@ mevent_dispatch(void) | ||||
| 	ret = pipe(mevent_pipefd); | ||||
| 	if (ret < 0) { | ||||
| 		perror("pipe"); | ||||
| 		exit(0); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
|   | ||||
							
								
								
									
										8
									
								
								vendor/github.com/docker/hyperkit/src/lib/pci_virtio_net_vmnet.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/docker/hyperkit/src/lib/pci_virtio_net_vmnet.c
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -728,14 +728,6 @@ pci_vtnet_init(struct pci_devinst *pi, UNUSED char *opts) | ||||
| 		return (-1); | ||||
| 	} | ||||
|  | ||||
|     if (print_mac == 1) | ||||
|     { | ||||
| 		printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", | ||||
| 			sc->vms->mac[0], sc->vms->mac[1], sc->vms->mac[2], | ||||
| 			sc->vms->mac[3], sc->vms->mac[4], sc->vms->mac[5]); | ||||
| 		exit(0); | ||||
|     } | ||||
|  | ||||
| 	sc->vsc_config.mac[0] = sc->vms->mac[0]; | ||||
| 	sc->vsc_config.mac[1] = sc->vms->mac[1]; | ||||
| 	sc->vsc_config.mac[2] = sc->vms->mac[2]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user