From f51885a9732c84d3b91d049ae5fe995d9296795e Mon Sep 17 00:00:00 2001 From: Cian O'Driscoll Date: Tue, 31 Jul 2012 10:29:42 +0000 Subject: Implements volume usage metering. Add volume usage cache tables to record no. of reads, bytes read, no. of write, bytes written to a volume. A periodic task runs in compute manager to query each volume mounted on a compute host and record its usage, this task also send a volume.usage notification contains volume usage statistics Part of blueprint volume-usage-metering Change-Id: I215ce0c94e9ea5a07e18940802c20d1379b8f6d1 --- nova/virt/driver.py | 5 +++++ nova/virt/fake.py | 7 +++++++ nova/virt/libvirt/driver.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/driver.py b/nova/virt/driver.py index ee775bc6b..005012c7f 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -251,6 +251,11 @@ class ComputeDriver(object): running VM""" raise NotImplementedError() + def get_all_volume_usage(self, context, compute_host_bdms): + """Return usage info for volumes attached to vms on + a given host""" + raise NotImplementedError() + def get_host_ip_addr(self): """ Retrieves the IP address of the dom0 diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 9f5956b0d..fb1ed5558 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -248,6 +248,13 @@ class FakeDriver(driver.ComputeDriver): bw = [] return bw + def get_all_volume_usage(self, context, instances, start_time, + stop_time=None): + """Return usage info for volumes attached to vms on + a given host""" + volusage = [] + return volusage + def block_stats(self, instance_name, disk_id): return [0L, 0L, 0L, 0L, None] diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index b39fd773b..8cc79614e 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -2190,12 +2190,50 @@ class LibvirtDriver(driver.ComputeDriver): # data format needs to be standardized across drivers return jsonutils.dumps(cpu_info) + def get_all_volume_usage(self, context, compute_host_bdms): + """Return usage info for volumes attached to vms on + a given host""" + vol_usage = [] + + for instance_bdms in compute_host_bdms: + instance = instance_bdms['instance'] + + for bdm in instance_bdms['instance_bdms']: + vol_stats = [] + mountpoint = bdm['device_name'] + if mountpoint.startswith('/dev/'): + mountpoint = mountpoint[5:] + + LOG.debug(_("Trying to get stats for the volume %s"), + bdm['volume_id']) + vol_stats = self.block_stats(instance['name'], mountpoint) + + if vol_stats: + rd_req, rd_bytes, wr_req, wr_bytes, flush_ops = vol_stats + vol_usage.append(dict(volume=bdm['volume_id'], + instance_id=instance['id'], + rd_req=rd_req, + rd_bytes=rd_bytes, + wr_req=wr_req, + wr_bytes=wr_bytes, + flush_operations=flush_ops)) + return vol_usage + def block_stats(self, instance_name, disk): """ Note that this function takes an instance name. """ - domain = self._lookup_by_name(instance_name) - return domain.blockStats(disk) + try: + domain = self._lookup_by_name(instance_name) + return domain.blockStats(disk) + except libvirt.libvirtError as e: + errcode = e.get_error_code() + LOG.info(_("Getting block stats failed, device might have " + "been detached. Code=%(errcode)s Error=%(e)s") + % locals()) + except exception.InstanceNotFound: + LOG.info(_("Could not find domain in libvirt for instance %s. " + "Cannot get block stats for device") % instance_name) def interface_stats(self, instance_name, interface): """ -- cgit