示例#1
0
    def __init__(self, router=None):
        BaseNode.__init__(self)

        self._own_router = True
        if router is not None:
            self._local_router = router
            self._own_router = False
        else:
            self._local_router = LocalRouter(get_sys_name())
        self._channel_id_pool = IDPool()
示例#2
0
    def setUp(self):
        self.lr = LocalRouter(get_sys_name())
        self.lr.start()
        self.addCleanup(self.lr.stop)

        # make a hook so we can tell when a message gets routed
        self.ev = Event()

        def new_route(*args, **kwargs):
            self.ev.set()
            self.lr._oldroute(*args, **kwargs)

        self.lr._oldroute = self.lr._route
        self.lr._route = new_route
示例#3
0
    def test__run_consumer(self):
        propsmock = Mock()
        propsmock.copy.return_value = sentinel.props
        gqueue = Mock()
        m = (sentinel.exchange, sentinel.routing_key, sentinel.body, propsmock)
        gqueue.get.side_effect = [m, LocalRouter.ConsumerClosedMessage()]
        cb = Mock()
        self.lr._generate_dtag = Mock(return_value=sentinel.dtag)

        self.lr._run_consumer(sentinel.ctag, sentinel.queue, gqueue, cb)

        self.assertEquals(cb.call_count, 1)
        self.assertEquals(cb.call_args[0][0], self.lr)
        self.assertEquals(
            dict(cb.call_args[0][1]), {
                'consumer_tag': sentinel.ctag,
                'delivery_tag': sentinel.dtag,
                'redelivered': False,
                'exchange': sentinel.exchange,
                'routing_key': sentinel.routing_key
            })
        self.assertEquals(dict(cb.call_args[0][2]),
                          {'headers': sentinel.props})
        self.assertEquals(cb.call_args[0][3], sentinel.body)

        self.assertIn((sentinel.ctag, sentinel.queue, m),
                      self.lr._unacked.itervalues())
示例#4
0
    def __init__(self, router=None):
        BaseNode.__init__(self)

        self._own_router = True
        if router is not None:
            self._local_router = router
            self._own_router = False
        else:
            self._local_router = LocalRouter(get_sys_name())
        self._channel_id_pool = IDPool()
示例#5
0
    def setUp(self):
        self.lr = LocalRouter(get_sys_name())
        self.lr.start()
        self.addCleanup(self.lr.stop)

        # make a hook so we can tell when a message gets routed
        self.ev = Event()
        def new_route(*args, **kwargs):
            self.ev.set()
            self.lr._oldroute(*args, **kwargs)
        self.lr._oldroute = self.lr._route
        self.lr._route = new_route
示例#6
0
class LocalNode(BaseNode):
    def __init__(self, router=None):
        BaseNode.__init__(self)

        self._own_router = True
        if router is not None:
            self._local_router = router
            self._own_router = False
        else:
            self._local_router = LocalRouter(get_sys_name())
        self._channel_id_pool = IDPool()

    def start_node(self):
        BaseNode.start_node(self)
        if self._own_router:
            self._local_router.start()

    def stop_node(self):
        if self.running:
            if self._own_router:
                self._local_router.stop()
        self.running = False

    def _new_transport(self, ch_number=None):
        trans = LocalTransport(self._local_router, ch_number)
        return trans

    def channel(self, ch_type, transport=None):
        ch = self._new_channel(ch_type,
                               ch_number=self._channel_id_pool.get_id(),
                               transport=transport)
        # @TODO keep track of all channels to close them later from the top

        ch._transport.add_on_close_callback(self._on_channel_close)
        return ch

    def _on_channel_close(self, ch, code, text):
        log.debug("LocalNode._on_channel_close (%s)", ch.channel_number)
        self._channel_id_pool.release_id(ch.channel_number)
示例#7
0
class LocalNode(BaseNode):
    def __init__(self, router=None):
        BaseNode.__init__(self)

        self._own_router = True
        if router is not None:
            self._local_router = router
            self._own_router = False
        else:
            self._local_router = LocalRouter(get_sys_name())
        self._channel_id_pool = IDPool()

    def start_node(self):
        BaseNode.start_node(self)
        if self._own_router:
            self._local_router.start()

    def stop_node(self):
        if self.running:
            if self._own_router:
                self._local_router.stop()
        self.running = False

    def _new_transport(self, ch_number=None):
        trans = LocalTransport(self._local_router, ch_number)
        return trans

    def channel(self, ch_type, transport=None):
        ch = self._new_channel(ch_type, ch_number=self._channel_id_pool.get_id(), transport=transport)
        # @TODO keep track of all channels to close them later from the top

        ch._transport.add_on_close_callback(self._on_channel_close)
        return ch

    def _on_channel_close(self, ch, code, text):
        log.debug("ZeroMQNode._on_channel_close (%s)", ch.channel_number)
        self._channel_id_pool.release_id(ch.channel_number)
