diff --git a/lib/Bastion/Vaults/BFD.py b/lib/Bastion/Vaults/BFD.py new file mode 100644 index 0000000..db11355 --- /dev/null +++ b/lib/Bastion/Vaults/BFD.py @@ -0,0 +1,172 @@ +import os +import pathlib +import subprocess +import operator +import datetime +import json +import socket +import logging +import getpass + +from Bastion.Common import Thing, Unknown +import Bastion.Model +from Bastion.Curator import Manifest, BLONDE, Snap + + +class Vault(Bastion.Model.Vault): + PROTOCOL = 'BFD' + + def __init__(self, name, **kwargs): + Bastion.Model.Vault.__init__(self, name, **kwargs) + self.bfd = pathlib.Path("/") + self.root = self.bfd / "bastion" / "bank" + self.scratch = self.bfd / "bastion" / "scratch" + self.tarx = 'tar' + + + def configured(self, conf): + confkey = "vaults.{}".format(self.name) + if confkey in conf: + section = conf[confkey] + self.bfd = pathlib.Path( section['bfd.path'] ) + self.root = self.bfd / "bastion" / "bank" + self.scratch = self.bfd / "bastion" / "scratch" + + if 'root.path' in section: + self.root = pathlib.Path( section['root.path'] ) + + if 'scratch.path' in section: + self.scratch = pathlib.Path( section['scratch.path'] ) + + if 'tarx' in section: + self.tarx = section['tarx'] + + return self + +#--------------------------------------- +#-- BEGIN Bastion.Model.Vault PROTOCOL | +#↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ + @property + def ARKs(self): + arks = [ ] + for site in self.sites: + for zone in self.zones(site): + for asset in self.assets(site, zone): + arks.append( ARK(site, zone, asset) ) + return tuple(sorted(arks)) + + @property + def sites(self): + #-- sites are top level elements relative to the root of the vault. + sites = [ ] + for entry in self.root.iterdir(): + if entry.is_dir(): + sites.append(entry.name) + + return tuple(sorted(sites)) + + def zones(self, site): + #-- a zone will be a subdirectory (subfolder) of the given site. + #-- look for all of the subfolders of root / site + zones = [ ] + sroot = self.root / site + if sroot.exists( ): + for entry in sroot.iterdir( ): + if entry.is_dir(): + zones.append(entry.name) + return tuple(sorted(zones)) + + def assets(self, site, zone): + #-- assets will be subdirectories (subfolders) of a given site, zone. + assets = [ ] + zroot = self.root / site / zone + if zroot.exists( ): + for entry in zroot.is_dir(): + assets.append(entry.name) + return tuple(sorted(assets)) + + def manifest(self, *args): + """ + I answer a manifest of the named asset... + manifest(ark) + manifest(site, zone, asset) + """ + if len(args) == 1: + return self._manifest_ark( args[0] ) + elif len(args) == 3: + return self._manifest_site_zone_asset( args[0], args[1], args[2] ) + else: + raise ValueError + + def provision(self, *args): + """ + provision(ark) - ensures that the site, zone, and asset folders exist. + provision(site, zone, asset_name) - an alias for provision(ark) + """ + if len(args) == 1: + return self._provision_ark( args[0] ) + elif len(args) == 3: + return self._provision_site_zone_asset( args[0], args[1], args[2] ) + else: + raise ValueError + + def push(self, asset, **kwargs): + #-- tar asset to scratch + #-- move from scratch to asset repository + raise NotImplementedError + + def pull(self, ark, **kwargs): + raise NotImplementedError + + def put(self, halo, asARK, **kwargs): + raise NotImplementedError + + def get(self, ark, time, halo): + raise NotImplementedError + + +#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ +#-- END Bastion.Model.Vault PROTOCOL | +#------------------------------------- + def _tar_asset(self, asset, **kwargs): + ark = asset.ARK + bucket = self.scratch / ark.site / ark.zone / ark.asset + bucket.mkdir(parents = True, exist_ok = True) + subprocess.run(cmd_tar, + raise NotImplementedError + + def _copy_blonde(self, blonde, **kwargs): + raise NotImplementedError + + def _empty_scratch(self, ark, **kwargs): + pass + + + def _manifest_ark(self, ark): + #-- The contents of {root}/{site}/{zone}/{asset} are backup blobs + #-- Each name in this folder is a "BLOND" (BLOb Name and Descriptor) + #-- The manifest a catalog of all of the backup objects for the asset. + cell = self.root / ark.site / ark.zone / ark.asset + if cell.exists(): + blondes = [ ] + for item in cell.iterdir(): + if not item.is_dir(): + blondes.append( item.name ) + manifest = Bastion.Curator.Manifest(ark, blondes) + + return manifest + + def _manifest_site_zone_asset(self, site, zone, asset): + return self._manifest_ark( ARK(site, zone, asset) ) + + + def _provision_ark(self, ark): + repo = self.root / ark.site / ark.zone / ark.asset + return repo.mkdir(parents = True, exist_ok = True) + + + def _provision_site_zone_asset(self, site, zone, asset_name): + return self._provision_ark( ARK(site, zone, asset_name) ) + + +Vault.register()