Example #1
0
    def test_run_base_raises_error(self):
        """The base class agent, raises a notimplemented error when started."""
        client = self.mocker.patch(ZookeeperClient)
        client.connect(get_test_zookeeper_address())
        client_mock = self.mocker.mock()
        self.mocker.result(succeed(client_mock))
        self.mocker.replay()

        agent = BaseAgent()
        agent.configure({"zookeeper_servers": get_test_zookeeper_address(), "juju_directory": self.makeDir()})
        d = agent.startService()
        self.failUnlessFailure(d, NotImplementedError)
        return d
        def verify_upstart(_):
            conf_path = os.path.join(self.init_dir, "juju-wordpress-0.conf")
            with open(conf_path) as f:
                lines = f.readlines()

            env = []
            for line in lines:
                if line.startswith("env "):
                    env.append(line[4:-1].split("=", 1))
                if line.startswith("exec "):
                    exec_ = line[5:-1]

            env = dict((k, v.strip('"')) for (k, v) in env)
            env.pop("PYTHONPATH")
            self.assertEquals(env, {
                "JUJU_HOME": self.juju_directory,
                "JUJU_UNIT_NAME": self.unit_name,
                "JUJU_ZOOKEEPER": get_test_zookeeper_address(),
                "JUJU_MACHINE_ID": "123"})

            log_file = os.path.join(
                self.deployment.directory, "charm.log")
            command = " ".join([
                "/usr/bin/python", "-m", "juju.agents.dummy", "--nodaemon",
                "--logfile", log_file, "--session-file",
                "/var/run/juju/unit-wordpress-0-agent.zksession",
                ">> /tmp/juju-wordpress-0.output 2>&1"])
            self.assertEquals(exec_, command)
Example #3
0
    def test_watch_new_service_unit(self):
        """
        Adding a new service unit is detected by the watch.
        """
        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        mock_deployment = self.mocker.patch(self.agent.deploy_factory)
        mock_deployment.start("0", get_test_zookeeper_address(), MATCH_BUNDLE)

        test_deferred = Deferred()

        def test_complete(machine_id, servers, bundle):
            test_deferred.callback(True)

        self.mocker.call(test_complete)
        self.mocker.replay()

        # Create a new service unit
        self.service_unit = yield self.service.add_unit_state()
        yield self.service_unit.assign_to_machine(self.machine_state)

        yield test_deferred
        self.assertIn("Units changed old:set([]) new:set(['fatality-blog/0'])",
                      self.output.getvalue())
Example #4
0
    def test_bootstrap(self):
        self.bootstrap_mock()
        self.mocker.replay()

        yield self.provider.bootstrap()

        children = yield self.client.get_children("/")
        self.assertEqual(
            sorted([
                'services', 'settings', 'charms', 'relations', 'zookeeper',
                'initialized', 'topology', 'machines', 'units'
            ]), sorted(children))
        output = self.output.getvalue()
        self.assertIn("Starting networking...", output)
        self.assertIn("Starting zookeeper...", output)
        self.assertIn("Initializing state...", output)
        self.assertIn("Starting storage server", output)
        self.assertIn("Starting machine agent", output)
        self.assertIn("Environment bootstrapped", output)

        self.assertDir(self.provider.config["data-dir"], self.qualified_name,
                       "files")
        self.assertDir(self.provider.config["data-dir"], self.qualified_name,
                       "zookeeper")

        self.assertEqual(
            (yield self.provider.load_state()), {
                "zookeeper-address": get_test_zookeeper_address(),
                "zookeeper-instances": ["local"]
            })
Example #5
0
    def test_run_base_raises_error(self):
        """The base class agent, raises a notimplemented error when started."""
        client = self.mocker.patch(ZookeeperClient)
        client.connect(get_test_zookeeper_address())
        client_mock = self.mocker.mock()
        self.mocker.result(succeed(client_mock))
        self.mocker.replay()

        agent = BaseAgent()
        agent.configure({
            "zookeeper_servers": get_test_zookeeper_address(),
            "juju_directory": self.makeDir()
        })
        d = agent.startService()
        self.failUnlessFailure(d, NotImplementedError)
        return d
Example #6
0
 def test_bad_session_file(self):
     """If the session file cannot be created an error should be raised.
     """
     data = {"zookeeper_servers": get_test_zookeeper_address(),
             "juju_directory": self.makeDir(),
             "session_file": None}
     self.assertRaises(JujuError, BaseAgent().configure, data)
Example #7
0
    def test_wait_for_initialize(self):
        """
        A connection to a zookeeper that is running, but whose juju state
        is not ready, should wait until that state is ready.
        """
        client = ZookeeperClient()
        self.client = client  # for poke_zk
        self.mock_connect(False, succeed(client))
        self.mocker.replay()

        zookeeper.set_debug_level(0)
        yield client.connect(get_test_zookeeper_address())

        provider = DummyProvider(ProviderMachine("i-amok", "foo.example.com"))
        d = provider.connect()
        client_result = []
        d.addCallback(client_result.append)

        # Give it a chance to do it incorrectly.
        yield self.poke_zk()

        try:
            self.assertEquals(client_result, [])
            yield client.create("/initialized")
            yield d
            self.assertTrue(client_result, client_result)
            self.assertIdentical(client_result[0], client)
        finally:
            deleteTree("/", client.handle)
            client.close()