示例#8
0
class TestLocalRouter(PyonTestCase):
    def setUp(self):
        self.lr = LocalRouter(get_sys_name())
        self.lr.start()
        self.addCleanup(self.lr.stop)

        # make a hook so we can tell when a message gets routed
        self.ev = Event()

        def new_route(*args, **kwargs):
            self.ev.set()
            self.lr._oldroute(*args, **kwargs)

        self.lr._oldroute = self.lr._route
        self.lr._route = new_route

    def test_publish_to_unknown_exchange(self):
        self.assertEquals(len(self.lr.errors), 0)
        self.lr.publish('ex', 'rkey', 'body', 'props')
        self.ev.wait(timeout=10)
        self.assertEquals(len(self.lr.errors), 1)

    def test_publish_to_known_exchange(self):
        # declare exchange
        self.lr.declare_exchange('known')

        # send message
        self.lr.publish('known', 'rkey', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # message is binned but no errors
        self.assertEquals(len(self.lr.errors), 0)

    def test_publish_to_queue(self):
        # declare exchange/queue/binding
        self.lr.declare_exchange('known')
        self.lr.declare_queue('iamqueue')
        self.lr.bind('known', 'iamqueue', 'binzim')
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0)

        # send message
        self.lr.publish('known', 'binzim', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be sitting in a queue waiting
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1)
        #self.assertIn(('known', 'binzim', 'body', 'props'), self.lr._queues['iamqueue'])

    def test_publish_to_many_queues(self):
        # declare exchange/queue/binding
        self.lr.declare_exchange('known')
        self.lr.declare_queue('q1')
        self.lr.bind('known', 'q1', 'a.*')

        self.lr.declare_queue('q2')
        self.lr.bind('known', 'q2', 'a.b')

        self.lr.declare_queue('q3')
        self.lr.bind('known', 'q3', '*.b')

        # send message
        self.lr.publish('known', 'a.b', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be in 3 queues
        for q in ['q1', 'q2', 'q3']:
            self.assertEquals(self.lr._queues[q].qsize(), 1)
            #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues[q])

    def test_publish_to_queue_with_multiple_matching_binds_only_makes_one_message(
            self):
        # exchange/queue/bindings
        self.lr.declare_exchange('known')
        self.lr.declare_queue('iamqueue')
        self.lr.bind('known', 'iamqueue', 'a.*')
        self.lr.bind('known', 'iamqueue', 'a.b')
        self.lr.bind('known', 'iamqueue', '*.b')

        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0)

        # send message
        self.lr.publish('known', 'a.b', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be in the queue
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1)
        #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues['iamqueue'])

    def test_publish_with_binds_and_unbinds(self):
        # declare exchange/queue
        self.lr.declare_exchange('known')
        self.lr.declare_queue('ein')

        self.assertEquals(self.lr._queues['ein'].qsize(), 0)

        # send message
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear()  # we need to use again

        # not bound, so doesn't go into the queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 0)

        # bind now
        self.lr.bind('known', 'ein', 'ein')

        # send message
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear()  # we need to use again

        # should be in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 1)

        # send again
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear()  # we need to use again

        # now 2 in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 2)

        # unbind
        self.lr.unbind('known', 'ein', 'ein')

        # send again
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear()  # we need to use again

        # still 2 in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 2)

    def test__connect_addr(self):
        self.assertEquals(self.lr._connect_addr,
                          "inproc://%s" % get_sys_name())

    def test__child_failed(self):
        self.lr.gl_ioloop = Mock()

        fail = Mock()
        self.lr._child_failed(fail)

        self.lr.gl_ioloop.kill.assert_called_once_with(
            exception=fail.exception, block=False)

    def test__run_ioloop(self):
        self.lr._gl_pool = Mock()
        self.lr._run_ioloop()

        self.lr._gl_pool.join.assert_called_once_with()

    def test_declare_exchange(self):
        self.lr.declare_exchange(sentinel.exchange)

        self.assertIn(sentinel.exchange, self.lr._exchanges)
        self.assertIsInstance(self.lr._exchanges[sentinel.exchange], TopicTrie)

    def test_declare_exchange_existing(self):
        tt = TopicTrie()
        self.lr._exchanges[sentinel.exchange] = tt

        self.lr.declare_exchange(sentinel.exchange)
        self.assertEquals(tt, self.lr._exchanges[sentinel.exchange])

    def test_delete_exchange(self):
        self.lr.declare_exchange(sentinel.exchange)
        self.lr.delete_exchange(sentinel.exchange)

        self.assertEquals(self.lr._exchanges, {})

    def test_declare_queue(self):
        self.lr.declare_queue(sentinel.queue)
        self.assertIn(sentinel.queue, self.lr._queues)

    def test_declare_queue_made_up(self):
        q = self.lr.declare_queue('')
        self.assertIn("q-", q)
        self.assertIn(q, self.lr._queues)

    def test_delete_queue(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr.delete_queue(sentinel.queue)
        self.assertNotIn(sentinel.queue, self.lr._queues)

    def test_delete_queue_deletes_bindings(self):
        self.lr.declare_exchange(sentinel.exchange)
        self.lr.declare_queue(sentinel.queue)
        self.lr.bind(sentinel.exchange, sentinel.queue, 'binder')

        self.lr.delete_queue(sentinel.queue)
        self.assertNotIn(sentinel.queue, self.lr._queues)
        self.assertNotIn(sentinel.queue, self.lr._bindings_by_queue)

    def test_start_consume(self):
        self.lr._gl_pool = Mock()
        self.lr.declare_queue(sentinel.queue)
        ctag = self.lr.start_consume(sentinel.callback, sentinel.queue)

        self.assertIn(sentinel.queue, self.lr._consumers)
        self.assertIn(ctag, self.lr._consumers_by_ctag)

        self.assertEquals(self.lr._consumers[sentinel.queue],
                          [(ctag, sentinel.callback, False, False,
                            self.lr._gl_pool.spawn.return_value)])

    def test_stop_consume(self):
        self.lr._gl_pool = Mock()
        self.lr.declare_queue(sentinel.queue)
        ctag = self.lr.start_consume(sentinel.callback, sentinel.queue)

        self.lr.stop_consume(ctag)

        self.assertNotIn(ctag, self.lr._consumers_by_ctag)
        self.lr._gl_pool.spawn().join.assert_called_once_with(timeout=5)
        self.lr._gl_pool.spawn().kill.assert_called_once_with()
        self.assertEquals(len(self.lr._consumers[sentinel.queue]), 0)

    def test__run_consumer(self):
        propsmock = Mock()
        propsmock.copy.return_value = sentinel.props
        gqueue = Mock()
        m = (sentinel.exchange, sentinel.routing_key, sentinel.body, propsmock)
        gqueue.get.side_effect = [m, LocalRouter.ConsumerClosedMessage()]
        cb = Mock()
        self.lr._generate_dtag = Mock(return_value=sentinel.dtag)

        self.lr._run_consumer(sentinel.ctag, sentinel.queue, gqueue, cb)

        self.assertEquals(cb.call_count, 1)
        self.assertEquals(cb.call_args[0][0], self.lr)
        self.assertEquals(
            dict(cb.call_args[0][1]), {
                'consumer_tag': sentinel.ctag,
                'delivery_tag': sentinel.dtag,
                'redelivered': False,
                'exchange': sentinel.exchange,
                'routing_key': sentinel.routing_key
            })
        self.assertEquals(dict(cb.call_args[0][2]),
                          {'headers': sentinel.props})
        self.assertEquals(cb.call_args[0][3], sentinel.body)

        self.assertIn((sentinel.ctag, sentinel.queue, m),
                      self.lr._unacked.itervalues())

    def test__generate_ctag(self):
        self.lr._ctag_pool = Mock()
        self.lr._ctag_pool.get_id.return_value = sentinel.ctagid

        self.assertEquals(self.lr._generate_ctag(),
                          "zctag-%s" % str(sentinel.ctagid))

    def test__return_ctag(self):
        self.lr._ctag_pool = Mock()

        self.lr._return_ctag("m-5")

        self.lr._ctag_pool.release_id.assert_called_once_with(5)

    def test__generate_and_return_ctag(self):
        ctag = self.lr._generate_ctag()
        ctagnum = int(ctag.split("-")[-1])
        self.assertIn(ctagnum, self.lr._ctag_pool._ids_in_use)

        self.lr._return_ctag(ctag)
        self.assertIn(ctagnum, self.lr._ctag_pool._ids_free)
        self.assertNotIn(ctagnum, self.lr._ctag_pool._ids_in_use)

    def test__generate_dtag(self):
        dtag = self.lr._generate_dtag(sentinel.ctag, sentinel.cnt)

        self.assertIn(str(sentinel.ctag), dtag)
        self.assertIn(str(sentinel.cnt), dtag)

    def test_ack(self):
        self.lr._unacked[sentinel.dtag] = True

        self.lr.ack(sentinel.dtag)
        self.assertEquals(len(self.lr._unacked), 0)

    def test_reject(self):
        self.lr._unacked[sentinel.dtag] = (None, None, None)

        self.lr.reject(sentinel.dtag)
        self.assertEquals(len(self.lr._unacked), 0)

    def test_reject_requeue(self):
        q = Mock()
        self.lr._queues[sentinel.queue] = q
        self.lr._unacked[sentinel.dtag] = (None, sentinel.queue, sentinel.m)

        self.lr.reject(sentinel.dtag, requeue=True)
        self.assertEquals(len(self.lr._unacked), 0)
        q.put.assert_called_once_with(sentinel.m)

    def test_transport_close(self):
        # no body in localrouter method
        pass

    def test_get_stats(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)

        mc, cc = self.lr.get_stats(sentinel.queue)

        self.assertEquals((mc, cc), (1, 0))

    def test_get_stats_with_consumers(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)
        self.lr._consumers[sentinel.queue] = [sentinel.ctag]

        mc, cc = self.lr.get_stats(sentinel.queue)

        self.assertEquals((mc, cc), (1, 1))

    def test_purge(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)
        self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 1)

        self.lr.purge(sentinel.queue)

        self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 0)
