Example #1
0
def terminate_machine(config, environment, verbose, log, machine_ids):
    """Terminates the machines in `machine_ids`.

    Like the underlying code in MachineStateManager, it's permissible
    if the machine ID is already terminated or even never running. If
    we determine this is not desired behavior, presumably propagate
    that back to the state manager.

    XXX However, we currently special case support of not terminating
    the "root" machine, that is the one running the provisioning
    agent. At some point, this will be managed like any other service,
    but until then it seems best to ensure it's not terminated at this
    level.
    """

    provider = environment.get_machine_provider()
    client = yield provider.connect()
    terminated_machine_ids = []
    try:
        machine_state_manager = MachineStateManager(client)
        for machine_id in machine_ids:
            if machine_id == 0:
                raise CannotTerminateMachine(0,
                                             "environment would be destroyed")
            removed = yield machine_state_manager.remove_machine_state(
                machine_id)
            if not removed:
                raise MachineStateNotFound(machine_id)
            terminated_machine_ids.append(machine_id)
    finally:
        yield client.close()
        if terminated_machine_ids:
            log.info("Machines terminated: %s",
                     ", ".join(str(id) for id in terminated_machine_ids))
Example #2
0
def terminate_machine(config, environment, verbose, log, machine_ids):
    """Terminates the machines in `machine_ids`.

    Like the underlying code in MachineStateManager, it's permissible
    if the machine ID is already terminated or even never running. If
    we determine this is not desired behavior, presumably propagate
    that back to the state manager.

    XXX However, we currently special case support of not terminating
    the "root" machine, that is the one running the provisioning
    agent. At some point, this will be managed like any other service,
    but until then it seems best to ensure it's not terminated at this
    level.
    """

    provider = environment.get_machine_provider()
    client = yield provider.connect()
    terminated_machine_ids = []
    try:
        machine_state_manager = MachineStateManager(client)
        for machine_id in machine_ids:
            if machine_id == 0:
                raise CannotTerminateMachine(
                    0, "environment would be destroyed")
            removed = yield machine_state_manager.remove_machine_state(
                machine_id)
            if not removed:
                raise MachineStateNotFound(machine_id)
            terminated_machine_ids.append(machine_id)
    finally:
        yield client.close()
        if terminated_machine_ids:
            log.info(
                "Machines terminated: %s",
                ", ".join(str(id) for id in terminated_machine_ids))
Example #3
0
class MachineStateManagerTest(StateTestBase):

    @inlineCallbacks
    def setUp(self):
        yield super(MachineStateManagerTest, self).setUp()
        self.charm_state_manager = CharmStateManager(self.client)
        self.machine_state_manager = MachineStateManager(self.client)
        self.service_state_manager = ServiceStateManager(self.client)
        self.charm_state = yield self.charm_state_manager.add_charm_state(
            local_charm_id(self.charm), self.charm, "")

    @inlineCallbacks
    def add_service(self, service_name):
        service_state = yield self.service_state_manager.add_service_state(
            service_name, self.charm_state)
        returnValue(service_state)

    @inlineCallbacks
    def test_add_machine(self):
        """
        Adding a machine state should register it in zookeeper.
        """
        machine_state1 = yield self.machine_state_manager.add_machine_state()
        machine_state2 = yield self.machine_state_manager.add_machine_state()

        self.assertEquals(machine_state1.id, 0)
        self.assertEquals(machine_state1.internal_id, "machine-0000000000")
        self.assertEquals(machine_state2.id, 1)
        self.assertEquals(machine_state2.internal_id, "machine-0000000001")

        children = yield self.client.get_children("/machines")
        self.assertEquals(sorted(children),
                          ["machine-0000000000", "machine-0000000001"])

        topology = yield self.get_topology()
        self.assertTrue(topology.has_machine("machine-0000000000"))
        self.assertTrue(topology.has_machine("machine-0000000001"))

    @inlineCallbacks
    def test_machine_str_representation(self):
        """The str(machine) value includes the machine id.
        """
        machine_state1 = yield self.machine_state_manager.add_machine_state()
        self.assertEqual(
            str(machine_state1), "<MachineState id:machine-%010d>" % (0))

    @inlineCallbacks
    def test_remove_machine(self):
        """
        Adding a machine state should register it in zookeeper.
        """
        machine_state1 = yield self.machine_state_manager.add_machine_state()
        yield self.machine_state_manager.add_machine_state()

        removed = yield self.machine_state_manager.remove_machine_state(
            machine_state1.id)
        self.assertTrue(removed)
        children = yield self.client.get_children("/machines")
        self.assertEquals(sorted(children),
                          ["machine-0000000001"])

        topology = yield self.get_topology()
        self.assertFalse(topology.has_machine("machine-0000000000"))
        self.assertTrue(topology.has_machine("machine-0000000001"))

        # Removing a non-existing machine again won't fail, since the end
        # intention is preserved.  This makes dealing with concurrency easier.
        # However, False will be returned in this case.
        removed = yield self.machine_state_manager.remove_machine_state(
            machine_state1.id)
        self.assertFalse(removed)

    @inlineCallbacks
    def test_remove_machine_with_agent(self):
        """Removing a machine with a connected machine agent should succeed.

        The removal signals intent to remove a working machine (with an agent)
        with the provisioning agent to remove it subsequently.
        """

        # Add two machines.
        machine_state1 = yield self.machine_state_manager.add_machine_state()
        yield self.machine_state_manager.add_machine_state()

        # Connect an agent
        yield machine_state1.connect_agent()

        # Remove a machine
        removed = yield self.machine_state_manager.remove_machine_state(
            machine_state1.id)
        self.assertTrue(removed)

        # Verify the second one is still present
        children = yield self.client.get_children("/machines")
        self.assertEquals(sorted(children),
                          ["machine-0000000001"])

        # Verify the topology state.
        topology = yield self.get_topology()
        self.assertFalse(topology.has_machine("machine-0000000000"))
        self.assertTrue(topology.has_machine("machine-0000000001"))

    @inlineCallbacks
    def test_get_machine_and_check_attributes(self):
        """
        Getting a machine state should be possible using both the
        user-oriented id and the internal id.
        """
        yield self.machine_state_manager.add_machine_state()
        yield self.machine_state_manager.add_machine_state()
        machine_state = yield self.machine_state_manager.get_machine_state(0)
        self.assertEquals(machine_state.id, 0)

        machine_state = yield self.machine_state_manager.get_machine_state("0")
        self.assertEquals(machine_state.id, 0)

        yield self.assertFailure(
            self.machine_state_manager.get_machine_state("a"),
            MachineStateNotFound)

    @inlineCallbacks
    def test_get_machine_not_found(self):
        """
        Getting a machine state which is not available should errback
        a meaningful error.
        """
        # No state whatsoever.
        try:
            yield self.machine_state_manager.get_machine_state(0)
        except MachineStateNotFound, e:
            self.assertEquals(e.machine_id, 0)
        else: