From b5e956b9fc2cfec265f3762e4d60c53d9245131e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 14 Aug 2016 16:54:06 -0700 Subject: [PATCH] pixiecore/cli: implement v1 compatibility for the CLI. This hack tries to interpret the commandline based on what Pixiecore v1 did, before handing off to the fancier v2 CLI logic. Doesn't support API mode yet, since that's not yet implemented in the library. --- pixiecore/cli/cli.go | 7 ++- pixiecore/cli/v1compat.go | 113 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 pixiecore/cli/v1compat.go diff --git a/pixiecore/cli/cli.go b/pixiecore/cli/cli.go index 385101e..5314714 100644 --- a/pixiecore/cli/cli.go +++ b/pixiecore/cli/cli.go @@ -42,6 +42,10 @@ func CLI() { rootCmd.PersistentFlags().Var(ipxeFirmwareFlag(pixiecore.FirmwareEFI32), "ipxe-efi32", "iPXE binary for 32-bit UEFI") rootCmd.PersistentFlags().Var(ipxeFirmwareFlag(pixiecore.FirmwareEFI64), "ipxe-efi64", "iPXE binary for 64-bit UEFI") + if v1compatCLI() { + return + } + if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(-1) @@ -53,9 +57,6 @@ var rootCmd = &cobra.Command{ Use: "pixiecore", Short: "All-in-one network booting", Long: `Pixiecore is a tool to make network booting easy.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, } type ipxeFirmwareFlag pixiecore.Firmware diff --git a/pixiecore/cli/v1compat.go b/pixiecore/cli/v1compat.go new file mode 100644 index 0000000..e0cd40b --- /dev/null +++ b/pixiecore/cli/v1compat.go @@ -0,0 +1,113 @@ +// Copyright 2016 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "flag" + "fmt" + "log" + "os" + "strings" + + "go.universe.tf/netboot/pixiecore" +) + +func v1compatCLI() bool { + fs := flag.NewFlagSet("main", flag.ContinueOnError) + fs.Usage = func() {} + + portDHCP := fs.Int("port-dhcp", 67, "Port to listen on for DHCP requests") + portPXE := fs.Int("port-pxe", 4011, "Port to listen on for PXE requests") + portTFTP := fs.Int("port-tftp", 69, "Port to listen on for TFTP requests") + portHTTP := fs.Int("port-http", 70, "Port to listen on for HTTP requests") + listenAddr := fs.String("listen-addr", "", "Address to listen on (default all)") + + apiServer := fs.String("api", "", "Path to the boot API server") + //apiTimeout := fs.Duration("api-timeout", 5*time.Second, "Timeout on boot API server requests") + + kernelFile := fs.String("kernel", "", "Path to the linux kernel file to boot") + initrdFile := fs.String("initrd", "", "Comma-separated list of initrds to pass to the kernel") + kernelCmdline := fs.String("cmdline", "", "Additional arguments for the kernel commandline") + + //debug := fs.Bool("debug", false, "Log more things that aren't directly related to booting a recognized client") + + if err := fs.Parse(os.Args[1:]); err != nil { + // This error path includes passing -h or --help. We want the + // modern CLI to respond to such cries for help, not the + // compat CLI. + return false + } + + // Successful flag parsing might mean no flags were passed, so + // heuristically decide if the parsed commandline looks + // v1-compat-ish: no positional arguments, and one of kernelFile + // or apiServer passed. + if fs.NArg() > 0 || (*apiServer == "" && *kernelFile == "") { + return false + } + + // Run in compat mode. + + switch { + case *apiServer != "": + if *kernelFile != "" { + fatalf("cannot provide -kernel with -api") + } + if *initrdFile != "" { + fatalf("cannot provide -initrd with -api") + } + if *kernelCmdline != "" { + fatalf("cannot provide -cmdline with -api") + } + + log.Printf("Starting Pixiecore in API mode, with server %s", *apiServer) + todo("API mode not ready yet") + + case *kernelFile != "": + if *apiServer != "" { + fatalf("cannot provide -api with -kernel") + } + + log.Printf("Starting Pixiecore in static mode") + var initrds []string + if *initrdFile != "" { + initrds = strings.Split(*initrdFile, ",") + } + spec := &pixiecore.Spec{ + Kernel: pixiecore.ID(*kernelFile), + Cmdline: map[string]interface{}{*kernelCmdline: ""}, + } + for _, initrd := range initrds { + spec.Initrd = append(spec.Initrd, pixiecore.ID(initrd)) + } + + s := &pixiecore.Server{ + Booter: pixiecore.StaticBooter(spec), + Ipxe: Ipxe, + Log: func(msg string) { fmt.Println(msg) }, + Address: *listenAddr, + HTTPPort: *portHTTP, + DHCPPort: *portDHCP, + TFTPPort: *portTFTP, + PXEPort: *portPXE, + } + fmt.Println(s.Serve()) + + default: + fatalf("must specify either -api, or -kernel/-initrd") + } + + return true +}