示例#9
0
文件: cc.py 项目: pkediyal/pyon
class Container(BaseContainerAgent):
    """
    The Capability Container. Its purpose is to spawn/monitor processes and services
    that do the bulk of the work in the ION system. It also manages connections to the Exchange
    and the various forms of datastores in the systems.
    """

    # Singleton static variables
    #node        = None
    id          = None
    name        = None
    pidfile     = None
    instance    = None

    def __init__(self, *args, **kwargs):
        BaseContainerAgent.__init__(self, *args, **kwargs)

        self._is_started = False
        # set container id and cc_agent name (as they are set in base class call)
        self.id = get_default_container_id()
        self.name = "cc_agent_%s" % self.id
        self._capabilities = []

        bootstrap.container_instance = self
        Container.instance = self

        log.debug("Container (sysname=%s) initializing ..." % bootstrap.get_sys_name())

        # Keep track of the overrides from the command-line, so they can trump app/rel file data
        self.spawn_args = kwargs

        # DatastoreManager - controls access to Datastores (both mock and couch backed)
        self.datastore_manager = DatastoreManager()

        # TODO: Do not start a capability here. Symmetric start/stop
        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        # Instantiate Directory
        self.directory = Directory()

        # internal router
        self.local_router = None

        # Create this Container's specific ExchangeManager instance
        self.ex_manager = ExchangeManager(self)

        # Create this Container's specific ProcManager instance
        self.proc_manager = ProcManager(self)

        # Create this Container's specific AppManager instance
        self.app_manager = AppManager(self)

        # File System - Interface to the OS File System, using correct path names and setups
        self.file_system = FileSystem(CFG)

        # Governance Controller - manages the governance related interceptors
        self.governance_controller = GovernanceController(self)

        # sFlow manager - controls sFlow stat emission
        self.sflow_manager = SFlowManager(self)

        # Coordinates the container start
        self._status = "INIT"

        # protection for when the container itself is used as a Process for clients
        self.container = self

        # publisher, initialized in start()
        self.event_pub = None

        # context-local storage
        self.context = LocalContextMixin()

        log.debug("Container initialized, OK.")

    def start(self):
        log.debug("Container starting...")
        if self._is_started:
            raise ContainerError("Container already started")

        # Check if this UNIX process already runs a Container.
        self.pidfile = "cc-pid-%d" % os.getpid()
        if os.path.exists(self.pidfile):
            raise ContainerError("Container.on_start(): Container is a singleton per UNIX process. Existing pid file found: %s" % self.pidfile)

        # write out a PID file containing our agent messaging name
        with open(self.pidfile, 'w') as f:
            pid_contents = {'messaging': dict(CFG.server.amqp),
                            'container-agent': self.name,
                            'container-xp': bootstrap.get_sys_name()}
            f.write(msgpack.dumps(pid_contents))
            atexit.register(self._cleanup_pid)
            self._capabilities.append("PID_FILE")

        # set up abnormal termination handler for this container
        def handl(signum, frame):
            try:
                self._cleanup_pid()     # cleanup the pidfile first
                self.quit()             # now try to quit - will not error on second cleanup pidfile call
            finally:
                signal.signal(signal.SIGTERM, self._normal_signal)
                os.kill(os.getpid(), signal.SIGTERM)
        self._normal_signal = signal.signal(signal.SIGTERM, handl)

        # set up greenlet debugging signal handler
        gevent.signal(signal.SIGUSR2, self._handle_sigusr2)

        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        self._capabilities.append("DIRECTORY")

        # Event repository
        self.event_repository = EventRepository()
        self.event_pub = EventPublisher()
        self._capabilities.append("EVENT_REPOSITORY")

        # Local resource registry
        self.resource_registry = ResourceRegistry()
        self._capabilities.append("RESOURCE_REGISTRY")

        # Persistent objects
        self.datastore_manager.get_datastore("objects", DataStore.DS_PROFILE.OBJECTS)

        # State repository
        self.state_repository = StateRepository()
        self._capabilities.append("STATE_REPOSITORY")

        # internal router for local transports
        self.local_router = LocalRouter(bootstrap.get_sys_name())
        self.local_router.start()
        self.local_router.ready.wait(timeout=2)
        self._capabilities.append("LOCAL_ROUTER")

        # Start ExchangeManager, which starts the node (broker connection)
        self.ex_manager.start()
        self._capabilities.append("EXCHANGE_MANAGER")

        self.proc_manager.start()
        self._capabilities.append("PROC_MANAGER")

        self.app_manager.start()
        self._capabilities.append("APP_MANAGER")

        self.governance_controller.start()
        self._capabilities.append("GOVERNANCE_CONTROLLER")

        if CFG.get_safe('container.sflow.enabled', False):
            self.sflow_manager.start()
            self._capabilities.append("SFLOW_MANAGER")

        # Start the CC-Agent API
        rsvc = ProcessRPCServer(node=self.node, from_name=self.name, service=self, process=self)

        cleanup = lambda _: self.proc_manager._cleanup_method(self.name, rsvc)

        # Start an ION process with the right kind of endpoint factory
        proc = self.proc_manager.proc_sup.spawn(name=self.name, listeners=[rsvc], service=self, cleanup_method=cleanup)
        self.proc_manager.proc_sup.ensure_ready(proc)
        proc.start_listeners()
        self._capabilities.append("CONTAINER_AGENT")

        self.event_pub.publish_event(event_type="ContainerLifecycleEvent",
                                     origin=self.id, origin_type="CapabilityContainer",
                                     sub_type="START",
                                     state=ContainerStateEnum.START)

        self._is_started    = True
        self._status        = "RUNNING"

        log.info("Container (%s) started, OK." , self.id)

    def _handle_sigusr2(self):#, signum, frame):
        """
        Handles SIGUSR2, prints debugging greenlet information.
        """
        gls = GreenletLeak.get_greenlets()

        allgls = []

        for gl in gls:
            status = GreenletLeak.format_greenlet(gl)

            # build formatted output:
            # Greenlet at 0xdeadbeef
            #     self: <EndpointUnit at 0x1ffcceef>
            #     func: bound, EndpointUnit.some_func

            status[0].insert(0, "%s at %s:" % (gl.__class__.__name__, hex(id(gl))))
            # indent anything in status a second time
            prefmt = [s.replace("\t", "\t\t") for s in status[0]]
            prefmt.append("traceback:")

            for line in status[1]:
                for subline in line.split("\n")[0:2]:
                    prefmt.append(subline)

            glstr = "\n\t".join(prefmt)

            allgls.append(glstr)

        # print it out!
        print >>sys.stderr, "\n\n".join(allgls)
        with open("gls-%s" % os.getpid(), "w") as f:
            f.write("\n\n".join(allgls))


    @property
    def node(self):
        """
        Returns the active/default Node that should be used for most communication in the system.

        Defers to exchange manager, but only if it has been started, otherwise returns None.
        """
        if "EXCHANGE_MANAGER" in self._capabilities:
            return self.ex_manager.default_node

        return None

    @contextmanager
    def _push_status(self, new_status):
        """
        Temporarily sets the internal status flag.
        Use this as a decorator or in a with-statement before calling a temporary status changing
        method, like start_rel_from_url.
        """
        curstatus = self._status
        self._status = new_status
        try:
            yield
        finally:
            self._status = curstatus

    def serve_forever(self):
        """ Run the container until killed. """
        log.debug("In Container.serve_forever")

        if not self.proc_manager.proc_sup.running:
            self.start()

        # serve forever short-circuits if immediate is on and children len is ok
        num_procs = len(self.proc_manager.proc_sup.children)
        immediate = CFG.system.get('immediate', False)
        if not (immediate and num_procs == 1):  # only spawned greenlet is the CC-Agent

            # print a warning just in case
            if immediate and num_procs != 1:
                log.warn("CFG.system.immediate=True but number of spawned processes is not 1 (%d)", num_procs)

            try:
                # This just waits in this Greenlet for all child processes to complete,
                # which is triggered somewhere else.
                self.proc_manager.proc_sup.join_children()
            except (KeyboardInterrupt, SystemExit) as ex:
                log.info('Received a kill signal, shutting down the container.')

                if hasattr(self, 'gl_parent_watch') and self.gl_parent_watch is not None:
                    self.gl_parent_watch.kill()

            except:
                log.exception('Unhandled error! Forcing container shutdown')
        else:
            log.debug("Container.serve_forever short-circuiting due to CFG.system.immediate")

        self.proc_manager.proc_sup.shutdown(CFG.cc.timeout.shutdown)

    def status(self):
        """
        Returns the internal status.
        """
        return self._status

    def _cleanup_pid(self):
        if self.pidfile:
            log.debug("Cleanup pidfile: %s", self.pidfile)
            try:
                os.remove(self.pidfile)
            except Exception, e:
                log.warn("Pidfile could not be deleted: %s" % str(e))
            self.pidfile = None
