예제 #1
0
    def count_both_users(self):
        """Count both normal and site-to-site users at the same time.

        This is useful for e.g. Ajax code to minimize RDF impact.
        """

        licinfo = helpers.get_license_info()
        limit = licinfo.getS(ns_ui.maxNormalConnections, rdf.Integer)
        limit_leeway = self._add_leeway(limit)
        s2s_limit = licinfo.getS(ns_ui.maxSiteToSiteConnections, rdf.Integer)
        s2s_limit_leeway = self._add_leeway(s2s_limit)

        count, s2s_count = 0, 0
        for dev in helpers.get_ppp_devices():
            try:
                # XXX: we'd ideally want to ignore inactive devices, but that did not
                # seem reliable enough

                if dev.getS(ns.connectionType).hasType(ns.NormalUser):
                    if not dev.getS(ns.restrictedConnection, rdf.Boolean):
                        count += 1
                else:
                    # XXX: assume it is site-to-site, minimize rdf impact
                    if not dev.getS(ns.restrictedConnection, rdf.Boolean):
                        s2s_count += 1
            except:
                _log.exception('count_both_users: failed')

        return count, limit, limit_leeway, s2s_count, s2s_limit, s2s_limit_leeway
예제 #2
0
    def count_both_users(self):
        """Count both normal and site-to-site users at the same time.

        This is useful for e.g. Ajax code to minimize RDF impact.
        """

        licinfo = helpers.get_license_info()
        limit = licinfo.getS(ns_ui.maxNormalConnections, rdf.Integer)
        limit_leeway = self._add_leeway(limit)
        s2s_limit = licinfo.getS(ns_ui.maxSiteToSiteConnections, rdf.Integer)
        s2s_limit_leeway = self._add_leeway(s2s_limit)

        count, s2s_count = 0, 0
        for dev in helpers.get_ppp_devices():
            try:
                # XXX: we'd ideally want to ignore inactive devices, but that did not
                # seem reliable enough

                if dev.getS(ns.connectionType).hasType(ns.NormalUser):
                    if not dev.getS(ns.restrictedConnection, rdf.Boolean):
                        count += 1
                else:
                    # XXX: assume it is site-to-site, minimize rdf impact
                    if not dev.getS(ns.restrictedConnection, rdf.Boolean):
                        s2s_count += 1
            except:
                _log.exception('count_both_users: failed')

        return count, limit, limit_leeway, s2s_count, s2s_limit, s2s_limit_leeway
예제 #3
0
    def _count_devices(self, filterfunc):
        """Count devices from RDF state matching a certain filter."""

        res = 0
        for d in helpers.get_ppp_devices():
            try:
                if filterfunc(d):
                    res += 1
            except:
                _log.exception('_count_devices: filterfunc failed')

        return res
예제 #4
0
    def _count_devices(self, filterfunc):
        """Count devices from RDF state matching a certain filter."""

        res = 0
        for d in helpers.get_ppp_devices():
            try:
                if filterfunc(d):
                    res += 1
            except:
                _log.exception('_count_devices: filterfunc failed')

        return res
예제 #5
0
    def measure_ppp_devs(self, filterfunc):
        devs = helpers.get_ppp_devices()

        fdevs = []
        for dev in devs:
            if filterfunc(dev):
                fdevs.append(dev)

        count = len(fdevs)
        rxtotal, txtotal = 0.0, 0.0
        rxmax, txmax = 0.0, 0.0
        for d in fdevs:
            rxrate = d.getS(ns.rxRateCurrent, rdf.Float)
            txrate = d.getS(ns.txRateCurrent, rdf.Float)
            rxtotal += rxrate
            txtotal += txrate
            if rxrate > rxmax:
                rxmax = rxrate
            if txrate > txmax:
                txmax = txrate
        
        if count > 0:
            return count, rxtotal, txtotal, rxtotal / count, txtotal / count, rxmax, txmax
        return count, rxtotal, txtotal, 'U', 'U', rxmax, txmax
