blob: ad3d92bcc0bd53aacb236f8dd2730b3d05b4cd0e [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package impl
2
3import (
Bogdan Capritac87a9142014-07-21 10:38:13 -07004 "fmt"
Bogdan Caprita4d67c042014-08-19 10:41:19 -07005 "strings"
Jiri Simsa24e87aa2014-06-09 09:27:34 -07006
Bogdan Caprita4d67c042014-08-19 10:41:19 -07007 inode "veyron/services/mgmt/node"
Bogdan Capritac87a9142014-07-21 10:38:13 -07008 "veyron/services/mgmt/node/config"
Jiri Simsa24e87aa2014-06-09 09:27:34 -07009
Jiri Simsa5293dcb2014-05-10 09:56:38 -070010 "veyron2/ipc"
11 "veyron2/security"
Bogdan Caprita4d67c042014-08-19 10:41:19 -070012 "veyron2/services/mgmt/node"
13 "veyron2/verror"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070014)
15
Bogdan Caprita4d67c042014-08-19 10:41:19 -070016// internalState wraps state shared between different node manager
17// invocations.
18type internalState struct {
19 callback *callbackState
20 updating *updatingState
21}
22
Jiri Simsa5293dcb2014-05-10 09:56:38 -070023// dispatcher holds the state of the node manager dispatcher.
24type dispatcher struct {
Bogdan Caprita4d67c042014-08-19 10:41:19 -070025 auth security.Authorizer
26 // internal holds the state that persists across RPC method invocations.
Bogdan Capritac87a9142014-07-21 10:38:13 -070027 internal *internalState
Bogdan Caprita4d67c042014-08-19 10:41:19 -070028 // config holds the node manager's (immutable) configuration state.
29 config *config.State
Jiri Simsa5293dcb2014-05-10 09:56:38 -070030}
31
Bogdan Caprita4d67c042014-08-19 10:41:19 -070032const (
33 appsSuffix = "apps"
34 nodeSuffix = "nm"
35 configSuffix = "cfg"
36)
37
38var (
39 errInvalidSuffix = verror.BadArgf("invalid suffix")
40 errOperationFailed = verror.Internalf("operation failed")
41 errInProgress = verror.Existsf("operation in progress")
42 errIncompatibleUpdate = verror.BadArgf("update failed: mismatching app title")
43 errUpdateNoOp = verror.NotFoundf("no different version available")
44 errNotExist = verror.NotFoundf("object does not exist")
45 errInvalidOperation = verror.BadArgf("invalid operation")
46)
47
Jiri Simsa24e87aa2014-06-09 09:27:34 -070048// NewDispatcher is the node manager dispatcher factory.
Bogdan Capritac87a9142014-07-21 10:38:13 -070049func NewDispatcher(auth security.Authorizer, config *config.State) (*dispatcher, error) {
50 if err := config.Validate(); err != nil {
51 return nil, fmt.Errorf("Invalid config %v: %v", config, err)
52 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -070053 return &dispatcher{
Jiri Simsa70c32052014-06-18 11:38:21 -070054 auth: auth,
Bogdan Capritac87a9142014-07-21 10:38:13 -070055 internal: &internalState{
Bogdan Caprita4d67c042014-08-19 10:41:19 -070056 callback: newCallbackState(),
57 updating: newUpdatingState(),
Jiri Simsa70c32052014-06-18 11:38:21 -070058 },
Bogdan Capritac87a9142014-07-21 10:38:13 -070059 config: config,
60 }, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -070061}
62
63// DISPATCHER INTERFACE IMPLEMENTATION
64
Cosmos Nicolaou8bfacf22014-08-19 11:19:36 -070065func (d *dispatcher) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
Bogdan Caprita4d67c042014-08-19 10:41:19 -070066 components := strings.Split(suffix, "/")
67 for i := 0; i < len(components); i++ {
68 if len(components[i]) == 0 {
69 components = append(components[:i], components[i+1:]...)
70 i--
71 }
72 }
73 if len(components) == 0 {
74 return nil, nil, errInvalidSuffix
75 }
76 // The implementation of the node manager is split up into several
77 // invokers, which are instantiated depending on the receiver name
78 // prefix.
79 var receiver interface{}
80 switch components[0] {
81 case nodeSuffix:
82 receiver = node.NewServerNode(&nodeInvoker{
83 callback: d.internal.callback,
84 updating: d.internal.updating,
85 config: d.config,
86 })
87 case appsSuffix:
88 receiver = node.NewServerApplication(&appInvoker{
89 callback: d.internal.callback,
90 config: d.config,
91 suffix: components[1:],
92 })
93 case configSuffix:
94 if len(components) != 2 {
95 return nil, nil, errInvalidSuffix
96 }
97 receiver = inode.NewServerConfig(&configInvoker{
98 callback: d.internal.callback,
99 suffix: components[1],
100 })
101 default:
102 return nil, nil, errInvalidSuffix
103 }
104 return ipc.ReflectInvoker(receiver), d.auth, nil
Jiri Simsa24e87aa2014-06-09 09:27:34 -0700105}