示例#10
0
文件: cc.py 项目: pkediyal/pyon
    def start(self):
        log.debug("Container starting...")
        if self._is_started:
            raise ContainerError("Container already started")

        # Check if this UNIX process already runs a Container.
        self.pidfile = "cc-pid-%d" % os.getpid()
        if os.path.exists(self.pidfile):
            raise ContainerError("Container.on_start(): Container is a singleton per UNIX process. Existing pid file found: %s" % self.pidfile)

        # write out a PID file containing our agent messaging name
        with open(self.pidfile, 'w') as f:
            pid_contents = {'messaging': dict(CFG.server.amqp),
                            'container-agent': self.name,
                            'container-xp': bootstrap.get_sys_name()}
            f.write(msgpack.dumps(pid_contents))
            atexit.register(self._cleanup_pid)
            self._capabilities.append("PID_FILE")

        # set up abnormal termination handler for this container
        def handl(signum, frame):
            try:
                self._cleanup_pid()     # cleanup the pidfile first
                self.quit()             # now try to quit - will not error on second cleanup pidfile call
            finally:
                signal.signal(signal.SIGTERM, self._normal_signal)
                os.kill(os.getpid(), signal.SIGTERM)
        self._normal_signal = signal.signal(signal.SIGTERM, handl)

        # set up greenlet debugging signal handler
        gevent.signal(signal.SIGUSR2, self._handle_sigusr2)

        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        self._capabilities.append("DIRECTORY")

        # Event repository
        self.event_repository = EventRepository()
        self.event_pub = EventPublisher()
        self._capabilities.append("EVENT_REPOSITORY")

        # Local resource registry
        self.resource_registry = ResourceRegistry()
        self._capabilities.append("RESOURCE_REGISTRY")

        # Persistent objects
        self.datastore_manager.get_datastore("objects", DataStore.DS_PROFILE.OBJECTS)

        # State repository
        self.state_repository = StateRepository()
        self._capabilities.append("STATE_REPOSITORY")

        # internal router for local transports
        self.local_router = LocalRouter(bootstrap.get_sys_name())
        self.local_router.start()
        self.local_router.ready.wait(timeout=2)
        self._capabilities.append("LOCAL_ROUTER")

        # Start ExchangeManager, which starts the node (broker connection)
        self.ex_manager.start()
        self._capabilities.append("EXCHANGE_MANAGER")

        self.proc_manager.start()
        self._capabilities.append("PROC_MANAGER")

        self.app_manager.start()
        self._capabilities.append("APP_MANAGER")

        self.governance_controller.start()
        self._capabilities.append("GOVERNANCE_CONTROLLER")

        if CFG.get_safe('container.sflow.enabled', False):
            self.sflow_manager.start()
            self._capabilities.append("SFLOW_MANAGER")

        # Start the CC-Agent API
        rsvc = ProcessRPCServer(node=self.node, from_name=self.name, service=self, process=self)

        cleanup = lambda _: self.proc_manager._cleanup_method(self.name, rsvc)

        # Start an ION process with the right kind of endpoint factory
        proc = self.proc_manager.proc_sup.spawn(name=self.name, listeners=[rsvc], service=self, cleanup_method=cleanup)
        self.proc_manager.proc_sup.ensure_ready(proc)
        proc.start_listeners()
        self._capabilities.append("CONTAINER_AGENT")

        self.event_pub.publish_event(event_type="ContainerLifecycleEvent",
                                     origin=self.id, origin_type="CapabilityContainer",
                                     sub_type="START",
                                     state=ContainerStateEnum.START)

        self._is_started    = True
        self._status        = "RUNNING"

        log.info("Container (%s) started, OK." , self.id)
