Пример #1
0
 def __init__(self, clock, name, apiclient, store_query, interval):
     self.log = logging.getLogger('executor.controller.%s' % (name,))
     self.name = name
     self.apiclient = apiclient
     self.store_query = store_query
     self.interval = interval
     self._problematic = True
     self._terminated = []
     self._containers = {}
     self._task = LoopingCall(clock, self._check_status)
     self._started = Event()
Пример #2
0
    def build(self, config):
        for name, spec in config.iteritems():
            self.states[name] = State(time)
            if name != self.name:
                self.nodes[name] = Node(name, spec['host'], spec['port'],
                                        self.states[name])
        self.cluster = Cluster(self.name, self.nodes, self.requests)
        self.combined_state = CombinedState(self.states)

        self._consume_peer_state_task = LoopingCall(self.clock,
                                                    _consume_peer_state,
                                                    self.cluster,
                                                    self.combined_state)
        self._purge_expired_deltas_task = LoopingCall(self.clock,
                                                      _purge_expired_deltas,
                                                      self.clock, self.states,
                                                      self.combined_state,
                                                      self._liveness)
        rest_api = RestApi(self.states[self.name], self.combined_state)
        self.server = WSGIServer(('', self.port), rest_api)
Пример #3
0
 def __init__(self, clock, name, apiclient, store_query, interval):
     self.log = logging.getLogger("executor.controller.%s" % (name,))
     self.name = name
     self.apiclient = apiclient
     self.store_query = store_query
     self.interval = interval
     self._problematic = True
     self._terminated = []
     self._containers = {}
     self._task = LoopingCall(clock, self._check_status)
     self._started = Event()
Пример #4
0
class _ExecutorController(object):

    def __init__(self, clock, name, apiclient, store_query, interval):
        self.log = logging.getLogger('executor.controller.%s' % (name,))
        self.name = name
        self.apiclient = apiclient
        self.store_query = store_query
        self.interval = interval
        self._problematic = True
        self._terminated = []
        self._containers = {}
        self._task = LoopingCall(clock, self._check_status)
        self._started = Event()

    def containers(self):
        return self._containers.keys()

    def start(self):
        self._task.start(self.interval)
        self._started.wait()
        return self

    def dispatch(self, inst):
        container = self._handle_error(self.apiclient.create, inst)
        self._remember(container.id, container)

    def statuses(self, instances):
        for instance in instances:
            container = self.find(instance)
            yield (container.state if container is not None
                   else 'unknown')

    def delete(self, instance):
        """Delete instance."""
        container = self.find(instance)
        if container is not None:
            self._forget(container.id)
            try:
                self._handle_error(self.apiclient.delete, container.id)
            except Exception:
                self._terminated.add(container.id)
                raise

    def restart(self, instance):
        container = self.find(instance)
        if container is not None:
            container = self._handle_error(
                self.apiclient.restart, container.id, instance)
            self._remember(container.id, container)

    def _check_status(self):
        try:
            containers = self.apiclient.containers()
        except Exception:
            raise
        else:
            if self._problematic:
                self._reconcile(containers)
                self._problematic = False
            for id, container in containers.items():
                self._remember(id, container)
            self._update_state()
        self._started.set()

    def _update_state(self):
        for id, container in self._containers.items():
            if container.state == 'error':
                inst = self._geti(container)
                if inst is not None and inst.state != inst.STATE_LOST:
                    inst.set_state(inst.STATE_LOST)

    def _reconcile(self, containers):
        self._reconcile_missing_containers(containers)
        self._mark_lost_containers_as_lost(containers)
        self._delete_terminated_containers(containers)

    def _reconcile_missing_containers(self, containers):
        missing = (set(containers)
                   - set(self._containers)
                   - set(self._terminated))
        self.log.info("reconscile: %s" % (', '.join(missing)))
        for cid, state in [(cid, containers[cid]) for cid in missing]:
            if self._geti(state) is not None:
                self._remember(cid, state)
            # FIXME: what to do with containers where the instance
            # cannot be found?  at what stage do we remove them?
            # NOW!?  self._delete_container(cid)

    def _mark_lost_containers_as_lost(self, containers):
        missing = set(self._containers) - set(containers)
        self.log.info("mark containers %s as lost" % (
                ', '.join(missing)))
        for state in [self._containers[cid] for cid in missing]:
            inst = self._geti(state)
            if inst is not None and inst.state != inst.STATE_LOST:
                inst.set_state(inst.STATE_LOST)

    def _delete_terminated_containers(self, containers):
        for cid in self._terminated:
            if cid in containers:
                self._client.delete(cid)
        del self._terminated[:]

    def _handle_error(self, m, *args, **kwargs):
        if self._problematic:
            raise DispatchError("problematic")
        try:
            return m(*args, **kwargs)
        except Exception, err:
            self._problematic = True
            raise DispatchError(str(err))