예제 #6
0
    def _do_runner(self):
        """Handle runner command line commands."""

        if len(sys.argv) == 1:
            self.usage_and_exit()
        cmd = sys.argv[1]

        opt = optparse.OptionParser(usage='%prog', version='%prog')
        opt.add_option('-r', '--rdf-file', help='RDF file instead of default database',
                       action='store', dest='rdf_file', type='string', metavar='<file>')
        opt.add_option('-m', '--mode', help='Mode for start',
                       action='store', dest='mode', type='string', metavar='<string>')
        opt.add_option('-i', '--import-path', dest='importpath')
        opt.add_option('-n', '--no-distro-restart', help='Prevent distro networking restart on runner stop',
                       action='store_true', dest='no_distro_restart', default=False)

        opt.set_defaults(rdf_file=None,
                         mode=None,
                         importpath='system')

        (opts, args) = opt.parse_args(sys.argv[2:])
        
        print 'Command = %s, Options: %s' % (cmd, str(opts))

        if opts.rdf_file is not None:
            print 'runner using database file: %s' % opts.rdf_file
            db.replace_database_with_file(opts.rdf_file, constants.RUNNER_TEMPORARY_SQLITE_DATABASE)

        if opts.mode is not None:
            mode = opts.mode
        else:
            mode = 'FULL'
            print 'no mode given, using %s' % mode

        importpath = 'system'
        if opts.importpath is not None:
            importpath = opts.importpath

        nodistrorestart = False
        if opts.no_distro_restart is not None and opts.no_distro_restart:
            nodistrorestart = True

        # XXX: these need rethinking, currently ripped from startstop.py.
        
        # XXX: this should probably be some command name => lambda system, to make command help etc easier

        # XXX: also need transactions here to make things reasonably fast (e.g. for rdf dumps)
        try:
            if mode == 'FULL':
                runner_mode = startstop._mode_full
            elif mode == 'NETWORK-ONLY':
                runner_mode = startstop._mode_network_only
            else:
                raise Exception('unknown mode: %s' % mode)

            _log.debug('starting runner in mode: %s' % runner_mode)
            r = startstop.L2tpRunner(mode=runner_mode, nodistrorestart=nodistrorestart, importpath=importpath)

            if cmd == 'run':
                r.create_pidfile()
                r.run()

            elif cmd == 'resetstate':
                # Set to a fresh node - this orphans all previous state
                return db.get_db().getRoot().setS(ns.l2tpDeviceStatus, rdf.Type(ns.L2tpDeviceStatus))

            elif cmd == 'dumpall':
                rd = rdfdumper.RdfDumper()
                print rd.dump_resource(db.get_db().getRoot(), escaped=True)
            
            elif cmd == 'dumpstatus':
                rd = rdfdumper.RdfDumper()
                print rd.dump_resource(db.get_db().getRoot().getS(ns.l2tpDeviceStatus), escaped=True)

            elif cmd == 'dumpconfig':
                rd = rdfdumper.RdfDumper()
                print rd.dump_resource(db.get_db().getRoot().getS(ns.l2tpDeviceConfig), escaped=True)
            
            elif cmd == 'status':
                st_root = helpers.get_status()

                st_last_str = 'unknown'
                if st_root.hasS(ns.lastStateUpdate):
                    st_last_str = st_root.getS(ns.lastStateUpdate, rdf.Datetime).isoformat()
                
                st_start_str = 'unknown'
                if st_root.hasS(ns.startTime):
                    st_start_str = st_root.getS(ns.startTime, rdf.Datetime).isoformat()

                st_stop_str = 'unknown'
                if st_root.hasS(ns.stopTime):
                    st_stop_str = st_root.getS(ns.stopTime, rdf.Datetime).isoformat()

                st_str = 'unknown'
                st = st_root.getS(ns.state)
                if st.hasType(ns.StateStarting):
                    st_str = 'starting'
                    subst = st.getS(ns.subState)
                    if subst.hasType(ns.StateStartingPreparing):
                        st_str += ' - preparing'
                    if subst.hasType(ns.StateStartingWaitingForDhcp):
                        st_str += ' - waiting for dhcp'
                    if subst.hasType(ns.StateStartingNetwork):
                        st_str += ' - starting network'
                    if subst.hasType(ns.StateStartingDaemons):
                        st_str += ' - starting daemons'
                elif st.hasType(ns.StateRunning):
                    st_str = 'running'
                elif st.hasType(ns.StateStopping):
                    st_str = 'stopping'
                elif st.hasType(ns.StateStopped):
                    st_str = 'stopped'

                st_ppp = 'unknown'
                if st_root.hasS(ns.pppDevices):
                    st_ppp = '%s' % len(helpers.get_ppp_devices())
            
                print 'STATUS: start=%s, stop=%s, last_update=%s, devs=%s, state: %s' % (st_start_str, st_stop_str, st_last_str, st_ppp, st_str)

            elif cmd == 'start':
                r.start()

            elif cmd == 'public-interface-test':
                # XXX
                pass

            elif cmd == 'private-interface-test':
                # XXX
                pass

            elif cmd == 'route-test':
                # XXX
                pass

            elif cmd == 'stop':
                r.stop()

            else:
                raise Exception('unknown command: %s' % cmd)

        except:
            _log.exception('l2tpgw-runner command "%s" failed.' % cmd)
            raise
