aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/linux/modules/hwmon.mk
Commit message (Expand)AuthorAgeFilesLines
* linux/modules: Add SCH5627 Super I/O chipsLucian Cristian2016-08-031-0/+16
* kernel: Build it87 hardware monitor moduleDaniel Dickinson2016-05-181-0/+14
* modules: hwmon: package driver for INA209 power monitorDaniel Golle2016-05-161-0/+15
* modules: hwmon: package driver for LTC4151 current sensorDaniel Golle2016-05-161-0/+14
* build: remove leftover dependenices on TARGET_rdcFelix Fietkau2016-05-121-1/+1
* kernel: make kmod-thermal dependency conditional to match upstream kernel mod...Felix Fietkau2015-12-231-1/+1
* kernel: make kmod-thermal dependency conditional to match upstream kernel mod...Felix Fietkau2015-12-221-1/+1
* kernel: make kmod-gpiofan depend on kmod-thermal to fix build errorsFelix Fietkau2015-12-221-1/+1
* package: kernel: update dependencies for 4.4Jonas Gorski2015-12-021-1/+1
* kernel: fix kmod-k10temp target dependenciesJo-Philipp Wich2015-05-291-1/+1
* kernel: remove kernel module checks/dependencies for 3.14Felix Fietkau2015-04-111-1/+0
* kernel: drop obsolete linux 3.10 related dependencies/checksFelix Fietkau2015-04-101-1/+1
* kernel: remove obsolete kernel version dependenciesFelix Fietkau2015-03-191-7/+1
* kernel: fix typo in hwmon.mk (#18813)Felix Fietkau2015-01-251-1/+1
* kernel: eliminate a few kernel_patchver_*/CompareKernelPatchVer callsFelix Fietkau2015-01-241-1/+1
* build: drop obsolete kernel version dependenciesFelix Fietkau2015-01-241-2/+2
* pwm support can't be compiled as a moduleImre Kaloz2015-01-121-1/+1
* kernel/hwmon: package pwm-fan kernel moduleFelix Fietkau2015-01-051-0/+16
* linux: add kmod-hwmon-k10tempJo-Philipp Wich2014-10-221-0/+16
* modules: fix typo in package description defineZoltan Herpai2014-09-211-4/+4
* kernel: make hwmon-lm75 only depend on kmod-thermal if neededHauke Mehrtens2014-09-141-1/+1
* kernel: make kmod-hwmon-lm75 depend on kmod-thermalHauke Mehrtens2014-09-131-1/+1
* package the gpio-fan moduleImre Kaloz2014-06-201-0/+16
* package the TI TMP421 driverImre Kaloz2014-06-171-1/+15
* package/kernel: add hwmon driver for ADT7410Gabor Juhos2013-09-251-0/+25
* kernel: make most modules use AutoProbeJohn Crispin2013-09-171-12/+11
* kernel: gsc depends on kmod-i2c-coreLuka Perkov2013-09-121-3/+3
* kernel: allow hwmon GSC driver for all targetsLuka Perkov2013-09-101-0/+15
* kernel: be consistent with formatting styleLuka Perkov2013-07-261-2/+2
* brcm47xx: do not load the kernel modules needed for Ethernet manuallyHauke Mehrtens2013-07-141-1/+1
* packages: clean up the package folderJohn Crispin2013-06-211-0/+221
ref='#n394'>394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>

import traceback

import errno
import sys
import socket
import time
import types

from twisted.internet import reactor
from twisted.internet import defer
#defer.Deferred.debug = 1
from twisted.internet.protocol import Protocol
from twisted.internet.protocol import ClientFactory
from twisted.python.failure import Failure

import sxp
import XendDB
import EventServer; eserver = EventServer.instance()
from XendError import XendError
from XendLogging import log
        
"""The port for the migrate/save daemon xfrd."""
XFRD_PORT = 8002

"""The transfer protocol major version number."""
XFR_PROTO_MAJOR = 1
"""The transfer protocol minor version number."""
XFR_PROTO_MINOR = 0

class Xfrd(Protocol):
    """Protocol handler for a connection to the migration/save daemon xfrd.
    """

    def __init__(self, xinfo):
        self.parser = sxp.Parser()
        self.xinfo = xinfo

    def connectionMade(self):
        # Send hello.
        self.request(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR])
        # Send request.
        self.xinfo.request(self)

    def request(self, req):
        sxp.show(req, out=self.transport)

    def loseConnection(self):
        self.transport.loseConnection()

    def connectionLost(self, reason):
        self.xinfo.connectionLost(reason)

    def dataReceived(self, data):
        self.parser.input(data)
        if self.parser.ready():
            val = self.parser.get_val()
            self.xinfo.dispatch(self, val)
        if self.parser.at_eof():
            self.loseConnection()
            

