"physical-lock": Simplify scanning for lock devices
This CL simplifies the mechanism for discovering lock
devices by globbing the neighborhood.
Major changes
1) neighborhood-name under which a lock device's mounttable
is made visible is always of the form "lock-<lock name>", regardless of
whether the lock is claimed or unclaimed. Therefore discovering
lock devices simply requires a glob with the pattern "nh/lock-*".
This is a purely local operation at the clients. All locks objects
are accessible, by convention, under the name "nh/lock-<lock name>/lock.
2) The command for scanning lock objects globs over the neighborhood
in a loop in order to accomodate for any time lags in listening to MDNS
advertisments from the lock devices.
Minor change:
The command for scanning for lock objects is renamed from "find-locks"
to "scan".
Change-Id: Ie95b7dcffae7bc3a67de6b06b2e125a2359b09f4
diff --git a/go/src/v.io/x/lock/lock/main.go b/go/src/v.io/x/lock/lock/main.go
index 0ef63b2..2ea6e82 100644
--- a/go/src/v.io/x/lock/lock/main.go
+++ b/go/src/v.io/x/lock/lock/main.go
@@ -25,10 +25,11 @@
)
var (
- cmdFindLocks = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runFindLocks),
- Name: "findlocks",
- Short: "Find locks objects mounted in the neighborhood",
+ lockGlobPattern = path.Join("nh", locklib.LockNhPrefix+"*")
+ cmdScan = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runScan),
+ Name: "scan",
+ Short: "Scan the neighborhood for lock objects",
Long: `
Globs over the neighborhood to find names of lock objects (both claimed
and unclaimed).
@@ -87,67 +88,38 @@
}
)
-func runFindLocks(ctx *context.T, env *cmdline.Env, args []string) error {
- const (
- unclaimedSuffix = "[UNCLAIMED]"
- claimedSuffix = "[CLAIMED]"
- )
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
- defer cancel()
+func runScan(ctx *context.T, env *cmdline.Env, args []string) error {
ctx, stop, err := withLocalNamespace(ctx)
if err != nil {
return err
}
defer stop()
- ns := v23.GetNamespace(ctx)
- // TODO(ataly): Currently we simply glob over the neighborhood with
- // specific patterns to find claimed and unclaimed locks, and print
- // all the names found. Longer term, we should print a name only after
- // verifying that the object that the name resolves to exposes the
- // appropricate Lock or UnclaimedLock interface and authenticates with
- // blessings that are recognized by this client.
-
- unclaimedCh, err := ns.Glob(ctx, path.Join("nh", locklib.UnclaimedLockNeighborhood, "*"))
- if err != nil {
- return err
- }
- claimedCh, err := ns.Glob(ctx, path.Join("nh", locklib.ClaimedLockNeighborhood, "*"))
- if err != nil {
- // TODO(ataly): We should drain unclaimedCh to avoid a gorouting leak.
- return err
- }
- loop := true
- for loop {
- select {
- case v, ok := <-unclaimedCh:
- if !ok {
- loop = false
- } else {
- printObjectName(v, unclaimedSuffix)
- }
- case v, ok := <-claimedCh:
- if !ok {
- loop = false
- } else {
- printObjectName(v, claimedSuffix)
- }
+ locksFound := make(map[string]bool)
+ fmt.Println("Scanning for Locks...")
+ for {
+ ch, err := v23.GetNamespace(ctx).Glob(ctx, lockGlobPattern)
+ if err != nil {
+ return err
}
- }
- for v := range unclaimedCh {
- printObjectName(v, unclaimedSuffix)
- }
- for v := range claimedCh {
- printObjectName(v, claimedSuffix)
- }
- return nil
-}
+ for v := range ch {
+ switch entry := v.(type) {
+ case *naming.GlobReplyEntry:
+ if name, servers := entry.Value.Name, entry.Value.Servers; len(name) != 0 && !locksFound[name] && len(servers) != 0 {
+ epStr, _ := naming.SplitAddressName(servers[0].Server)
+ ep, err := v23.NewEndpoint(epStr)
+ if err != nil {
+ continue
+ }
-func printObjectName(glob naming.GlobReply, suffix string) {
- switch v := glob.(type) {
- case *naming.GlobReplyEntry:
- if v.Value.Name != "" {
- fmt.Println(v.Value.Name, suffix)
+ locksFound[name] = true
+ if bn := ep.BlessingNames(); len(bn) != 0 {
+ fmt.Printf("%v [owned by %v]\n", name, bn)
+ } else {
+ fmt.Printf("%v\n", name)
+ }
+ }
+ }
}
}
}
@@ -157,17 +129,19 @@
return fmt.Errorf("requires exactly two arguments <lock>, <name>, provided %d", numargs)
}
lockname, name := args[0], args[1]
+ lockname = path.Join(lockname, locklib.LockSuffix)
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
- defer cancel()
ctx, stop, err := withLocalNamespace(ctx)
if err != nil {
return err
}
defer stop()
- // Skip server endpoint authorization since an unclaimed lock would have
- // roots that will not be recognized by the claimer.
+ ctx, cancel := context.WithTimeout(ctx, time.Minute)
+ defer cancel()
+ // TODO(ataly): We should not skip server endpoint authorization while
+ // claiming locks but instead fetch the blessing root of the lock manufacturer
+ // from an authoritative source and then appropriately authenticate the server.
b, err := lock.UnclaimedLockClient(lockname).Claim(ctx, name, options.SkipServerEndpointAuthorization{})
if err != nil {
return err
@@ -197,15 +171,16 @@
return fmt.Errorf("requires exactly one arguments <lock>, provided %d", numargs)
}
lockname := args[0]
+ lockname = path.Join(lockname, locklib.LockSuffix)
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
- defer cancel()
ctx, stop, err := withLocalNamespace(ctx)
if err != nil {
return err
}
defer stop()
+ ctx, cancel := context.WithTimeout(ctx, time.Minute)
+ defer cancel()
if status == lock.Locked {
err = lock.LockClient(lockname).Lock(ctx)
} else {
@@ -224,15 +199,16 @@
return fmt.Errorf("requires exactly one arguments <lock>, provided %d", numargs)
}
lockname := args[0]
+ lockname = path.Join(lockname, locklib.LockSuffix)
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
- defer cancel()
ctx, stop, err := withLocalNamespace(ctx)
if err != nil {
return err
}
defer stop()
+ ctx, cancel := context.WithTimeout(ctx, time.Minute)
+ defer cancel()
status, err := lock.LockClient(lockname).Status(ctx)
if err != nil {
return err
@@ -285,7 +261,7 @@
Long: `
Command lock claims and manages lock objects.
`,
- Children: []*cmdline.Command{cmdFindLocks, cmdClaim, cmdLock, cmdUnlock, cmdStatus},
+ Children: []*cmdline.Command{cmdScan, cmdClaim, cmdLock, cmdUnlock, cmdStatus},
}
cmdline.Main(root)
}
diff --git a/go/src/v.io/x/lock/lockd/starter.go b/go/src/v.io/x/lock/lockd/starter.go
index cee86b3..f40f56e 100644
--- a/go/src/v.io/x/lock/lockd/starter.go
+++ b/go/src/v.io/x/lock/lockd/starter.go
@@ -6,6 +6,7 @@
import (
"fmt"
+ "math/rand"
"v.io/v23"
"v.io/v23/context"
@@ -16,7 +17,7 @@
"v.io/x/lock/locklib"
)
-const unclaimedLockSuffix = "unclaimed-lock-42"
+var unclaimedLockNhSuffix = "unclaimed-lock-" + fmt.Sprintf("%d", rand.Intn(1000000))
// startServer checks whether the lock has been claimed and then appropriately
// starts the server.
@@ -48,7 +49,7 @@
// Start a local mounttable where the unclaimed lock server would
// be mounted, and make this mounttable visible in the local
// neighborhood.
- mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.UnclaimedLockNeighborhood)
+ mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.LockNhPrefix+unclaimedLockNhSuffix)
if err != nil {
return nil, nil, err
}
@@ -75,8 +76,7 @@
}
claimed := make(chan struct{})
- name := objectName(ctx, unclaimedLockSuffix)
- if err := server.Serve(name, newUnclaimedLock(claimed, configDir), security.AllowEveryone()); err != nil {
+ if err := server.Serve(lockObjectName(ctx), newUnclaimedLock(claimed, configDir), security.AllowEveryone()); err != nil {
stopUnclaimedLock()
return nil, nil, err
}
@@ -87,10 +87,11 @@
}
func startLockServer(ctx *context.T, configDir string) (func(), error) {
+ lockNhSuffix := fmt.Sprintf("%v", v23.GetPrincipal(ctx).BlessingStore().Default())
// Start a local mounttable where the lock server would be
// mounted, and make this mounttable visible in the local
// neighborhood.
- mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.ClaimedLockNeighborhood)
+ mtName, stopMT, err := locklib.StartMounttable(ctx, configDir, locklib.LockNhPrefix+lockNhSuffix)
if err != nil {
return nil, err
}
@@ -116,8 +117,7 @@
return nil, err
}
- name := objectName(ctx, fmt.Sprintf("%v", v23.GetPrincipal(ctx).BlessingStore().Default()))
- if err := server.Serve(name, newLock(), security.DefaultAuthorizer()); err != nil {
+ if err := server.Serve(lockObjectName(ctx), newLock(), security.DefaultAuthorizer()); err != nil {
stopLock()
return nil, err
}
@@ -145,10 +145,10 @@
<-stop // Wait to be stopped
}
-func objectName(ctx *context.T, suffix string) string {
+func lockObjectName(ctx *context.T) string {
nsroots := v23.GetNamespace(ctx).Roots()
if len(nsroots) == 0 {
return ""
}
- return naming.Join(nsroots[0], suffix)
+ return naming.Join(nsroots[0], locklib.LockSuffix)
}
diff --git a/go/src/v.io/x/lock/locklib/mounttable.go b/go/src/v.io/x/lock/locklib/mounttable.go
index 3028e31..5344ae7 100644
--- a/go/src/v.io/x/lock/locklib/mounttable.go
+++ b/go/src/v.io/x/lock/locklib/mounttable.go
@@ -23,12 +23,13 @@
const (
permsFile = "mounttable.perms"
- // UnclaimedLockNeighborhood is the name in the local neighborhood on which
- // an unclaimed lock server's mounttable is made visible
- UnclaimedLockNeighborhood = "unclaimed-locks"
- // ClaimedLockNeighborhood is the name in the local neighborhood on which
- // a claimed lock server's mounttable is made visible
- ClaimedLockNeighborhood = "locks"
+ // LockSuffix is the name under which a lock server is mounted in its
+ // mounttable.
+ LockSuffix = "lock"
+ // LockNeighborhoodPrefix is a prefix of the name in the local
+ // neighborhood on which a lock server's mounttable is made
+ // visible.
+ LockNhPrefix = "lock-"
)
// StartMounttable starts a local mounttable server with an authorization
@@ -36,7 +37,7 @@
// other operations to the principal specified by the provided context.
//
// The mounttable makes itself visible in the local neighborhood under the
-// provided 'nhName'.
+// name LockNeighborhoodPrefix + <nhName>.
//
// Returns the endpoint of the mounttable server and a callback to
// be invoked to shutdown the mounttable server on success, or an error