예제 #7
0
    def reconcile_system_and_rdf_state(self, first_time=False):
        """Reconcile system and RDF states.

        Checks system device list and compares it against RDF device information.
        Extra PPP devices without RDF book-keeping information are terminated.
        Devices present in RDF but not in the system are also removed from RDF.
        After calling this function, the system and RDF should be reasonably
        synchronized.

        This function also detects and updates the 'liveness' of each PPP device.
        Devices which are not live are not taken into account in license computations,
        thus making their detection important.

        The function also updates global public/private interface rx/tx counters,
        rates, etc.

        This function should be periodically, with an interval of 1-10 minutes or so.
        """

        #
        #  XXX: If status is incomplete for some reason, this will now
        #  spout exceptions.  The code should check whether checking and
        #  updating e.g. public interface status is useful at this point.
        #
        
        (pub_if, pub_if_name), (priv_if, priv_if_name) = helpers.get_ifaces(helpers.get_config())

        # start timestamp
        now = datetime.datetime.utcnow()
        
        # get device info from system (ip command)
        _log.debug('reconcile: getting system info')
        ifaces = interfacehelper.get_interfaces()

        # build devname->node dict
        _log.debug('reconcile: build devname->rdf dev dict')
        rdfdevs = helpers.get_ppp_devices()
        rdfdevmap = self._build_rdf_devmap(rdfdevs)
        
        # reconcile devices, pass 1: system vs rdf  [collect sysdevs dict at the same time]
        _log.debug('reconcile: pass 1, system vs rdf')
        sysdevs, pub_di, priv_di = self._reconcile_system_vs_rdf(rdfdevmap, ifaces, pub_if_name, priv_if_name)

        # do sysnukes for devices exceeding threshold
        for k in self._sysnuke_failures.keys():
            if self._sysnuke_failures[k] >= SYSNUKE_FAILURE_LIMIT:
                try:
                    _log.warning('sysnuke failure count for device %s too high, nuking' % k)
                    self._nuke_system_device(k)
                    del self._sysnuke_failures[k]
                except:
                    _log.exception('sysnuke failed')
                
        # reconcile devices, pass 2: rdf vs system
        _log.debug('reconcile: pass 2, rdf vs system')
        self._reconcile_rdf_vs_system(rdfdevs, sysdevs)

        # do rdfnukes for devices exceeding threshold
        for k in self._rdfnuke_failures.keys():  # key = rdf node of type PppDevice
            if self._rdfnuke_failures[k] >= RDFNUKE_FAILURE_LIMIT:
                try:
                    if k.hasS(ns.deviceName):
                        devname = k.getS(ns.deviceName, rdf.String)
                    else:
                        devname = '<unknown devname>'
                    _log.warning('rdfnuke failure count for device %s (%s) too high, nuking' % (k, devname))
                    self._nuke_rdf_device(k)
                    del self._rdfnuke_failures[k]
                except:
                    _log.exception('failed during reconcile, skipping device')
            # NB: device will be left in _rdfnuke_failures, and be removed next time

        # update rx/tx counters, transfer rates, etc
        # (reget devs because we may have nuked something)
        _log.debug('reconcile: updating rx/tx counters')
        rdfdevs = helpers.get_ppp_devices()
        self._update_rxtx_etc(now, rdfdevs, sysdevs)

        # update device liveness status
        _log.debug('reconcile: updating liveness status')
        rdfdevs = helpers.get_ppp_devices()
        self._update_liveness_status(now, rdfdevs)

        # update public/private interface status
        _log.debug('reconcile: updating public and/or private interface status')
        self._update_public_private_ifaces(now, ifaces, pub_di, priv_di, first_time)
