コード例 #1
0
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
コード例 #2
0
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
コード例 #3
0
    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!")
コード例 #4
0
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
コード例 #5
0
    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)
コード例 #6
0
    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)
コード例 #7
0
    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)