Example #8
0
    def test_managed_agent_root(self):
        juju_directory = self.makeDir()
        log_file = tempfile.mktemp()

        # The pid file and log file get written as root
        def cleanup_root_file(cleanup_file):
            subprocess.check_call(
                ["sudo", "rm", "-f", cleanup_file], stderr=subprocess.STDOUT)
        self.addCleanup(cleanup_root_file, log_file)

        agent = ManagedMachineAgent(
            "test-ns", machine_id="0",
            log_file=log_file,
            juju_series="precise",
            zookeeper_hosts=get_test_zookeeper_address(),
            juju_directory=juju_directory)

        agent.agent_module = "juju.agents.dummy"
        self.assertFalse((yield agent.is_running()))
        yield agent.start()
        # Give a moment for the process to start and write its config
        yield self.sleep(0.1)
        self.assertTrue((yield agent.is_running()))

        # running start again is fine, detects the process is running
        yield agent.start()
        yield agent.stop()
        self.assertFalse((yield agent.is_running()))

        # running stop again is fine, detects the process is stopped.
        yield agent.stop()
    def test_run_actual_process(self):
        # "unpatch" to use real /etc/init
        self.patch(UpstartService, "init_dir", self.real_init_dir)
        yield self.deployment.start(
            "0", get_test_zookeeper_address(), self.bundle)
        old_pid = yield self.deployment.get_pid()
        self.assert_pid_running(old_pid, True)

        # Give the job a chance to fall over and be restarted (if the
        # pid doesn't change, that hasn't hapened)
        yield self.sleep(0.1)
        self.assertEquals((yield self.deployment.get_pid()), old_pid)
        self.assert_pid_running(old_pid, True)

        # Kick the job over ourselves; check it comes back
        os.system("sudo kill -9 %s" % old_pid)
        yield self.sleep(0.1)
        self.assert_pid_running(old_pid, False)
        new_pid = yield self.deployment.get_pid()
        self.assertNotEquals(new_pid, old_pid)
        self.assert_pid_running(new_pid, True)

        yield self.deployment.destroy()
        self.assertEquals((yield self.deployment.get_pid()), None)
        self.assert_pid_running(new_pid, False)
Example #10
0
    def test_watch_new_service_unit(self):
        """
        Adding a new service unit is detected by the watch.
        """
        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        mock_deployment = self.mocker.patch(self.agent.deploy_factory)
        mock_deployment.start("0", get_test_zookeeper_address(), MATCH_BUNDLE)

        test_deferred = Deferred()

        def test_complete(machine_id, servers, bundle):
            test_deferred.callback(True)

        self.mocker.call(test_complete)
        self.mocker.replay()

        # Create a new service unit
        self.service_unit = yield self.service.add_unit_state()
        yield self.service_unit.assign_to_machine(self.machine_state)

        yield test_deferred
        self.assertIn(
            "Units changed old:set([]) new:set(['fatality-blog/0'])",
            self.output.getvalue())
Example #11
0
    def test_agent_machine_id_cli_error(self):
        """
        If the machine id can't be found, a detailed error message
        is given.
        """
        # initially setup by get_agent_config in setUp
        self.change_environment(JUJU_MACHINE_ID="")
        self.change_args("es-agent",
                         "--zookeeper-servers",
                         get_test_zookeeper_address(),
                         "--juju-directory",
                         self.makeDir())
        parser = argparse.ArgumentParser()
        self.agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())

        e = self.assertRaises(
            JujuError,
            self.agent.configure,
            options)

        self.assertIn(
            ("--machine-id must be provided in the command line,"
            " or $JUJU_MACHINE_ID in the environment"),
            str(e))
Example #12
0
    def test_service_unit_removed(self):
        """
        Service unit removed with manual invocation of watch_service_units.
        """
        # Start the agent with watching enabled
        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        test_deferred = Deferred()

        mock_deployment = self.mocker.patch(self.agent.deploy_factory)
        mock_deployment.start("0", get_test_zookeeper_address(), MATCH_BUNDLE)
        self.mocker.result(succeed(True))
        mock_deployment.destroy()
        self.mocker.result(succeed(True))

        def test_complete():
            test_deferred.callback(True)

        self.mocker.call(test_complete)
        self.mocker.replay()

        # Create a new service unit
        self.service_unit = yield self.service.add_unit_state()
        yield self.service_unit.assign_to_machine(self.machine_state)

        # And now remove it
        yield self.service_unit.unassign_from_machine()
        yield test_deferred
Example #13
0
    def test_wait_for_initialize(self):
        """
        A connection to a zookeeper that is running, but whose juju state
        is not ready, should wait until that state is ready.
        """
        client = ZookeeperClient()
        self.client = client  # for poke_zk
        self.mock_connect(False, succeed(client))
        self.mocker.replay()

        zookeeper.set_debug_level(0)
        yield client.connect(get_test_zookeeper_address())

        provider = DummyProvider(ProviderMachine("i-amok", "foo.example.com"))
        d = provider.connect()
        client_result = []
        d.addCallback(client_result.append)

        # Give it a chance to do it incorrectly.
        yield self.poke_zk()

        try:
            self.assertEquals(client_result, [])
            yield client.create("/initialized")
            yield d
            self.assertTrue(client_result, client_result)
            self.assertIdentical(client_result[0], client)
        finally:
            deleteTree("/", client.handle)
            client.close()
