// 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 // with 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 com.cloud.hypervisor.kvm.resource; import java.io.File; import org.apache.log4j.Logger; import org.libvirt.LibvirtException; import org.libvirt.StoragePool; import org.libvirt.StoragePoolInfo; import org.libvirt.StoragePoolInfo.StoragePoolState; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.OutputInterpreter.AllLinesParser; import com.cloud.utils.script.Script; public class KVMHABase { private static final Logger s_logger = Logger.getLogger(KVMHABase.class); private long _timeout = 60000; /* 1 minutes */ protected static String s_heartBeatPath; protected long _heartBeatUpdateTimeout = 60000; protected long _heartBeatUpdateFreq = 60000; protected long _heartBeatUpdateMaxRetry = 3; public static enum PoolType { PrimaryStorage, SecondaryStorage } public static class NfsStoragePool { String _poolUUID; String _poolIp; String _poolMountSourcePath; String _mountDestPath; PoolType _type; public NfsStoragePool(String poolUUID, String poolIp, String poolSourcePath, String mountDestPath, PoolType type) { _poolUUID = poolUUID; _poolIp = poolIp; _poolMountSourcePath = poolSourcePath; _mountDestPath = mountDestPath; _type = type; } } protected String checkingMountPoint(NfsStoragePool pool, String poolName) { String mountSource = pool._poolIp + ":" + pool._poolMountSourcePath; String mountPaths = Script.runSimpleBashScript("cat /proc/mounts | grep " + mountSource); String destPath = pool._mountDestPath; if (mountPaths != null) { String token[] = mountPaths.split(" "); String mountType = token[2]; String mountDestPath = token[1]; if (mountType.equalsIgnoreCase("nfs")) { if (poolName != null && !mountDestPath.startsWith(destPath)) { /* we need to mount it under poolName */ Script mount = new Script("/bin/bash", 60000); mount.add("-c"); mount.add("mount " + mountSource + " " + destPath); String result = mount.execute(); if (result != null) { destPath = null; } destroyVMs(destPath); } else if (poolName == null) { destPath = mountDestPath; } } } else { /* Can't find the mount point? */ /* we need to mount it under poolName */ if (poolName != null) { Script mount = new Script("/bin/bash", 60000); mount.add("-c"); mount.add("mount " + mountSource + " " + destPath); String result = mount.execute(); if (result != null) { destPath = null; } destroyVMs(destPath); } } return destPath; } protected String getMountPoint(NfsStoragePool storagePool) { StoragePool pool = null; String poolName = null; try { pool = LibvirtConnection.getConnection().storagePoolLookupByUUIDString(storagePool._poolUUID); if (pool != null) { StoragePoolInfo spi = pool.getInfo(); if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) { pool.create(0); } else { /* * Sometimes, the mount point is lost, even libvirt thinks * the storage pool still running */ } poolName = pool.getName(); } } catch (LibvirtException e) { s_logger.debug("Ignoring libvirt error.", e); } finally { try { if (pool != null) { pool.free(); } } catch (LibvirtException e) { s_logger.debug("Ignoring libvirt error.", e); } } return checkingMountPoint(storagePool, poolName); } protected void destroyVMs(String mountPath) { /* if there are VMs using disks under this mount path, destroy them */ Script cmd = new Script("/bin/bash", _timeout); cmd.add("-c"); cmd.add("ps axu|grep qemu|grep " + mountPath + "* |awk '{print $2}'"); AllLinesParser parser = new OutputInterpreter.AllLinesParser(); String result = cmd.execute(parser); if (result != null) { return; } String pids[] = parser.getLines().split("\n"); for (String pid : pids) { Script.runSimpleBashScript("kill -9 " + pid); } } protected String getHBFile(String mountPoint, String hostIP) { return mountPoint + File.separator + "KVMHA" + File.separator + "hb-" + hostIP; } protected String getHBFolder(String mountPoint) { return mountPoint + File.separator + "KVMHA" + File.separator; } protected String runScriptRetry(String cmdString, OutputInterpreter interpreter) { String result = null; for (int i = 0; i < 3; i++) { Script cmd = new Script("/bin/bash", _timeout); cmd.add("-c"); cmd.add(cmdString); if (interpreter != null) result = cmd.execute(interpreter); else { result = cmd.execute(); } if (result == Script.ERR_TIMEOUT) { continue; } else if (result == null) { break; } } return result; } }