def register(self, parent, key, **kwargs): """ Add/replace an entry to directory below a parent node. Note: Does not merge the attribute values of the entry if existing """ if not (parent and key): raise BadRequest("Illegal arguments") if not type(parent) is str or not parent.startswith("/"): raise BadRequest("Illegal arguments: parent") dn = self._get_dn(parent, key) log.debug("Directory.add(%s): %s" % (dn, kwargs)) entry_old = None direntry = self._safe_read(dn) cur_time = get_ion_ts() if direntry: entry_old = direntry.attributes direntry.attributes = kwargs direntry.ts_updated = cur_time # TODO: This may fail because of concurrent update self.dir_store.update(direntry) else: parent_dn = self._get_dn(parent) direntry = DirEntry(parent=parent_dn, key=key, attributes=kwargs, ts_created=cur_time, ts_updated=cur_time) self.dir_store.create(direntry, dn) return entry_old
def _create_dir_entry(self, parent, key, orgname=None, ts=None, attributes=None): """ Standard way to create a DirEntry object (without persisting it) """ orgname = orgname or self.orgname ts = ts or get_ion_ts() attributes = attributes if attributes is not None else {} de = DirEntry(org=orgname, parent=parent, key=key, attributes=attributes, ts_created=ts, ts_updated=ts) return de
def _create(self): """ Method which will create the underlying data store and persist an empty Directory object. """ # Persist ROOT Directory object root_obj = DirEntry(parent='', key=self.orgname, attributes=dict(sys_name=bootstrap.get_sys_name())) root_id, rev = self.dir_store.create(root_obj, self.orgname) self._assert_existence( "/", "Agents", description="Running agents are registered here") self._assert_existence( "/", "Config", description="System configuration is registered here") self._assert_existence( "/", "Containers", description="Running containers are registered here") self._assert_existence("/", "ObjectTypes", description="ObjectTypes are registered here") self._assert_existence("/", "Org", description="Org specifics are registered here", is_root=self.is_root) self._assert_existence( "/Org", "Resources", description="Shared Org resources are registered here") self._assert_existence( "/", "ResourceTypes", description="Resource types are registered here") self._assert_existence( "/", "ServiceInterfaces", description="Service interface definitions are registered here") self._assert_existence( "/", "Services", description="Service instances are registered here")
def _create(self): """ Method which will create the underlying data store and persist an empty Directory object. """ # Persist empty Directory object under known name #self.dir_name = bootstrap.get_sys_name() #directory_obj = IonObject('Directory', name=self.dir_name) #dir_id,rev = self.dir_store.create(directory_obj, 'DIR') # Persist ROOT Directory object root_obj = DirEntry(parent='', key=self.orgname, attributes=dict(sys_name=bootstrap.get_sys_name())) root_id, rev = self.dir_store.create(root_obj, self.orgname)
def _assert_existence(self, parent, key, **kwargs): """ Make sure an entry is in the directory. @retval True if entry existed """ dn = self._get_path(parent, key) direntry = self._safe_read(dn) existed = bool(direntry) if not direntry: cur_time = get_ion_ts() parent_dn = self._get_path(parent) direntry = DirEntry(parent=parent_dn, key=key, attributes=kwargs, ts_created=cur_time, ts_updated=cur_time) # TODO: This may fail because of concurrent create self.dir_store.create(direntry, dn) return existed
def register_mult(self, entries): """ Registers multiple directory entries efficiently in one datastore access. Note: this fails of entries are currently existing, so works for create only. """ if type(entries) not in (list, tuple): raise BadRequest("Bad entries type") de_list = [] deid_list = [] cur_time = get_ion_ts() for parent, key, attrs in entries: parent_dn = self._get_dn(parent) de = DirEntry(parent=parent_dn, key=key, attributes=attrs, ts_created=cur_time, ts_updated=cur_time) de_list.append(de) dn = self._get_dn(parent, key) deid_list.append(dn) self.dir_store.create_mult(de_list, deid_list)
def test_directory(self): dsm = DatastoreManager() ds = dsm.get_datastore("resources", "DIRECTORY") ds.delete_datastore() ds.create_datastore() self.patch_cfg('pyon.ion.directory.CFG', {'service': { 'directory': { 'publish_events': False } }}) directory = Directory(datastore_manager=dsm) directory.start() #self.addCleanup(directory.dir_store.delete_datastore) objs = directory.dir_store.list_objects() root = directory.lookup("/DIR") self.assert_(root is not None) entry = directory.lookup("/temp") self.assert_(entry is None) entry_old = directory.register("/", "temp") self.assertEquals(entry_old, None) # Create a node entry = directory.lookup("/temp") self.assertEquals(entry, {}) # The create case entry_old = directory.register("/temp", "entry1", foo="awesome") self.assertEquals(entry_old, None) entry_new = directory.lookup("/temp/entry1") self.assertEquals(entry_new, {"foo": "awesome"}) # The update case entry_old = directory.register("/temp", "entry1", foo="ingenious") self.assertEquals(entry_old, {"foo": "awesome"}) # The delete case entry_old = directory.unregister("/temp", "entry1") self.assertEquals(entry_old, {"foo": "ingenious"}) entry_new = directory.lookup("/temp/entry1") self.assertEquals(entry_new, None) directory.register("/BranchA", "X", resource_id="rid1") directory.register("/BranchA", "Y", resource_id="rid2") directory.register("/BranchA", "Z", resource_id="rid3") directory.register("/BranchA/X", "a", resource_id="rid4") directory.register("/BranchA/X", "b", resource_id="rid5") directory.register("/BranchB", "k", resource_id="rid6") directory.register("/BranchB", "l", resource_id="rid7") directory.register("/BranchB/k", "m", resource_id="rid7") directory.register("/BranchB/k", "X") res_list = directory.find_by_value("/", attribute="resource_id", value="rid3") self.assertEquals(len(res_list), 1) self.assertEquals(res_list[0].org, "ION") self.assertEquals(res_list[0].parent, "/BranchA") self.assertEquals(res_list[0].key, "Z") res_list = directory.find_by_value("/", attribute="resource_id", value="rid34") self.assertEquals(len(res_list), 0) res_list = directory.find_by_value("/", attribute="resource_id", value="rid7") self.assertEquals(len(res_list), 2) res_list = directory.find_by_value("/BranchB", attribute="resource_id", value="rid7") self.assertEquals(len(res_list), 2) res_list = directory.find_by_value("/Branch", attribute="resource_id", value="rid7") self.assertEquals(len(res_list), 2) res_list = directory.find_by_value("/BranchB/k", attribute="resource_id", value="rid7") self.assertEquals(len(res_list), 1) res_list = directory.find_child_entries("/BranchB/k/m") self.assertEquals(len(res_list), 0) res_list = directory.find_child_entries("/BranchB") self.assertEquals(len(res_list), 2) res_list = directory.find_child_entries("/BranchB/k/m", direct_only=False) self.assertEquals(len(res_list), 0) res_list = directory.find_child_entries("/BranchB", direct_only=False) self.assertEquals(len(res_list), 4) res_list = directory.find_by_key("X") self.assertEquals(len(res_list), 2) res_list = directory.find_by_key("X", parent="/BranchB") self.assertEquals(len(res_list), 1) entry_list = directory.lookup_mult("/BranchA", ["X", "Z"]) self.assertEquals(len(entry_list), 2) self.assertEquals(entry_list[0]["resource_id"], "rid1") self.assertEquals(entry_list[1]["resource_id"], "rid3") entry_list = directory.lookup_mult("/BranchA", ["Y", "FOO"]) self.assertEquals(len(entry_list), 2) self.assertEquals(entry_list[0]["resource_id"], "rid2") self.assertEquals(entry_list[1], None) # Test prevent duplicate entries directory.register("/some", "dupentry", foo="ingenious") de = directory.lookup("/some/dupentry", return_entry=True) de1_attrs = de.__dict__.copy() del de1_attrs["_id"] del de1_attrs["_rev"] del de1_attrs["type_"] de1 = DirEntry(**de1_attrs) with self.assertRaises(BadRequest) as ex: de_id1, _ = directory.dir_store.create(de1) self.assertTrue(ex.message.startswith("DirEntry already exists")) res_list = directory.find_by_key("dupentry", parent="/some") self.assertEquals(1, len(res_list))