Example #14
0
    def test_full_run(self):
        """Verify a functional agent start via the 'run' method.

        This test requires Zookeeper running on the default port of localhost.
        The mocked portions are to prevent the daemon start from altering the
        test environment (sys.stdout/sys.stderr, and reactor start).
        """
        zookeeper.set_debug_level(0)
        started = Deferred()

        class DummyAgent(BaseAgent):
            started = False

            def start(self):
                started.callback(self)

        def validate_started(agent):
            self.assertTrue(agent.client.connected)

        started.addCallback(validate_started)

        pid_file = self.makeFile()
        self.change_args("es-agent", "--zookeeper-servers",
                         get_test_zookeeper_address(), "--pidfile", pid_file)
        runner = self.mocker.patch(AgentRunner)
        logger = self.mocker.patch(AppLogger)
        logger.start(MATCH_APP)
        runner.startReactor(None, sys.stdout, sys.stderr)
        logger.stop()
        self.mocker.replay()
        DummyAgent.run()
        return started
Example #15
0
    def test_service_unit_removed(self):
        """
        Service unit removed with manual invocation of watch_service_units.
        """
        # Start the agent with watching enabled
        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        test_deferred = Deferred()

        mock_deployment = self.mocker.patch(self.agent.deploy_factory)
        mock_deployment.start("0", get_test_zookeeper_address(), MATCH_BUNDLE)
        self.mocker.result(succeed(True))
        mock_deployment.destroy()
        self.mocker.result(succeed(True))

        def test_complete():
            test_deferred.callback(True)

        self.mocker.call(test_complete)
        self.mocker.replay()

        # Create a new service unit
        self.service_unit = yield self.service.add_unit_state()
        yield self.service_unit.assign_to_machine(self.machine_state)

        # And now remove it
        yield self.service_unit.unassign_from_machine()
        yield test_deferred
Example #16
0
    def test_full_run(self):
        """Verify a functional agent start via the 'run' method.

        This test requires Zookeeper running on the default port of localhost.
        The mocked portions are to prevent the daemon start from altering the
        test environment (sys.stdout/sys.stderr, and reactor start).
        """
        zookeeper.set_debug_level(0)
        started = Deferred()

        class DummyAgent(BaseAgent):
            started = False

            def start(self):
                started.callback(self)

        def validate_started(agent):
            self.assertTrue(agent.client.connected)

        started.addCallback(validate_started)

        pid_file = self.makeFile()
        self.change_args("es-agent", "--zookeeper-servers", get_test_zookeeper_address(), "--pidfile", pid_file)
        runner = self.mocker.patch(AgentRunner)
        logger = self.mocker.patch(AppLogger)
        logger.start(MATCH_APP)
        runner.startReactor(None, sys.stdout, sys.stderr)
        logger.stop()
        self.mocker.replay()
        DummyAgent.run()
        return started
Example #17
0
    def test_bootstrap(self):
        self.bootstrap_mock()
        self.mocker.replay()

        yield self.provider.bootstrap()

        children = yield self.client.get_children("/")
        self.assertEqual(
            sorted(['services', 'settings', 'charms', 'relations', 'zookeeper',
                    'initialized', 'topology', 'machines', 'units']),
            sorted(children))
        output = self.output.getvalue()
        self.assertIn("Starting networking...", output)
        self.assertIn("Starting zookeeper...", output)
        self.assertIn("Initializing state...", output)
        self.assertIn("Starting storage server", output)
        self.assertIn("Starting machine agent", output)
        self.assertIn("Environment bootstrapped", output)

        self.assertDir(
            self.provider.config["data-dir"], self.qualified_name, "files")
        self.assertDir(
            self.provider.config["data-dir"], self.qualified_name, "zookeeper")

        self.assertEqual((yield self.provider.load_state()),
                         {"zookeeper-address": get_test_zookeeper_address(),
                          "zookeeper-instances": ["local"]})
Example #18
0
    def test_kill_service_unit(self):
        """Verify killing a service unit destroys the deployment."""
        mock_deployment = self.mocker.patch(self.unit_manager.deploy_factory)
        mock_deployment.start("0", get_test_zookeeper_address(), MATCH_BUNDLE)
        self.mocker.result(succeed(True))
        mock_deployment.destroy()
        self.mocker.result(succeed(True))
        test_deferred = Deferred()

        def test_complete():
            test_deferred.callback(True)

        self.mocker.call(test_complete)
        self.mocker.replay()

        # Start
        yield self.unit_manager.start_service_unit("myblog/0")

        # and stop.
        yield self.unit_state.unassign_from_machine()
        yield self.unit_manager.kill_service_unit("myblog/0")

        yield test_deferred
        self.assertLogLines(
            self.output.getvalue(),
            ["Downloading charm local:series/dummy-1 to %s" % \
                 os.path.join(self.juju_dir, "charms"),
             "Starting service unit myblog/0...",
             "Started service unit myblog/0",
             "Stopping service unit myblog/0...",
             "Stopped service unit myblog/0"])
