def test_broken_pending_file(self): '''Test that we discare the other hosts file if the file is broken (a future sync will rewrite it)''' self.copy_state('brokenpending') host = Hosts() self.assertEqual(host.get_hostid_pending_change('foo', 'bar'), None) host.add_hostid_pending_change({'foo': {'bar': 'baz'}}) self.assertEqual(host.get_hostid_pending_change('foo', 'bar'), 'baz')
def __init__(self, hosts=None): self.hosts = hosts if not hosts: self.hosts = Hosts() self.distro = get_distro() if not self.distro: raise PackageSetInitError( "Can't initialize PackageSetHandler: no valid distro provided") self.last_storage_sync = None # create cache for storage package list, indexed by hostid self.package_list = {}
def __init__(self, loop): '''registration over dbus''' bus_name = dbus.service.BusName(ONECONF_SERVICE_NAME, bus=dbus.SessionBus()) dbus.service.Object.__init__(self, bus_name, HOSTS_OBJECT_NAME) # Only import oneconf module now for only getting it on server side from oneconf.hosts import Hosts self.hosts = Hosts() self._packageSetHandler = None self.activity = False self.synchandler = None self.loop = loop
def set_share_inventory(self, share_inventory, hostid=None, hostname=None): '''update if we share the chosen host inventory on the server''' try: Hosts().set_share_inventory(share_inventory, hostid, hostname) except HostError as e: print(e) sys.exit(1)
def __init__(self, hosts=None): self.hosts = hosts if not hosts: self.hosts = Hosts() self.distro = get_distro() self.last_storage_sync = None # create cache for storage package list, indexed by hostid self.package_list = {}
def test_broken_otherhosts_file(self): '''Test that we discare the other hosts file if the file is broken (a future sync will rewrite it)''' self.copy_state('brokenotherhosts') host = Hosts() self.assertEqual(host._load_other_hosts(), {})
class PackageSetHandler(object): """ Direct access to database for getting and updating the list """ def __init__(self, hosts=None): self.hosts = hosts if not hosts: self.hosts = Hosts() self.distro = get_distro() self.last_storage_sync = None # create cache for storage package list, indexed by hostid self.package_list = {} def update(self): '''update the store with package list''' hostid = self.hosts.current_host['hostid'] LOG.debug("Updating package list") newpkg_list = self.distro.compute_local_packagelist() LOG.debug("Creating the checksum") checksum = hashlib.sha224(str(newpkg_list)).hexdigest() LOG.debug("Package list need refresh") self.package_list[hostid] = {'valid': True, 'package_list': newpkg_list} with open(os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), 'w') as f: json.dump(self.package_list[hostid]['package_list'], f) if self.hosts.current_host['packages_checksum'] != checksum: self.hosts.current_host['packages_checksum'] = checksum self.hosts.save_current_host() LOG.debug("Update done") def get_packages(self, hostid=None, hostname=None, only_manual=False): '''get all installed packages from the storage''' hostid = self.hosts.get_hostid_from_context(hostid, hostname) LOG.debug ("Request for package list for %s with only manual packages reduced scope to: %s", hostid, only_manual) package_list = self._get_installed_packages(hostid) if only_manual: package_list = [package_elem for package_elem in package_list if package_list[package_elem]["auto"] == False] return package_list def _get_installed_packages(self, hostid): '''get installed packages from the storage or cache Return: uptodate package_list''' need_reload = False try: if self.package_list[hostid]['valid']: LOG.debug("Hit cache for package list") package_list = self.package_list[hostid]['package_list'] else: need_reload = True except KeyError: need_reload = True if need_reload: self.package_list[hostid] = {'valid': True, 'package_list': self._get_packagelist_from_store(hostid)} return self.package_list[hostid]['package_list'] def diff(self, distant_hostid=None, distant_hostname=None): '''get a diff from current package state from another host This function can be use to make a diff between all packages installed on both computer , use_cache Return: (packages_to_install (packages in distant_hostid not in local_hostid), packages_to_remove (packages in local hostid not in distant_hostid)) ''' distant_hostid = self.hosts.get_hostid_from_context(distant_hostid, distant_hostname) LOG.debug("Collecting all installed packages on this system") local_package_list = set(self.get_packages(self.hosts.current_host['hostid'], False)) LOG.debug("Collecting all installed packages on the other system") distant_package_list = set(self.get_packages(distant_hostid, False)) LOG.debug("Comparing") packages_to_install = [x for x in distant_package_list if x not in local_package_list] packages_to_remove = [x for x in local_package_list if x not in distant_package_list] # for Dbus which doesn't like empty list if not packages_to_install: packages_to_install = '' if not packages_to_remove: packages_to_remove = '' return(packages_to_install, packages_to_remove) def _get_packagelist_from_store(self, hostid): '''load package list for every computer in cache''' LOG.debug('get package list from store for hostid: %s' % hostid) # load current content in cache try: with open(os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), 'r') as f: # can be none in corrupted null file pkg_list = json.load(f) except (IOError, ValueError): LOG.warning ("no valid package list stored for hostid: %s" % hostid) pkg_list = None if pkg_list is None: pkg_list = {} # there is no way that no package is installed in current host # At least, there is oneconf ;) Ask for refresh if hostid == self.hosts.current_host['hostid']: LOG.debug ("Processing first update for current host") self.update() pkg_list = self.package_list[hostid]['package_list'] return pkg_list
class DbusHostsService(dbus.service.Object): """ Dbus service, daemon side """ def __init__(self, loop): '''registration over dbus''' bus_name = dbus.service.BusName(ONECONF_SERVICE_NAME, bus=dbus.SessionBus()) dbus.service.Object.__init__(self, bus_name, HOSTS_OBJECT_NAME) # Only import oneconf module now for only getting it on server side from oneconf.hosts import Hosts self.hosts = Hosts() self._packageSetHandler = None self.activity = False self.synchandler = None self.loop = loop # TODO: can be a decorator, handling null case and change the API so that if it returns # the None value -> no result def get_packageSetHandler(self): '''Ensure we load the package set handler at the right time''' if not self._packageSetHandler: from oneconf.packagesethandler import PackageSetHandler, PackageSetInitError try: self._packageSetHandler = PackageSetHandler(self.hosts) except PackageSetInitError as e: LOG.error (e) self._packageSetHandler = None return self._packageSetHandler @dbus.service.method(HOSTS_INTERFACE) def get_all_hosts(self): self.activity = True return self.hosts.get_all_hosts() @dbus.service.method(HOSTS_INTERFACE) def set_share_inventory(self, share_inventory, hostid, hostname): self.activity = True if share_inventory: # map to boolean to avoid difference in dbus call and direct share_inventory = True else: share_inventory = False return self.hosts.set_share_inventory(share_inventory, hostid, hostname) @dbus.service.method(PACKAGE_SET_INTERFACE) def get_packages(self, hostid, hostname, only_manual): self.activity = True if not self.get_packageSetHandler(): return '' return none_to_null(self.get_packageSetHandler().get_packages(hostid, hostname, only_manual)) @dbus.service.method(PACKAGE_SET_INTERFACE) def diff(self, hostid, hostname): self.activity = True if not self.get_packageSetHandler(): return ('', '') return self.get_packageSetHandler().diff(hostid, hostname) @dbus.service.method(PACKAGE_SET_INTERFACE) def update(self): self.activity = True if self.get_packageSetHandler(): self.get_packageSetHandler().update() @dbus.service.method(PACKAGE_SET_INTERFACE) def async_update(self): self.activity = True if self.get_packageSetHandler(): GLib.timeout_add_seconds(1, self.get_packageSetHandler().update) @dbus.service.signal(HOSTS_INTERFACE) def hostlist_changed(self): LOG.debug("Send host list changed dbus signal") @dbus.service.signal(PACKAGE_SET_INTERFACE) def packagelist_changed(self, hostid): LOG.debug("Send package list changed dbus signal for hostid: %s" % hostid) @dbus.service.signal(HOSTS_INTERFACE) def logo_changed(self, hostid): LOG.debug("Send logo changed dbus signal for hostid: %s" % hostid) @dbus.service.signal(HOSTS_INTERFACE) def latestsync_changed(self, timestamp): LOG.debug("Send last sync timestamp: %s" % timestamp) @dbus.service.method(HOSTS_INTERFACE) def get_last_sync_date(self): self.activity = True return self.hosts.get_last_sync_date() @dbus.service.method(HOSTS_INTERFACE) def stop_service(self): LOG.debug("Request for stopping OneConf service") self.loop.quit() return True
def test_broken_latestsync_file(self): '''Test that we return a dummy latest sync date if we can't load it. Next update will rewrite it''' self.copy_state('brokenlatestsync') host = Hosts() self.assertEqual(host.get_last_sync_date(), _("Was never synced"))
class PackageSetHandler(object): """ Direct access to database for getting and updating the list """ def __init__(self, hosts=None): self.hosts = hosts if not hosts: self.hosts = Hosts() self.distro = get_distro() if not self.distro: raise PackageSetInitError( "Can't initialize PackageSetHandler: no valid distro provided") self.last_storage_sync = None # create cache for storage package list, indexed by hostid self.package_list = {} def update(self): '''update the store with package list''' hostid = self.hosts.current_host['hostid'] LOG.debug("Updating package list") newpkg_list = self.distro.compute_local_packagelist() LOG.debug("Creating the checksum") # We need to get a reliable checksum for the dictionary in # newpkg_list. Dictionary order is unpredictable, so to get a # reproducible checksum, we need a predictable string representation # of the dictionary. pprint.pformat() seems to give us the best # option here since it guarantees that dictionary keys are sorted. # hashlib works on bytes only though, so assume utf-8. hash_input = pformat(newpkg_list).encode('utf-8') checksum = hashlib.sha224(hash_input).hexdigest() LOG.debug("Package list need refresh") self.package_list[hostid] = { 'valid': True, 'package_list': newpkg_list } utils.save_json_file_update( os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), self.package_list[hostid]['package_list']) if self.hosts.current_host['packages_checksum'] != checksum: self.hosts.current_host['packages_checksum'] = checksum self.hosts.save_current_host() LOG.debug("Update done") def get_packages(self, hostid=None, hostname=None, only_manual=False): '''get all installed packages from the storage''' hostid = self.hosts.get_hostid_from_context(hostid, hostname) LOG.debug( "Request for package list for %s with only manual packages reduced scope to: %s", hostid, only_manual) package_list = self._get_installed_packages(hostid) if only_manual: package_list = [ package_elem for package_elem in package_list if not package_list[package_elem]["auto"] ] return package_list def _get_installed_packages(self, hostid): '''get installed packages from the storage or cache Return: uptodate package_list''' need_reload = False try: if self.package_list[hostid]['valid']: LOG.debug("Hit cache for package list") package_list = self.package_list[hostid]['package_list'] else: need_reload = True except KeyError: need_reload = True if need_reload: self.package_list[hostid] = { 'valid': True, 'package_list': self._get_packagelist_from_store(hostid), } return self.package_list[hostid]['package_list'] def diff(self, distant_hostid=None, distant_hostname=None): """get a diff from current package state from another host This function can be use to make a diff between all packages installed on both computer, use_cache Return: (packages_to_install (packages in distant_hostid not in local_hostid), packages_to_remove (packages in local hostid not in distant_hostid)) """ distant_hostid = self.hosts.get_hostid_from_context( distant_hostid, distant_hostname) LOG.debug("Collecting all installed packages on this system") local_package_list = set( self.get_packages(self.hosts.current_host['hostid'], False)) LOG.debug("Collecting all installed packages on the other system") distant_package_list = set(self.get_packages(distant_hostid, False)) LOG.debug("Comparing") packages_to_install = [ x for x in sorted(distant_package_list) if x not in local_package_list ] packages_to_remove = [ x for x in sorted(local_package_list) if x not in distant_package_list ] # for Dbus which doesn't like empty list if not packages_to_install: packages_to_install = '' if not packages_to_remove: packages_to_remove = '' return packages_to_install, packages_to_remove def _get_packagelist_from_store(self, hostid): '''load package list for every computer in cache''' LOG.debug('get package list from store for hostid: %s' % hostid) # load current content in cache try: with open( os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), 'r') as f: # can be none in corrupted null file pkg_list = json.load(f) except (IOError, ValueError): LOG.warning("no valid package list stored for hostid: %s" % hostid) pkg_list = None if pkg_list is None: pkg_list = {} # there is no way that no package is installed in current host # At least, there is oneconf ;) Ask for refresh if hostid == self.hosts.current_host['hostid']: LOG.debug("Processing first update for current host") self.update() pkg_list = self.package_list[hostid]['package_list'] return pkg_list
class PackageSetHandler(object): """ Direct access to database for getting and updating the list """ def __init__(self, hosts=None): self.hosts = hosts if not hosts: self.hosts = Hosts() self.distro = get_distro() if not self.distro: raise PackageSetInitError( "Can't initialize PackageSetHandler: no valid distro provided") self.last_storage_sync = None # create cache for storage package list, indexed by hostid self.package_list = {} def update(self): '''update the store with package list''' hostid = self.hosts.current_host['hostid'] LOG.debug("Updating package list") newpkg_list = self.distro.compute_local_packagelist() LOG.debug("Creating the checksum") # We need to get a reliable checksum for the dictionary in # newpkg_list. Dictionary order is unpredictable, so to get a # reproducible checksum, we need a predictable string representation # of the dictionary. pprint.pformat() seems to give us the best # option here since it guarantees that dictionary keys are sorted. # hashlib works on bytes only though, so assume utf-8. hash_input = pformat(newpkg_list).encode('utf-8') checksum = hashlib.sha224(hash_input).hexdigest() LOG.debug("Package list need refresh") self.package_list[hostid] = {'valid': True, 'package_list': newpkg_list} utils.save_json_file_update(os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), self.package_list[hostid]['package_list']) if self.hosts.current_host['packages_checksum'] != checksum: self.hosts.current_host['packages_checksum'] = checksum self.hosts.save_current_host() LOG.debug("Update done") def get_packages(self, hostid=None, hostname=None, only_manual=False): '''get all installed packages from the storage''' hostid = self.hosts.get_hostid_from_context(hostid, hostname) LOG.debug ("Request for package list for %s with only manual packages reduced scope to: %s", hostid, only_manual) package_list = self._get_installed_packages(hostid) if only_manual: package_list = [ package_elem for package_elem in package_list if not package_list[package_elem]["auto"]] return package_list def _get_installed_packages(self, hostid): '''get installed packages from the storage or cache Return: uptodate package_list''' need_reload = False try: if self.package_list[hostid]['valid']: LOG.debug("Hit cache for package list") package_list = self.package_list[hostid]['package_list'] else: need_reload = True except KeyError: need_reload = True if need_reload: self.package_list[hostid] = { 'valid': True, 'package_list': self._get_packagelist_from_store(hostid), } return self.package_list[hostid]['package_list'] def diff(self, distant_hostid=None, distant_hostname=None): """get a diff from current package state from another host This function can be use to make a diff between all packages installed on both computer, use_cache Return: (packages_to_install (packages in distant_hostid not in local_hostid), packages_to_remove (packages in local hostid not in distant_hostid)) """ distant_hostid = self.hosts.get_hostid_from_context( distant_hostid, distant_hostname) LOG.debug("Collecting all installed packages on this system") local_package_list = set( self.get_packages(self.hosts.current_host['hostid'], False)) LOG.debug("Collecting all installed packages on the other system") distant_package_list = set(self.get_packages(distant_hostid, False)) LOG.debug("Comparing") packages_to_install = [ x for x in sorted(distant_package_list) if x not in local_package_list] packages_to_remove = [ x for x in sorted(local_package_list) if x not in distant_package_list] # for Dbus which doesn't like empty list if not packages_to_install: packages_to_install = '' if not packages_to_remove: packages_to_remove = '' return packages_to_install, packages_to_remove def _get_packagelist_from_store(self, hostid): '''load package list for every computer in cache''' LOG.debug('get package list from store for hostid: %s' % hostid) # load current content in cache try: with open(os.path.join(self.hosts.get_currenthost_dir(), '%s_%s' % (PACKAGE_LIST_PREFIX, hostid)), 'r') as f: # can be none in corrupted null file pkg_list = json.load(f) except (IOError, ValueError): LOG.warning ("no valid package list stored for hostid: %s" % hostid) pkg_list = None if pkg_list is None: pkg_list = {} # there is no way that no package is installed in current host # At least, there is oneconf ;) Ask for refresh if hostid == self.hosts.current_host['hostid']: LOG.debug ("Processing first update for current host") self.update() pkg_list = self.package_list[hostid]['package_list'] return pkg_list
def test_no_valid_wallpaper(self): '''Test that no crash occurs with an invalid wallpaper URL''' host = Hosts() self.assertEqual(host._get_current_wallpaper_data(), (None, None))
class DbusHostsService(dbus.service.Object): """ Dbus service, daemon side """ def __init__(self, loop): '''registration over dbus''' bus_name = dbus.service.BusName(ONECONF_SERVICE_NAME, bus=dbus.SessionBus()) dbus.service.Object.__init__(self, bus_name, HOSTS_OBJECT_NAME) # Only import oneconf module now for only getting it on server side from oneconf.hosts import Hosts self.hosts = Hosts() self._packageSetHandler = None self.activity = False self.synchandler = None self.loop = loop # TODO: can be a decorator, handling null case and change the API so that if it returns # the None value -> no result def get_packageSetHandler(self): '''Ensure we load the package set handler at the right time''' if not self._packageSetHandler: from oneconf.packagesethandler import PackageSetHandler, PackageSetInitError try: self._packageSetHandler = PackageSetHandler(self.hosts) except PackageSetInitError as e: LOG.error(e) self._packageSetHandler = None return self._packageSetHandler @dbus.service.method(HOSTS_INTERFACE) def get_all_hosts(self): self.activity = True return self.hosts.get_all_hosts() @dbus.service.method(HOSTS_INTERFACE) def set_share_inventory(self, share_inventory, hostid, hostname): self.activity = True if share_inventory: # map to boolean to avoid difference in dbus call and direct share_inventory = True else: share_inventory = False return self.hosts.set_share_inventory(share_inventory, hostid, hostname) @dbus.service.method(PACKAGE_SET_INTERFACE) def get_packages(self, hostid, hostname, only_manual): self.activity = True if not self.get_packageSetHandler(): return '' return none_to_null(self.get_packageSetHandler().get_packages( hostid, hostname, only_manual)) @dbus.service.method(PACKAGE_SET_INTERFACE) def diff(self, hostid, hostname): self.activity = True if not self.get_packageSetHandler(): return ('', '') return self.get_packageSetHandler().diff(hostid, hostname) @dbus.service.method(PACKAGE_SET_INTERFACE) def update(self): self.activity = True if self.get_packageSetHandler(): self.get_packageSetHandler().update() @dbus.service.method(PACKAGE_SET_INTERFACE) def async_update(self): self.activity = True if self.get_packageSetHandler(): GLib.timeout_add_seconds(1, self.get_packageSetHandler().update) @dbus.service.signal(HOSTS_INTERFACE) def hostlist_changed(self): LOG.debug("Send host list changed dbus signal") @dbus.service.signal(PACKAGE_SET_INTERFACE) def packagelist_changed(self, hostid): LOG.debug("Send package list changed dbus signal for hostid: %s" % hostid) @dbus.service.signal(HOSTS_INTERFACE) def logo_changed(self, hostid): LOG.debug("Send logo changed dbus signal for hostid: %s" % hostid) @dbus.service.signal(HOSTS_INTERFACE) def latestsync_changed(self, timestamp): LOG.debug("Send last sync timestamp: %s" % timestamp) @dbus.service.method(HOSTS_INTERFACE) def get_last_sync_date(self): self.activity = True return self.hosts.get_last_sync_date() @dbus.service.method(HOSTS_INTERFACE) def stop_service(self): LOG.debug("Request for stopping OneConf service") self.loop.quit() return True
def get_last_sync_date(self): '''get last time the store was successfully synced''' return Hosts().get_last_sync_date()
def get_all_hosts(self): '''get a dict of all available hosts''' return Hosts().get_all_hosts()