Esempio n. 1
0
    def clean_up_endpoint_statuses(self, our_endpoints_ids):
        """
        Mark any endpoint status reports for non-existent endpoints
        for cleanup.

        :param set our_endpoints_ids: Set of endpoint IDs for endpoints on
               this host.
        """
        if not self._config.REPORT_ENDPOINT_STATUS:
            _log.debug("Endpoint status reporting disabled, ignoring.")
            return

        our_host_dir = "/".join([FELIX_STATUS_DIR, self._config.HOSTNAME, "workload"])
        try:
            # Grab all the existing status reports.
            response = self.client.read(our_host_dir, recursive=True)
        except EtcdKeyNotFound:
            _log.info("No endpoint statuses found, nothing to clean up")
        else:
            for node in response.leaves:
                combined_id = get_endpoint_id_from_key(node.key)
                if combined_id and combined_id not in our_endpoints_ids:
                    # We found an endpoint in our status reporting tree that
                    # wasn't in the main tree.  Mark it as dirty so the status
                    # reporting thread will clean it up.
                    _log.debug("Endpoint %s removed by resync, marking " "status key for cleanup", combined_id)
                    self._status_reporter.mark_endpoint_dirty(combined_id, async=True)
                elif node.dir:
                    # This leaf is an empty directory, try to clean it up.
                    # This is safe even if another thread is adding keys back
                    # into the directory.
                    _log.debug("Found empty directory %s, cleaning up", node.key)
                    delete_empty_parents(self.client, node.key, our_host_dir)
Esempio n. 2
0
 def _attempt_cleanup(self):
     our_host_dir = "/".join(
         [FELIX_STATUS_DIR, self._config.HOSTNAME, "workload"])
     try:
         # Grab all the existing status reports.
         response = self.client.read(our_host_dir, recursive=True)
     except EtcdKeyNotFound:
         _log.info("No endpoint statuses found, nothing to clean up")
     else:
         # Mark all statuses we find as dirty.  This will result in any
         # unknown endpoints being cleaned up.
         for node in response.leaves:
             combined_id = get_endpoint_id_from_key(node.key)
             if combined_id:
                 _log.debug(
                     "Endpoint %s removed by resync, marking "
                     "status key for cleanup", combined_id)
                 self._mark_endpoint_dirty(combined_id)
             elif node.dir:
                 # This leaf is an empty directory, try to clean it up.
                 # This is safe even if another thread is adding keys back
                 # into the directory.
                 _log.debug("Found empty directory %s, cleaning up",
                            node.key)
                 delete_empty_parents(self.client, node.key, our_host_dir)
Esempio n. 3
0
 def _attempt_cleanup(self):
     our_host_dir = "/".join([FELIX_STATUS_DIR, self._config.HOSTNAME,
                              "workload"])
     try:
         # Grab all the existing status reports.
         response = self.client.read(our_host_dir,
                                     recursive=True)
     except EtcdKeyNotFound:
         _log.info("No endpoint statuses found, nothing to clean up")
     else:
         # Mark all statuses we find as dirty.  This will result in any
         # unknown endpoints being cleaned up.
         for node in response.leaves:
             combined_id = get_endpoint_id_from_key(node.key)
             if combined_id:
                 _log.debug("Endpoint %s removed by resync, marking "
                            "status key for cleanup",
                            combined_id)
                 self._mark_endpoint_dirty(combined_id)
             elif node.dir:
                 # This leaf is an empty directory, try to clean it up.
                 # This is safe even if another thread is adding keys back
                 # into the directory.
                 _log.debug("Found empty directory %s, cleaning up",
                            node.key)
                 delete_empty_parents(self.client, node.key, our_host_dir)
Esempio n. 4
0
 def test_delete_empty_parents_other_exception(self):
     m_client = Mock()
     m_client.delete = Mock()
     m_client.delete.side_effect = etcd.EtcdValueError()
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(m_client.delete.mock_calls, [
         call("foo/bar/baz/biff", dir=True, timeout=5),
     ])
Esempio n. 5
0
 def test_delete_empty_parents_mainline(self):
     m_client = Mock()
     m_client.delete = Mock()
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(m_client.delete.mock_calls, [
         call("foo/bar/baz/biff", dir=True, timeout=5),
         call("foo/bar/baz", dir=True, timeout=5),
         call("foo/bar", dir=True, timeout=5),
     ])
