Do not drop firewalls with unknown states
Currently, Ceilometer checks the state of Neutron FWaaS firewalls and does not generate samples if they have unknown status, leaving a warning in the Ceilometer logs. There are two major issues with this: * It makes visibility of resources with unknown/invalid state worse, since samples are not being generated for affected resources at all. * Downstream rating/billing services such as CloudKitty prefer to know everything about as many resources as possible, so business logic can be implemented around that information. Sometimes resources should be billed even if they are in unknown/error state, because they still consume resources. This patch changes the network.services.firewall pollster to always sample all found firewalls. For resources with unknown status or status None, the sample volume is set to -1. This lines FWaaS polling up with the changes previously made for floating IPs and VPNaaS [1]. FWaaS was not done as at the time FWaaS polling was deprecated. [1]: https://review.opendev.org/c/openstack/ceilometer/+/942022 Change-Id: I79d31127267facab30a18a137144a525fa10379c Signed-off-by: Callum Dickinson <callum.dickinson@catalystcloud.nz>
This commit is contained in:
@@ -42,12 +42,12 @@ class FirewallPollster(base.BaseServicesPollster):
|
||||
LOG.debug("Firewall : %s", fw)
|
||||
status = self.get_status_id(fw['status'])
|
||||
if status == -1:
|
||||
# unknown status, skip this sample
|
||||
LOG.warning("Unknown status %(stat)s received on fw %(id)s,"
|
||||
"skipping sample",
|
||||
{'stat': fw['status'], 'id': fw['id']})
|
||||
continue
|
||||
|
||||
LOG.warning(
|
||||
"Unknown status %(status)s for firewall %(name)s "
|
||||
"(%(id)s), setting volume to -1",
|
||||
{"status": fw['status'],
|
||||
"name": fw['name'],
|
||||
"id": fw['id']})
|
||||
yield sample.Sample(
|
||||
name='network.services.firewall',
|
||||
type=sample.TYPE_GAUGE,
|
||||
|
||||
@@ -43,77 +43,96 @@ class TestFirewallPollster(_BaseTestFWPollster):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.pollster = fwaas.FirewallPollster(self.CONF)
|
||||
fake_fw = self.fake_get_fw_service()
|
||||
self.fake_fw = self.fake_get_fw_service()
|
||||
self.useFixture(fixtures.MockPatch('ceilometer.neutron_client.Client.'
|
||||
'firewall_get_all',
|
||||
return_value=fake_fw))
|
||||
return_value=self.fake_fw))
|
||||
|
||||
@staticmethod
|
||||
def fake_get_fw_service():
|
||||
return [{'status': 'ACTIVE',
|
||||
'name': 'myfw',
|
||||
'name': 'myfw1',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'fdde3d818-fdcb-fg4b-de7f-6750dc8a9d7a',
|
||||
'firewall_policy_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
{'status': 'INACTIVE',
|
||||
'name': 'myfw',
|
||||
'name': 'myfw2',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'fdde3d818-fdcb-fg4b-de7f-6750dc8a9d7a',
|
||||
'firewall_policy_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'id': 'e0d707dc-6194-4471-8286-0635bf65a055',
|
||||
'firewall_policy_id': 'e0d707dc-6194-4471-8286-0635bf65a055',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
{'status': 'PENDING_CREATE',
|
||||
'name': 'myfw',
|
||||
'name': 'myfw3',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'fdde3d818-fdcb-fg4b-de7f-6750dc8a9d7a',
|
||||
'id': 'e538d353-31e9-4581-a511-0a487ff71d0d',
|
||||
'firewall_policy_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
{'status': 'error',
|
||||
'name': 'myfw',
|
||||
{'status': 'ERROR',
|
||||
'name': 'myfw4',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'fdde3d818-fdcb-fg4b-de7f-6750dc8a9d7a',
|
||||
'firewall_policy_id': 'bbe3d818-bdcb-4e4b-b47f-5650dc8a9d7a',
|
||||
'id': '06f698c4-dc63-43c4-a2d9-7b978e80f09a',
|
||||
'firewall_policy_id': 'bef98f97-789f-418e-82ad-3e5d69618916',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
{'status': 'UNKNOWN',
|
||||
'name': 'myfw5',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'c65a1bec-ab59-44ce-b784-1c725f427998',
|
||||
'firewall_policy_id': 'd45b975e-738f-42c3-a4b3-760d3a58ab51',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
{'status': None,
|
||||
'name': 'myfw6',
|
||||
'description': '',
|
||||
'admin_state_up': True,
|
||||
'id': 'ab5d19ff-32a8-49e5-aa2b-d008157359d9',
|
||||
'firewall_policy_id': '79b9c933-2a7c-4f93-bbf9-d165f0326581',
|
||||
'tenant_id': 'a4eb9f4938bb418bbc4f8eb31802fefa'},
|
||||
]
|
||||
|
||||
def test_fw_get_samples(self):
|
||||
samples = list(self.pollster.get_samples(
|
||||
self.manager, {},
|
||||
resources=self.fake_get_fw_service()))
|
||||
self.assertEqual(4, len(samples))
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(self.fake_get_fw_service()[0][field],
|
||||
samples[0].resource_metadata[field])
|
||||
resources=self.fake_fw))
|
||||
self.assertEqual(len(self.fake_fw), len(samples))
|
||||
self.assertEqual({fw['id'] for fw in self.fake_fw},
|
||||
{sample.resource_id for sample in samples})
|
||||
samples_dict = {sample.resource_id: sample for sample in samples}
|
||||
for fw in self.fake_fw:
|
||||
sample = samples_dict[fw['id']]
|
||||
for field in self.pollster.FIELDS:
|
||||
self.assertEqual(fw[field],
|
||||
sample.resource_metadata[field])
|
||||
|
||||
def test_vpn_volume(self):
|
||||
samples = list(self.pollster.get_samples(
|
||||
self.manager, {},
|
||||
resources=self.fake_get_fw_service()))
|
||||
resources=self.fake_fw))
|
||||
self.assertEqual(1, samples[0].volume)
|
||||
self.assertEqual(0, samples[1].volume)
|
||||
self.assertEqual(2, samples[2].volume)
|
||||
self.assertEqual(7, samples[3].volume)
|
||||
self.assertEqual(-1, samples[4].volume)
|
||||
self.assertEqual(-1, samples[5].volume)
|
||||
|
||||
def test_get_vpn_meter_names(self):
|
||||
samples = list(self.pollster.get_samples(
|
||||
self.manager, {},
|
||||
resources=self.fake_get_fw_service()))
|
||||
resources=self.fake_fw))
|
||||
self.assertEqual({'network.services.firewall'},
|
||||
{s.name for s in samples})
|
||||
|
||||
def test_vpn_discovery(self):
|
||||
discovered_fws = discovery.FirewallDiscovery(
|
||||
self.CONF).discover(self.manager)
|
||||
self.assertEqual(3, len(discovered_fws))
|
||||
self.assertEqual(len(self.fake_fw), len(discovered_fws))
|
||||
|
||||
for vpn in self.fake_get_fw_service():
|
||||
if vpn['status'] == 'error':
|
||||
self.assertNotIn(vpn, discovered_fws)
|
||||
else:
|
||||
self.assertIn(vpn, discovered_fws)
|
||||
for vpn in self.fake_fw:
|
||||
self.assertIn(vpn, discovered_fws)
|
||||
|
||||
|
||||
class TestIPSecConnectionsPollster(_BaseTestFWPollster):
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
The ``network.services.firewall`` pollster now publishes samples for all
|
||||
found firewalls, even if they are known to have an unknown state, when
|
||||
they would previously be dropped. The volume of samples for such firewalls
|
||||
will be set to ``-1``. This improves visibility of firewalls with unknown
|
||||
states, allowing them to be monitored via samples and the
|
||||
Gnocchi/Prometheus metrics, making it easier to discover such resources
|
||||
for troubleshooting. It also moves some of the "business logic" for
|
||||
downstream rating/billing services such as CloudKitty out of Ceilometer
|
||||
itself.
|
||||
Reference in New Issue
Block a user