Example #19
0
 def test_deployment_get_environment(self):
     zk_address = get_test_zookeeper_address()
     environ = self.deployment.get_environment(21, zk_address)
     environ.pop("PYTHONPATH")
     self.assertEqual(environ["JUJU_HOME"], self.juju_directory)
     self.assertEqual(environ["JUJU_UNIT_NAME"], self.unit_name)
     self.assertEqual(environ["JUJU_ZOOKEEPER"], zk_address)
     self.assertEqual(environ["JUJU_MACHINE_ID"], "21")
Example #20
0
 def setUp(self):
     self.log = self.capture_logging("juju.state.init")
     zookeeper.set_debug_level(0)
     self.client = ZookeeperClient(get_test_zookeeper_address())
     self.identity = make_identity("admin:genie")
     self.layout = StateHierarchy(self.client, self.identity, "i-abcdef",
                                  "dummy")
     return self.client.connect()
Example #21
0
 def test_deployment_get_environment(self):
     zk_address = get_test_zookeeper_address()
     environ = self.deployment.get_environment(21, zk_address)
     environ.pop("PYTHONPATH")
     self.assertEqual(environ["JUJU_HOME"], self.juju_directory)
     self.assertEqual(environ["JUJU_UNIT_NAME"], self.unit_name)
     self.assertEqual(environ["JUJU_ZOOKEEPER"], zk_address)
     self.assertEqual(environ["JUJU_MACHINE_ID"], "21")
Example #22
0
 def setUp(self):
     self.log = self.capture_logging("juju.state.init")
     zookeeper.set_debug_level(0)
     self.client = ZookeeperClient(get_test_zookeeper_address())
     self.identity = make_identity("admin:genie")
     self.layout = StateHierarchy(
         self.client, self.identity, "i-abcdef", "dummy")
     return self.client.connect()
Example #23
0
 def xtest_service_unit_start_pre_unpack(self):
     """
     Attempting to start a charm before the charm is unpacked
     results in an exception.
     """
     error = yield self.assertFailure(
         self.deployment.start("0", get_test_zookeeper_address(),
                               self.bundle), UnitDeploymentError)
     self.assertEquals(str(error), "Charm must be unpacked first.")
Example #24
0
    def test_non_existant_directory(self):
        """If the juju directory does not exist an error should be raised.
        """
        juju_directory = self.makeDir()
        os.rmdir(juju_directory)
        data = {"zookeeper_servers": get_test_zookeeper_address(), "juju_directory": juju_directory}

        agent = BaseAgent()
        self.assertRaises(JujuError, agent.configure, data)
Example #25
0
 def tearDown(self):
     # Close and reopen connection, so that watches set during
     # testing are not affected by the cleaning up.
     self.client.close()
     client = ZookeeperClient(get_test_zookeeper_address())
     yield client.connect()
     deleteTree(handle=client.handle)
     client.close()
     yield super(StateTestBase, self).tearDown()
Example #26
0
 def tearDown(self):
     # Close and reopen connection, so that watches set during
     # testing are not affected by the cleaning up.
     self.client.close()
     client = ZookeeperClient(get_test_zookeeper_address())
     yield client.connect()
     deleteTree(handle=client.handle)
     client.close()
     yield super(StateTestBase, self).tearDown()
Example #27
0
    def test_watch_stops_on_closed_connection(self):
        """Verify watches stops when the connection is closed."""

        # Use a separate client connection for watching so it can be
        # disconnected.
        watch_client = ZookeeperClient(get_test_zookeeper_address())
        yield watch_client.connect()
        watch_base = StateBase(watch_client)

        wait_callback = Deferred()
        finish_callback = Deferred()
        calls = []

        def watcher(old_topology, new_topology):
            calls.append((old_topology, new_topology))
            wait_callback.callback(True)
            return finish_callback

        # Start watching.
        yield watch_base._watch_topology(watcher)

        # Create the topology.
        topology = InternalTopology()
        topology.add_machine("m-0")
        yield self.set_topology(topology)
        
        # Hold off until callback is started.
        yield wait_callback

        # Change the topology.
        topology.add_machine("m-1")
        yield self.set_topology(topology)

        # Ensure that the watch has been called just once so far
        # (although still pending due to the finish_callback).
        self.assertEquals(len(calls), 1)

        # Now disconnect the client.
        watch_client.close()
        self.assertFalse(watch_client.connected)
        self.assertTrue(self.client.connected)

        # Change the topology again.
        topology.add_machine("m-2")
        yield self.set_topology(topology)

        # Allow the first call to be completed, starting a process of
        # watching for the next change. At this point, the watch will
        # encounter that the client is disconnected.
        finish_callback.callback(True)

        # Give a chance for something bad to happen.
        yield self.poke_zk()

        # Ensure the watch was still not called.
        self.assertEquals(len(calls), 1)