Esempio n. 6
0
 def test_delete_empty_parents_not_found(self):
     m_client = Mock()
     m_client.delete = Mock()
     m_client.delete.side_effect = [None, etcd.EtcdKeyNotFound(), None]
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(m_client.delete.mock_calls, [
         call("foo/bar/baz/biff", dir=True, timeout=5),
         call("foo/bar/baz", dir=True, timeout=5),
         call("foo/bar", dir=True, timeout=5),
     ])
 def test_delete_empty_parents_other_exception(self):
     m_client = Mock()
     m_client.delete = Mock()
     m_client.delete.side_effect = etcd.EtcdValueError()
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(
         m_client.delete.mock_calls,
         [
             call("foo/bar/baz/biff", dir=True, timeout=5),
         ]
     )
 def test_delete_empty_parents_mainline(self):
     m_client = Mock()
     m_client.delete = Mock()
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(
         m_client.delete.mock_calls,
         [
             call("foo/bar/baz/biff", dir=True, timeout=5),
             call("foo/bar/baz", dir=True, timeout=5),
             call("foo/bar", dir=True, timeout=5),
         ]
     )
 def test_delete_empty_parents_not_empty(self):
     m_client = Mock()
     m_client.delete = Mock()
     m_client.delete.side_effect = [
         None,
         etcd.EtcdDirNotEmpty(),
     ]
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(
         m_client.delete.mock_calls,
         [
             call("foo/bar/baz/biff", dir=True, timeout=5),
             call("foo/bar/baz", dir=True, timeout=5),
         ]
     )
Esempio n. 10
0
 def _write_endpoint_status_to_etcd(self, ep_id, status):
     """
     Try to actually write the status dict into etcd or delete the key
     if it is no longer needed.
     """
     status_key = ep_id.path_for_status
     if status:
         _log.debug("Writing endpoint status %s = %s", ep_id, status)
         self.client.set(status_key, json.dumps(status))
     else:
         _log.debug("Removing endpoint status %s", ep_id)
         try:
             self.client.delete(status_key)
         except EtcdKeyNotFound:
             _log.debug("Tried to delete %s but it was already gone", status_key)
         # Clean up any now-empty parent directories.
         delete_empty_parents(
             self.client,
             status_key.rsplit("/", 1)[0],  # Snip off final path segment.
             dir_for_felix_status(self._config.HOSTNAME),
         )
Esempio n. 11
0
 def _write_endpoint_status_to_etcd(self, ep_id, status):
     """
     Try to actually write the status dict into etcd or delete the key
     if it is no longer needed.
     """
     status_key = ep_id.path_for_status
     if status:
         _log.debug("Writing endpoint status %s = %s", ep_id, status)
         self.client.set(status_key, json.dumps(status))
     else:
         _log.debug("Removing endpoint status %s", ep_id)
         try:
             self.client.delete(status_key)
         except EtcdKeyNotFound:
             _log.debug("Tried to delete %s but it was already gone",
                        status_key)
         # Clean up any now-empty parent directories.
         delete_empty_parents(
             self.client,
             status_key.rsplit("/", 1)[0],  # Snip off final path segment.
             dir_for_felix_status(self._config.HOSTNAME))
Esempio n. 12
0
    def clean_up_endpoint_statuses(self, our_endpoints_ids):
        """
        Mark any endpoint status reports for non-existent endpoints
        for cleanup.

        :param set our_endpoints_ids: Set of endpoint IDs for endpoints on
               this host.
        """
        if not self._config.REPORT_ENDPOINT_STATUS:
            _log.debug("Endpoint status reporting disabled, ignoring.")
            return

        our_host_dir = "/".join(
            [FELIX_STATUS_DIR, self._config.HOSTNAME, "workload"])
        try:
            # Grab all the existing status reports.
            response = self.client.read(our_host_dir, recursive=True)
        except EtcdKeyNotFound:
            _log.info("No endpoint statuses found, nothing to clean up")
        else:
            for node in response.leaves:
                combined_id = get_endpoint_id_from_key(node.key)
                if combined_id and combined_id not in our_endpoints_ids:
                    # We found an endpoint in our status reporting tree that
                    # wasn't in the main tree.  Mark it as dirty so the status
                    # reporting thread will clean it up.
                    _log.debug(
                        "Endpoint %s removed by resync, marking "
                        "status key for cleanup", combined_id)
                    self._status_reporter.mark_endpoint_dirty(combined_id,
                                                              async=True)
                elif node.dir:
                    # This leaf is an empty directory, try to clean it up.
                    # This is safe even if another thread is adding keys back
                    # into the directory.
                    _log.debug("Found empty directory %s, cleaning up",
                               node.key)
                    delete_empty_parents(self.client, node.key, our_host_dir)