示例#1
0
 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 = {}
示例#3
0
    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
示例#4
0
 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 __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 __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 = {}
示例#8
0
 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
示例#10
0
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
示例#11
0
 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"))
示例#12
0
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
示例#14
0
 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))
示例#15
0
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
示例#16
0
 def get_last_sync_date(self):
     '''get last time the store was successfully synced'''
     return Hosts().get_last_sync_date()
示例#17
0
 def get_all_hosts(self):
     '''get a dict of all available hosts'''
     return Hosts().get_all_hosts()