class XfrdClientFactory(ClientFactory):
    """Factory for clients of the migration/save daemon xfrd.
    """

    def __init__(self, xinfo):
        #ClientFactory.__init__(self)
        self.xinfo = xinfo

    def startedConnecting(self, connector):
        pass

    def buildProtocol(self, addr):
        return Xfrd(self.xinfo)

    def clientConnectionLost(self, connector, reason):
        pass

    def clientConnectionFailed(self, connector, reason):
        self.xinfo.error(reason)

class XfrdInfo:
    """Abstract class for info about a session with xfrd.
    Has subclasses for save and migrate.
    """

    """Suspend timeout (seconds).
    We set a timeout because suspending a domain can hang."""
    timeout = 10

    def __init__(self):
        from xen.xend import XendDomain
        self.xd = XendDomain.instance()
        self.deferred = defer.Deferred()
        self.suspended = {}
        self.paused = {}
        self.state = 'init'
        # List of errors encountered.
        self.errors = []
        
    def vmconfig(self):
        dominfo = self.xd.domain_get(self.src_dom)
        if dominfo:
            val = sxp.to_string(dominfo.sxpr())
        else:
            val = None
        return val

    def add_error(self, err):
        """Add an error to the error list.
        Returns the error added (which may have been unwrapped if it
        was a Twisted Failure).
        """
        while isinstance(err, Failure):
            err = err.value
        if err not in self.errors:
            self.errors.append(err)
        return err

    def error_summary(self, msg=None):
        """Get a XendError summarising the errors (if any).
        """
        if msg is None:
            msg = "errors"
        if self.errors:
            errmsg = msg + ': ' + ', '.join(map(str, self.errors))
        else:
            errmsg = msg
        return XendError(errmsg)

    def get_errors(self):
        """Get the list of errors.
        """
        return self.errors

    def error(self, err):
        self.state = 'error'
        self.add_error(err)
        if not self.deferred.called:
            self.deferred.errback(self.error_summary())

    def dispatch(self, xfrd, val):
        
        def cbok(v):
            if v is None: return
            sxp.show(v, out=xfrd.transport)

        def cberr(err):
            v = ['xfr.err', errno.EINVAL]
            sxp.show(v, out=xfrd.transport)
            self.error(err)

        op = sxp.name(val)
        op = op.replace('.', '_')
        if op.startswith('xfr_'):
            fn = getattr(self, op, self.unknown)
        else:
            fn = self.unknown
        val = fn(xfrd, val)
        if isinstance(val, defer.Deferred):
            val.addCallback(cbok)
            val.addErrback(cberr)
        else:
            cbok(val)

    def unknown(self, xfrd, val):
        xfrd.loseConnection()
        return None

    def xfr_err(self, xfrd, val):
        # If we get an error with non-zero code the operation failed.
        # An error with code zero indicates hello success.
        v = sxp.child0(val)
        err = int(sxp.child0(val))
        if not err: return
        self.error("transfer daemon (xfrd) error: " + str(err))
        xfrd.loseConnection()
        return None

    def xfr_progress(self, xfrd, val):
        return None

    def xfr_vm_destroy(self, xfrd, val):
        try:
            vmid = sxp.child0(val)
            val = self.xd.domain_destroy(vmid)
            if vmid in self.paused:
                del self.paused[vmid]
            if vmid in self.suspended:
                del self.suspended[vmid]
        except StandardError, err:
            self.add_error("vm_destroy failed")
            self.add_error(err)
            val = errno.EINVAL
        return ['xfr.err', val]
    
    def xfr_vm_pause(self, xfrd, val):
        try:
            vmid = sxp.child0(val)
            val = self.xd.domain_pause(vmid)
            self.paused[vmid] = 1
        except StandardError, err:
            self.add_error("vm_pause failed")
            self.add_error(err)
            val = errno.EINVAL
        return ['xfr.err', val]

    def xfr_vm_unpause(self, xfrd, val):
        try:
            vmid = sxp.child0(val)
            val = self.xd.domain_unpause(vmid)
            if vmid in self.paused:
                del self.paused[vmid]
        except StandardError, err:
            self.add_error("vm_unpause failed")
            self.add_error(err)
            val = errno.EINVAL
        return ['xfr.err', val]

    def xfr_vm_suspend(self, xfrd, val):
        """Suspend a domain. Suspending takes time, so we return
        a Deferred that is called when the suspend completes.
        Suspending can hang, so we set a timeout and fail if it
        takes too long.
        """
        try:
            vmid = sxp.child0(val)
            d = defer.Deferred()
            # Subscribe to 'suspended' events so we can tell when the
            # suspend completes. Subscribe to 'died' events so we can tell if
            # the domain died. Set a timeout and error handler so the subscriptions
            # will be cleaned up if suspending hangs or there is an error.
            def onSuspended(e, v):
                if v[1] != vmid: return
                subscribe(on=0)
                if not d.called:
                    d.callback(v)
                
            def onDied(e, v):
                if v[1] != vmid: return
                if not d.called:
                    d.errback(XendError('Domain %s died while suspending' % vmid))
                
            def subscribe(on=1):
                if on:
                    action = eserver.subscribe
                else:
                    action = eserver.unsubscribe
                action('xend.domain.suspended', onSuspended)
                action('xend.domain.died', onDied)

            def cberr(err):
                subscribe(on=0)
                self.add_error("suspend failed")
                self.add_error(err)
                return err

            d.addErrback(cberr)
            d.setTimeout(self.timeout)
            subscribe()
            val = self.xd.domain_shutdown(vmid, reason='suspend')
            self.suspended[vmid] = 1
            return d
        except Exception, err:
            self.add_error("suspend failed")
            self.add_error(err)
            traceback.print_exc()
            val = errno.EINVAL
        return ['xfr.err', val]

    def connectionLost(self, reason=None):
        for vmid in self.suspended:
            try:
                self.xd.domain_destroy(vmid)
            except:
                pass
        for vmid in self.paused:
            try:
                self.xd.domain_unpause(vmid)
            except:
                pass

