veyron/services/mgmt/device/deviced: re-implement deviced using cmdline library
As we've been adding more options to run deviced as a command (e.g. install,
uninstall), it makes sense to use the cmdline library.
Change-Id: Icee15d70dbb02b09bcb5bce17f63abfb9df2b5f6
diff --git a/services/mgmt/device/deviced/commands.go b/services/mgmt/device/deviced/commands.go
new file mode 100644
index 0000000..a597091
--- /dev/null
+++ b/services/mgmt/device/deviced/commands.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "os"
+
+ "v.io/lib/cmdline"
+
+ "v.io/core/veyron/services/mgmt/device/impl"
+ "v.io/core/veyron2/vlog"
+)
+
+var installFrom string
+
+var cmdInstall = &cmdline.Command{
+ Run: runInstall,
+ Name: "install",
+ Short: "Install the device manager.",
+ Long: "Performs installation of device manager based on the config specified via the environment.",
+ ArgsName: "[-- <arguments for device manager>]",
+ ArgsLong: `
+Arguments to be passed to the installed device manager`,
+}
+
+func init() {
+ cmdInstall.Flags.StringVar(&installFrom, "from", "", "if specified, performs the installation from the provided application envelope object name")
+}
+
+func runInstall(_ *cmdline.Command, args []string) error {
+ if installFrom != "" {
+ // TODO(caprita): Also pass args into InstallFrom.
+ if err := impl.InstallFrom(installFrom); err != nil {
+ vlog.Errorf("InstallFrom(%v) failed: %v", installFrom, err)
+ return err
+ }
+ return nil
+ }
+ if err := impl.SelfInstall(args, os.Environ()); err != nil {
+ vlog.Errorf("SelfInstall failed: %v", err)
+ return err
+ }
+ return nil
+}
+
+var cmdUninstall = &cmdline.Command{
+ Run: runUninstall,
+ Name: "uninstall",
+ Short: "Uninstall the device manager.",
+ Long: "Removes the device manager installation based on the config specified via the environment.",
+}
+
+func runUninstall(*cmdline.Command, []string) error {
+ if err := impl.Uninstall(); err != nil {
+ vlog.Errorf("Uninstall failed: %v", err)
+ return err
+ }
+ return nil
+}
diff --git a/services/mgmt/device/deviced/main.go b/services/mgmt/device/deviced/main.go
index 4e72e4e..f0631db 100644
--- a/services/mgmt/device/deviced/main.go
+++ b/services/mgmt/device/deviced/main.go
@@ -1,104 +1,16 @@
package main
-import (
- "flag"
- "os"
-
- "v.io/core/veyron2/naming"
- "v.io/core/veyron2/rt"
- "v.io/core/veyron2/vlog"
-
- "v.io/core/veyron/lib/signals"
- "v.io/core/veyron/profiles/roaming"
- "v.io/core/veyron/services/mgmt/device/config"
- "v.io/core/veyron/services/mgmt/device/impl"
-)
-
-var (
- // TODO(caprita): publishAs and stopExitCode should be provided by the config?
- publishAs = flag.String("name", "", "name to publish the device manager at")
- stopExitCode = flag.Int("stop_exit_code", 0, "exit code to return when stopped via the Stop RPC")
- installSelf = flag.Bool("install_self", false, "perform installation using environment and command-line flags")
- installFrom = flag.String("install_from", "", "if not-empty, perform installation from the provided application envelope object name")
- uninstall = flag.Bool("uninstall", false, "uninstall the installation specified via the config")
-)
+import "v.io/lib/cmdline"
func main() {
- exitCode := 0
- defer func() {
- os.Exit(exitCode)
- }()
- flag.Parse()
- runtime, err := rt.New()
- if err != nil {
- vlog.Fatalf("Could not initialize runtime: %v", err)
+ rootCmd := cmdline.Command{
+ Name: "deviced",
+ Short: "Veyron device manager setup",
+ Long: `
+deviced can be used to launch, configure, or manage the device manager.
+`,
+ Children: []*cmdline.Command{cmdInstall, cmdUninstall},
+ Run: runServer,
}
- defer runtime.Cleanup()
-
- if len(*installFrom) > 0 {
- if err := impl.InstallFrom(*installFrom); err != nil {
- vlog.Errorf("InstallFrom failed: %v", err)
- exitCode = 1
- }
- return
- }
-
- if *installSelf {
- // TODO(caprita): Make the flags survive updates.
- if err := impl.SelfInstall(flag.Args(), os.Environ()); err != nil {
- vlog.Errorf("SelfInstall failed: %v", err)
- exitCode = 1
- }
- return
- }
-
- if *uninstall {
- if err := impl.Uninstall(); err != nil {
- vlog.Errorf("Uninstall failed: %v", err)
- exitCode = 1
- }
- return
- }
-
- server, err := runtime.NewServer()
- if err != nil {
- vlog.Errorf("NewServer() failed: %v", err)
- exitCode = 1
- return
- }
- defer server.Stop()
- endpoints, err := server.Listen(roaming.ListenSpec)
- if err != nil {
- vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
- exitCode = 1
- return
- }
- name := naming.JoinAddressName(endpoints[0].String(), "")
- vlog.VI(0).Infof("Device manager object name: %v", name)
- configState, err := config.Load()
- if err != nil {
- vlog.Errorf("Failed to load config passed from parent: %v", err)
- exitCode = 1
- return
- }
- configState.Name = name
- // TODO(caprita): We need a way to set config fields outside of the
- // update mechanism (since that should ideally be an opaque
- // implementation detail).
- dispatcher, err := impl.NewDispatcher(runtime.Principal(), configState, func() { exitCode = *stopExitCode })
- if err != nil {
- vlog.Errorf("Failed to create dispatcher: %v", err)
- exitCode = 1
- return
- }
- if err := server.ServeDispatcher(*publishAs, dispatcher); err != nil {
- vlog.Errorf("Serve(%v) failed: %v", *publishAs, err)
- exitCode = 1
- return
- }
- vlog.VI(0).Infof("Device manager published as: %v", *publishAs)
- impl.InvokeCallback(runtime.NewContext(), name)
-
- // Wait until shutdown.
- <-signals.ShutdownOnSignals(runtime)
+ rootCmd.Main()
}
diff --git a/services/mgmt/device/deviced/server.go b/services/mgmt/device/deviced/server.go
new file mode 100644
index 0000000..efc649a
--- /dev/null
+++ b/services/mgmt/device/deviced/server.go
@@ -0,0 +1,72 @@
+package main
+
+import (
+ "flag"
+
+ "v.io/lib/cmdline"
+
+ "v.io/core/veyron/lib/signals"
+ "v.io/core/veyron/profiles/roaming"
+ "v.io/core/veyron/services/mgmt/device/config"
+ "v.io/core/veyron/services/mgmt/device/impl"
+ "v.io/core/veyron2/naming"
+ "v.io/core/veyron2/rt"
+ "v.io/core/veyron2/vlog"
+)
+
+var (
+ // TODO(caprita): publishAs and stopExitCode should be provided by the
+ // config?
+ publishAs = flag.String("name", "", "name to publish the device manager at")
+ stopExitCode = flag.Int("stop_exit_code", 0, "exit code to return when stopped via the Stop RPC")
+)
+
+func runServer(*cmdline.Command, []string) error {
+ runtime, err := rt.New()
+ if err != nil {
+ vlog.Errorf("Could not initialize runtime: %v", err)
+ return err
+ }
+ defer runtime.Cleanup()
+
+ server, err := runtime.NewServer()
+ if err != nil {
+ vlog.Errorf("NewServer() failed: %v", err)
+ return err
+ }
+ defer server.Stop()
+ endpoints, err := server.Listen(roaming.ListenSpec)
+ if err != nil {
+ vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
+ return err
+ }
+ name := naming.JoinAddressName(endpoints[0].String(), "")
+ vlog.VI(0).Infof("Device manager object name: %v", name)
+ configState, err := config.Load()
+ if err != nil {
+ vlog.Errorf("Failed to load config passed from parent: %v", err)
+ return err
+ }
+ configState.Name = name
+ // TODO(caprita): We need a way to set config fields outside of the
+ // update mechanism (since that should ideally be an opaque
+ // implementation detail).
+
+ var exitErr error
+ dispatcher, err := impl.NewDispatcher(runtime.Principal(), configState, func() { exitErr = cmdline.ErrExitCode(*stopExitCode) })
+ if err != nil {
+ vlog.Errorf("Failed to create dispatcher: %v", err)
+ return err
+ }
+ if err := server.ServeDispatcher(*publishAs, dispatcher); err != nil {
+ vlog.Errorf("Serve(%v) failed: %v", *publishAs, err)
+ return err
+ }
+ vlog.VI(0).Infof("Device manager published as: %v", *publishAs)
+ impl.InvokeCallback(runtime.NewContext(), name)
+
+ // Wait until shutdown.
+ <-signals.ShutdownOnSignals(runtime)
+
+ return exitErr
+}
diff --git a/tools/mgmt/device/dminstall b/tools/mgmt/device/dminstall
index 4f46805..b2d38dd 100755
--- a/tools/mgmt/device/dminstall
+++ b/tools/mgmt/device/dminstall
@@ -193,7 +193,7 @@
exit 1
fi
- VEYRON_DM_CURRENT="${INSTALL_DIR}/deviced.curr" VEYRON_DM_ROOT="${DM_ROOT}" VEYRON_DM_HELPER="${SETUID_SCRIPT}" "${BIN_INSTALL}/deviced" --install_self -- --name="${PUBLISH}" --stop_exit_code=${STOP_EXIT_CODE} "$@"
+ VEYRON_DM_CURRENT="${INSTALL_DIR}/deviced.curr" VEYRON_DM_ROOT="${DM_ROOT}" VEYRON_DM_HELPER="${SETUID_SCRIPT}" "${BIN_INSTALL}/deviced" install -- --name="${PUBLISH}" --stop_exit_code=${STOP_EXIT_CODE} "$@"
echo "Device manager installed."
local -r SECURITY_DIR="${INSTALL_DIR}/security"
diff --git a/tools/mgmt/device/dmuninstall b/tools/mgmt/device/dmuninstall
index ce12747..489e068 100755
--- a/tools/mgmt/device/dmuninstall
+++ b/tools/mgmt/device/dmuninstall
@@ -39,7 +39,7 @@
local -r BIN_INSTALL="${INSTALL_DIR}/bin"
- VEYRON_DM_CURRENT="${INSTALL_DIR}/deviced.curr" VEYRON_DM_ROOT="${DM_ROOT}" VEYRON_DM_HELPER="unused" "${BIN_INSTALL}/deviced" --uninstall
+ VEYRON_DM_CURRENT="${INSTALL_DIR}/deviced.curr" VEYRON_DM_ROOT="${DM_ROOT}" VEYRON_DM_HELPER="unused" "${BIN_INSTALL}/deviced" uninstall
echo "Device manager uninstalled."
if [[ ${SINGLE_USER} == false ]]; then