blob: ecf2ea4a4271109aadfe25c74930238112be9731 [file] [log] [blame]
Robin Thellend18205cf2014-10-21 13:53:59 -07001package main
Robin Thellend6b17da72014-05-14 09:55:14 -07002
3import (
Robin Thellend39ac3232014-12-02 09:50:41 -08004 "errors"
Robin Thellend6b17da72014-05-14 09:55:14 -07005 "fmt"
Robin Thellend6b17da72014-05-14 09:55:14 -07006 "time"
7
Todd Wang478fcf92014-12-26 12:37:37 -08008 "v.io/lib/cmdline"
Jiri Simsa6ac95222015-02-23 16:11:49 -08009 "v.io/v23"
10 "v.io/v23/context"
11 "v.io/v23/ipc"
12 "v.io/v23/naming"
13 "v.io/v23/options"
14 "v.io/v23/security"
15 "v.io/v23/vlog"
Robin Thellend6b17da72014-05-14 09:55:14 -070016)
17
18var cmdGlob = &cmdline.Command{
19 Run: runGlob,
20 Name: "glob",
21 Short: "returns all matching entries in the mount table",
22 Long: "returns all matching entries in the mount table",
Bogdan Capritadecd1052014-11-08 16:15:54 -080023 ArgsName: "[<mount name>] <pattern>",
Robin Thellend6b17da72014-05-14 09:55:14 -070024 ArgsLong: `
Bogdan Capritadecd1052014-11-08 16:15:54 -080025<mount name> is a mount name on a mount table. Defaults to namespace root.
Robin Thellend6b17da72014-05-14 09:55:14 -070026<pattern> is a glob pattern that is matched against all the entries below the
27specified mount name.
28`,
29}
30
31func runGlob(cmd *cmdline.Command, args []string) error {
Matt Rosencrantza5ad2722015-01-22 11:17:47 -080032 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantzd599e382015-01-12 11:13:32 -080033 defer cancel()
34
Bogdan Capritadecd1052014-11-08 16:15:54 -080035 if len(args) == 1 {
Jiri Simsa6ac95222015-02-23 16:11:49 -080036 roots := v23.GetNamespace(ctx).Roots()
Robin Thellend39ac3232014-12-02 09:50:41 -080037 if len(roots) == 0 {
38 return errors.New("no namespace root")
39 }
40 args = append([]string{roots[0]}, args...)
Bogdan Capritadecd1052014-11-08 16:15:54 -080041 }
Robin Thellend6b17da72014-05-14 09:55:14 -070042 if expected, got := 2, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -070043 return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -070044 }
Matt Rosencrantzd599e382015-01-12 11:13:32 -080045
Robin Thellend39ac3232014-12-02 09:50:41 -080046 name, pattern := args[0], args[1]
Jiri Simsa6ac95222015-02-23 16:11:49 -080047 client := v23.GetClient(ctx)
Matt Rosencrantz6edab562015-01-12 11:07:55 -080048 call, err := client.StartCall(ctx, name, ipc.GlobMethod, []interface{}{pattern}, options.NoResolve{})
Robin Thellend6b17da72014-05-14 09:55:14 -070049 if err != nil {
50 return err
51 }
Robin Thellend39ac3232014-12-02 09:50:41 -080052 for {
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080053 var gr naming.VDLGlobReply
54 if err := call.Recv(&gr); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -080055 break
56 }
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080057 switch v := gr.(type) {
58 case naming.VDLGlobReplyEntry:
59 fmt.Fprint(cmd.Stdout(), v.Value.Name)
60 for _, s := range v.Value.Servers {
61 fmt.Fprintf(cmd.Stdout(), " %s (TTL %s)", s.Server, time.Duration(s.TTL)*time.Second)
62 }
63 fmt.Fprintln(cmd.Stdout())
Robin Thellend6b17da72014-05-14 09:55:14 -070064 }
Robin Thellend6b17da72014-05-14 09:55:14 -070065 }
Todd Wange77f9952015-02-18 13:20:50 -080066 if err := call.Finish(); err != nil {
67 return err
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -070068 }
Todd Wange77f9952015-02-18 13:20:50 -080069 return nil
Robin Thellend6b17da72014-05-14 09:55:14 -070070}
71
Asim Shankarb2cc1292015-02-23 15:22:45 -080072type blessingPatterns struct {
73 list []security.BlessingPattern
74}
75
76func (bp *blessingPatterns) Set(s string) error {
77 bp.list = append(bp.list, security.BlessingPattern(s))
78 return nil
79}
80
81func (bp *blessingPatterns) String() string {
82 return fmt.Sprintf("%v", bp.list)
83}
84
85func (bp *blessingPatterns) Get() interface{} { return bp.list }
86
87var flagMountBlessingPatterns blessingPatterns
88
Robin Thellend6b17da72014-05-14 09:55:14 -070089var cmdMount = &cmdline.Command{
90 Run: runMount,
91 Name: "mount",
92 Short: "Mounts a server <name> onto a mount table",
93 Long: "Mounts a server <name> onto a mount table",
Robin Thellend58206662015-02-17 17:36:08 -080094 ArgsName: "<mount name> <name> <ttl> [M|R]",
Robin Thellend6b17da72014-05-14 09:55:14 -070095 ArgsLong: `
96<mount name> is a mount name on a mount table.
Robin Thellend58206662015-02-17 17:36:08 -080097
Bogdan Capritad9281a32014-07-02 14:40:39 -070098<name> is the rooted object name of the server.
Robin Thellend58206662015-02-17 17:36:08 -080099
Robin Thellend6b17da72014-05-14 09:55:14 -0700100<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
101suffix (s, m, h). A value of 0s represents an infinite duration.
Robin Thellend58206662015-02-17 17:36:08 -0800102
103[M|R] are mount options. M indicates that <name> is a mounttable. R indicates
104that existing entries should be removed.
Robin Thellend6b17da72014-05-14 09:55:14 -0700105`,
106}
107
108func runMount(cmd *cmdline.Command, args []string) error {
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700109 got := len(args)
110 if got < 2 || got > 4 {
111 return cmd.UsageErrorf("mount: incorrect number of arguments, expected 2, 3, or 4, got %d", got)
112 }
Asim Shankarb2cc1292015-02-23 15:22:45 -0800113 name := args[0]
114 server := args[1]
Todd Wang1aa57692014-11-11 13:53:29 -0800115 var flags naming.MountFlag
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700116 var seconds uint32
117 if got >= 3 {
118 ttl, err := time.ParseDuration(args[2])
119 if err != nil {
120 return fmt.Errorf("TTL parse error: %v", err)
121 }
122 seconds = uint32(ttl.Seconds())
123 }
124 if got >= 4 {
125 for _, c := range args[3] {
126 switch c {
127 case 'M':
Todd Wang1aa57692014-11-11 13:53:29 -0800128 flags |= naming.MountFlag(naming.MT)
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700129 case 'R':
Todd Wang1aa57692014-11-11 13:53:29 -0800130 flags |= naming.MountFlag(naming.Replace)
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700131 }
132 }
Robin Thellend6b17da72014-05-14 09:55:14 -0700133 }
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800134 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700135 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800136 client := v23.GetClient(ctx)
Asim Shankarb2cc1292015-02-23 15:22:45 -0800137
138 patterns := flagMountBlessingPatterns.list
139 if len(patterns) == 0 {
140 var err error
141 if patterns, err = blessingPatternsFromServer(ctx, server); err != nil {
142 return err
143 }
144 vlog.Infof("Server at %q has blessings %v", name, patterns)
145 }
146 call, err := client.StartCall(ctx, name, "MountX", []interface{}{server, patterns, seconds, flags}, options.NoResolve{})
Robin Thellend6b17da72014-05-14 09:55:14 -0700147 if err != nil {
148 return err
149 }
Todd Wange77f9952015-02-18 13:20:50 -0800150 if err := call.Finish(); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -0800151 return err
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700152 }
Robin Thellend6b17da72014-05-14 09:55:14 -0700153 fmt.Fprintln(cmd.Stdout(), "Name mounted successfully.")
154 return nil
155}
156
157var cmdUnmount = &cmdline.Command{
158 Run: runUnmount,
159 Name: "unmount",
160 Short: "removes server <name> from the mount table",
161 Long: "removes server <name> from the mount table",
162 ArgsName: "<mount name> <name>",
163 ArgsLong: `
164<mount name> is a mount name on a mount table.
Bogdan Capritad9281a32014-07-02 14:40:39 -0700165<name> is the rooted object name of the server.
Robin Thellend6b17da72014-05-14 09:55:14 -0700166`,
167}
168
169func runUnmount(cmd *cmdline.Command, args []string) error {
170 if expected, got := 2, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700171 return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -0700172 }
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800173 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700174 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800175 client := v23.GetClient(ctx)
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800176 call, err := client.StartCall(ctx, args[0], "Unmount", []interface{}{args[1]}, options.NoResolve{})
Robin Thellend6b17da72014-05-14 09:55:14 -0700177 if err != nil {
178 return err
179 }
Todd Wange77f9952015-02-18 13:20:50 -0800180 if err := call.Finish(); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -0800181 return err
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700182 }
David Why Use Two When One Will Do Presottoe250ae92015-02-19 16:32:35 -0800183 fmt.Fprintln(cmd.Stdout(), "Unmount successful or name not mounted.")
Todd Wange77f9952015-02-18 13:20:50 -0800184 return nil
Robin Thellend6b17da72014-05-14 09:55:14 -0700185}
186
187var cmdResolveStep = &cmdline.Command{
188 Run: runResolveStep,
189 Name: "resolvestep",
190 Short: "takes the next step in resolving a name.",
191 Long: "takes the next step in resolving a name.",
192 ArgsName: "<mount name>",
193 ArgsLong: `
194<mount name> is a mount name on a mount table.
195`,
196}
197
198func runResolveStep(cmd *cmdline.Command, args []string) error {
199 if expected, got := 1, len(args); expected != got {
Todd Wanga615e4d2014-09-29 16:56:05 -0700200 return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -0700201 }
Matt Rosencrantza5ad2722015-01-22 11:17:47 -0800202 ctx, cancel := context.WithTimeout(gctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700203 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800204 client := v23.GetClient(ctx)
David Why Use Two When One Will Do Presottod3aa6632015-01-20 10:15:39 -0800205 call, err := client.StartCall(ctx, args[0], "ResolveStep", []interface{}{}, options.NoResolve{})
Robin Thellend6b17da72014-05-14 09:55:14 -0700206 if err != nil {
David Why Use Two When One Will Do Presotto8b4dbbf2014-11-06 10:50:14 -0800207 return err
Robin Thellend6b17da72014-05-14 09:55:14 -0700208 }
Todd Wang1aa57692014-11-11 13:53:29 -0800209 var entry naming.VDLMountEntry
Todd Wange77f9952015-02-18 13:20:50 -0800210 if err := call.Finish(&entry); err != nil {
Robin Thellend6b17da72014-05-14 09:55:14 -0700211 return err
212 }
David Why Use Two When One Will Do Presotto6f9f5742014-10-20 16:27:05 -0700213 fmt.Fprintf(cmd.Stdout(), "Servers: %v Suffix: %q MT: %v\n", entry.Servers, entry.Name, entry.MT)
Robin Thellend6b17da72014-05-14 09:55:14 -0700214 return nil
215}
216
Robin Thellend18205cf2014-10-21 13:53:59 -0700217func root() *cmdline.Command {
Asim Shankarb2cc1292015-02-23 15:22:45 -0800218 cmdMount.Flags.Var(&flagMountBlessingPatterns, "blessing_pattern", "blessing pattern that matches the blessings of the server being mounted. Can be specified multiple times to add multiple patterns. If none is provided, the server will be contacted to determine this value.")
Robin Thellend6b17da72014-05-14 09:55:14 -0700219 return &cmdline.Command{
Todd Wangfcb72a52014-10-01 09:53:56 -0700220 Name: "mounttable",
221 Short: "Tool for interacting with a Veyron mount table",
222 Long: `
223The mounttable tool facilitates interaction with a Veyron mount table.
224`,
Robin Thellend6b17da72014-05-14 09:55:14 -0700225 Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolveStep},
226 }
227}
Asim Shankarb2cc1292015-02-23 15:22:45 -0800228
229func blessingPatternsFromServer(ctx *context.T, server string) ([]security.BlessingPattern, error) {
230 vlog.Infof("Contacting %q to determine the blessings presented by it", server)
231 ctx, cancel := context.WithTimeout(ctx, time.Minute)
232 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800233 call, err := v23.GetClient(ctx).StartCall(ctx, server, ipc.ReservedSignature, nil)
Asim Shankarb2cc1292015-02-23 15:22:45 -0800234 if err != nil {
235 return nil, fmt.Errorf("Unable to extract blessings presented by %q: %v", server, err)
236 }
237 blessings, _ := call.RemoteBlessings()
238 if len(blessings) == 0 {
239 return nil, fmt.Errorf("No recognizable blessings presented by %q, it cannot be securely mounted", server)
240 }
241 // This translation between BlessingPattern and string is silly!
242 // Kill the BlessingPatterns type and make methods on that type
243 // functions instead!
244 patterns := make([]security.BlessingPattern, len(blessings))
245 for i := range blessings {
246 patterns[i] = security.BlessingPattern(blessings[i])
247 }
248 return patterns, nil
249}