Beispiel #1
0
    def test_stop(self):
        """Executing the stop transition, results in the workflow going
        to the down state.
        """
        file_path = self.makeFile()
        self.write_hook("install",
                        "#!/bin/bash\necho installed >> %s\n" % file_path)
        self.write_hook("start", "#!/bin/bash\necho start >> %s\n" % file_path)
        self.write_hook("stop", "#!/bin/bash\necho stop >> %s\n" % file_path)
        result = yield self.workflow.fire_transition("install")
        result = yield self.workflow.fire_transition("start")
        result = yield self.workflow.fire_transition("stop")
        self.assertTrue(result)
        current_state = yield self.workflow.get_state()
        self.assertEqual(current_state, "stopped")
        f_state, history, zk_state = yield self.read_persistent_state()
        self.assertEqual(f_state, zk_state)
        self.assertEqual(f_state, {"state": "stopped", "state_variables": {}})

        workflow_client = WorkflowStateClient(self.client, self.states["unit"])
        value = yield workflow_client.get_state()
        self.assertEqual(value, "stopped")

        self.assertEqual(history, [{
            "state": "installed",
            "state_variables": {}
        }, {
            "state": "started",
            "state_variables": {}
        }, {
            "state": "stopped",
            "state_variables": {}
        }])
Beispiel #2
0
    def test_client_readonly(self):
        yield self.workflow.fire_transition("install")
        workflow_client = WorkflowStateClient(self.client, self.states["unit"])

        self.assertEqual((yield workflow_client.get_state()), "installed")
        yield self.assertFailure(workflow_client.set_state("started"),
                                 NotImplementedError)
        self.assertEqual((yield workflow_client.get_state()), "installed")
Beispiel #3
0
    def test_client_read_state(self):
        """The relation workflow client can read the state of a unit
        relation."""
        yield self.workflow.fire_transition("start")
        yield self.assertState(self.workflow, "up")

        self.write_hook("%s-relation-changed" % self.relation_name,
                        "#!/bin/bash\necho hello\n")
        wait_on_hook = self.wait_on_hook("app-relation-changed")
        yield self.add_opposite_service_unit(self.states)
        yield wait_on_hook

        workflow = WorkflowStateClient(self.client,
                                       self.states["unit_relation"])
        self.assertEqual("up", (yield workflow.get_state()))