class XendMigrateInfo(XfrdInfo):
    """Representation of a migrate in-progress and its interaction with xfrd.
    """

    def __init__(self, xid, dominfo, host, port, live=0, resource=0):
        XfrdInfo.__init__(self)
        self.xid = xid
        self.dominfo = dominfo
        self.state = 'begin'
        self.src_host = socket.gethostname()
        self.src_dom = dominfo.id
        self.dst_host = host
        self.dst_port = port
        self.dst_dom = None
        self.live = live
        self.resource = resource
        self.start = 0
        
    def sxpr(self):
        sxpr = ['migrate',
                ['id',    self.xid   ],
                ['state', self.state ],
                ['live',  self.live  ],
                ['resource', self.resource ] ]
        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
        sxpr.append(sxpr_src)
        sxpr_dst = ['dst', ['host', self.dst_host] ]
        if self.dst_dom:
            sxpr_dst.append(['domain', self.dst_dom])
        sxpr.append(sxpr_dst)
        return sxpr

    def request(self, xfrd):
        vmconfig = self.vmconfig()
        if not vmconfig:
            self.error(XendError("vm config not found"))
            xfrd.loseConnection()
            return
        log.info('Migrate BEGIN: %s' % str(self.sxpr()))
        eserver.inject('xend.domain.migrate',
                       [ self.dominfo.name, self.dominfo.id, "begin", self.sxpr() ])
        xfrd.request(['xfr.migrate',
                      self.src_dom,
                      vmconfig,
                      self.dst_host,
                      self.dst_port,
                      self.live,
                      self.resource ])
        
    def xfr_migrate_ok(self, xfrd, val):
        dom = int(sxp.child0(val))
        self.state = 'ok'
        self.dst_dom = dom
        self.xd.domain_destroy(self.src_dom)
        if not self.deferred.called:
            self.deferred.callback(self)

    def connectionLost(self, reason=None):
        XfrdInfo.connectionLost(self, reason)
        if self.state =='ok':
            log.info('Migrate OK: ' + str(self.sxpr()))
        else:
            self.state = 'error'
            self.error("migrate failed")
            log.info('Migrate ERROR: ' + str(self.sxpr()))
        eserver.inject('xend.domain.migrate',
                       [ self.dominfo.name, self.dominfo.id, self.state, self.sxpr() ])

class XendSaveInfo(XfrdInfo):
    """Representation of a save in-progress and its interaction with xfrd.
    """
    
    def __init__(self, xid, dominfo, file):
        XfrdInfo.__init__(self)
        self.xid = xid
        self.dominfo = dominfo
        self.state = 'begin'
        self.src_dom = dominfo.id
        self.file = file
        self.start = 0
        
    def sxpr(self):
        sxpr = ['save',
                ['id', self.xid],
                ['state', self.state],
                ['domain', self.src_dom],
                ['file', self.file] ]
        return sxpr

    def request(self, xfrd):
        vmconfig = self.vmconfig()
        if not vmconfig:
            self.error(XendError("vm config not found"))
            xfrd.loseConnection()
            return
        log.info('Save BEGIN: ' + str(self.sxpr()))
        eserver.inject('xend.domain.save',
                       [ self.dominfo.name, self.dominfo.id,
                         "begin", self.sxpr() ])
        xfrd.request(['xfr.save', self.src_dom, vmconfig, self.file ])
        
    def xfr_save_ok(self, xfrd, val):
        self.state = 'ok'
        self.xd.domain_destroy(self.src_dom)
        if not self.deferred.called:
            self.deferred.callback(self)

    def connectionLost(self, reason=None):
        XfrdInfo.connectionLost(self, reason)
        if self.state =='ok':
            log.info('Save OK: ' + str(self.sxpr()))
        else:
            self.state = 'error'
            self.error("save failed")
            log.info('Save ERROR: ' + str(self.sxpr()))
        eserver.inject('xend.domain.save',
                       [ self.dominfo.name, self.dominfo.id,
                         self.state, self.sxpr() ])
    
