class KeystoneToken(DataWatcher): """ A plugin which pulls the admin_token from the keystone configuration file and sends it to the landscape server. """ message_type = "keystone-token" message_key = "data" run_interval = 60 * 15 scope = "openstack" def __init__(self, keystone_config_file=KEYSTONE_CONFIG_FILE): self._keystone_config_file = keystone_config_file def register(self, client): super(KeystoneToken, self).register(client) self._persist_filename = os.path.join(self.registry.config.data_path, "keystone.bpickle") self._persist = Persist(filename=self._persist_filename) self.registry.reactor.call_every(self.registry.config.flush_interval, self.flush) def _reset(self): """ Reset the persist. """ self._persist.remove("data") def flush(self): self._persist.save(self._persist_filename) def get_data(self): """ Return the Keystone administrative token. """ if not os.path.exists(self._keystone_config_file): return None config = ConfigParser() if _PY3: # We need to use the surrogateescape error handler as the # admin_token my contain arbitrary bytes. The ConfigParser in # Python 2 on the other hand does not support read_string. config_str = read_binary_file( self._keystone_config_file).decode("utf-8", "surrogateescape") config.read_string(config_str) else: config.read(self._keystone_config_file) try: admin_token = config.get("DEFAULT", "admin_token") except NoOptionError: logging.error("KeystoneToken: No admin_token found in %s" % (self._keystone_config_file)) return None # There is no support for surrogateescape in Python 2, but we actually # have bytes in this case anyway. if _PY3: admin_token = admin_token.encode("utf-8", "surrogateescape") return admin_token
def get_versioned_persist(service): """Get a L{Persist} database with upgrade rules applied. Load a L{Persist} database for the given C{service} and upgrade or mark as current, as necessary. """ persist = Persist(filename=service.persist_filename) upgrade_manager = UPGRADE_MANAGERS[service.service_name] if os.path.exists(service.persist_filename): upgrade_manager.apply(persist) else: upgrade_manager.initialize(persist) persist.save(service.persist_filename) return persist
def test_creating_loads_persist(self): """ If C{persist_filename} exists, it is loaded by the constructor. """ filename = self.makeFile() persist = Persist() persist.set("a", "Hi there!") persist.save(filename) monitor = Monitor(self.reactor, self.config, persist=Persist(), persist_filename=filename) self.assertEqual(monitor.persist.get("a"), "Hi there!")
class KeystoneToken(DataWatcher): """ A plugin which pulls the admin_token from the keystone configuration file and sends it to the landscape server. """ message_type = "keystone-token" message_key = "data" run_interval = 60 * 15 scope = "openstack" def __init__(self, keystone_config_file=KEYSTONE_CONFIG_FILE): self._keystone_config_file = keystone_config_file def register(self, client): super(KeystoneToken, self).register(client) self._persist_filename = os.path.join(self.registry.config.data_path, "keystone.bpickle") self._persist = Persist(filename=self._persist_filename) self.registry.reactor.call_every(self.registry.config.flush_interval, self.flush) def _reset(self): """ Reset the persist. """ self._persist.remove("data") def flush(self): self._persist.save(self._persist_filename) def get_data(self): """ Return the Keystone administrative token. """ if not os.path.exists(self._keystone_config_file): return None config = ConfigParser() config.read(self._keystone_config_file) try: admin_token = config.get("DEFAULT", "admin_token") except NoOptionError: logging.error("KeystoneToken: No admin_token found in %s" % (self._keystone_config_file)) return None return admin_token
def test_run_with_attachment_ids(self): """ The most recent protocol for script message doesn't include the attachment body inside the message itself, but instead gives an attachment ID, and the plugin fetches the files separately. """ self.manager.config.url = "https://localhost/message-system" persist = Persist( filename=os.path.join(self.config.data_path, "broker.bpickle")) registration_persist = persist.root_at("registration") registration_persist.set("secure-id", "secure_id") persist.save() patch_fetch = mock.patch( "landscape.client.manager.scriptexecution.fetch_async") mock_fetch = patch_fetch.start() mock_fetch.return_value = succeed(b"some other data") headers = { "User-Agent": "landscape-client/%s" % VERSION, "Content-Type": "application/octet-stream", "X-Computer-ID": "secure_id" } result = self.plugin.run_script( u"/bin/sh", u"ls $LANDSCAPE_ATTACHMENTS && cat $LANDSCAPE_ATTACHMENTS/file1", attachments={u"file1": 14}) def check(result): self.assertEqual(result, "file1\nsome other data") mock_fetch.assert_called_with("https://localhost/attachment/14", headers=headers, cainfo=None) def cleanup(result): patch_fetch.stop() # We have to return the Failure or result to get a working test. return result return result.addCallback(check).addBoth(cleanup)
def test_run_with_attachment_ids_and_ssl(self): """ When fetching attachments, L{ScriptExecution} passes the optional ssl certificate file if the configuration specifies it. """ self.manager.config.url = "https://localhost/message-system" self.manager.config.ssl_public_key = "/some/key" persist = Persist( filename=os.path.join(self.config.data_path, "broker.bpickle")) registration_persist = persist.root_at("registration") registration_persist.set("secure-id", "secure_id") persist.save() patch_fetch = mock.patch( "landscape.client.manager.scriptexecution.fetch_async") mock_fetch = patch_fetch.start() mock_fetch.return_value = succeed(b"some other data") headers = { "User-Agent": "landscape-client/%s" % VERSION, "Content-Type": "application/octet-stream", "X-Computer-ID": "secure_id" } result = self.plugin.run_script( u"/bin/sh", u"ls $LANDSCAPE_ATTACHMENTS && cat $LANDSCAPE_ATTACHMENTS/file1", attachments={u"file1": 14}) def check(result): self.assertEqual(result, "file1\nsome other data") mock_fetch.assert_called_with("https://localhost/attachment/14", headers=headers, cainfo="/some/key") def cleanup(result): patch_fetch.stop() return result return result.addCallback(check).addBoth(cleanup)
def test_fetch_attachment_failure(self, mock_fetch): """ If the plugin fails to retrieve the attachments with a L{HTTPCodeError}, a specific error code is shown. """ self.manager.config.url = "https://localhost/message-system" persist = Persist( filename=os.path.join(self.config.data_path, "broker.bpickle")) registration_persist = persist.root_at("registration") registration_persist.set("secure-id", "secure_id") persist.save() headers = { "User-Agent": "landscape-client/%s" % VERSION, "Content-Type": "application/octet-stream", "X-Computer-ID": "secure_id" } mock_fetch.return_value = fail(HTTPCodeError(404, "Not found")) self.manager.add(ScriptExecutionPlugin()) result = self._send_script("/bin/sh", "echo hi", attachments={u"file1": 14}) def got_result(ignored): self.assertMessages( self.broker_service.message_store.get_pending_messages(), [{ "type": "operation-result", "operation-id": 123, "result-text": "Server returned HTTP code 404", "result-code": FETCH_ATTACHMENTS_FAILED_RESULT, "status": FAILED }]) mock_fetch.assert_called_with("https://localhost/attachment/14", headers=headers, cainfo=None) return result.addCallback(got_result)