Beispiel #4
0
def collect(scope, machine_provider, client, log):
    """Extract status information into nested dicts for rendering.

       `scope`: an optional list of name specifiers. Globbing based
       wildcards supported. Defaults to all units, services and
       relations.

       `machine_provider`: machine provider for the environment

       `client`: ZK client connection

       `log`: a Python stdlib logger.
    """
    service_manager = ServiceStateManager(client)
    relation_manager = RelationStateManager(client)
    machine_manager = MachineStateManager(client)
    charm_manager = CharmStateManager(client)

    service_data = {}
    machine_data = {}
    state = dict(services=service_data, machines=machine_data)

    seen_machines = set()
    filter_services, filter_units = digest_scope(scope)

    services = yield service_manager.get_all_service_states()
    for service in services:
        if len(filter_services):
            found = False
            for filter_service in filter_services:
                if fnmatch(service.service_name, filter_service):
                    found = True
                    break
            if not found:
                continue

        unit_data = {}
        relation_data = {}

        charm_id = yield service.get_charm_id()
        charm = yield charm_manager.get_charm_state(charm_id)

        service_data[service.service_name] = dict(units=unit_data,
                                                  charm=charm.id,
                                                  relations=relation_data)
        exposed = yield service.get_exposed_flag()
        if exposed:
            service_data[service.service_name].update(exposed=exposed)

        units = yield service.get_all_unit_states()
        unit_matched = False

        relations = yield relation_manager.get_relations_for_service(service)

        for unit in units:
            if len(filter_units):
                found = False
                for filter_unit in filter_units:
                    if fnmatch(unit.unit_name, filter_unit):
                        found = True
                        break
                if not found:
                    continue

            u = unit_data[unit.unit_name] = dict()
            machine_id = yield unit.get_assigned_machine_id()
            u["machine"] = machine_id
            unit_workflow_client = WorkflowStateClient(client, unit)
            unit_state = yield unit_workflow_client.get_state()
            if not unit_state:
                u["state"] = "pending"
            else:
                unit_connected = yield unit.has_agent()
                u["state"] = unit_state if unit_connected else "down"
            if exposed:
                open_ports = yield unit.get_open_ports()
                u["open-ports"] = [
                    "{port}/{proto}".format(**port_info)
                    for port_info in open_ports
                ]

            u["public-address"] = yield unit.get_public_address()

            # indicate we should include information about this
            # machine later
            seen_machines.add(machine_id)
            unit_matched = True

            # collect info on each relation for the service unit
            relation_status = {}
            for relation in relations:
                try:
                    relation_unit = yield relation.get_unit_state(unit)
                except UnitRelationStateNotFound:
                    # This exception will occur when relations are
                    # established between services without service
                    # units, and therefore never have any
                    # corresponding service relation units. This
                    # scenario does not occur in actual deployments,
                    # but can happen in test circumstances. In
                    # particular, it will happen with a misconfigured
                    # provider, which exercises this codepath.
                    continue  # should not occur, but status should not fail
                relation_workflow_client = WorkflowStateClient(
                    client, relation_unit)
                relation_workflow_state = \
                    yield relation_workflow_client.get_state()
                relation_status[relation.relation_name] = dict(
                    state=relation_workflow_state)
            u["relations"] = relation_status

        # after filtering units check if any matched or remove the
        # service from the output
        if filter_units and not unit_matched:
            del service_data[service.service_name]
            continue

        for relation in relations:
            rel_services = yield relation.get_service_states()

            # A single related service implies a peer relation. More
            # imply a bi-directional provides/requires relationship.
            # In the later case we omit the local side of the relation
            # when reporting.
            if len(rel_services) > 1:
                # Filter out self from multi-service relations.
                rel_services = [
                    rsn for rsn in rel_services
                    if rsn.service_name != service.service_name
                ]

            if len(rel_services) > 1:
                raise ValueError("Unexpected relationship with more "
                                 "than 2 endpoints")

            rel_service = rel_services[0]
            relation_data[relation.relation_name] = rel_service.service_name

    machines = yield machine_manager.get_all_machine_states()
    for machine_state in machines:
        if (filter_services or filter_units) and \
                machine_state.id not in seen_machines:
            continue

        instance_id = yield machine_state.get_instance_id()
        m = {"instance-id": instance_id \
             if instance_id is not None else "pending"}
        if instance_id is not None:
            try:
                pm = yield machine_provider.get_machine(instance_id)
                m["dns-name"] = pm.dns_name
                m["instance-state"] = pm.state
                if (yield machine_state.has_agent()):
                    # if the agent's connected, we're fine
                    m["state"] = "running"
                else:
                    units = (yield machine_state.get_all_service_unit_states())
                    for unit in units:
                        unit_workflow_client = WorkflowStateClient(
                            client, unit)
                        if (yield unit_workflow_client.get_state()):
                            # for unit to have a state, its agent must have
                            # run, which implies the machine agent must have
                            # been running correctly at some point in the past
                            m["state"] = "down"
                            break
                    else:
                        # otherwise we're probably just still waiting
                        m["state"] = "not-started"
            except ProviderError:
                # The provider doesn't have machine information
                log.error("Machine provider information missing: machine %s" %
                          (machine_state.id))

        machine_data[machine_state.id] = m

    returnValue(state)
Beispiel #5
0
 def test_client_read_only(self):
     workflow_client = WorkflowStateClient(self.client,
                                           self.states["unit_relation"])
     yield self.assertFailure(workflow_client.set_state("up"),
                              NotImplementedError)
Beispiel #6
0
 def test_client_read_none(self):
     workflow = WorkflowStateClient(self.client,
                                    self.states["unit_relation"])
     self.assertEqual(None, (yield workflow.get_state()))
Beispiel #7
0
 def test_client_with_state(self):
     yield self.workflow.fire_transition("install")
     workflow_client = WorkflowStateClient(self.client, self.states["unit"])
     self.assertEqual((yield workflow_client.get_state()), "installed")
Beispiel #8
0
 def test_client_with_no_state(self):
     workflow_client = WorkflowStateClient(self.client, self.states["unit"])
     state = yield workflow_client.get_state()
     self.assertEqual(state, None)