Пример #5
0
class _ExecutorController(object):

    def __init__(self, clock, name, apiclient, store_query, state_cache,
                 interval):
        self.log = logging.getLogger('executor.controller.%s' % (name,))
        self.name = name
        self.apiclient = apiclient
        self.store_query = store_query
        self.state_cache = state_cache
        self.interval = interval
        self._problematic = True
        self._terminated = []
        self._containers = {}
        self._task = LoopingCall(clock, self._check_status)
        self._started = Event()

    def containers(self):
        return self._containers.keys()

    def start(self):
        self._task.start(self.interval)
        self._started.wait()
        return self

    def dispatch(self, inst):
        container = self._handle_error(self.apiclient.create, inst)
        self._remember(container.id, container)

    def statuses(self, instances):
        for instance in instances:
            container = self.find(instance)
            yield (container.state if container is not None
                   else 'unknown')

    def delete(self, instance):
        """Delete instance."""
        container = self.find(instance)
        if container is not None:
            self._forget(container.id)
            try:
                self._handle_error(self.apiclient.delete, container.id)
            except Exception:
                self._terminated.add(container.id)
                raise

    def restart(self, instance):
        container = self.find(instance)
        if container is not None:
            container = self._handle_error(
                self.apiclient.restart, container.id, instance)
            self._remember(container.id, container)

    def _check_status(self):
        try:
            containers = self.apiclient.containers()
        except Exception:
            raise
        else:
            if self._problematic:
                self._reconcile(containers)
                self._problematic = False
            for id, container in containers.items():
                self._remember(id, container)
        self._started.set()

    def _reconcile(self, containers):
        self._reconcile_missing_containers(containers)
        self._mark_lost_containers_as_lost(containers)
        self._delete_terminated_containers(containers)

    def _reconcile_missing_containers(self, containers):
        missing = (set(containers)
                   - set(self._containers)
                   - set(self._terminated))
        self.log.info("reconscile: %s" % (', '.join(missing)))
        for cid, state in [(cid, containers[cid]) for cid in missing]:
            if self._geti(state) is not None:
                self._remember(cid, state)
            # FIXME: what to do with containers where the instance
            # cannot be found?  at what stage do we remove them?
            # NOW!?  self._delete_container(cid)

    def _mark_lost_containers_as_lost(self, containers):
        missing = set(self._containers) - set(containers)
        self.log.info("mark containers %s as lost" % (
                ', '.join(missing)))
        for state in [self._containers[cid] for cid in missing]:
            inst = self._geti(state)
            if inst is not None and inst.state != inst.STATE_LOST:
                inst.set_state(inst.STATE_LOST)

    def _delete_terminated_containers(self, containers):
        for cid in self._terminated:
            if cid in containers:
                self._client.delete(cid)
        del self._terminated[:]

    def _handle_error(self, m, *args, **kwargs):
        if self._problematic:
            raise DispatchError("problematic")
        try:
            return m(*args, **kwargs)
        except Exception, err:
            self._problematic = True
            raise DispatchError(str(err))