Robin Thellend | 18205cf | 2014-10-21 13:53:59 -0700 | [diff] [blame] | 1 | package main |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 2 | |
| 3 | import ( |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 4 | "errors" |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 5 | "fmt" |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 6 | "time" |
| 7 | |
Todd Wang | 478fcf9 | 2014-12-26 12:37:37 -0800 | [diff] [blame] | 8 | "v.io/lib/cmdline" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 9 | "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 Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 16 | ) |
| 17 | |
| 18 | var 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 Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 23 | ArgsName: "[<mount name>] <pattern>", |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 24 | ArgsLong: ` |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 25 | <mount name> is a mount name on a mount table. Defaults to namespace root. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 26 | <pattern> is a glob pattern that is matched against all the entries below the |
| 27 | specified mount name. |
| 28 | `, |
| 29 | } |
| 30 | |
| 31 | func runGlob(cmd *cmdline.Command, args []string) error { |
Matt Rosencrantz | a5ad272 | 2015-01-22 11:17:47 -0800 | [diff] [blame] | 32 | ctx, cancel := context.WithTimeout(gctx, time.Minute) |
Matt Rosencrantz | d599e38 | 2015-01-12 11:13:32 -0800 | [diff] [blame] | 33 | defer cancel() |
| 34 | |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 35 | if len(args) == 1 { |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 36 | roots := v23.GetNamespace(ctx).Roots() |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 37 | if len(roots) == 0 { |
| 38 | return errors.New("no namespace root") |
| 39 | } |
| 40 | args = append([]string{roots[0]}, args...) |
Bogdan Caprita | decd105 | 2014-11-08 16:15:54 -0800 | [diff] [blame] | 41 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 42 | if expected, got := 2, len(args); expected != got { |
Todd Wang | a615e4d | 2014-09-29 16:56:05 -0700 | [diff] [blame] | 43 | return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 44 | } |
Matt Rosencrantz | d599e38 | 2015-01-12 11:13:32 -0800 | [diff] [blame] | 45 | |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 46 | name, pattern := args[0], args[1] |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 47 | client := v23.GetClient(ctx) |
Matt Rosencrantz | 6edab56 | 2015-01-12 11:07:55 -0800 | [diff] [blame] | 48 | call, err := client.StartCall(ctx, name, ipc.GlobMethod, []interface{}{pattern}, options.NoResolve{}) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 49 | if err != nil { |
| 50 | return err |
| 51 | } |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 52 | for { |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 53 | var gr naming.VDLGlobReply |
| 54 | if err := call.Recv(&gr); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 55 | break |
| 56 | } |
David Why Use Two When One Will Do Presotto | e5e62d0 | 2015-02-19 14:35:20 -0800 | [diff] [blame] | 57 | 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 Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 64 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 65 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 66 | if err := call.Finish(); err != nil { |
| 67 | return err |
Shyam Jayaraman | c4aed6e | 2014-07-22 14:25:06 -0700 | [diff] [blame] | 68 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 69 | return nil |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 70 | } |
| 71 | |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 72 | type blessingPatterns struct { |
| 73 | list []security.BlessingPattern |
| 74 | } |
| 75 | |
| 76 | func (bp *blessingPatterns) Set(s string) error { |
| 77 | bp.list = append(bp.list, security.BlessingPattern(s)) |
| 78 | return nil |
| 79 | } |
| 80 | |
| 81 | func (bp *blessingPatterns) String() string { |
| 82 | return fmt.Sprintf("%v", bp.list) |
| 83 | } |
| 84 | |
| 85 | func (bp *blessingPatterns) Get() interface{} { return bp.list } |
| 86 | |
| 87 | var flagMountBlessingPatterns blessingPatterns |
| 88 | |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 89 | var 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 Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 94 | ArgsName: "<mount name> <name> <ttl> [M|R]", |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 95 | ArgsLong: ` |
| 96 | <mount name> is a mount name on a mount table. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 97 | |
Bogdan Caprita | d9281a3 | 2014-07-02 14:40:39 -0700 | [diff] [blame] | 98 | <name> is the rooted object name of the server. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 99 | |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 100 | <ttl> is the TTL of the new entry. It is a decimal number followed by a unit |
| 101 | suffix (s, m, h). A value of 0s represents an infinite duration. |
Robin Thellend | 5820666 | 2015-02-17 17:36:08 -0800 | [diff] [blame] | 102 | |
| 103 | [M|R] are mount options. M indicates that <name> is a mounttable. R indicates |
| 104 | that existing entries should be removed. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 105 | `, |
| 106 | } |
| 107 | |
| 108 | func runMount(cmd *cmdline.Command, args []string) error { |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 109 | 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 Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 113 | name := args[0] |
| 114 | server := args[1] |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 115 | var flags naming.MountFlag |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 116 | 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 Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 128 | flags |= naming.MountFlag(naming.MT) |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 129 | case 'R': |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 130 | flags |= naming.MountFlag(naming.Replace) |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 131 | } |
| 132 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 133 | } |
Matt Rosencrantz | a5ad272 | 2015-01-22 11:17:47 -0800 | [diff] [blame] | 134 | ctx, cancel := context.WithTimeout(gctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 135 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 136 | client := v23.GetClient(ctx) |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 137 | |
| 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 Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 147 | if err != nil { |
| 148 | return err |
| 149 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 150 | if err := call.Finish(); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 151 | return err |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 152 | } |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 153 | fmt.Fprintln(cmd.Stdout(), "Name mounted successfully.") |
| 154 | return nil |
| 155 | } |
| 156 | |
| 157 | var 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 Caprita | d9281a3 | 2014-07-02 14:40:39 -0700 | [diff] [blame] | 165 | <name> is the rooted object name of the server. |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 166 | `, |
| 167 | } |
| 168 | |
| 169 | func runUnmount(cmd *cmdline.Command, args []string) error { |
| 170 | if expected, got := 2, len(args); expected != got { |
Todd Wang | a615e4d | 2014-09-29 16:56:05 -0700 | [diff] [blame] | 171 | return cmd.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 172 | } |
Matt Rosencrantz | a5ad272 | 2015-01-22 11:17:47 -0800 | [diff] [blame] | 173 | ctx, cancel := context.WithTimeout(gctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 174 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 175 | client := v23.GetClient(ctx) |
Matt Rosencrantz | 6edab56 | 2015-01-12 11:07:55 -0800 | [diff] [blame] | 176 | call, err := client.StartCall(ctx, args[0], "Unmount", []interface{}{args[1]}, options.NoResolve{}) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 177 | if err != nil { |
| 178 | return err |
| 179 | } |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 180 | if err := call.Finish(); err != nil { |
Robin Thellend | 39ac323 | 2014-12-02 09:50:41 -0800 | [diff] [blame] | 181 | return err |
David Why Use Two When One Will Do Presotto | 59a254c | 2014-10-30 13:09:29 -0700 | [diff] [blame] | 182 | } |
David Why Use Two When One Will Do Presotto | e250ae9 | 2015-02-19 16:32:35 -0800 | [diff] [blame] | 183 | fmt.Fprintln(cmd.Stdout(), "Unmount successful or name not mounted.") |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 184 | return nil |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | var 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 | |
| 198 | func runResolveStep(cmd *cmdline.Command, args []string) error { |
| 199 | if expected, got := 1, len(args); expected != got { |
Todd Wang | a615e4d | 2014-09-29 16:56:05 -0700 | [diff] [blame] | 200 | return cmd.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 201 | } |
Matt Rosencrantz | a5ad272 | 2015-01-22 11:17:47 -0800 | [diff] [blame] | 202 | ctx, cancel := context.WithTimeout(gctx, time.Minute) |
Matt Rosencrantz | 137b8d2 | 2014-08-18 09:56:15 -0700 | [diff] [blame] | 203 | defer cancel() |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 204 | client := v23.GetClient(ctx) |
David Why Use Two When One Will Do Presotto | d3aa663 | 2015-01-20 10:15:39 -0800 | [diff] [blame] | 205 | call, err := client.StartCall(ctx, args[0], "ResolveStep", []interface{}{}, options.NoResolve{}) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 206 | if err != nil { |
David Why Use Two When One Will Do Presotto | 8b4dbbf | 2014-11-06 10:50:14 -0800 | [diff] [blame] | 207 | return err |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 208 | } |
Todd Wang | 1aa5769 | 2014-11-11 13:53:29 -0800 | [diff] [blame] | 209 | var entry naming.VDLMountEntry |
Todd Wang | e77f995 | 2015-02-18 13:20:50 -0800 | [diff] [blame] | 210 | if err := call.Finish(&entry); err != nil { |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 211 | return err |
| 212 | } |
David Why Use Two When One Will Do Presotto | 6f9f574 | 2014-10-20 16:27:05 -0700 | [diff] [blame] | 213 | fmt.Fprintf(cmd.Stdout(), "Servers: %v Suffix: %q MT: %v\n", entry.Servers, entry.Name, entry.MT) |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 214 | return nil |
| 215 | } |
| 216 | |
Robin Thellend | 18205cf | 2014-10-21 13:53:59 -0700 | [diff] [blame] | 217 | func root() *cmdline.Command { |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 218 | 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 Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 219 | return &cmdline.Command{ |
Todd Wang | fcb72a5 | 2014-10-01 09:53:56 -0700 | [diff] [blame] | 220 | Name: "mounttable", |
| 221 | Short: "Tool for interacting with a Veyron mount table", |
| 222 | Long: ` |
| 223 | The mounttable tool facilitates interaction with a Veyron mount table. |
| 224 | `, |
Robin Thellend | 6b17da7 | 2014-05-14 09:55:14 -0700 | [diff] [blame] | 225 | Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolveStep}, |
| 226 | } |
| 227 | } |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 228 | |
| 229 | func 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 Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 233 | call, err := v23.GetClient(ctx).StartCall(ctx, server, ipc.ReservedSignature, nil) |
Asim Shankar | b2cc129 | 2015-02-23 15:22:45 -0800 | [diff] [blame] | 234 | 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 | } |