diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 7e7afb05068..a29ecb418f1 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -61,6 +61,7 @@ import java.util.regex.Pattern; import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.utils.linux.MemStat; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; @@ -463,6 +464,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected int _timeout; protected int _cmdsTimeout; protected int _stopTimeout; + private MemStat _memStat = new MemStat(); protected static final HashMap s_powerStatesTable; static { @@ -3276,28 +3278,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } double cpuUtil = (100.0D - Double.parseDouble(parser.getLine())); - long freeMem = 0; - final Script memScript = new Script("/bin/bash", 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(cmd, false, result); - } - freeMem = Long.parseLong(Memparser.getLine()); - - Script totalMem = new Script("/bin/bash", 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(cmd, false, result); - } - long totMem = Long.parseLong(totMemparser.getLine()); + _memStat.refresh(); + double totMem = _memStat.getTotal(); + double freeMem = _memStat.getAvailable(); Pair nicStats = getNicStats(_publicBridgeName); 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..c418b3c7fab --- /dev/null +++ b/plugins/hypervisors/kvm/src/org/apache/cloudstack/utils/linux/MemStat.java @@ -0,0 +1,72 @@ +// 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() { + refresh(); + } + + 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..a73071780ae --- /dev/null +++ b/plugins/hypervisors/kvm/test/org/apache/cloudstack/utils/linux/MemStatTest.java @@ -0,0 +1,55 @@ +// 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)); + } +} +