Repository: cloudstack Updated Branches: refs/heads/master 0c6758f91 -> c37060a1f
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 <[email protected]> Conflicts: plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/c37060a1 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/c37060a1 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/c37060a1 Branch: refs/heads/master Commit: c37060a1ffc1e63ea2f7ec01887b4c9ff5fcbb48 Parents: 0c6758f Author: Rohit Yadav <[email protected]> Authored: Fri May 22 09:25:03 2015 +0100 Committer: Rohit Yadav <[email protected]> Committed: Fri May 22 12:10:54 2015 +0100 ---------------------------------------------------------------------- .../LibvirtGetHostStatsCommandWrapper.java | 27 ++------ .../apache/cloudstack/utils/linux/MemStat.java | 71 ++++++++++++++++++++ .../cloudstack/utils/linux/MemStatTest.java | 54 +++++++++++++++ 3 files changed, 130 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c37060a1/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetHostStatsCommandWrapper.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 32bec35..198eb3b 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<GetH } final double cpuUtil = 100.0D - Double.parseDouble(parser.getLine()); - long freeMem = 0; - final Script memScript = new Script(bashScriptPath, s_logger); - memScript.add("-c"); - memScript.add("freeMem=$(free|grep cache:|awk '{print $4}');echo $freeMem"); - final OutputInterpreter.OneLineParser Memparser = new OutputInterpreter.OneLineParser(); - result = memScript.execute(Memparser); - if (result != null) { - s_logger.debug("Unable to get the host Mem state: " + result); - return new Answer(command, false, result); - } - freeMem = Long.parseLong(Memparser.getLine()); - - final Script totalMem = new Script(bashScriptPath, s_logger); - totalMem.add("-c"); - totalMem.add("free|grep Mem:|awk '{print $2}'"); - final OutputInterpreter.OneLineParser totMemparser = new OutputInterpreter.OneLineParser(); - result = totalMem.execute(totMemparser); - if (result != null) { - s_logger.debug("Unable to get the host Mem state: " + result); - return new Answer(command, false, result); - } - final long totMem = Long.parseLong(totMemparser.getLine()); + MemStat memStat = new MemStat(); + memStat.refresh(); + double totMem = memStat.getTotal(); + double freeMem = memStat.getAvailable(); final Pair<Double, Double> nicStats = libvirtComputingResource.getNicStats(libvirtComputingResource.getPublicBridgeName()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c37060a1/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java ---------------------------------------------------------------------- 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 0000000..1e3c872 --- /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<String, Double> _memStats = new HashMap<String, Double>(); + + 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+",""))); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c37060a1/plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java ---------------------------------------------------------------------- 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 0000000..5e77606 --- /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)); + } +}