Example #28
0
 def xtest_service_unit_start_pre_unpack(self):
     """
     Attempting to start a charm before the charm is unpacked
     results in an exception.
     """
     error = yield self.assertFailure(
         self.deployment.start(
             "0", get_test_zookeeper_address(), self.bundle),
         UnitDeploymentError)
     self.assertEquals(str(error), "Charm must be unpacked first.")
Example #29
0
 def test_agent_invalid_unit_name(self):
     """If the unit agent is given an invalid unit name, an error
     message is raised."""
     options = {}
     options["juju_directory"] = self.juju_directory
     options["zookeeper_servers"] = get_test_zookeeper_address()
     options["unit_name"] = "rabbit-1"
     agent = self.agent_class()
     agent.configure(options)
     return self.assertFailure(agent.startService(), ServiceStateNotFound)
Example #30
0
 def test_agent_invalid_unit_name(self):
     """If the unit agent is given an invalid unit name, an error
     message is raised."""
     options = {}
     options["juju_directory"] = self.juju_directory
     options["zookeeper_servers"] = get_test_zookeeper_address()
     options["unit_name"] = "rabbit-1"
     agent = self.agent_class()
     agent.configure(options)
     return self.assertFailure(agent.startService(), ServiceStateNotFound)
Example #31
0
 def create_agent(self, agent_cls, path, **extra_options):
     agent = agent_cls()
     options = TwistedOptionNamespace()
     options["juju_directory"] = path
     options["zookeeper_servers"] = get_test_zookeeper_address()
     for k, v in extra_options.items():
         options[k] = v
     agent.configure(options)
     agent.set_watch_enabled(False)
     agent.client = self.client
     yield agent.start()
     self.agents.append(agent)
Example #32
0
    def test_non_existant_directory(self):
        """If the juju directory does not exist an error should be raised.
        """
        juju_directory = self.makeDir()
        os.rmdir(juju_directory)
        data = {
            "zookeeper_servers": get_test_zookeeper_address(),
            "juju_directory": juju_directory
        }

        agent = BaseAgent()
        self.assertRaises(JujuError, agent.configure, data)
    def test_fail_to_run_actual_process(self):
        self.deployment.unit_agent_module = "haha.disregard.that"
        self.patch(UpstartService, "init_dir", self.real_init_dir)

        d = self.deployment.start(
            "0", get_test_zookeeper_address(), self.bundle)
        e = yield self.assertFailure(d, UnitDeploymentError)
        self.assertTrue(str(e).startswith(
            "Failed to start job juju-wordpress-0; got output:\n"))
        self.assertIn("No module named haha", str(e))

        yield self.deployment.destroy()
Example #34
0
 def create_agent(self, agent_cls, path, **extra_options):
     agent = agent_cls()
     options = TwistedOptionNamespace()
     options["juju_directory"] = path
     options["zookeeper_servers"] = get_test_zookeeper_address()
     for k, v in extra_options.items():
         options[k] = v
     agent.configure(options)
     agent.set_watch_enabled(False)
     agent.client = self.client
     yield agent.start()
     self.agents.append(agent)
Example #35
0
    def test_managed_agent_args(self):

        captured_args = []

        def intercept_args(args):
            captured_args.extend(args)
            return True

        self.patch(subprocess, "check_call", intercept_args)

        juju_directory = self.makeDir()
        pid_file = self.makeFile()
        log_file = self.makeFile()

        agent = ManagedMachineAgent(pid_file,
                                    get_test_zookeeper_address(),
                                    juju_directory=juju_directory,
                                    log_file=log_file,
                                    juju_unit_namespace="ns1",
                                    juju_origin="lp:juju/trunk")

        mock_agent = self.mocker.patch(agent)
        mock_agent.is_running()
        self.mocker.result(succeed(False))
        self.mocker.replay()

        self.assertEqual(agent.juju_origin, "lp:juju/trunk")
        yield agent.start()

        # Verify machine agent environment
        env_vars = dict(
            [arg.split("=") for arg in captured_args if "=" in arg])
        env_vars.pop("PYTHONPATH")
        self.assertEqual(
            env_vars,
            dict(JUJU_ZOOKEEPER=get_test_zookeeper_address(),
                 JUJU_MACHINE_ID="0",
                 JUJU_HOME=juju_directory,
                 JUJU_ORIGIN="lp:juju/trunk",
                 JUJU_UNIT_NS="ns1"))
Example #36
0
    def test_connect(self):
        """
        Forwarding a port spawns an ssh process with port forwarding arguments.
        """
        connect_deferred = self.client.connect(
            get_test_zookeeper_address(), timeout=20)

        def validate_connected(client):
            self.assertTrue(client.connected)
            client.close()

        connect_deferred.addCallback(validate_connected)
        return connect_deferred