示例#11
0
 def start(self):
     # internal router for local transports
     self.container.local_router = LocalRouter(bootstrap.get_sys_name())
     self.container.local_router.start()
     self.container.local_router.ready.wait(timeout=2)
示例#12
0
class TestLocalRouter(PyonTestCase):

    def setUp(self):
        self.lr = LocalRouter(get_sys_name())
        self.lr.start()
        self.addCleanup(self.lr.stop)

        # make a hook so we can tell when a message gets routed
        self.ev = Event()
        def new_route(*args, **kwargs):
            self.ev.set()
            self.lr._oldroute(*args, **kwargs)
        self.lr._oldroute = self.lr._route
        self.lr._route = new_route

    def test_publish_to_unknown_exchange(self):
        self.assertEquals(len(self.lr.errors), 0)
        self.lr.publish('ex', 'rkey', 'body', 'props')
        self.ev.wait(timeout=10)
        self.assertEquals(len(self.lr.errors), 1)

    def test_publish_to_known_exchange(self):
        # declare exchange
        self.lr.declare_exchange('known')

        # send message
        self.lr.publish('known', 'rkey', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # message is binned but no errors
        self.assertEquals(len(self.lr.errors), 0)

    def test_publish_to_queue(self):
        # declare exchange/queue/binding
        self.lr.declare_exchange('known')
        self.lr.declare_queue('iamqueue')
        self.lr.bind('known', 'iamqueue', 'binzim')
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0)

        # send message
        self.lr.publish('known', 'binzim', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be sitting in a queue waiting
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1)
        #self.assertIn(('known', 'binzim', 'body', 'props'), self.lr._queues['iamqueue'])

    def test_publish_to_many_queues(self):
        # declare exchange/queue/binding
        self.lr.declare_exchange('known')
        self.lr.declare_queue('q1')
        self.lr.bind('known', 'q1', 'a.*')

        self.lr.declare_queue('q2')
        self.lr.bind('known', 'q2', 'a.b')

        self.lr.declare_queue('q3')
        self.lr.bind('known', 'q3', '*.b')

        # send message
        self.lr.publish('known', 'a.b', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be in 3 queues
        for q in ['q1','q2','q3']:
            self.assertEquals(self.lr._queues[q].qsize(), 1)
            #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues[q])

    def test_publish_to_queue_with_multiple_matching_binds_only_makes_one_message(self):
        # exchange/queue/bindings
        self.lr.declare_exchange('known')
        self.lr.declare_queue('iamqueue')
        self.lr.bind('known', 'iamqueue', 'a.*')
        self.lr.bind('known', 'iamqueue', 'a.b')
        self.lr.bind('known', 'iamqueue', '*.b')

        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0)

        # send message
        self.lr.publish('known', 'a.b', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)

        # should be in the queue
        self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1)
        #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues['iamqueue'])

    def test_publish_with_binds_and_unbinds(self):
        # declare exchange/queue
        self.lr.declare_exchange('known')
        self.lr.declare_queue('ein')

        self.assertEquals(self.lr._queues['ein'].qsize(), 0)

        # send message
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear() # we need to use again

        # not bound, so doesn't go into the queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 0)

        # bind now
        self.lr.bind('known', 'ein', 'ein')

        # send message
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear() # we need to use again

        # should be in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 1)

        # send again
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear() # we need to use again

        # now 2 in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 2)

        # unbind
        self.lr.unbind('known', 'ein', 'ein')

        # send again
        self.lr.publish('known', 'ein', 'body', 'props')

        # wait for route
        self.ev.wait(timeout=10)
        self.ev.clear() # we need to use again

        # still 2 in queue
        self.assertEquals(self.lr._queues['ein'].qsize(), 2)


    def test__connect_addr(self):
        self.assertEquals(self.lr._connect_addr, "inproc://%s" % get_sys_name())

    def test__child_failed(self):
        self.lr.gl_ioloop = Mock()

        fail = Mock()
        self.lr._child_failed(fail)

        self.lr.gl_ioloop.kill.assert_called_once_with(exception=fail.exception,
                                                       block=False)

    def test__run_ioloop(self):
        self.lr._gl_pool = Mock()
        self.lr._run_ioloop()

        self.lr._gl_pool.join.assert_called_once_with()

    def test_declare_exchange(self):
        self.lr.declare_exchange(sentinel.exchange)

        self.assertIn(sentinel.exchange, self.lr._exchanges)
        self.assertIsInstance(self.lr._exchanges[sentinel.exchange], TopicTrie)

    def test_declare_exchange_existing(self):
        tt = TopicTrie()
        self.lr._exchanges[sentinel.exchange] = tt

        self.lr.declare_exchange(sentinel.exchange)
        self.assertEquals(tt, self.lr._exchanges[sentinel.exchange])

    def test_delete_exchange(self):
        self.lr.declare_exchange(sentinel.exchange)
        self.lr.delete_exchange(sentinel.exchange)

        self.assertEquals(self.lr._exchanges, {})

    def test_declare_queue(self):
        self.lr.declare_queue(sentinel.queue)
        self.assertIn(sentinel.queue, self.lr._queues)

    def test_declare_queue_made_up(self):
        q = self.lr.declare_queue('')
        self.assertIn("q-", q)
        self.assertIn(q, self.lr._queues)

    def test_delete_queue(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr.delete_queue(sentinel.queue)
        self.assertNotIn(sentinel.queue, self.lr._queues)

    def test_delete_queue_deletes_bindings(self):
        self.lr.declare_exchange(sentinel.exchange)
        self.lr.declare_queue(sentinel.queue)
        self.lr.bind(sentinel.exchange, sentinel.queue, 'binder')

        self.lr.delete_queue(sentinel.queue)
        self.assertNotIn(sentinel.queue, self.lr._queues)
        self.assertNotIn(sentinel.queue, self.lr._bindings_by_queue)

    def test_start_consume(self):
        self.lr._gl_pool = Mock()
        self.lr.declare_queue(sentinel.queue)
        ctag = self.lr.start_consume(sentinel.callback, sentinel.queue)

        self.assertIn(sentinel.queue, self.lr._consumers)
        self.assertIn(ctag, self.lr._consumers_by_ctag)

        self.assertEquals(self.lr._consumers[sentinel.queue], [(ctag,
                                                                sentinel.callback,
                                                                False,
                                                                False,
                                                                self.lr._gl_pool.spawn.return_value)])

    def test_stop_consume(self):
        self.lr._gl_pool = Mock()
        self.lr.declare_queue(sentinel.queue)
        ctag = self.lr.start_consume(sentinel.callback, sentinel.queue)

        self.lr.stop_consume(ctag)

        self.assertNotIn(ctag, self.lr._consumers_by_ctag)
        self.lr._gl_pool.spawn().join.assert_called_once_with(timeout=5)
        self.lr._gl_pool.spawn().kill.assert_called_once_with()
        self.assertEquals(len(self.lr._consumers[sentinel.queue]), 0)

    def test__run_consumer(self):
        propsmock = Mock()
        propsmock.copy.return_value = sentinel.props
        gqueue = Mock()
        m = (sentinel.exchange, sentinel.routing_key, sentinel.body, propsmock)
        gqueue.get.side_effect = [m,
                                  LocalRouter.ConsumerClosedMessage()]
        cb = Mock()
        self.lr._generate_dtag=Mock(return_value=sentinel.dtag)

        self.lr._run_consumer(sentinel.ctag, sentinel.queue, gqueue, cb)

        self.assertEquals(cb.call_count, 1)
        self.assertEquals(cb.call_args[0][0], self.lr)
        self.assertEquals(dict(cb.call_args[0][1]), {'consumer_tag': sentinel.ctag,
                                                     'delivery_tag': sentinel.dtag,
                                                     'redelivered': False,
                                                     'exchange': sentinel.exchange,
                                                     'routing_key': sentinel.routing_key})
        self.assertEquals(dict(cb.call_args[0][2]), {'headers':sentinel.props})
        self.assertEquals(cb.call_args[0][3], sentinel.body)

        self.assertIn((sentinel.ctag, sentinel.queue, m), self.lr._unacked.itervalues())

    def test__generate_ctag(self):
        self.lr._ctag_pool = Mock()
        self.lr._ctag_pool.get_id.return_value = sentinel.ctagid

        self.assertEquals(self.lr._generate_ctag(), "zctag-%s" % str(sentinel.ctagid))

    def test__return_ctag(self):
        self.lr._ctag_pool = Mock()

        self.lr._return_ctag("m-5")

        self.lr._ctag_pool.release_id.assert_called_once_with(5)

    def test__generate_and_return_ctag(self):
        ctag = self.lr._generate_ctag()
        ctagnum = int(ctag.split("-")[-1])
        self.assertIn(ctagnum, self.lr._ctag_pool._ids_in_use)

        self.lr._return_ctag(ctag)
        self.assertIn(ctagnum, self.lr._ctag_pool._ids_free)
        self.assertNotIn(ctagnum, self.lr._ctag_pool._ids_in_use)

    def test__generate_dtag(self):
        dtag = self.lr._generate_dtag(sentinel.ctag, sentinel.cnt)

        self.assertIn(str(sentinel.ctag), dtag)
        self.assertIn(str(sentinel.cnt), dtag)

    def test_ack(self):
        self.lr._unacked[sentinel.dtag] = True

        self.lr.ack(sentinel.dtag)
        self.assertEquals(len(self.lr._unacked), 0)

    def test_reject(self):
        self.lr._unacked[sentinel.dtag] = (None, None, None)

        self.lr.reject(sentinel.dtag)
        self.assertEquals(len(self.lr._unacked), 0)

    def test_reject_requeue(self):
        q = Mock()
        self.lr._queues[sentinel.queue] = q
        self.lr._unacked[sentinel.dtag] = (None, sentinel.queue, sentinel.m)

        self.lr.reject(sentinel.dtag, requeue=True)
        self.assertEquals(len(self.lr._unacked), 0)
        q.put.assert_called_once_with(sentinel.m)

    def test_transport_close(self):
        # no body in localrouter method
        pass

    def test_get_stats(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)

        mc, cc = self.lr.get_stats(sentinel.queue)

        self.assertEquals((mc, cc), (1, 0))

    def test_get_stats_with_consumers(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)
        self.lr._consumers[sentinel.queue] = [sentinel.ctag]

        mc, cc = self.lr.get_stats(sentinel.queue)

        self.assertEquals((mc, cc), (1, 1))

    def test_purge(self):
        self.lr.declare_queue(sentinel.queue)
        self.lr._queues[sentinel.queue].put(sentinel.m)
        self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 1)

        self.lr.purge(sentinel.queue)

        self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 0)
