blob: f3b49746caae19dd36610f36ceaa34ebb0b0a61f [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Todd Wang338f90c2015-05-07 19:42:46 -07005// The following enables go generate to generate the doc.go file.
Nicolas Lacasse1b1b9382015-09-24 10:00:35 -07006//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go .
Todd Wang338f90c2015-05-07 19:42:46 -07007
Robin Thellend18205cf2014-10-21 13:53:59 -07008package main
Robin Thellend6b17da72014-05-14 09:55:14 -07009
10import (
Robin Thellend39ac3232014-12-02 09:50:41 -080011 "errors"
Robin Thellend6b17da72014-05-14 09:55:14 -070012 "fmt"
Todd Wang1624bf92015-04-22 16:53:57 -070013 "regexp"
Robin Thellend6b17da72014-05-14 09:55:14 -070014 "time"
15
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070016 "v.io/x/lib/cmdline"
17
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23"
19 "v.io/v23/context"
Jiri Simsa6ac95222015-02-23 16:11:49 -080020 "v.io/v23/naming"
21 "v.io/v23/options"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070022 "v.io/v23/rpc"
Jiri Simsa6ac95222015-02-23 16:11:49 -080023 "v.io/v23/security"
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070024
Todd Wang338f90c2015-05-07 19:42:46 -070025 "v.io/x/ref/lib/v23cmd"
Suharsh Sivakumardcc11d72015-05-11 12:19:20 -070026 _ "v.io/x/ref/runtime/factories/generic"
Robin Thellend6b17da72014-05-14 09:55:14 -070027)
28
Todd Wang338f90c2015-05-07 19:42:46 -070029func main() {
Todd Wang9560b9c2015-05-11 13:27:58 -070030 cmdline.HideGlobalFlagsExcept(regexp.MustCompile(`^v23\.namespace\.root$`))
31 cmdline.Main(cmdRoot)
Todd Wang1624bf92015-04-22 16:53:57 -070032}
33
Todd Wang9560b9c2015-05-11 13:27:58 -070034var cmdGlob = &cmdline.Command{
Todd Wang338f90c2015-05-07 19:42:46 -070035 Runner: v23cmd.RunnerFunc(runGlob),
Robin Thellend6b17da72014-05-14 09:55:14 -070036 Name: "glob",
37 Short: "returns all matching entries in the mount table",
38 Long: "returns all matching entries in the mount table",
Bogdan Capritadecd1052014-11-08 16:15:54 -080039 ArgsName: "[<mount name>] <pattern>",
Robin Thellend6b17da72014-05-14 09:55:14 -070040 ArgsLong: `
Bogdan Capritadecd1052014-11-08 16:15:54 -080041<mount name> is a mount name on a mount table. Defaults to namespace root.
Robin Thellend6b17da72014-05-14 09:55:14 -070042<pattern> is a glob pattern that is matched against all the entries below the
43specified mount name.
44`,
45}
46
Todd Wang9560b9c2015-05-11 13:27:58 -070047func runGlob(ctx *context.T, env *cmdline.Env, args []string) error {
Todd Wang338f90c2015-05-07 19:42:46 -070048 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantzd599e382015-01-12 11:13:32 -080049 defer cancel()
50
Bogdan Capritadecd1052014-11-08 16:15:54 -080051 if len(args) == 1 {
Jiri Simsa6ac95222015-02-23 16:11:49 -080052 roots := v23.GetNamespace(ctx).Roots()
Robin Thellend39ac3232014-12-02 09:50:41 -080053 if len(roots) == 0 {
54 return errors.New("no namespace root")
55 }
56 args = append([]string{roots[0]}, args...)
Bogdan Capritadecd1052014-11-08 16:15:54 -080057 }
Robin Thellend6b17da72014-05-14 09:55:14 -070058 if expected, got := 2, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -070059 return env.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -070060 }
Matt Rosencrantzd599e382015-01-12 11:13:32 -080061
Robin Thellend39ac3232014-12-02 09:50:41 -080062 name, pattern := args[0], args[1]
Jiri Simsa6ac95222015-02-23 16:11:49 -080063 client := v23.GetClient(ctx)
David Why Use Two When One Will Do Presottoc2798412015-09-08 12:53:34 -070064 call, err := client.StartCall(ctx, name, rpc.GlobMethod, []interface{}{pattern}, options.Preresolved{})
Robin Thellend6b17da72014-05-14 09:55:14 -070065 if err != nil {
66 return err
67 }
Robin Thellend39ac3232014-12-02 09:50:41 -080068 for {
Todd Wang2331dd02015-03-17 15:38:39 -070069 var gr naming.GlobReply
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080070 if err := call.Recv(&gr); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -080071 break
72 }
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080073 switch v := gr.(type) {
Todd Wang2331dd02015-03-17 15:38:39 -070074 case naming.GlobReplyEntry:
Todd Wang338f90c2015-05-07 19:42:46 -070075 fmt.Fprint(env.Stdout, v.Value.Name)
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080076 for _, s := range v.Value.Servers {
Todd Wang338f90c2015-05-07 19:42:46 -070077 fmt.Fprintf(env.Stdout, " %s (Deadline %s)", s.Server, s.Deadline.Time)
David Why Use Two When One Will Do Presottoe5e62d02015-02-19 14:35:20 -080078 }
Todd Wang338f90c2015-05-07 19:42:46 -070079 fmt.Fprintln(env.Stdout)
Robin Thellend6b17da72014-05-14 09:55:14 -070080 }
Robin Thellend6b17da72014-05-14 09:55:14 -070081 }
Todd Wange77f9952015-02-18 13:20:50 -080082 if err := call.Finish(); err != nil {
83 return err
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -070084 }
Todd Wange77f9952015-02-18 13:20:50 -080085 return nil
Robin Thellend6b17da72014-05-14 09:55:14 -070086}
87
Todd Wang9560b9c2015-05-11 13:27:58 -070088var cmdMount = &cmdline.Command{
Todd Wang338f90c2015-05-07 19:42:46 -070089 Runner: v23cmd.RunnerFunc(runMount),
Robin Thellend6b17da72014-05-14 09:55:14 -070090 Name: "mount",
91 Short: "Mounts a server <name> onto a mount table",
92 Long: "Mounts a server <name> onto a mount table",
Robin Thellend58206662015-02-17 17:36:08 -080093 ArgsName: "<mount name> <name> <ttl> [M|R]",
Robin Thellend6b17da72014-05-14 09:55:14 -070094 ArgsLong: `
95<mount name> is a mount name on a mount table.
Robin Thellend58206662015-02-17 17:36:08 -080096
Bogdan Capritad9281a32014-07-02 14:40:39 -070097<name> is the rooted object name of the server.
Robin Thellend58206662015-02-17 17:36:08 -080098
Robin Thellend6b17da72014-05-14 09:55:14 -070099<ttl> is the TTL of the new entry. It is a decimal number followed by a unit
100suffix (s, m, h). A value of 0s represents an infinite duration.
Robin Thellend58206662015-02-17 17:36:08 -0800101
102[M|R] are mount options. M indicates that <name> is a mounttable. R indicates
103that existing entries should be removed.
Robin Thellend6b17da72014-05-14 09:55:14 -0700104`,
105}
106
Todd Wang9560b9c2015-05-11 13:27:58 -0700107func runMount(ctx *context.T, env *cmdline.Env, args []string) error {
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700108 got := len(args)
109 if got < 2 || got > 4 {
Todd Wang338f90c2015-05-07 19:42:46 -0700110 return env.UsageErrorf("mount: incorrect number of arguments, expected 2, 3, or 4, got %d", got)
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700111 }
Asim Shankarb2cc1292015-02-23 15:22:45 -0800112 name := args[0]
113 server := args[1]
Cosmos Nicolaou036c30c2015-03-24 10:05:20 -0700114
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 }
Todd Wang338f90c2015-05-07 19:42:46 -0700134 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700135 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800136 client := v23.GetClient(ctx)
David Why Use Two When One Will Do Presottoc2798412015-09-08 12:53:34 -0700137 if err := client.Call(ctx, name, "Mount", []interface{}{server, seconds, flags}, nil, options.Preresolved{}); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -0800138 return err
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700139 }
Todd Wang338f90c2015-05-07 19:42:46 -0700140 fmt.Fprintln(env.Stdout, "Name mounted successfully.")
Robin Thellend6b17da72014-05-14 09:55:14 -0700141 return nil
142}
143
Todd Wang9560b9c2015-05-11 13:27:58 -0700144var cmdUnmount = &cmdline.Command{
Todd Wang338f90c2015-05-07 19:42:46 -0700145 Runner: v23cmd.RunnerFunc(runUnmount),
Robin Thellend6b17da72014-05-14 09:55:14 -0700146 Name: "unmount",
147 Short: "removes server <name> from the mount table",
148 Long: "removes server <name> from the mount table",
149 ArgsName: "<mount name> <name>",
150 ArgsLong: `
151<mount name> is a mount name on a mount table.
Bogdan Capritad9281a32014-07-02 14:40:39 -0700152<name> is the rooted object name of the server.
Robin Thellend6b17da72014-05-14 09:55:14 -0700153`,
154}
155
Todd Wang9560b9c2015-05-11 13:27:58 -0700156func runUnmount(ctx *context.T, env *cmdline.Env, args []string) error {
Robin Thellend6b17da72014-05-14 09:55:14 -0700157 if expected, got := 2, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700158 return env.UsageErrorf("unmount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -0700159 }
Todd Wang338f90c2015-05-07 19:42:46 -0700160 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700161 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800162 client := v23.GetClient(ctx)
David Why Use Two When One Will Do Presottoc2798412015-09-08 12:53:34 -0700163 if err := client.Call(ctx, args[0], "Unmount", []interface{}{args[1]}, nil, options.Preresolved{}); err != nil {
Robin Thellend39ac3232014-12-02 09:50:41 -0800164 return err
David Why Use Two When One Will Do Presotto59a254c2014-10-30 13:09:29 -0700165 }
Todd Wang338f90c2015-05-07 19:42:46 -0700166 fmt.Fprintln(env.Stdout, "Unmount successful or name not mounted.")
Todd Wange77f9952015-02-18 13:20:50 -0800167 return nil
Robin Thellend6b17da72014-05-14 09:55:14 -0700168}
169
Todd Wang9560b9c2015-05-11 13:27:58 -0700170var cmdResolveStep = &cmdline.Command{
Todd Wang338f90c2015-05-07 19:42:46 -0700171 Runner: v23cmd.RunnerFunc(runResolveStep),
Robin Thellend6b17da72014-05-14 09:55:14 -0700172 Name: "resolvestep",
173 Short: "takes the next step in resolving a name.",
174 Long: "takes the next step in resolving a name.",
175 ArgsName: "<mount name>",
176 ArgsLong: `
177<mount name> is a mount name on a mount table.
178`,
179}
180
Todd Wang9560b9c2015-05-11 13:27:58 -0700181func runResolveStep(ctx *context.T, env *cmdline.Env, args []string) error {
Robin Thellend6b17da72014-05-14 09:55:14 -0700182 if expected, got := 1, len(args); expected != got {
Todd Wang338f90c2015-05-07 19:42:46 -0700183 return env.UsageErrorf("mount: incorrect number of arguments, expected %d, got %d", expected, got)
Robin Thellend6b17da72014-05-14 09:55:14 -0700184 }
Todd Wang338f90c2015-05-07 19:42:46 -0700185 ctx, cancel := context.WithTimeout(ctx, time.Minute)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700186 defer cancel()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800187 client := v23.GetClient(ctx)
Todd Wang2331dd02015-03-17 15:38:39 -0700188 var entry naming.MountEntry
David Why Use Two When One Will Do Presottoc2798412015-09-08 12:53:34 -0700189 if err := client.Call(ctx, args[0], "ResolveStep", nil, []interface{}{&entry}, options.Preresolved{}); err != nil {
Robin Thellend6b17da72014-05-14 09:55:14 -0700190 return err
191 }
Todd Wang338f90c2015-05-07 19:42:46 -0700192 fmt.Fprintf(env.Stdout, "Servers: %v Suffix: %q MT: %v\n", entry.Servers, entry.Name, entry.ServesMountTable)
Robin Thellend6b17da72014-05-14 09:55:14 -0700193 return nil
194}
195
Todd Wang9560b9c2015-05-11 13:27:58 -0700196var cmdRoot = &cmdline.Command{
Todd Wang338f90c2015-05-07 19:42:46 -0700197 Name: "mounttable",
198 Short: "sends commands to Vanadium mounttable services",
199 Long: `
Todd Wang6ed3b6c2015-04-08 14:37:04 -0700200Command mounttable sends commands to Vanadium mounttable services.
Todd Wangfcb72a52014-10-01 09:53:56 -0700201`,
Todd Wang9560b9c2015-05-11 13:27:58 -0700202 Children: []*cmdline.Command{cmdGlob, cmdMount, cmdUnmount, cmdResolveStep},
Robin Thellend6b17da72014-05-14 09:55:14 -0700203}
Asim Shankarb2cc1292015-02-23 15:22:45 -0800204
205func blessingPatternsFromServer(ctx *context.T, server string) ([]security.BlessingPattern, error) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700206 ctx.Infof("Contacting %q to determine the blessings presented by it", server)
Asim Shankarb2cc1292015-02-23 15:22:45 -0800207 ctx, cancel := context.WithTimeout(ctx, time.Minute)
208 defer cancel()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700209 call, err := v23.GetClient(ctx).StartCall(ctx, server, rpc.ReservedSignature, nil)
Asim Shankarb2cc1292015-02-23 15:22:45 -0800210 if err != nil {
211 return nil, fmt.Errorf("Unable to extract blessings presented by %q: %v", server, err)
212 }
213 blessings, _ := call.RemoteBlessings()
214 if len(blessings) == 0 {
215 return nil, fmt.Errorf("No recognizable blessings presented by %q, it cannot be securely mounted", server)
216 }
217 // This translation between BlessingPattern and string is silly!
218 // Kill the BlessingPatterns type and make methods on that type
219 // functions instead!
220 patterns := make([]security.BlessingPattern, len(blessings))
221 for i := range blessings {
222 patterns[i] = security.BlessingPattern(blessings[i])
223 }
224 return patterns, nil
225}