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 +}