veyron/services/mgmt/device: Add persistent arguments
With this change, device manager arguments that should be persistent are
saved in a separate file. When an update happens, the persistent
arguments are merged with the arguments from the new envelope.
Also updated test.sh to include updating and reverting the device
manager. Without the persistent arguments, the new tests would fail.
Change-Id: Ib69824f64aa2cec9d9e7f902b5abe1552b8102b9
diff --git a/services/mgmt/device/impl/device_installer.go b/services/mgmt/device/impl/device_installer.go
index ee59788..25e0e8a 100644
--- a/services/mgmt/device/impl/device_installer.go
+++ b/services/mgmt/device/impl/device_installer.go
@@ -15,6 +15,9 @@
// base/ - initial installation of device manager
// deviced - link to deviced (self)
// deviced.sh - script to start the device manager
+// device-data/
+// persistent-args - list of persistent arguments for the device
+// manager (json encoded)
// logs/ - device manager logs will go here
// current - set as <Config.CurrentLink>
// agent_deviced.sh - script to launch device manager under agent
@@ -156,6 +159,9 @@
// device manager in a different way.
Env: VeyronEnvironment(env),
}
+ if err := savePersistentArgs(root, envelope.Args); err != nil {
+ return err
+ }
if err := linkSelf(deviceDir, "deviced"); err != nil {
return err
}
diff --git a/services/mgmt/device/impl/device_service.go b/services/mgmt/device/impl/device_service.go
index d570d3e..629a283 100644
--- a/services/mgmt/device/impl/device_service.go
+++ b/services/mgmt/device/impl/device_service.go
@@ -21,6 +21,8 @@
// data
// signature
// associated.accounts
+// persistent-args - list of persistent arguments for the device
+// manager (json encoded)
//
// The device manager is always expected to be started through the symbolic link
// passed in as config.CurrentLink, which is monitored by an init daemon. This
@@ -139,6 +141,32 @@
return info, nil
}
+func savePersistentArgs(root string, args []string) error {
+ dir := filepath.Join(root, "device-manager", "device-data")
+ if err := os.MkdirAll(dir, 0700); err != nil {
+ return fmt.Errorf("MkdirAll(%q) failed: %v", dir)
+ }
+ data, err := json.Marshal(args)
+ if err != nil {
+ return fmt.Errorf("Marshal(%v) failed: %v", args, err)
+ }
+ fileName := filepath.Join(dir, "persistent-args")
+ return ioutil.WriteFile(fileName, data, 0600)
+}
+
+func loadPersistentArgs(root string) ([]string, error) {
+ fileName := filepath.Join(root, "device-manager", "device-data", "persistent-args")
+ bytes, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return nil, err
+ }
+ args := []string{}
+ if err := json.Unmarshal(bytes, &args); err != nil {
+ return nil, fmt.Errorf("json.Unmarshal(%v) failed: %v", bytes, err)
+ }
+ return args, nil
+}
+
func (s *deviceService) Claim(ctx ipc.ServerContext) error {
return s.disp.claimDeviceManager(ctx)
}
@@ -355,6 +383,10 @@
vlog.Errorf("app title mismatch. Got %q, expected %q.", envelope.Title, application.DeviceManagerTitle)
return verror2.Make(ErrAppTitleMismatch, ctx)
}
+ // Read and merge persistent args, if present.
+ if args, err := loadPersistentArgs(s.config.Root); err == nil {
+ envelope.Args = append(envelope.Args, args...)
+ }
if s.config.Envelope != nil && reflect.DeepEqual(envelope, s.config.Envelope) {
return verror2.Make(ErrUpdateNoOp, ctx)
}
diff --git a/tools/mgmt/test.sh b/tools/mgmt/test.sh
index 6441eb7..9aa9e2b 100755
--- a/tools/mgmt/test.sh
+++ b/tools/mgmt/test.sh
@@ -113,6 +113,9 @@
cd "${WORKDIR}"
build
+ local -r APPLICATIOND_NAME="applicationd"
+ local -r DEVICED_APP_NAME="${APPLICATIOND_NAME}/deviced/test"
+
BIN_STAGING_DIR=$(shell::tmp_dir)
cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${INITHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
shell_test::setup_server_test
@@ -123,9 +126,9 @@
export VANADIUM_DEVICE_DIR="${DM_INSTALL_DIR}/dm"
if [[ "${WITH_SUID}" == "--with_suid" ]]; then
- "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" --veyron.tcp.address=127.0.0.1:0
+ "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" --origin="${DEVICED_APP_NAME}" -- --veyron.tcp.address=127.0.0.1:0
else
- "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" --single_user -- --veyron.tcp.address=127.0.0.1:0
+ "${DEVICE_SCRIPT}" install "${BIN_STAGING_DIR}" --single_user --origin="${DEVICED_APP_NAME}" -- --veyron.tcp.address=127.0.0.1:0
fi
"${VRUN}" "${DEVICE_SCRIPT}" start
@@ -147,6 +150,7 @@
shell_test::fail "line ${LINENO}: store set failed"
# Claim the device as "alice/myworkstation".
+ echo ">> Claiming the device manager"
"${DEVICE_BIN}" claim "${DM_NAME}/device" myworkstation
if [[ "${WITH_SUID}" == "--with_suid" ]]; then
@@ -172,6 +176,7 @@
# Upload a binary to the binary server. The binary we upload is binaryd
# itself.
local -r SAMPLE_APP_BIN_NAME="${BINARYD_NAME}/testapp"
+ echo ">> Uploading ${SAMPLE_APP_BIN_NAME}"
"${BINARY_BIN}" upload "${SAMPLE_APP_BIN_NAME}" "${BINARYD_BIN}"
# Verify that the binary we uploaded is shown by glob.
@@ -180,7 +185,6 @@
# Start an application server under the blessing "alice/myworkstation/applicationd" so that
# the device ("alice/myworkstation") can talk to it.
- local -r APPLICATIOND_NAME="applicationd"
shell_test::start_server "${VRUN}" --name=myworkstation/applicationd "${APPLICATIOND_BIN}" --name="${APPLICATIOND_NAME}" \
--store="$(shell::tmp_dir)" --veyron.tcp.address=127.0.0.1:0 \
|| shell_test::fail "line ${LINENO} failed to start applicationd"
@@ -188,6 +192,7 @@
# Upload an envelope for our test app.
local -r SAMPLE_APP_NAME="${APPLICATIOND_NAME}/testapp/v0"
local -r APP_PUBLISH_NAME="testbinaryd"
+ echo ">> Uploading ${SAMPLE_APP_NAME}"
echo "{\"Title\":\"BINARYD\", \"Args\":[\"--name=${APP_PUBLISH_NAME}\", \"--root_dir=./binstore\", \"--veyron.tcp.address=127.0.0.1:0\"], \"Binary\":\"${SAMPLE_APP_BIN_NAME}\", \"Env\":[]}" > ./app.envelope && \
"${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" ./app.envelope && rm ./app.envelope
@@ -196,6 +201,7 @@
"BINARYD" "${LINENO}"
# Install the app on the device.
+ echo ">> Installing ${SAMPLE_APP_NAME}"
local -r INSTALLATION_NAME=$("${DEVICE_BIN}" install "${DM_NAME}/apps" "${SAMPLE_APP_NAME}" | sed -e 's/Successfully installed: "//' | sed -e 's/"//')
# Verify that the installation shows up when globbing the device manager.
@@ -203,6 +209,7 @@
"${INSTALLATION_NAME}" "${LINENO}"
# Start an instance of the app, granting it blessing extension myapp.
+ echo ">> Starting ${INSTALLATION_NAME}"
local -r INSTANCE_NAME=$("${DEVICE_BIN}" start "${INSTALLATION_NAME}" myapp | sed -e 's/Successfully started: "//' | sed -e 's/"//')
wait_for_mountentry "${NAMESPACE_BIN}" "5" "${APP_PUBLISH_NAME}"
@@ -216,12 +223,41 @@
"alice/myapp/BINARYD" "${LINENO}"
# Stop the instance.
+ echo ">> Stopping ${INSTANCE_NAME}"
"${DEVICE_BIN}" stop "${INSTANCE_NAME}"
# Verify that logs, but not stats, show up when globbing the stopped instance.
shell_test::assert_eq "$("${NAMESPACE_BIN}" glob "${INSTANCE_NAME}/stats/...")" "" "${LINENO}"
shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${INSTANCE_NAME}/logs/...")" "" "${LINENO}"
+ # Upload a deviced binary.
+ local -r DEVICED_APP_BIN_NAME="${BINARYD_NAME}/deviced"
+ echo ">> Uploading ${DEVICEMANAGER_BIN}"
+ "${BINARY_BIN}" upload "${DEVICED_APP_BIN_NAME}" "${DEVICEMANAGER_BIN}"
+
+ # Upload a device manager envelope.
+ echo ">> Uploading ${DEVICED_APP_NAME}"
+ echo "{\"Title\":\"device manager\", \"Binary\":\"${DEVICED_APP_BIN_NAME}\"}" > ./deviced.envelope && \
+ "${APPLICATION_BIN}" put "${DEVICED_APP_NAME}" "${DEVICE_PROFILE}" ./deviced.envelope && rm ./deviced.envelope
+
+ # Update the device manager.
+ echo ">> Updating device manager"
+ "${DEVICE_BIN}" update "${DM_NAME}/device"
+ DM_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${DM_NAME}" "${DM_EP}")
+
+ # Verify that device manager is still published under the expected name
+ # (hostname).
+ shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${DM_NAME}")" "" "${LINENO}"
+
+ # Revert the device manager.
+ echo ">> Reverting device manager"
+ "${DEVICE_BIN}" revert "${DM_NAME}/device"
+ DM_EP=$(wait_for_mountentry "${NAMESPACE_BIN}" 5 "${DM_NAME}" "${DM_EP}")
+
+ # Verify that device manager is still published under the expected name
+ # (hostname).
+ shell_test::assert_ne "$("${NAMESPACE_BIN}" glob "${DM_NAME}")" "" "${LINENO}"
+
# Restart the device manager.
"${DEVICE_BIN}" suspend "${DM_NAME}/device"
wait_for_mountentry "${NAMESPACE_BIN}" "5" "${DM_NAME}" "{DM_EP}"