예제 #8
0
    def reconcile_system_and_rdf_state(self, first_time=False):
        """Reconcile system and RDF states.

        Checks system device list and compares it against RDF device information.
        Extra PPP devices without RDF book-keeping information are terminated.
        Devices present in RDF but not in the system are also removed from RDF.
        After calling this function, the system and RDF should be reasonably
        synchronized.

        This function also detects and updates the 'liveness' of each PPP device.
        Devices which are not live are not taken into account in license computations,
        thus making their detection important.

        The function also updates global public/private interface rx/tx counters,
        rates, etc.

        This function should be periodically, with an interval of 1-10 minutes or so.
        """

        #
        #  XXX: If status is incomplete for some reason, this will now
        #  spout exceptions.  The code should check whether checking and
        #  updating e.g. public interface status is useful at this point.
        #

        (pub_if, pub_if_name), (priv_if, priv_if_name) = helpers.get_ifaces(
            helpers.get_config())

        # start timestamp
        now = datetime.datetime.utcnow()

        # get device info from system (ip command)
        _log.debug('reconcile: getting system info')
        ifaces = interfacehelper.get_interfaces()

        # build devname->node dict
        _log.debug('reconcile: build devname->rdf dev dict')
        rdfdevs = helpers.get_ppp_devices()
        rdfdevmap = self._build_rdf_devmap(rdfdevs)

        # reconcile devices, pass 1: system vs rdf  [collect sysdevs dict at the same time]
        _log.debug('reconcile: pass 1, system vs rdf')
        sysdevs, pub_di, priv_di = self._reconcile_system_vs_rdf(
            rdfdevmap, ifaces, pub_if_name, priv_if_name)

        # do sysnukes for devices exceeding threshold
        for k in self._sysnuke_failures.keys():
            if self._sysnuke_failures[k] >= SYSNUKE_FAILURE_LIMIT:
                try:
                    _log.warning(
                        'sysnuke failure count for device %s too high, nuking'
                        % k)
                    self._nuke_system_device(k)
                    del self._sysnuke_failures[k]
                except:
                    _log.exception('sysnuke failed')

        # reconcile devices, pass 2: rdf vs system
        _log.debug('reconcile: pass 2, rdf vs system')
        self._reconcile_rdf_vs_system(rdfdevs, sysdevs)

        # do rdfnukes for devices exceeding threshold
        for k in self._rdfnuke_failures.keys(
        ):  # key = rdf node of type PppDevice
            if self._rdfnuke_failures[k] >= RDFNUKE_FAILURE_LIMIT:
                try:
                    if k.hasS(ns.deviceName):
                        devname = k.getS(ns.deviceName, rdf.String)
                    else:
                        devname = '<unknown devname>'
                    _log.warning(
                        'rdfnuke failure count for device %s (%s) too high, nuking'
                        % (k, devname))
                    self._nuke_rdf_device(k)
                    del self._rdfnuke_failures[k]
                except:
                    _log.exception('failed during reconcile, skipping device')
            # NB: device will be left in _rdfnuke_failures, and be removed next time

        # update rx/tx counters, transfer rates, etc
        # (reget devs because we may have nuked something)
        _log.debug('reconcile: updating rx/tx counters')
        rdfdevs = helpers.get_ppp_devices()
        self._update_rxtx_etc(now, rdfdevs, sysdevs)

        # update device liveness status
        _log.debug('reconcile: updating liveness status')
        rdfdevs = helpers.get_ppp_devices()
        self._update_liveness_status(now, rdfdevs)

        # update public/private interface status
        _log.debug(
            'reconcile: updating public and/or private interface status')
        self._update_public_private_ifaces(now, ifaces, pub_di, priv_di,
                                           first_time)