Example #37
0
    def test_managed_agent_args(self):

        captured_args = []

        def intercept_args(args):
            captured_args.extend(args)
            return True

        self.patch(subprocess, "check_call", intercept_args)

        juju_directory = self.makeDir()
        pid_file = self.makeFile()
        log_file = self.makeFile()

        agent = ManagedMachineAgent(
            pid_file, get_test_zookeeper_address(),
            juju_directory=juju_directory,
            log_file=log_file, juju_unit_namespace="ns1",
            juju_origin="lp:juju/trunk")

        mock_agent = self.mocker.patch(agent)
        mock_agent.is_running()
        self.mocker.result(succeed(False))
        self.mocker.replay()

        self.assertEqual(agent.juju_origin, "lp:juju/trunk")
        yield agent.start()

        # Verify machine agent environment
        env_vars = dict(
            [arg.split("=") for arg in captured_args if "=" in arg])
        env_vars.pop("PYTHONPATH")
        self.assertEqual(
            env_vars,
            dict(JUJU_ZOOKEEPER=get_test_zookeeper_address(),
                 JUJU_MACHINE_ID="0",
                 JUJU_HOME=juju_directory,
                 JUJU_ORIGIN="lp:juju/trunk",
                 JUJU_UNIT_NS="ns1"))
Example #38
0
    def test_directory_cli_option(self):
        """The juju directory can be configured on the cli."""
        juju_directory = self.makeDir()
        self.change_args("es-agent", "--zookeeper-servers",
                         get_test_zookeeper_address(), "--juju-directory",
                         juju_directory)

        agent = BaseAgent()
        parser = argparse.ArgumentParser()
        agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())
        agent.configure(options)
        self.assertEqual(agent.config["juju_directory"], juju_directory)
Example #39
0
 def test_session_file_permissions(self):
     session_file = self.makeFile()
     agent = DummyAgent()
     agent.configure({
         "session_file": session_file,
         "juju_directory": self.makeDir(),
         "zookeeper_servers": get_test_zookeeper_address()})
     yield agent.startService()
     mode = os.stat(session_file).st_mode
     mask = stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO
     self.assertEquals(mode & mask, stat.S_IRUSR | stat.S_IWUSR)
     yield agent.stopService()
     self.assertFalse(os.path.exists(session_file))
Example #40
0
    def test_directory_env(self):
        """The juju directory passed via environment."""
        self.change_args("es-agent")

        juju_directory = self.makeDir()
        self.change_environment(JUJU_HOME=juju_directory, JUJU_ZOOKEEPER=get_test_zookeeper_address())

        agent = BaseAgent()
        parser = argparse.ArgumentParser()
        agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())
        agent.configure(options)
        self.assertEqual(agent.config["juju_directory"], juju_directory)
Example #41
0
    def test_directory_cli_option(self):
        """The juju directory can be configured on the cli."""
        juju_directory = self.makeDir()
        self.change_args(
            "es-agent", "--zookeeper-servers", get_test_zookeeper_address(), "--juju-directory", juju_directory
        )

        agent = BaseAgent()
        parser = argparse.ArgumentParser()
        agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())
        agent.configure(options)
        self.assertEqual(agent.config["juju_directory"], juju_directory)
Example #42
0
    def test_connect(self):
        """
        Forwarding a port spawns an ssh process with port forwarding arguments.
        """
        connect_deferred = self.client.connect(get_test_zookeeper_address(),
                                               timeout=20)

        def validate_connected(client):
            self.assertTrue(client.connected)
            client.close()

        connect_deferred.addCallback(validate_connected)
        return connect_deferred
Example #43
0
    def test_directory_env(self):
        """The juju directory passed via environment."""
        self.change_args("es-agent")

        juju_directory = self.makeDir()
        self.change_environment(JUJU_HOME=juju_directory,
                                JUJU_ZOOKEEPER=get_test_zookeeper_address())

        agent = BaseAgent()
        parser = argparse.ArgumentParser()
        agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())
        agent.configure(options)
        self.assertEqual(agent.config["juju_directory"], juju_directory)
Example #44
0
    def setUp(self):
        zookeeper.set_debug_level(0)
        self.client = yield SecurityPolicyConnection(
            get_test_zookeeper_address()).connect()

        admin = Principal("admin", "admin")

        self.token_db = TokenDatabase(self.client)
        yield self.token_db.add(admin)
        self.policy = SecurityPolicy(self.client, self.token_db, owner=admin)
        attach_defer = admin.attach(self.client)
        # Trick to speed up the auth response processing (fixed in ZK trunk)
        self.client.exists("/")
        yield attach_defer
Example #45
0
    def setUp(self):
        zookeeper.set_debug_level(0)
        self.client = yield SecurityPolicyConnection(
            get_test_zookeeper_address()).connect()

        admin = Principal("admin", "admin")

        self.token_db = TokenDatabase(self.client)
        yield self.token_db.add(admin)
        self.policy = SecurityPolicy(self.client, self.token_db, owner=admin)
        attach_defer = admin.attach(self.client)
        # Trick to speed up the auth response processing (fixed in ZK trunk)
        self.client.exists("/")
        yield attach_defer
Example #46
0
    def test_service_unit_start_with_agent_startup_error(self):
        """
        Starting a service unit will result in a unit workspace being created
        if it does not exist and a running service unit agent.
        """
        self.deployment.unit_agent_module = "magichat.xr1"
        d = self.deployment.start(
            "0", get_test_zookeeper_address(), self.bundle)

        self.failUnlessFailure(d, UnitDeploymentError)

        def validate_result(error):
            self.assertIn("No module named magichat", str(error))

        d.addCallback(validate_result)
        return d