示例#13
0
文件: cc.py 项目: pkediyal/pyon
class Container(BaseContainerAgent):
    """
    The Capability Container. Its purpose is to spawn/monitor processes and services
    that do the bulk of the work in the ION system. It also manages connections to the Exchange
    and the various forms of datastores in the systems.
    """

    # Singleton static variables
    #node        = None
    id = None
    name = None
    pidfile = None
    instance = None

    def __init__(self, *args, **kwargs):
        BaseContainerAgent.__init__(self, *args, **kwargs)

        self._is_started = False
        # set container id and cc_agent name (as they are set in base class call)
        self.id = get_default_container_id()
        self.name = "cc_agent_%s" % self.id
        self._capabilities = []

        bootstrap.container_instance = self
        Container.instance = self

        log.debug("Container (sysname=%s) initializing ..." %
                  bootstrap.get_sys_name())

        # Keep track of the overrides from the command-line, so they can trump app/rel file data
        self.spawn_args = kwargs

        # DatastoreManager - controls access to Datastores (both mock and couch backed)
        self.datastore_manager = DatastoreManager()

        # TODO: Do not start a capability here. Symmetric start/stop
        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        # Instantiate Directory
        self.directory = Directory()

        # internal router
        self.local_router = None

        # Create this Container's specific ExchangeManager instance
        self.ex_manager = ExchangeManager(self)

        # Create this Container's specific ProcManager instance
        self.proc_manager = ProcManager(self)

        # Create this Container's specific AppManager instance
        self.app_manager = AppManager(self)

        # File System - Interface to the OS File System, using correct path names and setups
        self.file_system = FileSystem(CFG)

        # Governance Controller - manages the governance related interceptors
        self.governance_controller = GovernanceController(self)

        # sFlow manager - controls sFlow stat emission
        self.sflow_manager = SFlowManager(self)

        # Coordinates the container start
        self._status = "INIT"

        # protection for when the container itself is used as a Process for clients
        self.container = self

        # publisher, initialized in start()
        self.event_pub = None

        # context-local storage
        self.context = LocalContextMixin()

        log.debug("Container initialized, OK.")

    def start(self):
        log.debug("Container starting...")
        if self._is_started:
            raise ContainerError("Container already started")

        # Check if this UNIX process already runs a Container.
        self.pidfile = "cc-pid-%d" % os.getpid()
        if os.path.exists(self.pidfile):
            raise ContainerError(
                "Container.on_start(): Container is a singleton per UNIX process. Existing pid file found: %s"
                % self.pidfile)

        # write out a PID file containing our agent messaging name
        with open(self.pidfile, 'w') as f:
            pid_contents = {
                'messaging': dict(CFG.server.amqp),
                'container-agent': self.name,
                'container-xp': bootstrap.get_sys_name()
            }
            f.write(msgpack.dumps(pid_contents))
            atexit.register(self._cleanup_pid)
            self._capabilities.append("PID_FILE")

        # set up abnormal termination handler for this container
        def handl(signum, frame):
            try:
                self._cleanup_pid()  # cleanup the pidfile first
                self.quit(
                )  # now try to quit - will not error on second cleanup pidfile call
            finally:
                signal.signal(signal.SIGTERM, self._normal_signal)
                os.kill(os.getpid(), signal.SIGTERM)

        self._normal_signal = signal.signal(signal.SIGTERM, handl)

        # set up greenlet debugging signal handler
        gevent.signal(signal.SIGUSR2, self._handle_sigusr2)

        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        self._capabilities.append("DIRECTORY")

        # Event repository
        self.event_repository = EventRepository()
        self.event_pub = EventPublisher()
        self._capabilities.append("EVENT_REPOSITORY")

        # Local resource registry
        self.resource_registry = ResourceRegistry()
        self._capabilities.append("RESOURCE_REGISTRY")

        # Persistent objects
        self.datastore_manager.get_datastore("objects",
                                             DataStore.DS_PROFILE.OBJECTS)

        # State repository
        self.state_repository = StateRepository()
        self._capabilities.append("STATE_REPOSITORY")

        # internal router for local transports
        self.local_router = LocalRouter(bootstrap.get_sys_name())
        self.local_router.start()
        self.local_router.ready.wait(timeout=2)
        self._capabilities.append("LOCAL_ROUTER")

        # Start ExchangeManager, which starts the node (broker connection)
        self.ex_manager.start()
        self._capabilities.append("EXCHANGE_MANAGER")

        self.proc_manager.start()
        self._capabilities.append("PROC_MANAGER")

        self.app_manager.start()
        self._capabilities.append("APP_MANAGER")

        self.governance_controller.start()
        self._capabilities.append("GOVERNANCE_CONTROLLER")

        if CFG.get_safe('container.sflow.enabled', False):
            self.sflow_manager.start()
            self._capabilities.append("SFLOW_MANAGER")

        # Start the CC-Agent API
        rsvc = ProcessRPCServer(node=self.node,
                                from_name=self.name,
                                service=self,
                                process=self)

        cleanup = lambda _: self.proc_manager._cleanup_method(self.name, rsvc)

        # Start an ION process with the right kind of endpoint factory
        proc = self.proc_manager.proc_sup.spawn(name=self.name,
                                                listeners=[rsvc],
                                                service=self,
                                                cleanup_method=cleanup)
        self.proc_manager.proc_sup.ensure_ready(proc)
        proc.start_listeners()
        self._capabilities.append("CONTAINER_AGENT")

        self.event_pub.publish_event(event_type="ContainerLifecycleEvent",
                                     origin=self.id,
                                     origin_type="CapabilityContainer",
                                     sub_type="START",
                                     state=ContainerStateEnum.START)

        self._is_started = True
        self._status = "RUNNING"

        log.info("Container (%s) started, OK.", self.id)

    def _handle_sigusr2(self):  #, signum, frame):
        """
        Handles SIGUSR2, prints debugging greenlet information.
        """
        gls = GreenletLeak.get_greenlets()

        allgls = []

        for gl in gls:
            status = GreenletLeak.format_greenlet(gl)

            # build formatted output:
            # Greenlet at 0xdeadbeef
            #     self: <EndpointUnit at 0x1ffcceef>
            #     func: bound, EndpointUnit.some_func

            status[0].insert(
                0, "%s at %s:" % (gl.__class__.__name__, hex(id(gl))))
            # indent anything in status a second time
            prefmt = [s.replace("\t", "\t\t") for s in status[0]]
            prefmt.append("traceback:")

            for line in status[1]:
                for subline in line.split("\n")[0:2]:
                    prefmt.append(subline)

            glstr = "\n\t".join(prefmt)

            allgls.append(glstr)

        # print it out!
        print >> sys.stderr, "\n\n".join(allgls)
        with open("gls-%s" % os.getpid(), "w") as f:
            f.write("\n\n".join(allgls))

    @property
    def node(self):
        """
        Returns the active/default Node that should be used for most communication in the system.

        Defers to exchange manager, but only if it has been started, otherwise returns None.
        """
        if "EXCHANGE_MANAGER" in self._capabilities:
            return self.ex_manager.default_node

        return None

    @contextmanager
    def _push_status(self, new_status):
        """
        Temporarily sets the internal status flag.
        Use this as a decorator or in a with-statement before calling a temporary status changing
        method, like start_rel_from_url.
        """
        curstatus = self._status
        self._status = new_status
        try:
            yield
        finally:
            self._status = curstatus

    def serve_forever(self):
        """ Run the container until killed. """
        log.debug("In Container.serve_forever")

        if not self.proc_manager.proc_sup.running:
            self.start()

        # serve forever short-circuits if immediate is on and children len is ok
        num_procs = len(self.proc_manager.proc_sup.children)
        immediate = CFG.system.get('immediate', False)
        if not (immediate
                and num_procs == 1):  # only spawned greenlet is the CC-Agent

            # print a warning just in case
            if immediate and num_procs != 1:
                log.warn(
                    "CFG.system.immediate=True but number of spawned processes is not 1 (%d)",
                    num_procs)

            try:
                # This just waits in this Greenlet for all child processes to complete,
                # which is triggered somewhere else.
                self.proc_manager.proc_sup.join_children()
            except (KeyboardInterrupt, SystemExit) as ex:
                log.info(
                    'Received a kill signal, shutting down the container.')

                if hasattr(self, 'gl_parent_watch'
                           ) and self.gl_parent_watch is not None:
                    self.gl_parent_watch.kill()

            except:
                log.exception('Unhandled error! Forcing container shutdown')
        else:
            log.debug(
                "Container.serve_forever short-circuiting due to CFG.system.immediate"
            )

        self.proc_manager.proc_sup.shutdown(CFG.cc.timeout.shutdown)

    def status(self):
        """
        Returns the internal status.
        """
        return self._status

    def _cleanup_pid(self):
        if self.pidfile:
            log.debug("Cleanup pidfile: %s", self.pidfile)
            try:
                os.remove(self.pidfile)
            except Exception, e:
                log.warn("Pidfile could not be deleted: %s" % str(e))
            self.pidfile = None
