Skip to content
__init__.py 2.72 KiB
Newer Older
from threading import Lock

from cloudcontrol.server.jobs.hotmigration import HotMigrationJob
from cloudcontrol.server.jobs.coldmigration import ColdMigrationJob
from cloudcontrol.server.jobs.clone import CloneJob
from cloudcontrol.server.jobs.killclient import KillClientJob
from cloudcontrol.server.jobs.killoldcli import KillOldCliJob

from cloudcontrol.server.exceptions import (BadJobTypeError, UnknownJobError)


class JobsManager(object):

    """ Manage the current job list.

    :param server: The :class:`CCServer` instance.
    """

    JOBS_TYPES = {
        'kill': KillClientJob,
        'kill_oldcli': KillOldCliJob,
        'cold_migrate': ColdMigrationJob,
        'hot_migrate': HotMigrationJob,
        'clone': CloneJob,
    }

    def __init__(self, logger, server):
        self.logger = logger
        # The main job dict, the keys are id of jobs.
        self._jobs = {}

        # The server:
        self.server = server

        # The id of the next job and it's lock:
        self._current_id = 1
        self._current_id_lock = Lock()

    def create(self, jtype, **kwargs):
        """ Create a new job.

        :param jtype: the type of the new job
        :param \*\*kwargs: arguments to pass to the job
        :raise BadJobTypeError: when invalid jtype is passed
        """

        jobid = self.get_id()
        jobtype = JobsManager.JOBS_TYPES.get(jtype)

        if jobtype is None:
            raise BadJobTypeError('Invalid job type %r' % jtype)

        job = jobtype(self.logger.getChild(str(jobid)), self, id=jobid, **kwargs)
        self._jobs[jobid] = job
        job.daemon = True
        job.start()
        return job

    def get_id(self):
        """ Get the current id and increment the counter.
        """

        with self._current_id_lock:
            jobid = self._current_id
            self._current_id += 1

        return jobid

    def cancel(self, jobid):
        """ Cancel the provided job.
        """

        job = self._jobs.get(jobid)

        if job is None:
            raise UnknownJobError('Invalid job id: %r' % jobid)
        elif job.get('_hidden', False):
            raise UnknownJobError('Invalid job id: %r (hidden)' % jobid)
        else:
            job.cancel()

    def purge(self):
        """ Purge all done jobs.
        """

        for job in self._jobs.values():
            if job['done']:
                del self._jobs[job['id']]

    def iterjobs(self, show_done=True, show_running=True):
        """ Iter over jobs.

        :param done: If set, iterate over done or not done jobs.
        """

        for job in self._jobs.itervalues():
            if (show_done and job['done'] or show_running and not job['done']
                and not job.get('_hidden')):
                yield job