Example #47
0
    def test_service_unit_start_with_agent_startup_error(self):
        """
        Starting a service unit will result in a unit workspace being created
        if it does not exist and a running service unit agent.
        """
        self.deployment.unit_agent_module = "magichat.xr1"
        d = self.deployment.start("0", get_test_zookeeper_address(),
                                  self.bundle)

        self.failUnlessFailure(d, UnitDeploymentError)

        def validate_result(error):
            self.assertIn("No module named magichat", str(error))

        d.addCallback(validate_result)
        return d
Example #48
0
 def test_service_unit_destroy(self):
     """
     Forcibly stop a unit, and destroy any directories associated to it
     on the machine, and kills the unit agent process.
     """
     yield self.deployment.start(
         "0", get_test_zookeeper_address(), self.bundle)
     # give the process time to write its pid file
     yield self.sleep(0.1)
     pid = int(open(self.deployment.pid_file).read())
     yield self.deployment.destroy()
     # give the process time to die.
     yield self.sleep(0.1)
     e = self.assertRaises(OSError, os.kill, pid, 0)
     self.assertEqual(e.errno, 3)
     self.assertFalse(os.path.exists(self.deployment.directory))
     self.assertFalse(os.path.exists(self.deployment.pid_file))
Example #49
0
 def test_service_unit_destroy(self):
     """
     Forcibly stop a unit, and destroy any directories associated to it
     on the machine, and kills the unit agent process.
     """
     yield self.deployment.start("0", get_test_zookeeper_address(),
                                 self.bundle)
     # give the process time to write its pid file
     yield self.sleep(0.1)
     pid = int(open(self.deployment.pid_file).read())
     yield self.deployment.destroy()
     # give the process time to die.
     yield self.sleep(0.1)
     e = self.assertRaises(OSError, os.kill, pid, 0)
     self.assertEqual(e.errno, 3)
     self.assertFalse(os.path.exists(self.deployment.directory))
     self.assertFalse(os.path.exists(self.deployment.pid_file))
Example #50
0
    def test_agent_unit_name_cli_extraction_error(self):
        """Failure to extract the unit name, results in a nice error message.
        """
        # We don't want JUJU_UNIT_NAME set, so that the expected
        # JujuError will be raised
        self.change_environment(PATH=get_cli_environ_path())
        self.change_args("unit-agent", "--juju-directory", self.makeDir(),
                         "--zookeeper-servers", get_test_zookeeper_address())

        parser = argparse.ArgumentParser()
        self.agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())

        e = self.assertRaises(JujuError, self.agent.configure, options)
        self.assertEquals(
            str(e), "--unit-name must be provided in the command line, or "
            "$JUJU_UNIT_NAME in the environment")
Example #51
0
    def setUp(self):
        super(CharmPublisherTest, self).setUp()
        zookeeper.set_debug_level(0)

        self.charm = CharmDirectory(self.sample_dir1)
        self.charm_id = local_charm_id(self.charm)
        self.charm_key = under.quote(self.charm_id)
        # provider storage key
        self.charm_storage_key = under.quote(
            "%s:%s" % (self.charm_id, self.charm.get_sha256()))

        self.client = ZookeeperClient(get_test_zookeeper_address())
        self.storage_dir = self.makeDir()
        self.storage = FileStorage(self.storage_dir)
        self.publisher = CharmPublisher(self.client, self.storage)

        yield self.client.connect()
        yield self.client.create("/charms")
Example #52
0
    def test_service_unit_start_with_integer_machine_id(self):
        """
        Starting a service unit will result in a unit workspace being created
        if it does not exist and a running service unit agent.
        """
        d = self.deployment.start(21, get_test_zookeeper_address(),
                                  self.bundle)

        @inlineCallbacks
        def validate_result(result):
            # give process time to write its pid
            yield self.sleep(0.1)
            self.addCleanup(self.process_kill,
                            int(open(self.deployment.pid_file).read()))
            self.assertEqual(result, True)

        d.addCallback(validate_result)
        return d
Example #53
0
    def setUp(self):
        super(CharmPublisherTest, self).setUp()
        zookeeper.set_debug_level(0)

        self.charm = CharmDirectory(self.sample_dir1)
        self.charm_id = local_charm_id(self.charm)
        self.charm_key = under.quote(self.charm_id)
        # provider storage key
        self.charm_storage_key = under.quote(
            "%s:%s" % (self.charm_id, self.charm.get_sha256()))

        self.client = ZookeeperClient(get_test_zookeeper_address())
        self.storage_dir = self.makeDir()
        self.storage = FileStorage(self.storage_dir)
        self.publisher = CharmPublisher(self.client, self.storage)

        yield self.client.connect()
        yield self.client.create("/charms")
Example #54
0
    def test_agent_machine_id_cli_error(self):
        """
        If the machine id can't be found, a detailed error message
        is given.
        """
        # initially setup by get_agent_config in setUp
        self.change_environment(JUJU_MACHINE_ID="")
        self.change_args("es-agent", "--zookeeper-servers",
                         get_test_zookeeper_address(), "--juju-directory",
                         self.makeDir())
        parser = argparse.ArgumentParser()
        self.agent.setup_options(parser)
        options = parser.parse_args(namespace=TwistedOptionNamespace())

        e = self.assertRaises(JujuError, self.agent.configure, options)

        self.assertIn(("--machine-id must be provided in the command line,"
                       " or $JUJU_MACHINE_ID in the environment"), str(e))
