From c37060a1ffc1e63ea2f7ec01887b4c9ff5fcbb48 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 22 May 2015 09:25:03 +0100 Subject: [PATCH] CLOUDSTACK-8338: Fix hypervisor stats reporting for KVM on EL7 EL7 has a different output to 'free', use /proc/meminfo instead of a tool to be more consistent across distros (cherry picked from commit 212a05a345aa19cd2597b7ff5d6a1da7b35b9fc1) Signed-off-by: Rohit Yadav Conflicts: plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java --- .../LibvirtGetHostStatsCommandWrapper.java | 27 ++----- .../cloudstack/utils/linux/MemStat.java | 71 +++++++++++++++++++ .../cloudstack/utils/linux/MemStatTest.java | 54 ++++++++++++++ 3 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java create mode 100644 plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java index 32bec3535b2..198eb3b24da 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.java @@ -19,6 +19,7 @@ package com.cloud.hypervisor.kvm.resource.wrapper; +import org.apache.cloudstack.utils.linux.MemStat; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -55,28 +56,10 @@ public final class LibvirtGetHostStatsCommandWrapper extends CommandWrapper nicStats = libvirtComputingResource.getNicStats(libvirtComputingResource.getPublicBridgeName()); diff --git a/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java b/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java new file mode 100644 index 00000000000..1e3c872c353 --- /dev/null +++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.utils.linux; + +import java.util.HashMap; +import java.util.Map; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; + +public class MemStat { + protected final static String MEMINFO_FILE = "/proc/meminfo"; + protected final static String FREE_KEY = "MemFree"; + protected final static String CACHE_KEY = "Cached"; + protected final static String TOTAL_KEY = "MemTotal"; + + private Map _memStats = new HashMap(); + + public MemStat() { + } + + public Double getTotal() { + return _memStats.get(TOTAL_KEY); + } + + public Double getAvailable() { + return getFree() + getCache(); + } + + public Double getFree() { + return _memStats.get(FREE_KEY); + } + + public Double getCache() { + return _memStats.get(CACHE_KEY); + } + + public void refresh() { + try { + Scanner fileScanner = new Scanner(new File(MEMINFO_FILE)); + parseFromScanner(fileScanner); + } catch (FileNotFoundException ex) { + throw new RuntimeException("File " + MEMINFO_FILE + " not found:" + ex.toString()); + } + } + + protected void parseFromScanner(Scanner scanner) { + scanner.useDelimiter("\\n"); + while(scanner.hasNext()) { + String[] stats = scanner.next().split("\\:\\s+"); + if (stats.length == 2) { + _memStats.put(stats[0], Double.valueOf(stats[1].replaceAll("\\s+\\w+",""))); + } + } + } +} diff --git a/plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java b/plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java new file mode 100644 index 00000000000..5e77606d36e --- /dev/null +++ b/plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.utils.linux; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Scanner; + +public class MemStatTest { + @Test + public void getMemInfoParseTest() { + String memInfo = "MemTotal: 5830236 kB\n" + + "MemFree: 156752 kB\n" + + "Buffers: 326836 kB\n" + + "Cached: 2606764 kB\n" + + "SwapCached: 0 kB\n" + + "Active: 4260808 kB\n" + + "Inactive: 949392 kB\n"; + + MemStat memStat = null; + try { + memStat = new MemStat(); + } catch (RuntimeException ex) { + // If test isn't run on linux we'll fail creation of linux-specific MemStat class due + // to dependency on /proc/meminfo if we don't catch here. + // We are really only interested in testing the parsing algorithm and getters. + if (memStat == null) { + throw ex; + } + } + Scanner scanner = new Scanner(memInfo); + memStat.parseFromScanner(scanner); + + Assert.assertEquals(memStat.getTotal(), Double.valueOf(5830236)); + Assert.assertEquals(memStat.getAvailable(), Double.valueOf(2763516)); + Assert.assertEquals(memStat.getFree(), Double.valueOf(156752)); + Assert.assertEquals(memStat.getCache(), Double.valueOf(2606764)); + } +}