def testFullUpdateOnMissingCache(self): """We fault to a full update if our cache is missing.""" original_modify_stamp = 1 updater = map_updater.MapUpdater(config.MAP_PASSWORD, self.workdir, {}) updater.WriteModifyTimestamp(original_modify_stamp) source_mock = self.mox.CreateMock(source.Source) # Try incremental first. source_mock.GetMap(config.MAP_PASSWORD, location=None, since=original_modify_stamp).AndReturn('first map') # Try full second. source_mock.GetMap(config.MAP_PASSWORD, location=None).AndReturn('second map') updater = map_updater.MapUpdater(config.MAP_PASSWORD, self.workdir, {}, can_do_incremental=True) self.mox.StubOutWithMock(updater, 'GetModifyTimestamp') updater.GetModifyTimestamp().AndReturn(original_modify_stamp) self.mox.StubOutWithMock(updater, '_IncrementalUpdateFromMap') # force a cache not found on incremental updater._IncrementalUpdateFromMap('cache', 'first map').AndRaise(error.CacheNotFound) self.mox.StubOutWithMock(updater, 'FullUpdateFromMap') updater.FullUpdateFromMap(mox.IgnoreArg(), 'second map', False).AndReturn(0) self.mox.ReplayAll() self.assertEqual(0, updater.UpdateCacheFromSource('cache', source_mock, incremental=True, force_write=False, location=None))
def testUpdate(self): """An update gets a master map and updates each entry.""" map_entry1 = automount.AutomountMapEntry() map_entry2 = automount.AutomountMapEntry() map_entry1.key = '/home' map_entry2.key = '/auto' map_entry1.location = 'ou=auto.home,ou=automounts' map_entry2.location = 'ou=auto.auto,ou=automounts' master_map = automount.AutomountMap([map_entry1, map_entry2]) source_mock = self.mox.CreateMock(source.Source) # return the master map source_mock.GetAutomountMasterMap().AndReturn(master_map) # the auto.home cache cache_home = self.mox.CreateMock(caches.Cache) # GetMapLocation() is called, and set to the master map map_entry cache_home.GetMapLocation().AndReturn('/etc/auto.home') # the auto.auto cache cache_auto = self.mox.CreateMock(caches.Cache) # GetMapLocation() is called, and set to the master map map_entry cache_auto.GetMapLocation().AndReturn('/etc/auto.auto') # the auto.master cache cache_master = self.mox.CreateMock(caches.Cache) self.mox.StubOutWithMock(cache_factory, 'Create') cache_factory.Create(mox.IgnoreArg(), 'automount', automount_mountpoint='/home').AndReturn(cache_home) cache_factory.Create(mox.IgnoreArg(), 'automount', automount_mountpoint='/auto').AndReturn(cache_auto) cache_factory.Create(mox.IgnoreArg(), 'automount', automount_mountpoint=None).AndReturn(cache_master) updater = map_updater.AutomountUpdater( config.MAP_AUTOMOUNT, self.workdir, {}) self.mox.StubOutClassWithMocks(map_updater, 'MapUpdater') updater_home = map_updater.MapUpdater(config.MAP_AUTOMOUNT, self.workdir, {}, automount_mountpoint='/home') updater_home.UpdateCacheFromSource(cache_home, source_mock, True, False, 'ou=auto.home,ou=automounts').AndReturn(0) updater_auto = map_updater.MapUpdater(config.MAP_AUTOMOUNT, self.workdir, {}, automount_mountpoint='/auto') updater_auto.UpdateCacheFromSource(cache_auto, source_mock, True, False, 'ou=auto.auto,ou=automounts').AndReturn(0) updater_master = map_updater.MapUpdater(config.MAP_AUTOMOUNT, self.workdir, {}) updater_master.FullUpdateFromMap(cache_master, master_map).AndReturn(0) self.mox.ReplayAll() updater.UpdateFromSource(source_mock) self.assertEqual(map_entry1.location, '/etc/auto.home') self.assertEqual(map_entry2.location, '/etc/auto.auto')
def testFullUpdate(self): """A full update reads the source, writes to cache, and updates times.""" original_modify_stamp = 1 new_modify_stamp = 2 updater = map_updater.MapUpdater( config.MAP_PASSWORD, self.workdir, {}) updater.WriteModifyTimestamp(original_modify_stamp) map_entry = passwd.PasswdMapEntry({'name': 'foo', 'uid': 10, 'gid': 10}) password_map = passwd.PasswdMap([map_entry]) password_map.SetModifyTimestamp(new_modify_stamp) cache_mock = self.mox.CreateMock(files.FilesCache) cache_mock.WriteMap(map_data=password_map).AndReturn(0) source_mock = self.mox.CreateMock(source.Source) source_mock.GetMap(config.MAP_PASSWORD, location=None).AndReturn(password_map) self.mox.ReplayAll() self.assertEqual(0, updater.UpdateCacheFromSource(cache_mock, source_mock, False, False, None)) self.assertEqual(updater.GetModifyTimestamp(), new_modify_stamp) self.assertNotEqual(updater.GetUpdateTimestamp(), None)
def _Updater(self, map_name, source, cache_options, conf): # Bit ugly. This just checks the class attribute UPDATER # to determine which type of updater the source uses. At the moment # there's only two, so not a huge deal. If we add another we should # refactor though. if hasattr(source, 'UPDATER') and source.UPDATER == config.UPDATER_FILE: if map_name == config.MAP_AUTOMOUNT: return files_updater.FileAutomountUpdater( map_name, conf.timestamp_dir, cache_options) else: return files_updater.FileMapUpdater(map_name, conf.timestamp_dir, cache_options, can_do_incremental=True) else: if map_name == config.MAP_AUTOMOUNT: return map_updater.AutomountUpdater(map_name, conf.timestamp_dir, cache_options) else: return map_updater.MapUpdater(map_name, conf.timestamp_dir, cache_options, can_do_incremental=True)
def testFullUpdateOnMissingTimestamp(self): """We fault to a full update if our modify timestamp is missing.""" updater = map_updater.MapUpdater(config.MAP_PASSWORD, self.workdir, {}) # We do not call WriteModifyTimestamp() so we force a full sync. source_mock = self.mox.CreateMock(source.Source) source_mock.GetMap(config.MAP_PASSWORD, location=None).AndReturn('second map') updater = map_updater.MapUpdater(config.MAP_PASSWORD, self.workdir, {}) self.mox.StubOutWithMock(updater, 'FullUpdateFromMap') updater.FullUpdateFromMap(mox.IgnoreArg(), 'second map', False).AndReturn(0) self.mox.ReplayAll() self.assertEqual(0, updater.UpdateCacheFromSource('cache', source_mock, True, False, None))
def GetSingleMapMetadata(self, map_name, conf, automount_mountpoint=None, epoch=False): """Return metadata from map specified. Args: map_name: name of map to extract data from conf: a config.Config object automount_mountpoint: information necessary for automount maps epoch: return times as an integer epoch (time_t) instead of a human readable name Returns: a list of dicts of metadata key/value pairs """ cache_options = conf.options[map_name].cache updater = map_updater.MapUpdater(map_name, conf.timestamp_dir, cache_options, automount_mountpoint) modify_dict = {'key': 'last-modify-timestamp', 'map': map_name} update_dict = {'key': 'last-update-timestamp', 'map': map_name} if map_name == config.MAP_AUTOMOUNT: # have to find out *which* automount map from a cache object! cache = cache_factory.Create( cache_options, config.MAP_AUTOMOUNT, automount_mountpoint=automount_mountpoint) automount = cache.GetMapLocation() modify_dict['automount'] = automount update_dict['automount'] = automount last_modify_timestamp = updater.GetModifyTimestamp() or 0 last_update_timestamp = updater.GetUpdateTimestamp() or 0 if not epoch: # If we are displaying the time as a string, do so in localtime. This is # the only place such a conversion is appropriate. if last_modify_timestamp: last_modify_timestamp = time.asctime( time.localtime(last_modify_timestamp)) else: last_modify_timestamp = 'Unknown' if last_update_timestamp: last_update_timestamp = time.asctime( time.localtime(last_update_timestamp)) else: last_update_timestamp = 'Unknown' modify_dict['value'] = last_modify_timestamp update_dict['value'] = last_update_timestamp return [modify_dict, update_dict]
def testIncrementalUpdate(self): """An incremental update reads a partial map and merges it.""" # Unlike in a full update, we create a cache map and a source map, and # let it merge them. If it goes to write the merged map, we're good. # Also check that timestamps were updated, as in testFullUpdate above. def compare_function(map_object): return len(map_object) == 2 original_modify_stamp = 1 new_modify_stamp = 2 updater = map_updater.MapUpdater(config.MAP_PASSWORD, self.workdir, {}, can_do_incremental=True) updater.WriteModifyTimestamp(original_modify_stamp) cache_map_entry = passwd.PasswdMapEntry({ 'name': 'bar', 'uid': 20, 'gid': 20 }) cache_map = passwd.PasswdMap([cache_map_entry]) cache_map.SetModifyTimestamp(original_modify_stamp) cache_mock = self.mox.CreateMock(caches.Cache) cache_mock.GetMap().AndReturn(cache_map) cache_mock.WriteMap(map_data=mox.Func(compare_function)).AndReturn(0) source_map_entry = passwd.PasswdMapEntry({ 'name': 'foo', 'uid': 10, 'gid': 10 }) source_map = passwd.PasswdMap([source_map_entry]) source_map.SetModifyTimestamp(new_modify_stamp) source_mock = self.mox.CreateMock(source.Source) source_mock.GetMap(config.MAP_PASSWORD, location=None, since=original_modify_stamp).AndReturn(source_map) self.mox.ReplayAll() self.assertEqual( 0, updater.UpdateCacheFromSource(cache_mock, source_mock, incremental=True, force_write=False, location=None)) self.assertEqual(updater.GetModifyTimestamp(), new_modify_stamp) self.assertNotEqual(updater.GetUpdateTimestamp(), None)
def testUpdateNoMaster(self): """An update skips updating the master map, and approprate sub maps.""" source_entry1 = automount.AutomountMapEntry() source_entry2 = automount.AutomountMapEntry() source_entry1.key = '/home' source_entry2.key = '/auto' source_entry1.location = 'ou=auto.home,ou=automounts' source_entry2.location = 'ou=auto.auto,ou=automounts' source_master = automount.AutomountMap([source_entry1, source_entry2]) local_entry1 = automount.AutomountMapEntry() local_entry2 = automount.AutomountMapEntry() local_entry1.key = '/home' local_entry2.key = '/auto' local_entry1.location = '/etc/auto.home' local_entry2.location = '/etc/auto.null' local_master = automount.AutomountMap([local_entry1, local_entry2]) source_mock = self.mox.CreateMock(source.Source) # return the source master map source_mock.GetAutomountMasterMap().AndReturn(source_master) # the auto.home cache cache_home = self.mox.CreateMock(caches.Cache) # GetMapLocation() is called, and set to the master map map_entry cache_home.GetMapLocation().AndReturn('/etc/auto.home') # the auto.auto cache cache_auto = self.mox.CreateMock(caches.Cache) # GetMapLocation() is called, and set to the master map map_entry cache_auto.GetMapLocation().AndReturn('/etc/auto.auto') # the auto.master cache, which should not be written to cache_master = self.mox.CreateMock(caches.Cache) cache_master.GetMap().AndReturn(local_master) self.mox.StubOutWithMock(cache_factory, 'Create') cache_factory.Create(mox.IgnoreArg(), mox.IgnoreArg(), automount_mountpoint=None).AndReturn(cache_master) cache_factory.Create(mox.IgnoreArg(), mox.IgnoreArg(), automount_mountpoint='/home').AndReturn(cache_home) cache_factory.Create(mox.IgnoreArg(), mox.IgnoreArg(), automount_mountpoint='/auto').AndReturn(cache_auto) skip = map_updater.AutomountUpdater.OPT_LOCAL_MASTER updater = map_updater.AutomountUpdater( config.MAP_AUTOMOUNT, self.workdir, {skip: 'yes'}) self.mox.StubOutClassWithMocks(map_updater, 'MapUpdater') updater_home = map_updater.MapUpdater(config.MAP_AUTOMOUNT, self.workdir, {'local_automount_master': 'yes'}, automount_mountpoint='/home') updater_home.UpdateCacheFromSource(cache_home, source_mock, True, False, 'ou=auto.home,ou=automounts').AndReturn(0) self.mox.ReplayAll() updater.UpdateFromSource(source_mock)