veyron/services/mgmt/node/impl: factor out parts of Start and Stop into subroutines.
Change-Id: Iea0a8ddcad03e9e554c8055ea9864af755dfea3e
diff --git a/services/mgmt/node/impl/app_invoker.go b/services/mgmt/node/impl/app_invoker.go
index db89956..ef8301a 100644
--- a/services/mgmt/node/impl/app_invoker.go
+++ b/services/mgmt/node/impl/app_invoker.go
@@ -205,6 +205,9 @@
}
func (i *appInvoker) Install(call ipc.ServerContext, applicationVON string) (string, error) {
+ if len(i.suffix) > 0 {
+ return "", errInvalidSuffix
+ }
ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
defer cancel()
envelope, err := fetchEnvelope(ctx, applicationVON)
@@ -311,21 +314,31 @@
return cmd, nil
}
-func (i *appInvoker) Start(ipc.ServerContext) ([]string, error) {
+// installationDir returns the path to the directory containing the app
+// installation referred to by the invoker's suffix. Returns an error if the
+// suffix does not name an installation or if the named installation does not
+// exist.
+func (i *appInvoker) installationDir() (string, error) {
components := i.suffix
- if nComponents := len(components); nComponents < 2 {
- return nil, fmt.Errorf("Start all installations / all applications not yet implemented (%v)", naming.Join(i.suffix...))
- } else if nComponents > 2 {
- return nil, errInvalidSuffix
+ if nComponents := len(components); nComponents != 2 {
+ return "", errInvalidSuffix
}
app, installation := components[0], components[1]
installationDir := filepath.Join(i.config.Root, applicationDirName(app), installationDirName(installation))
if _, err := os.Stat(installationDir); err != nil {
if os.IsNotExist(err) {
- return nil, errNotExist
+ return "", errNotExist
}
vlog.Errorf("Stat(%v) failed: %v", installationDir, err)
- return nil, errOperationFailed
+ return "", errOperationFailed
+ }
+ return installationDir, nil
+}
+
+func (i *appInvoker) Start(ipc.ServerContext) ([]string, error) {
+ installationDir, err := i.installationDir()
+ if err != nil {
+ return nil, err
}
currLink := filepath.Join(installationDir, "current")
envelope, err := loadEnvelope(currLink)
@@ -388,20 +401,55 @@
return []string{instanceID}, nil
}
-func (i *appInvoker) Stop(_ ipc.ServerContext, deadline uint32) error {
- // TODO(caprita): implement deadline.
- ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
- defer cancel()
+// instanceDir returns the path to the directory containing the app instance
+// referred to by the invoker's suffix, as well as the corresponding stopped
+// instance dir. Returns an error if the suffix does not name an instance.
+func (i *appInvoker) instanceDir() (string, string, error) {
components := i.suffix
- if nComponents := len(components); nComponents < 3 {
- return fmt.Errorf("Stop all instances / all installations / all applications not yet implemented (%v)", naming.Join(i.suffix...))
- } else if nComponents > 3 {
- return errInvalidSuffix
+ if nComponents := len(components); nComponents != 3 {
+ return "", "", errInvalidSuffix
}
app, installation, instance := components[0], components[1], components[2]
instancesDir := filepath.Join(i.config.Root, applicationDirName(app), installationDirName(installation), "instances")
instanceDir := filepath.Join(instancesDir, instanceDirName(instance))
stoppedInstanceDir := filepath.Join(instancesDir, stoppedInstanceDirName(instance))
+ return instanceDir, stoppedInstanceDir, nil
+}
+
+func stopAppRemotely(appVON string) error {
+ appStub, err := appcycle.BindAppCycle(appVON)
+ if err != nil {
+ vlog.Errorf("BindAppCycle(%v) failed: %v", appVON, err)
+ return errOperationFailed
+ }
+ ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
+ defer cancel()
+ stream, err := appStub.Stop(ctx)
+ if err != nil {
+ vlog.Errorf("%v.Stop() failed: %v", appVON, err)
+ return errOperationFailed
+ }
+ rstream := stream.RecvStream()
+ for rstream.Advance() {
+ vlog.VI(2).Infof("%v.Stop() task update: %v", appVON, rstream.Value())
+ }
+ if err := rstream.Err(); err != nil {
+ vlog.Errorf("Advance() failed: %v", err)
+ return errOperationFailed
+ }
+ if err := stream.Finish(); err != nil {
+ vlog.Errorf("Finish() failed: %v", err)
+ return errOperationFailed
+ }
+ return nil
+}
+
+func (i *appInvoker) Stop(_ ipc.ServerContext, deadline uint32) error {
+ // TODO(caprita): implement deadline.
+ instanceDir, stoppedInstanceDir, err := i.instanceDir()
+ if err != nil {
+ return err
+ }
if err := os.Rename(instanceDir, stoppedInstanceDir); err != nil {
vlog.Errorf("Rename(%v, %v) failed: %v", instanceDir, stoppedInstanceDir, err)
if os.IsNotExist(err) {
@@ -416,29 +464,7 @@
if err != nil {
return errOperationFailed
}
- appStub, err := appcycle.BindAppCycle(info.AppCycleMgrName)
- if err != nil {
- vlog.Errorf("BindAppCycle(%v) failed: %v", info.AppCycleMgrName, err)
- return errOperationFailed
- }
- stream, err := appStub.Stop(ctx)
- if err != nil {
- vlog.Errorf("Got error: %v", err)
- return errOperationFailed
- }
- rstream := stream.RecvStream()
- for rstream.Advance() {
- vlog.VI(2).Infof("%v.Stop(%v) task update: %v", i.suffix, deadline, rstream.Value())
- }
- if err := rstream.Err(); err != nil {
- vlog.Errorf("Stream returned an error: %v", err)
- return errOperationFailed
- }
- if err := stream.Finish(); err != nil {
- vlog.Errorf("Got error: %v", err)
- return errOperationFailed
- }
- return nil
+ return stopAppRemotely(info.AppCycleMgrName)
}
func (*appInvoker) Suspend(ipc.ServerContext) error {