示例#14
0
文件: cc.py 项目: pkediyal/pyon
    def start(self):
        log.debug("Container starting...")
        if self._is_started:
            raise ContainerError("Container already started")

        # Check if this UNIX process already runs a Container.
        self.pidfile = "cc-pid-%d" % os.getpid()
        if os.path.exists(self.pidfile):
            raise ContainerError(
                "Container.on_start(): Container is a singleton per UNIX process. Existing pid file found: %s"
                % self.pidfile)

        # write out a PID file containing our agent messaging name
        with open(self.pidfile, 'w') as f:
            pid_contents = {
                'messaging': dict(CFG.server.amqp),
                'container-agent': self.name,
                'container-xp': bootstrap.get_sys_name()
            }
            f.write(msgpack.dumps(pid_contents))
            atexit.register(self._cleanup_pid)
            self._capabilities.append("PID_FILE")

        # set up abnormal termination handler for this container
        def handl(signum, frame):
            try:
                self._cleanup_pid()  # cleanup the pidfile first
                self.quit(
                )  # now try to quit - will not error on second cleanup pidfile call
            finally:
                signal.signal(signal.SIGTERM, self._normal_signal)
                os.kill(os.getpid(), signal.SIGTERM)

        self._normal_signal = signal.signal(signal.SIGTERM, handl)

        # set up greenlet debugging signal handler
        gevent.signal(signal.SIGUSR2, self._handle_sigusr2)

        self.datastore_manager.start()
        self._capabilities.append("DATASTORE_MANAGER")

        self._capabilities.append("DIRECTORY")

        # Event repository
        self.event_repository = EventRepository()
        self.event_pub = EventPublisher()
        self._capabilities.append("EVENT_REPOSITORY")

        # Local resource registry
        self.resource_registry = ResourceRegistry()
        self._capabilities.append("RESOURCE_REGISTRY")

        # Persistent objects
        self.datastore_manager.get_datastore("objects",
                                             DataStore.DS_PROFILE.OBJECTS)

        # State repository
        self.state_repository = StateRepository()
        self._capabilities.append("STATE_REPOSITORY")

        # internal router for local transports
        self.local_router = LocalRouter(bootstrap.get_sys_name())
        self.local_router.start()
        self.local_router.ready.wait(timeout=2)
        self._capabilities.append("LOCAL_ROUTER")

        # Start ExchangeManager, which starts the node (broker connection)
        self.ex_manager.start()
        self._capabilities.append("EXCHANGE_MANAGER")

        self.proc_manager.start()
        self._capabilities.append("PROC_MANAGER")

        self.app_manager.start()
        self._capabilities.append("APP_MANAGER")

        self.governance_controller.start()
        self._capabilities.append("GOVERNANCE_CONTROLLER")

        if CFG.get_safe('container.sflow.enabled', False):
            self.sflow_manager.start()
            self._capabilities.append("SFLOW_MANAGER")

        # Start the CC-Agent API
        rsvc = ProcessRPCServer(node=self.node,
                                from_name=self.name,
                                service=self,
                                process=self)

        cleanup = lambda _: self.proc_manager._cleanup_method(self.name, rsvc)

        # Start an ION process with the right kind of endpoint factory
        proc = self.proc_manager.proc_sup.spawn(name=self.name,
                                                listeners=[rsvc],
                                                service=self,
                                                cleanup_method=cleanup)
        self.proc_manager.proc_sup.ensure_ready(proc)
        proc.start_listeners()
        self._capabilities.append("CONTAINER_AGENT")

        self.event_pub.publish_event(event_type="ContainerLifecycleEvent",
                                     origin=self.id,
                                     origin_type="CapabilityContainer",
                                     sub_type="START",
                                     state=ContainerStateEnum.START)

        self._is_started = True
        self._status = "RUNNING"

        log.info("Container (%s) started, OK.", self.id)