class XendRestoreInfo(XfrdInfo):
    """Representation of a restore in-progress and its interaction with xfrd.
    """

    def __init__(self, xid, file):
        XfrdInfo.__init__(self)
        self.xid = xid
        self.state = 'begin'
        self.file = file

    def sxpr(self):
         sxpr = ['restore',
                 ['id', self.xid],
                 ['file', self.file] ]
         return sxpr

    def request(self, xfrd):
        log.info('restore BEGIN: ' + str(self.sxpr()))
        eserver.inject('xend.restore', [ 'begin', self.sxpr()])
                       
        xfrd.request(['xfr.restore', self.file ])
        
    def xfr_restore_ok(self, xfrd, val):
        dom = int(sxp.child0(val))
        dominfo = self.xd.domain_get(dom)
        self.state = 'ok'
        if not self.deferred.called:
            self.deferred.callback(dominfo)
         
    def connectionLost(self, reason=None):
        XfrdInfo.connectionLost(self, reason)
        if self.state =='ok':
            log.info('Restore OK: ' + self.file)
        else:
            self.state = 'error'
            self.error("restore failed")
            log.info('Restore ERROR: ' + str(self.sxpr()))
        eserver.inject('xend.restore', [ self.state,  self.sxpr()])

class XendMigrate:
    """External api for interaction with xfrd for migrate and save.
    Singleton.
    """
    # Use log for indications of begin/end/errors?
    # Need logging of: domain create/halt, migrate begin/end/fail
    # Log via event server?

    dbpath = "migrate"
    
    def __init__(self):
        self.db = XendDB.XendDB(self.dbpath)
        self.session = {}
        self.session_db = self.db.fetchall("")
        self.xid = 0

    def nextid(self):
        self.xid += 1
        return "%d" % self.xid

    def sync(self):
        self.db.saveall("", self.session_db)

    def sync_session(self, xid):
        self.db.save(xid, self.session_db[xid])

    def close(self):
        pass

    def _add_session(self, info):
        xid = info.xid
        self.session[xid] = info
        self.session_db[xid] = info.sxpr()
        self.sync_session(xid)

    def _delete_session(self, xid):
        if xid in self.session:
            del self.session[xid]
        if xid in self.session_db:
            del self.session_db[xid]
            self.db.delete(xid)

    def session_ls(self):
        return self.session.keys()

    def sessions(self):
        return self.session.values()

    def session_get(self, xid):
        return self.session.get(xid)

    def session_begin(self, info):
        """Add the session to the table and start it.
        Set up callbacks to remove the session from the table
        when it finishes.

        @param info: session
        @return: deferred
        """
        dfr = defer.Deferred()
        def cbok(val):
            self._delete_session(info.xid)
            if not dfr.called:
                dfr.callback(val)
            return val
        def cberr(err):
            self._delete_session(info.xid)
            if not dfr.called:
                dfr.errback(err)
            return err
        self._add_session(info)
        info.deferred.addCallback(cbok)
        info.deferred.addErrback(cberr)
        xcf = XfrdClientFactory(info)
        reactor.connectTCP('localhost', XFRD_PORT, xcf)
        return dfr
    
    def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0):
        """Begin to migrate a domain to another host.

        @param dominfo:  domain info
        @param host: destination host
        @param port: destination port
        @return: deferred
        """
        xid = self.nextid()
        info = XendMigrateInfo(xid, dominfo, host, port, live, resource)
        return self.session_begin(info)

    def save_begin(self, dominfo, file):
        """Begin saving a domain to file.

        @param dominfo:  domain info
        @param file: destination file
        @return: deferred
        """
        xid = self.nextid()
        info = XendSaveInfo(xid, dominfo, file)
        return self.session_begin(info)

    def restore_begin(self, file):
        xid = self.nextid()
        info = XendRestoreInfo(xid, file)
        return self.session_begin(info)
        

def instance():
    global inst
    try:
        inst
    except:
        inst = XendMigrate()
    return inst