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)
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())
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"] })
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 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)
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()
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)
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())
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))
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
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
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"]})
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"])
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")
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()
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()
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.")
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 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()
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)
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.")
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)
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)
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()
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"))
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
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"))
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)
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))
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)
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)
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
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
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
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
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))
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))
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")
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")
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
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))
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)
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
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)
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()
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))