Example #55
0
    def test_watch_stops_on_early_closed_connection(self):
        """Verify watches stops when the connection is closed early.

        _watch_topology chains from an exists_and_watch to a
        get_and_watch. This test ensures that this chaining will fail
        gracefully if the connection is closed before this chaining
        can occur.
        """
        # Use a separate client connection for watching so it can be
        # disconnected.
        watch_client = ZookeeperClient(get_test_zookeeper_address())
        yield watch_client.connect()
        watch_base = StateBase(watch_client)

        calls = []

        @inlineCallbacks
        def watcher(old_topology, new_topology):
            calls.append((old_topology, new_topology))

        # Create the topology.
        topology = InternalTopology()
        topology.add_machine("m-0")
        yield self.set_topology(topology)
        
        # Now disconnect the client.
        watch_client.close()
        self.assertFalse(watch_client.connected)
        self.assertTrue(self.client.connected)

        # Start watching.
        yield watch_base._watch_topology(watcher)

        # Change the topology, this will trigger the watch.
        topology.add_machine("m-1")
        yield self.set_topology(topology)

        # Give a chance for something bad to happen.
        yield self.poke_zk()

        # Ensure the watcher was never called, because its client was
        # disconnected.
        self.assertEquals(len(calls), 0)
Example #56
0
    def test_invalid_user(self):
        """
        if a connection can not be made before a timeout period, an exception
        is raised.

        with the sshclient layer, tihs test no longer returns a failure..
        and its hard to cleanup the process tunnel..
        """
        SSHClient.remote_user = "******"
        connect_deferred = self.client.connect(get_test_zookeeper_address(),
                                               timeout=10)
        self.failUnlessFailure(connect_deferred, NoConnection)

        def validate_log(result):
            output = self.log.getvalue()
            self.assertEqual(output.strip(), "Invalid SSH key")

        connect_deferred.addCallback(validate_log)
        return connect_deferred
Example #57
0
    def test_managed_agent_root(self):
        juju_directory = self.makeDir()
        pid_file = tempfile.mktemp()
        log_file = tempfile.mktemp()

        # The pid file and log file get written as root
        def cleanup_root_file(cleanup_file):
            subprocess.check_call(["sudo", "rm", "-f", cleanup_file],
                                  stderr=subprocess.STDOUT)

        self.addCleanup(cleanup_root_file, pid_file)
        self.addCleanup(cleanup_root_file, log_file)

        agent = ManagedMachineAgent(
            pid_file,
            machine_id="0",
            log_file=log_file,
            zookeeper_hosts=get_test_zookeeper_address(),
            juju_directory=juju_directory)

        agent.agent_module = "juju.agents.dummy"
        self.assertFalse((yield agent.is_running()))
        yield agent.start()

        # Give a moment for the process to start and write its config
        yield self.sleep(0.1)
        self.assertTrue((yield agent.is_running()))

        # running start again is fine, detects the process is running
        yield agent.start()
        yield agent.stop()
        self.assertFalse((yield agent.is_running()))

        # running stop again is fine, detects the process is stopped.
        yield agent.stop()

        self.assertFalse(os.path.exists(pid_file))

        # Stop raises runtime error if the process doesn't match up.
        with open(pid_file, "w") as pid_handle:
            pid_handle.write("1")
        self.assertFailure(agent.stop(), RuntimeError)
Example #58
0
    def test_run(self):
        """Invokes the run class method on an agent.

        This will create an agent instance,  parse the cli args, passes them to
        the agent, and starts the agent runner.
        """
        self.change_args("es-agent", "--zookeeper-servers",
                         get_test_zookeeper_address())
        runner = self.mocker.patch(AgentRunner)
        runner.run()
        mock_agent = self.mocker.patch(BaseAgent)

        def match_args(config):
            self.assertEqual(config["zookeeper_servers"],
                             get_test_zookeeper_address())
            return True

        mock_agent.configure(MATCH(match_args))
        self.mocker.passthrough()

        self.mocker.replay()
        BaseAgent.run()
Example #59
0
    def bootstrap_mock(self):
        self.patch(local, "REQUIRED_PACKAGES", [])
        mock_network = self.mocker.patch(Network)
        mock_network.start()
        self.mocker.result(succeed(True))
        mock_network.get_attributes()
        self.mocker.result({"ip": {"address": "127.0.0.1"}})

        mock_storage = self.mocker.patch(StorageServer)
        mock_storage.start()
        self.mocker.result(succeed(True))

        mock_zookeeper = self.mocker.patch(Zookeeper)
        mock_zookeeper.start()
        self.mocker.result(succeed(True))

        mock_zookeeper.address
        self.mocker.result(get_test_zookeeper_address())
        self.mocker.count(3)

        mock_agent = self.mocker.patch(ManagedMachineAgent)
        mock_agent.start()
        self.mocker.result(succeed(True))