From 0b4c024c02e4f7e4844fbbfe908dc233e43ebbb3 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Tue, 11 Apr 2023 17:05:29 -0700 Subject: [PATCH] handle host id mapping on search results.. --- ui/fixtures/cmd.search.json | 45 ++++++++++++++++++++++++++++++---- ui/medashare/cli.py | 48 ++++++++++++++++++++++++++++++++----- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/ui/fixtures/cmd.search.json b/ui/fixtures/cmd.search.json index 504e9f7..ad1a7dc 100644 --- a/ui/fixtures/cmd.search.json +++ b/ui/fixtures/cmd.search.json @@ -4,6 +4,22 @@ "cmd": [ "genident", "name=A Test User" ], "exit": 0 }, +{ + "special": "set hostid", + "hostid": "ceaa4862-dd00-41ba-9787-7480ec1b2679" +}, +{ + "title": "create host", + "cmd": [ "hosts" ] +}, +{ + "special": "set hostid", + "hostid": "efdb5d9c-d123-4b30-aaa8-45a9ea8f6053" +}, +{ + "title": "create host", + "cmd": [ "hosts" ] +}, { "title": "add tag a", "cmd": [ "modify", "+tag=foo", "+dc:creator=John-Mark Gurney", "newfile.txt" ] @@ -14,8 +30,8 @@ }, { "special": "verify store object cnt", - "comment": "should have two file and two metadata", - "count": 4 + "comment": "should have two file and two metadata and two hosts", + "count": 6 }, { "title": "search tag foo", @@ -38,8 +54,29 @@ "stdout_re": "/newfile.txt\n$" }, { - "title": "search other", + "special": "set hostid", + "hostid": "ceaa4862-dd00-41ba-9787-7480ec1b2679" +}, +{ + "title": "test that no mapping works", "cmd": [ "search", "file", "+other" ], - "stdout_re": "/test.txt\n$" + "stdout_re": "^efdb5d9c-d123-4b30-aaa8-45a9ea8f6053:/.*/test.txt\n$" +}, +{ + "special": "set hostid", + "hostid": "efdb5d9c-d123-4b30-aaa8-45a9ea8f6053" +}, +{ + "title": "host mapping works", + "cmd": [ "mapping", "--create", ".", "ceaa4862-dd00-41ba-9787-7480ec1b2679:/foobar" ] +}, +{ + "special": "set hostid", + "hostid": "ceaa4862-dd00-41ba-9787-7480ec1b2679" +}, +{ + "title": "search other, mapped properly", + "cmd": [ "search", "file", "+other" ], + "stdout_re": "^/foobar/test.txt\n$" } ] diff --git a/ui/medashare/cli.py b/ui/medashare/cli.py index 4e3f1a4..473fc7d 100644 --- a/ui/medashare/cli.py +++ b/ui/medashare/cli.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import collections import stat import sys import logging @@ -573,7 +574,7 @@ class ObjectStore(object): return objs - def _get_hostmappings(self): + def get_hostmappings(self): '''Returns the tuple (lclpath, hostid, rempath) for all the mappings for this hostid.''' @@ -620,7 +621,7 @@ class ObjectStore(object): except KeyError: # check mappings fname = pathlib.Path(fname).resolve() - for lclpath, hostid, rempath in self._get_hostmappings(): + for lclpath, hostid, rempath in self.get_hostmappings(): if fname.parts[:len(lclpath.parts)] == lclpath.parts: try: rempath = pathlib.Path( @@ -693,6 +694,40 @@ class FileObject(MDBase): def fullname(self): return os.path.join(self.dir, self.filename) + @staticmethod + def prep_mapping(mapping): + r = collections.defaultdict(lambda: []) + for lclp, hid, remp in mapping: + r[hid].append((pathlib.PosixPath(lclp), + pathlib.PosixPath(remp))) + + return r + + def get_lcl_name(self, mapping): + '''Using mapping (obtained from the object store's + get_hostmappings method and passed through local prep_mapping + method), try to map the file to a local path. + + if not possible, returned will be hostid:remotepath. + ''' + + lclhostid = hostuuid() + + #_debprint('gln:', repr(self), repr(mapping), repr(lclhostid)) + + if self.hostid == lclhostid: + return self.fullname + + for lclp, remp in mapping[self.hostid]: + fname = pathlib.PosixPath(self.fullname) + if fname.parts[:len(remp.parts)] == remp.parts: + return pathlib.Path( + *lclp.parts + + fname.parts[len( + remp.parts):]) + else: + return str(self.hostid) + ':' + self.fullname + @staticmethod def make_id(fname, hostid=None): '''Take a local file name, and make the id for it. Note that @@ -957,9 +992,9 @@ def cmd_mapping(options, persona, objstr, cache): parts = [ x.split(':', 1) for x in options.mapping ] if len(parts[0]) == 1: - parts[0] = [ hostuuid(), parts[0][0] ] + parts[0] = [ str(hostuuid()), parts[0][0] ] - if parts[0][0] == hostuuid(): + if parts[0][0] == str(hostuuid()): parts[0][1] = str(pathlib.Path(parts[0][1]).resolve()) if parts[1][1][0] != '/': @@ -1478,7 +1513,8 @@ def cmd_search(options, persona, objstr, cache): r = ( x for x in objstr if x.type == 'file' and testfun(x) ) if _type == 'file': - r = ( x.fullname for x in r ) + mapping = FileObject.prep_mapping(objstr.get_hostmappings()) + r = ( x.get_lcl_name(mapping) for x in r ) else: raise ValueError('unhandled type: %s' % repr(_type)) @@ -2230,7 +2266,7 @@ class _TestCases(unittest.TestCase): self.assertEqual(objcnt, cmd['count']) elif special == 'set hostid': hostidpatch = mock.patch(__name__ + '.hostuuid') - hid = cmd['hostid'] if 'hostid' in cmd else uuid.uuid4() + hid = uuid.UUID(cmd['hostid']) if 'hostid' in cmd else uuid.uuid4() hostidpatch.start().return_value = hid patches.append(hostidpatch) elif special == 'iter is unique':