Browse Source

support a graph of mappings instead of just one layer...

This isn't the most effecient for now as we generate all the
possible mappings, but it's assumed that the number of mappings
will be low for now...
main
John-Mark Gurney 2 months ago
parent
commit
e6b5299db6
2 changed files with 96 additions and 8 deletions
  1. +20
    -0
      ui/fixtures/cmd.mapping.json
  2. +76
    -8
      ui/medashare/cli.py

+ 20
- 0
ui/fixtures/cmd.mapping.json View File

@@ -103,5 +103,25 @@
"title": "just mapping lists them",
"cmd": [ "mapping" ],
"stdout_re": "^efdb5d9c-d123-4b30-aaa8-45a9ea8f6053:/.*subdir/mapa <-> ceaa4862-dd00-41ba-9787-7480ec1b2679:/.*subdir/mapb\n$"
},
{
"special": "set hostid",
"comment": "that a third host",
"hostid": "809c2a62-0df9-42a2-adae-c0a532ad860b"
},
{
"title": "that creating host c works",
"cmd": [ "hosts" ],
"format": [ "cmd" ]
},
{
"title": "that host mapping c works",
"cmd": [ "mapping", "--create", "mapc", "ceaa4862-dd00-41ba-9787-7480ec1b2679:{mappathb}" ],
"format": [ "cmd" ]
},
{
"title": "the search will pass through other mappings to get a local mapping",
"cmd": [ "search", "file", "+sometag=anothervalue" ],
"stdout_re": "mapc/text.txt\n$"
}
]

+ 76
- 8
ui/medashare/cli.py View File

@@ -647,13 +647,16 @@ class ObjectStore(object):
'''Returns the tuple (lclpath, hostid, rempath) for all
the mappings for this hostid.'''

# this is a little trick to return all possible mappings
# as we will have to explore all hosts that might have a
# mapping through us

hostid = _makeuuid(hostuuid())

sel = select(orm.MetaDataObject.data).where(
orm.HostMapping.hostid == hostid,
orm.HostMapping.objid == orm.MetaDataObject.uuid)
orm.MetaDataObject.type == 'mapping')

res = []
allmappings = collections.defaultdict(lambda: [])
with self._ses() as session:
# XXX - view
for obj in session.scalars(sel):
@@ -661,11 +664,29 @@ class ObjectStore(object):
pathlib.Path(b).resolve()))(*x.split(':',
1)) for x in obj.mapping ]
for idx, (id, path) in enumerate(maps):
if hostid == id:
# add other to mapping
other = tuple(maps[(idx + 1) %
2])
res.append((path, ) + other)
other = tuple(maps[(idx + 1) %
2])
allmappings[id].append((path, ) + other)

res = set(allmappings[hostid])
tovisit = res.copy()
visited = set()

while tovisit:

lclpath, remhid, rempath = tovisit.pop()

if (remhid, rempath) in visited:
continue

visited.add((remhid, rempath))

addl = { (lclpath, x[1], x[2]) for x in
allmappings[remhid] if x[1] != hostid }

res.update(addl)
tovisit.update(addl)

return res

def by_file(self, fname, types=('metadata', )):
@@ -2588,6 +2609,47 @@ class _TestCases(unittest.TestCase):
# and that it can be verified
persona.verify(mdobj)

def test_get_hostmapping(self):
# that an object store
persona = self.persona
objst = ObjectStore.load(self.tempdir / 'sample.data.sqlite3')

with mock.patch(__name__ + '.hostuuid') as hostidpatch:
# with a local host uuid
hid = uuid.uuid4()
hostidpatch.return_value = hid

host = persona.Host(name='lclhost', hostuuid=hid)
objst.loadobj(host)

# and two other hosts:
hida = uuid.uuid4()
hidb = uuid.uuid4()

objst.loadobj(persona.Host(name='hosta',
hostuuid=hida))
objst.loadobj(persona.Host(name='hostb',
hostuuid=hidb))

# that when a mapping from lcl to a to b exists
objst.loadobj(persona.Mapping(mapping=[
':'.join((str(hid), '/lclpath')) ,
':'.join((str(hida), '/patha')) ]))
objst.loadobj(persona.Mapping(mapping=[
':'.join((str(hida), '/patha')) ,
':'.join((str(hidb), '/pathb')) ]))

# that both a and b are included in the mappings
mappings = sorted(objst.get_hostmappings())

from pathlib import PosixPath

lclpath = PosixPath('/lclpath')
self.assertEqual(mappings, sorted([
(lclpath, hida, PosixPath('/patha')),
(lclpath, hidb, PosixPath('/pathb'))
]))

def test_objectstore(self):
persona = self.persona
objst = ObjectStore.load(self.tempdir / 'sample.data.sqlite3')
@@ -2797,11 +2859,17 @@ class _TestCases(unittest.TestCase):
mappathb = self.tempdir / 'mapb'
mappathb.mkdir()

mappathc = self.tempdir / 'mapc'
mappathc.mkdir()

filea = mappatha / 'text.txt'
filea.write_text('abc123\n')
fileb = mappathb / 'text.txt'
filec = mappathc / 'text.txt'
shutil.copyfile(filea, fileb)
shutil.copystat(filea, fileb)
shutil.copyfile(filea, filec)
shutil.copystat(filea, filec)
elif special == 'delete files':
for i in cmd['files']:
os.unlink(i)


Loading…
Cancel
Save