diff --git a/ceilometer/compute/pollsters/net.py b/ceilometer/compute/pollsters/net.py index 3dd948990d..a452e802e0 100644 --- a/ceilometer/compute/pollsters/net.py +++ b/ceilometer/compute/pollsters/net.py @@ -109,3 +109,17 @@ class OutgoingErrorsPollster(NetworkPollster): sample_type = sample.TYPE_CUMULATIVE sample_unit = 'packet' sample_stats_key = 'tx_errors' + + +class IncomingBytesDeltaPollster(NetworkPollster): + sample_name = 'network.incoming.bytes.delta' + sample_type = sample.TYPE_DELTA + sample_unit = 'B' + sample_stats_key = 'rx_bytes_delta' + + +class OutgoingBytesDeltaPollster(NetworkPollster): + sample_name = 'network.outgoing.packets.delta' + sample_type = sample.TYPE_DELTA + sample_unit = 'B' + sample_stats_key = 'tx_bytes_delta' diff --git a/ceilometer/compute/virt/hyperv/inspector.py b/ceilometer/compute/virt/hyperv/inspector.py index 3d4fcb42dc..9fdd0de634 100644 --- a/ceilometer/compute/virt/hyperv/inspector.py +++ b/ceilometer/compute/virt/hyperv/inspector.py @@ -127,7 +127,9 @@ class HyperVInspector(virt_inspector.Inspector): tx_bytes=vnic_metrics['tx_mb'] * units.Mi, tx_packets=0, tx_drop=0, - tx_errors=0) + tx_errors=0, + rx_bytes_delta=0, + tx_bytes_delta=0) @convert_exceptions(exception_conversion_map) def inspect_disks(self, instance, duration): diff --git a/ceilometer/compute/virt/inspector.py b/ceilometer/compute/virt/inspector.py index eb705168fa..0ec9bc7317 100644 --- a/ceilometer/compute/virt/inspector.py +++ b/ceilometer/compute/virt/inspector.py @@ -82,7 +82,8 @@ InterfaceStats = collections.namedtuple('InterfaceStats', 'rx_bytes', 'tx_bytes', 'rx_packets', 'tx_packets', 'rx_drop', 'tx_drop', - 'rx_errors', 'tx_errors']) + 'rx_errors', 'tx_errors', + 'rx_bytes_delta', 'tx_bytes_delta']) # Named tuple representing vNIC rate statistics. diff --git a/ceilometer/compute/virt/libvirt/inspector.py b/ceilometer/compute/virt/libvirt/inspector.py index b1e2c1aa29..b57107230c 100755 --- a/ceilometer/compute/virt/libvirt/inspector.py +++ b/ceilometer/compute/virt/libvirt/inspector.py @@ -38,6 +38,7 @@ class LibvirtInspector(virt_inspector.Inspector): super(LibvirtInspector, self).__init__(conf) # NOTE(sileht): create a connection on startup self.connection + self.cache = {} @property def connection(self): @@ -115,6 +116,29 @@ class LibvirtInspector(virt_inspector.Inspector): params['bridge'] = bridge dom_stats = domain.interfaceStats(name) + + # Retrieve previous values + prev = self.cache.get(name) + + # Store values for next call + self.cache[name] = dom_stats + + if prev: + # Compute stats + rx_delta = dom_stats[0] - prev[0] + tx_delta = dom_stats[4] - prev[4] + + # Avoid negative values + if rx_delta < 0: + rx_delta = dom_stats[0] + if tx_delta < 0: + tx_delta = dom_stats[4] + else: + LOG.debug('No delta meter predecessor for %s / %s' % + (instance.id, name)) + rx_delta = 0 + tx_delta = 0 + yield virt_inspector.InterfaceStats(name=name, mac=mac_address, fref=fref, @@ -123,10 +147,12 @@ class LibvirtInspector(virt_inspector.Inspector): rx_packets=dom_stats[1], rx_errors=dom_stats[2], rx_drop=dom_stats[3], + rx_bytes_delta=rx_delta, tx_bytes=dom_stats[4], tx_packets=dom_stats[5], tx_errors=dom_stats[6], - tx_drop=dom_stats[7]) + tx_drop=dom_stats[7], + tx_bytes_delta=tx_delta) @staticmethod def _get_disk_devices(domain): diff --git a/ceilometer/compute/virt/xenapi/inspector.py b/ceilometer/compute/virt/xenapi/inspector.py index 6fa6f53ea6..31adaacc73 100644 --- a/ceilometer/compute/virt/xenapi/inspector.py +++ b/ceilometer/compute/virt/xenapi/inspector.py @@ -141,7 +141,8 @@ class XenapiInspector(virt_inspector.Inspector): parameters=None, rx_bytes=bw_vif['bw_in'], rx_packets=-1, rx_drop=-1, rx_errors=-1, tx_bytes=bw_vif['bw_out'], tx_packets=-1, - tx_drop=-1, tx_errors=-1) + tx_drop=-1, tx_errors=-1, rx_bytes_delta=-1, + tx_bytes_delta=-1) def inspect_vnic_rates(self, instance, duration): instance_name = util.instance_name(instance) diff --git a/ceilometer/tests/unit/compute/pollsters/test_net.py b/ceilometer/tests/unit/compute/pollsters/test_net.py index 63bbe6263f..190c93df41 100644 --- a/ceilometer/tests/unit/compute/pollsters/test_net.py +++ b/ceilometer/tests/unit/compute/pollsters/test_net.py @@ -50,7 +50,8 @@ class TestNetPollster(base.TestPollsterBase): rx_bytes=1, rx_packets=2, rx_drop=20, rx_errors=21, tx_bytes=3, tx_packets=4, - tx_drop=22, tx_errors=23) + tx_drop=22, tx_errors=23, + rx_bytes_delta=42, tx_bytes_delta=43) self.vnic1 = virt_inspector.InterfaceStats( name='vnet1', @@ -63,7 +64,8 @@ class TestNetPollster(base.TestPollsterBase): rx_bytes=5, rx_packets=6, rx_drop=24, rx_errors=25, tx_bytes=7, tx_packets=8, - tx_drop=26, tx_errors=27) + tx_drop=26, tx_errors=27, + rx_bytes_delta=44, tx_bytes_delta=45) self.vnic2 = virt_inspector.InterfaceStats( name='vnet2', @@ -76,7 +78,8 @@ class TestNetPollster(base.TestPollsterBase): rx_bytes=9, rx_packets=10, rx_drop=28, rx_errors=29, tx_bytes=11, tx_packets=12, - tx_drop=30, tx_errors=31) + tx_drop=30, tx_errors=31, + rx_bytes_delta=46, tx_bytes_delta=47) vnics = [ self.vnic0, @@ -117,7 +120,7 @@ class TestNetPollster(base.TestPollsterBase): self.faux_instance = FauxInstance(**self.INSTANCE_PROPERTIES) - def _check_get_samples(self, factory, expected): + def _check_get_samples(self, factory, expected, kind='cumulative'): mgr = manager.AgentManager(0, self.CONF) pollster = factory(self.CONF) samples = list(pollster.get_samples(mgr, {}, [self.instance])) @@ -131,7 +134,7 @@ class TestNetPollster(base.TestPollsterBase): ] self.assertEqual(len(match), 1, 'missing ip %s' % ip) self.assertEqual(expected_volume, match[0].volume) - self.assertEqual('cumulative', match[0].type) + self.assertEqual(kind, match[0].type) self.assertEqual(expected_rid, match[0].resource_id) for ip, volume, rid in expected: @@ -159,6 +162,30 @@ class TestNetPollster(base.TestPollsterBase): ], ) + def test_incoming_bytes_delta(self): + instance_name_id = "%s-%s" % (self.instance.name, self.instance.id) + self._check_get_samples( + net.IncomingBytesDeltaPollster, + [('10.0.0.2', 42, self.vnic0.fref), + ('192.168.0.3', 44, self.vnic1.fref), + ('192.168.0.4', 46, + "%s-%s" % (instance_name_id, self.vnic2.name)), + ], + 'delta', + ) + + def test_outgoing_bytes_delta(self): + instance_name_id = "%s-%s" % (self.instance.name, self.instance.id) + self._check_get_samples( + net.OutgoingBytesDeltaPollster, + [('10.0.0.2', 43, self.vnic0.fref), + ('192.168.0.3', 45, self.vnic1.fref), + ('192.168.0.4', 47, + "%s-%s" % (instance_name_id, self.vnic2.name)), + ], + 'delta', + ) + def test_incoming_packets(self): instance_name_id = "%s-%s" % (self.instance.name, self.instance.id) self._check_get_samples( diff --git a/setup.cfg b/setup.cfg index 004541a89c..d71985223d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -89,6 +89,8 @@ ceilometer.poll.compute = network.outgoing.packets = ceilometer.compute.pollsters.net:OutgoingPacketsPollster network.incoming.bytes.rate = ceilometer.compute.pollsters.net:IncomingBytesRatePollster network.outgoing.bytes.rate = ceilometer.compute.pollsters.net:OutgoingBytesRatePollster + network.incoming.bytes.delta = ceilometer.compute.pollsters.net:IncomingBytesDeltaPollster + network.outgoing.bytes.delta = ceilometer.compute.pollsters.net:OutgoingBytesDeltaPollster network.incoming.packets.drop = ceilometer.compute.pollsters.net:IncomingDropPollster network.outgoing.packets.drop = ceilometer.compute.pollsters.net:OutgoingDropPollster network.incoming.packets.error = ceilometer.compute.pollsters.net:IncomingErrorsPollster