http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3StoragePool.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3StoragePool.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3StoragePool.java new file mode 100644 index 0000000..1f7726a --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3StoragePool.java @@ -0,0 +1,749 @@ +/******************************************************************************* + * 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.ovm3.resources.helpers; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.GetStorageStatsAnswer; +import com.cloud.agent.api.GetStorageStatsCommand; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; +import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin; +import com.cloud.hypervisor.ovm3.objects.Connection; +import com.cloud.hypervisor.ovm3.objects.Linux; +import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException; +import com.cloud.hypervisor.ovm3.objects.OvmObject; +import com.cloud.hypervisor.ovm3.objects.Pool; +import com.cloud.hypervisor.ovm3.objects.PoolOCFS2; +import com.cloud.hypervisor.ovm3.objects.Repository; +import com.cloud.hypervisor.ovm3.objects.StoragePlugin; +import com.cloud.hypervisor.ovm3.objects.StoragePlugin.FileProperties; +import com.cloud.hypervisor.ovm3.objects.StoragePlugin.StorageDetails; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.template.TemplateProp; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.ssh.SshHelper; + +public class Ovm3StoragePool { + private static final Logger LOGGER = Logger + .getLogger(Ovm3StoragePool.class); + private Connection c; + private Ovm3Configuration config; + private OvmObject ovmObject = new OvmObject(); + + public Ovm3StoragePool(Connection conn, Ovm3Configuration ovm3config) { + c = conn; + config = ovm3config; + } + + /** + * Setting up the roles on a host, we set all roles on all hosts! + * + * @param pool + * @throws ConfigurationException + */ + private void setRoles(Pool pool) throws ConfigurationException { + try { + pool.setServerRoles(pool.getValidRoles()); + } catch (Ovm3ResourceException e) { + String msg = "Failed to set server role for host " + + config.getAgentHostname() + ": " + e.getMessage(); + LOGGER.error(msg); + throw new ConfigurationException(msg); + } + } + + /** + * If you don't own the host you can't fiddle with it. + * + * @param pool + * @throws ConfigurationException + */ + private void takeOwnership(Pool pool) throws ConfigurationException { + try { + LOGGER.debug("Take ownership of host " + config.getAgentHostname()); + pool.takeOwnership(config.getAgentOwnedByUuid(), ""); + } catch (Ovm3ResourceException e) { + String msg = "Failed to take ownership of host " + + config.getAgentHostname(); + LOGGER.error(msg); + throw new ConfigurationException(msg); + } + } + + /** + * If you don't own the host you can't fiddle with it. + * + * @param pool + * @throws ConfigurationException + */ + /* FIXME: Placeholders for now, implement later!!!! */ + private void takeOwnership33x(Pool pool) throws ConfigurationException { + try { + LOGGER.debug("Take ownership of host " + config.getAgentHostname()); + String event = "http://localhost:10024/event"; + String stats = "http://localhost:10024/stats"; + String mgrCert = "None"; + String signCert = "None"; + pool.takeOwnership33x(config.getAgentOwnedByUuid(), + event, + stats, + mgrCert, + signCert); + } catch (Ovm3ResourceException e) { + String msg = "Failed to take ownership of host " + + config.getAgentHostname(); + LOGGER.error(msg); + throw new ConfigurationException(msg); + } + } + /** + * Prepare a host to become part of a pool, the roles and ownership are + * important here. + * + * @return + * @throws ConfigurationException + */ + public boolean prepareForPool() throws ConfigurationException { + /* need single master uuid */ + try { + Linux host = new Linux(c); + Pool pool = new Pool(c); + + /* setup pool and role, needs utility to be able to do things */ + if (host.getServerRoles().contentEquals( + pool.getValidRoles().toString())) { + LOGGER.info("Server role for host " + config.getAgentHostname() + + " is ok"); + } else { + setRoles(pool); + } + if (host.getMembershipState().contentEquals("Unowned")) { + if (host.getOvmVersion().startsWith("3.2.")) { + takeOwnership(pool); + } else if (host.getOvmVersion().startsWith("3.3.")) { + takeOwnership33x(pool); + } + } else { + if (host.getManagerUuid().equals(config.getAgentOwnedByUuid())) { + String msg = "Host " + config.getAgentHostname() + + " owned by us"; + LOGGER.debug(msg); + return true; + } else { + String msg = "Host " + config.getAgentHostname() + + " already part of a pool, and not owned by us"; + LOGGER.error(msg); + throw new ConfigurationException(msg); + } + } + } catch (ConfigurationException | Ovm3ResourceException es) { + String msg = "Failed to prepare " + config.getAgentHostname() + + " for pool: " + es.getMessage(); + LOGGER.error(msg); + throw new ConfigurationException(msg); + } + return true; + } + + /** + * Setup a pool in general, this creates a repo if it doesn't exist yet, if + * it does however we mount it. + * + * @param cmd + * @return + * @throws Ovm3ResourceException + */ + private Boolean setupPool(StorageFilerTO cmd) throws Ovm3ResourceException { + String primUuid = cmd.getUuid(); + String ssUuid = ovmObject.deDash(primUuid); + String fsType = "nfs"; + String clusterUuid = config.getAgentOwnedByUuid().substring(0, 15); + String managerId = config.getAgentOwnedByUuid(); + String poolAlias = cmd.getHost() + ":" + cmd.getPath(); + String mountPoint = String.format("%1$s:%2$s", cmd.getHost(), + cmd.getPath()) + + "/VirtualMachines"; + Integer poolSize = 0; + + Pool poolHost = new Pool(c); + PoolOCFS2 poolFs = new PoolOCFS2(c); + if (config.getAgentIsMaster()) { + try { + LOGGER.debug("Create poolfs on " + config.getAgentHostname() + + " for repo " + primUuid); + /* double check if we're not overwritting anything here!@ */ + poolFs.createPoolFs(fsType, mountPoint, clusterUuid, primUuid, + ssUuid, managerId); + } catch (Ovm3ResourceException e) { + throw e; + } + try { + poolHost.createServerPool(poolAlias, primUuid, + config.getOvm3PoolVip(), poolSize + 1, + config.getAgentHostname(), c.getIp()); + } catch (Ovm3ResourceException e) { + throw e; + } + } else if (config.getAgentHasMaster()) { + try { + poolHost.joinServerPool(poolAlias, primUuid, + config.getOvm3PoolVip(), poolSize + 1, + config.getAgentHostname(), c.getIp()); + } catch (Ovm3ResourceException e) { + throw e; + } + } + try { + /* should contain check if we're in an OVM pool or not */ + CloudstackPlugin csp = new CloudstackPlugin(c); + Boolean vip = csp.dom0CheckPort(config.getOvm3PoolVip(), 22, 60, 1); + if (!vip) { + throw new Ovm3ResourceException( + "Unable to reach Ovm3 Pool VIP " + + config.getOvm3PoolVip()); + } + /* + * should also throw exception, we need to stop pool creation here, + * or is the manual addition fine? + */ + if (!addMembers()) { + return false; + } + } catch (Ovm3ResourceException e) { + throw new Ovm3ResourceException("Unable to add members to pool" + + e.getMessage()); + } + return true; + } + + /** + * Adding members to a pool, this is seperate from cluster configuration in + * OVM. + * + * @return + * @throws Ovm3ResourceException + */ + private Boolean addMembers() throws Ovm3ResourceException { + List<String> members = new ArrayList<String>(); + try { + Connection m = new Connection(config.getOvm3PoolVip(), c.getPort(), + c.getUserName(), c.getPassword()); + Pool poolMaster = new Pool(m); + if (poolMaster.isInAPool()) { + members.addAll(poolMaster.getPoolMemberList()); + if (!poolMaster.getPoolMemberList().contains(c.getIp()) + && c.getIp().equals(config.getOvm3PoolVip())) { + members.add(c.getIp()); + } + } else { + LOGGER.warn(c.getIp() + " noticed master " + + config.getOvm3PoolVip() + " is not part of pool"); + return false; + } + /* a cluster shares usernames and passwords */ + for (String member : members) { + Connection x = new Connection(member, c.getPort(), + c.getUserName(), c.getPassword()); + Pool poolM = new Pool(x); + if (poolM.isInAPool()) { + poolM.setPoolMemberList(members); + LOGGER.debug("Added " + members + " to pool " + + poolM.getPoolId() + " on member " + member); + } else { + LOGGER.warn(member + + " unable to be member of a pool it's not in"); + return false; + } + } + } catch (Exception e) { + throw new Ovm3ResourceException("Unable to add members: " + + e.getMessage(), e); + } + return true; + } + + /** + * Get a host out of a pool/cluster, this should unmount all FSs though. + * + * @param cmd + * @return + */ + public Answer execute(DeleteStoragePoolCommand cmd) { + try { + Pool pool = new Pool(c); + pool.leaveServerPool(cmd.getPool().getUuid()); + /* also connect to the master and update the pool list ? */ + } catch (Ovm3ResourceException e) { + LOGGER.debug( + "Delete storage pool on host " + + config.getAgentHostname() + + " failed, however, we leave to user for cleanup and tell managment server it succeeded", + e); + } + + return new Answer(cmd); + } + + /** + * Create primary storage, which is a repository in OVM. Pooling is part of + * this too and clustering should be in the future. + * + * @param cmd + * @return + * @throws XmlRpcException + */ + private boolean createRepo(StorageFilerTO cmd) throws XmlRpcException { + String basePath = config.getAgentOvmRepoPath(); + Repository repo = new Repository(c); + String primUuid = repo.deDash(cmd.getUuid()); + String ovsRepo = basePath + "/" + primUuid; + /* should add port ? */ + String mountPoint = String.format("%1$s:%2$s", cmd.getHost(), + cmd.getPath()); + String msg; + + if (cmd.getType() == StoragePoolType.NetworkFilesystem) { + Boolean repoExists = false; + /* base repo first */ + try { + repo.mountRepoFs(mountPoint, ovsRepo); + } catch (Ovm3ResourceException e) { + LOGGER.debug("Unable to mount NFS repository " + mountPoint + + " on " + ovsRepo + " requested for " + + config.getAgentHostname() + ": " + e.getMessage()); + } + try { + repo.addRepo(mountPoint, ovsRepo); + repoExists = true; + } catch (Ovm3ResourceException e) { + LOGGER.debug("NFS repository " + mountPoint + " on " + ovsRepo + + " not found creating repo: " + e.getMessage()); + } + if (!repoExists) { + try { + /* + * a mount of the NFS fs by the createrepo actually + * generates a null if it is already mounted... -sigh- + */ + repo.createRepo(mountPoint, ovsRepo, primUuid, + "OVS Repository"); + } catch (Ovm3ResourceException e) { + msg = "NFS repository " + mountPoint + " on " + ovsRepo + + " create failed!"; + LOGGER.debug(msg); + throw new CloudRuntimeException(msg + " " + e.getMessage(), + e); + } + } + + /* add base pooling first */ + if (config.getAgentInOvm3Pool()) { + try { + msg = "Configuring " + config.getAgentHostname() + "(" + + config.getAgentIp() + ") for pool"; + LOGGER.debug(msg); + setupPool(cmd); + msg = "Configured host for pool"; + /* add clustering after pooling */ + if (config.getAgentInOvm3Cluster()) { + msg = "Setup " + config.getAgentHostname() + "(" + + config.getAgentIp() + ") for cluster"; + LOGGER.debug(msg); + /* setup cluster */ + /* + * From cluster.java + * configure_server_for_cluster(cluster conf, fs, mount, + * fsuuid, poolfsbaseuuid) + */ + /* create_cluster(poolfsuuid,) */ + } + } catch (Ovm3ResourceException e) { + msg = "Unable to setup pool on " + + config.getAgentHostname() + "(" + + config.getAgentIp() + ") for " + ovsRepo; + throw new CloudRuntimeException(msg + " " + e.getMessage(), + e); + } + } else { + msg = "no way dude I can't stand for this"; + LOGGER.debug(msg); + } + /* + * this is to create the .generic_fs_stamp else we're not allowed to + * create any data\disks on this thing + */ + try { + URI uri = new URI(cmd.getType() + "://" + cmd.getHost() + ":" + + +cmd.getPort() + cmd.getPath() + "/VirtualMachines"); + setupNfsStorage(uri, cmd.getUuid()); + } catch (Exception e) { + msg = "NFS mount " + mountPoint + " on " + + config.getAgentSecStoragePath() + "/" + cmd.getUuid() + + " create failed!"; + throw new CloudRuntimeException(msg + " " + e.getMessage(), e); + } + } else { + msg = "NFS repository " + mountPoint + " on " + ovsRepo + + " create failed, was type " + cmd.getType(); + LOGGER.debug(msg); + return false; + } + + try { + /* systemvm iso is imported here */ + prepareSecondaryStorageStore(ovsRepo, cmd.getUuid(), cmd.getHost()); + } catch (Exception e) { + msg = "systemvm.iso copy failed to " + ovsRepo; + LOGGER.debug(msg, e); + return false; + } + return true; + } + + /** + * Copy the systemvm.iso in if it doesn't exist or the size differs. + * + * @param storageUrl + * @param poolUuid + * @param host + */ + private void prepareSecondaryStorageStore(String storageUrl, + String poolUuid, String host) { + String mountPoint = storageUrl; + + GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm"); + try { + /* double check */ + if (config.getAgentHasMaster() && config.getAgentInOvm3Pool()) { + LOGGER.debug("Skip systemvm iso copy, leave it to the master"); + return; + } + if (lock.lock(3600)) { + try { + /* + * save src iso real name for reuse, so we don't depend on + * other happy little accidents. + */ + File srcIso = getSystemVMPatchIsoFile(); + String destPath = mountPoint + "/ISOs/"; + try { + StoragePlugin sp = new StoragePlugin(c); + FileProperties fp = sp.storagePluginGetFileInfo( + poolUuid, host, destPath + File.separator + + srcIso.getName()); + if (fp.getSize() != srcIso.getTotalSpace()) { + LOGGER.info(" System VM patch ISO file already exists: " + + srcIso.getAbsolutePath().toString() + + ", destination: " + destPath); + } + } catch (Exception e) { + LOGGER.info("Copy System VM patch ISO file to secondary storage. source ISO: " + + srcIso.getAbsolutePath() + + ", destination: " + + destPath); + try { + /* Perhaps use a key instead ? */ + SshHelper + .scpTo(c.getIp(), 22, config + .getAgentSshUserName(), null, + config.getAgentSshPassword(), + destPath, srcIso.getAbsolutePath() + .toString(), "0644"); + } catch (Exception es) { + LOGGER.error("Unexpected exception ", es); + String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + + srcIso.toString() + + ", dest location: " + + destPath; + LOGGER.error(msg); + throw new CloudRuntimeException(msg, es); + } + } + } finally { + lock.unlock(); + } + } + } finally { + lock.releaseRef(); + } + } + + /** + * The secondary storage mountpoint is a uuid based on the host combined + * with the path. + * + * @param url + * @return + * @throws Ovm3ResourceException + */ + public String setupSecondaryStorage(String url) + throws Ovm3ResourceException { + URI uri = URI.create(url); + if (uri.getHost() == null) { + throw new Ovm3ResourceException( + "Secondary storage host can not be empty!"); + } + String uuid = ovmObject.newUuid(uri.getHost() + ":" + uri.getPath()); + LOGGER.info("Secondary storage with uuid: " + uuid); + return setupNfsStorage(uri, uuid); + } + + /** + * Sets up NFS Storage + * + * @param uri + * @param uuid + * @return + * @throws Ovm3ResourceException + */ + private String setupNfsStorage(URI uri, String uuid) + throws Ovm3ResourceException { + String fsUri = "nfs"; + String msg = ""; + String mountPoint = config.getAgentSecStoragePath() + "/" + uuid; + Linux host = new Linux(c); + + Map<String, Linux.FileSystem> fsList = host.getFileSystemMap(fsUri); + Linux.FileSystem fs = fsList.get(uuid); + if (fs == null || !fs.getRemoteDir().equals(mountPoint)) { + try { + StoragePlugin sp = new StoragePlugin(c); + sp.storagePluginMountNFS(uri.getHost(), uri.getPath(), uuid, + mountPoint); + msg = "Nfs storage " + uri + " mounted on " + mountPoint; + return uuid; + } catch (Ovm3ResourceException ec) { + msg = "Nfs storage " + uri + " mount on " + mountPoint + + " FAILED " + ec.getMessage(); + LOGGER.error(msg); + throw ec; + } + } else { + msg = "NFS storage " + uri + " already mounted on " + mountPoint; + return uuid; + } + } + + /** + * Gets statistics for storage. + * + * @param cmd + * @return + */ + public GetStorageStatsAnswer execute(final GetStorageStatsCommand cmd) { + LOGGER.debug("Getting stats for: " + cmd.getStorageId()); + try { + Linux host = new Linux(c); + Linux.FileSystem fs = host.getFileSystemByUuid(cmd.getStorageId(), + "nfs"); + StoragePlugin store = new StoragePlugin(c); + String propUuid = store.deDash(cmd.getStorageId()); + String mntUuid = cmd.getStorageId(); + if (store == null || propUuid == null || mntUuid == null + || fs == null) { + String msg = "Null returned when retrieving stats for " + + cmd.getStorageId(); + LOGGER.error(msg); + return new GetStorageStatsAnswer(cmd, msg); + } + /* or is it mntUuid ish ? */ + StorageDetails sd = store.storagePluginGetFileSystemInfo(propUuid, + mntUuid, fs.getHost(), fs.getDevice()); + /* + * FIXME: cure me or kill me, this needs to trigger a reinit of + * primary storage, actually the problem is more deeprooted, as when + * the hypervisor reboots it looses partial context and needs to be + * reinitiated.... actually a full configure round... how to trigger + * that ? + */ + if ("".equals(sd.getSize())) { + String msg = "No size when retrieving stats for " + + cmd.getStorageId(); + LOGGER.debug(msg); + return new GetStorageStatsAnswer(cmd, msg); + } + long total = Long.parseLong(sd.getSize()); + long used = total - Long.parseLong(sd.getFreeSize()); + return new GetStorageStatsAnswer(cmd, total, used); + } catch (Ovm3ResourceException e) { + LOGGER.debug("GetStorageStatsCommand for " + cmd.getStorageId() + + " failed", e); + return new GetStorageStatsAnswer(cmd, e.getMessage()); + } + } + + /** + * Try to figure out where the systemvm.iso resides on the fs of the + * management server + * + * @return + */ + public File getSystemVMPatchIsoFile() { + String iso = "systemvm.iso"; + String systemVmIsoPath = Script.findScript("", "vms/" + iso); + File isoFile = null; + if (systemVmIsoPath != null) { + LOGGER.debug("found systemvm patch iso " + systemVmIsoPath); + isoFile = new File(systemVmIsoPath); + } + if (isoFile == null || !isoFile.exists()) { + String svm = "client/target/generated-webapp/WEB-INF/classes/vms/" + + iso; + LOGGER.debug("last resort for systemvm patch iso " + svm); + isoFile = new File(svm); + } + assert isoFile != null; + if (!isoFile.exists()) { + LOGGER.error("Unable to locate " + iso + " in your setup at " + + isoFile.toString()); + } + return isoFile; + } + + /** + * Create and OCFS2 filesystem (not implemented) + * + * @param pool + * @return + * @throws XmlRpcException + */ + private Boolean createOCFS2Sr(StorageFilerTO pool) throws XmlRpcException { + LOGGER.debug("OCFS2 Not implemented yet"); + return false; + } + + /** + * Gets the details of a storage pool, size etc + * + * @param cmd + * @return + */ + public Answer execute(ModifyStoragePoolCommand cmd) { + StorageFilerTO pool = cmd.getPool(); + LOGGER.debug("modifying pool " + pool); + try { + if (config.getAgentInOvm3Cluster()) { + // no native ovm cluster for now, I got to break it in horrible + // ways + } + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + createRepo(pool); + StoragePlugin store = new StoragePlugin(c); + String propUuid = store.deDash(pool.getUuid()); + String mntUuid = pool.getUuid(); + String nfsHost = pool.getHost(); + String nfsPath = pool.getPath(); + StorageDetails ss = store.storagePluginGetFileSystemInfo( + propUuid, mntUuid, nfsHost, nfsPath); + + Map<String, TemplateProp> tInfo = new HashMap<String, TemplateProp>(); + return new ModifyStoragePoolAnswer(cmd, Long.parseLong(ss + .getSize()), Long.parseLong(ss.getFreeSize()), tInfo); + } else if (pool.getType() == StoragePoolType.OCFS2) { + createOCFS2Sr(pool); + } + return new Answer(cmd, false, "The pool type: " + + pool.getType().name() + " is not supported."); + } catch (Exception e) { + LOGGER.debug("ModifyStoragePoolCommand failed", e); + return new Answer(cmd, false, e.getMessage()); + } + } + + /** + * Create the primary storage pool, should add iSCSI and OCFS2 + * + * @param cmd + * @return + */ + public Answer execute(CreateStoragePoolCommand cmd) { + StorageFilerTO pool = cmd.getPool(); + LOGGER.debug("creating pool " + pool); + try { + if (pool.getType() == StoragePoolType.NetworkFilesystem) { + createRepo(pool); + } else if (pool.getType() == StoragePoolType.IscsiLUN) { + return new Answer(cmd, false, + "iSCSI is unsupported at the moment"); + /* + * iScsi like so: getIscsiSR(conn, pool.getUuid(), + * pool.getHost(), pool.getPath(), null, null, false); + */ + } else if (pool.getType() == StoragePoolType.OCFS2) { + return new Answer(cmd, false, + "OCFS2 is unsupported at the moment"); + } else if (pool.getType() == StoragePoolType.PreSetup) { + LOGGER.warn("pre setup for pool " + pool); + } else { + return new Answer(cmd, false, "The pool type: " + + pool.getType().name() + " is not supported."); + } + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + + ", create StoragePool failed due to " + e.toString() + + " on host:" + config.getAgentHostname() + " pool: " + + pool.getHost() + pool.getPath(); + LOGGER.warn(msg, e); + return new Answer(cmd, false, msg); + } + return new Answer(cmd, true, "success"); + } + + /** + * Download from template url into primary storage ?.. is this relevant ? + * + * @param cmd + * @return + */ + public PrimaryStorageDownloadAnswer execute( + final PrimaryStorageDownloadCommand cmd) { + try { + Repository repo = new Repository(c); + String tmplturl = cmd.getUrl(); + String poolName = cmd.getPoolUuid(); + String image = repo.deDash(repo.newUuid()) + ".raw"; + + /* url to download from, image name, and repo to copy it to */ + repo.importVirtualDisk(tmplturl, image, poolName); + return new PrimaryStorageDownloadAnswer(image); + } catch (Exception e) { + LOGGER.debug("PrimaryStorageDownloadCommand failed", e); + return new PrimaryStorageDownloadAnswer(e.getMessage()); + } + } +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VirtualRoutingSupport.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VirtualRoutingSupport.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VirtualRoutingSupport.java new file mode 100644 index 0000000..72578fa --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VirtualRoutingSupport.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * 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.ovm3.resources.helpers; + +import org.apache.log4j.Logger; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.NetworkRulesSystemVmCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin; +import com.cloud.hypervisor.ovm3.objects.Connection; +import com.cloud.hypervisor.ovm3.resources.Ovm3VirtualRoutingResource; +import com.cloud.utils.ExecutionResult; + +public class Ovm3VirtualRoutingSupport { + private static final Logger LOGGER = Logger + .getLogger(Ovm3VirtualRoutingSupport.class); + private static final String CREATE = "create"; + private static final String SUCCESS = "success"; + private Connection c; + private Ovm3VirtualRoutingResource vrr; + private Ovm3Configuration config; + public Ovm3VirtualRoutingSupport(Connection conn, Ovm3Configuration ovm3config, Ovm3VirtualRoutingResource ovm3vrr) { + c = conn; + vrr = ovm3vrr; + config = ovm3config; + } + + /* copy paste, why isn't this just generic in the VirtualRoutingResource ? */ + public Answer execute(NetworkUsageCommand cmd) { + if (cmd.isForVpc()) { + return vpcNetworkUsage(cmd); + } + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Executing resource NetworkUsageCommand " + cmd); + } + if (cmd.getOption() != null && CREATE.equals(cmd.getOption())) { + String result = networkUsage(cmd.getPrivateIP(), CREATE, null); + return new NetworkUsageAnswer(cmd, result, 0L, 0L); + } + long[] stats = getNetworkStats(cmd.getPrivateIP()); + + return new NetworkUsageAnswer(cmd, "", stats[0], stats[1]); + } + + /* copy paste, why isn't this just generic in the VirtualRoutingResource ? */ + private String networkUsage(final String privateIpAddress, + final String option, final String ethName) { + String args = null; + if ("get".equals(option)) { + args = "-g"; + } else if (CREATE.equals(option)) { + args = "-c"; + } else if ("reset".equals(option)) { + args = "-r"; + } else if ("addVif".equals(option)) { + args = "-a"; + args += ethName; + } else if ("deleteVif".equals(option)) { + args = "-d"; + args += ethName; + } + ExecutionResult result = vrr.executeInVR(privateIpAddress, "netusage.sh", + args); + + if (result == null || !result.isSuccess()) { + return null; + } + + return result.getDetails(); + } + + /* copy paste, why isn't this just generic in the VirtualRoutingResource ? */ + private long[] getNetworkStats(String privateIP) { + String result = networkUsage(privateIP, "get", null); + long[] stats = new long[2]; + if (result != null) { + try { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (Long.valueOf(splitResult[i++])).longValue(); + stats[1] += (Long.valueOf(splitResult[i++])).longValue(); + } + } catch (Exception e) { + LOGGER.warn( + "Unable to parse return from script return of network usage command: " + + e.toString(), e); + } + } + return stats; + } + + /* copy paste, why isn't this just generic in the VirtualRoutingResource ? */ + private NetworkUsageAnswer vpcNetworkUsage(NetworkUsageCommand cmd) { + String privateIp = cmd.getPrivateIP(); + String option = cmd.getOption(); + String publicIp = cmd.getGatewayIP(); + + String args = "-l " + publicIp + " "; + if ("get".equals(option)) { + args += "-g"; + } else if (CREATE.equals(option)) { + args += "-c"; + String vpcCIDR = cmd.getVpcCIDR(); + args += " -v " + vpcCIDR; + } else if ("reset".equals(option)) { + args += "-r"; + } else if ("vpn".equals(option)) { + args += "-n"; + } else if ("remove".equals(option)) { + args += "-d"; + } else { + return new NetworkUsageAnswer(cmd, SUCCESS, 0L, 0L); + } + + ExecutionResult callResult = vrr.executeInVR(privateIp, "vpc_netusage.sh", + args); + + if (!callResult.isSuccess()) { + LOGGER.error("Unable to execute NetworkUsage command on DomR (" + + privateIp + + "), domR may not be ready yet. failure due to " + + callResult.getDetails()); + } + + if ("get".equals(option) || "vpn".equals(option)) { + String result = callResult.getDetails(); + if (result == null || result.isEmpty()) { + LOGGER.error(" vpc network usage get returns empty "); + } + long[] stats = new long[2]; + if (result != null) { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (Long.valueOf(splitResult[i++])).longValue(); + stats[1] += (Long.valueOf(splitResult[i++])).longValue(); + } + return new NetworkUsageAnswer(cmd, SUCCESS, stats[0], + stats[1]); + } + } + return new NetworkUsageAnswer(cmd, SUCCESS, 0L, 0L); + } + + /* + * we don't for now, gave an error on migration though.... + */ + public Answer execute(NetworkRulesSystemVmCommand cmd) { + boolean success = true; + return new Answer(cmd, success, ""); + } + + public CheckSshAnswer execute(CheckSshCommand cmd) { + String vmName = cmd.getName(); + String privateIp = cmd.getIp(); + int cmdPort = cmd.getPort(); + int interval = cmd.getInterval(); + int retries = cmd.getRetries(); + + try { + CloudstackPlugin cSp = new CloudstackPlugin(c); + if (!cSp.dom0CheckPort(privateIp, cmdPort, retries, interval)) { + String msg = "Port " + cmdPort + " not reachable for " + vmName + + ": " + config.getAgentHostname(); + LOGGER.info(msg); + return new CheckSshAnswer(cmd, msg); + } + } catch (Exception e) { + String msg = "Can not reach port " + cmdPort + " on System vm " + + vmName + ": " + config.getAgentHostname() + + " due to exception: " + e; + LOGGER.error(msg); + return new CheckSshAnswer(cmd, msg); + } + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Ping " + cmdPort + " succeeded for vm " + vmName + + ": " + config.getAgentHostname() + " " + cmd); + } + return new CheckSshAnswer(cmd); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmGuestTypes.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmGuestTypes.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmGuestTypes.java new file mode 100755 index 0000000..e2906e6 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmGuestTypes.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +// 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.ovm3.resources.helpers; + +import java.util.HashMap; +import java.util.Map; + +public class Ovm3VmGuestTypes { + /* /usr/lib64/python2.4/site-packages/agent/lib/assembly */ + private static final Map<String, String> OVMHELPERMAP = new HashMap<String, String>(); + private static final String HVM = "hvm"; + private static final String PV = "xen_pvm"; + private static final String DOMSOL = "ldoms_pvm"; + { + OVMHELPERMAP.put("Oracle Enterprise Linux 6.0 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 6.0 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.0 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.0 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.1 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.1 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.2 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.2 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.3 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.3 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.4 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.4 (64-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.5 (32-bit)", PV); + OVMHELPERMAP.put("Oracle Enterprise Linux 5.5 (64-bit)", PV); + OVMHELPERMAP.put("Other Linux (32-bit)", PV); + OVMHELPERMAP.put("Other Linux (64-bit)", PV); + OVMHELPERMAP.put("Other PV (32-bit)", PV); + OVMHELPERMAP.put("Other PV (64-bit)", PV); + OVMHELPERMAP.put("Debian GNU/Linux 7(32-bit)", PV); + OVMHELPERMAP.put("Debian GNU/Linux 7(64-bit)", PV); + OVMHELPERMAP.put("Linux HVM (32-bit)", HVM); + OVMHELPERMAP.put("Linux HVM (64-bit)", HVM); + OVMHELPERMAP.put("Dos", HVM); + OVMHELPERMAP.put("Windows 7 (32-bit)", HVM); + OVMHELPERMAP.put("Windows 7 (64-bit)", HVM); + OVMHELPERMAP.put("Windows 8 (64-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2003 (32-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2003 (64-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2008 (32-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2008 (64-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2008 R2 (64-bit)", HVM); + OVMHELPERMAP.put("Windows Server 2012 (64-bit)", HVM); + OVMHELPERMAP.put("Windows 2000 SP4 (32-bit)", HVM); + OVMHELPERMAP.put("Windows Vista (32-bit)", HVM); + OVMHELPERMAP.put("Windows XP SP2 (32-bit)", HVM); + OVMHELPERMAP.put("Windows XP SP3 (32-bit)", HVM); + OVMHELPERMAP.put("Sun Solaris 10(32-bit)", HVM); + OVMHELPERMAP.put("Sun Solaris 10(64-bit)", HVM); + OVMHELPERMAP.put("Sun Solaris 9(Experimental)", HVM); + OVMHELPERMAP.put("Sun Solaris 8(Experimental)", HVM); + OVMHELPERMAP.put("Sun Solaris 11 (32-bit)", HVM); + OVMHELPERMAP.put("Sun Solaris 11 (64-bit)", HVM); + OVMHELPERMAP.put("Sun Solaris PV (32-bit)", PV); + OVMHELPERMAP.put("Sun Solaris PV (64-bit)", PV); + OVMHELPERMAP.put("Sun Solaris Sparc (32-bit)", DOMSOL); + OVMHELPERMAP.put("Sun Solaris Sparc (64-bit)", DOMSOL); + } + + public String getOvm3GuestType(String stdType) { + return OVMHELPERMAP.get(stdType); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmSupport.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmSupport.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmSupport.java new file mode 100644 index 0000000..fcff316 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3VmSupport.java @@ -0,0 +1,475 @@ +/******************************************************************************* + * 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.ovm3.resources.helpers; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.cloudstack.storage.to.TemplateObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.cloud.agent.api.Answer; +// import com.cloud.agent.api.AttachVolumeAnswer; +// import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.PlugNicAnswer; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.UnPlugNicAnswer; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; +import com.cloud.agent.api.to.NfsTO; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.HostVO; +import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin; +import com.cloud.hypervisor.ovm3.objects.Connection; +import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException; +import com.cloud.hypervisor.ovm3.objects.OvmObject; +import com.cloud.hypervisor.ovm3.objects.Xen; +import com.cloud.hypervisor.ovm3.resources.Ovm3StorageProcessor; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.Volume; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine.State; + +public class Ovm3VmSupport { + private final Logger LOGGER = Logger.getLogger(Ovm3VmSupport.class); + private OvmObject ovmObject = new OvmObject(); + private ResourceManager resourceMgr; + private Connection c; + private Ovm3HypervisorNetwork network; + private Ovm3Configuration config; + private Ovm3HypervisorSupport hypervisor; + private Ovm3StorageProcessor processor; + private Ovm3StoragePool pool; + private final Map<String, Map<String, String>> vmStats = new ConcurrentHashMap<String, Map<String, String>>(); + public Ovm3VmSupport(Connection conn, + Ovm3Configuration ovm3config, + Ovm3HypervisorSupport ovm3hyper, + Ovm3StorageProcessor ovm3stp, + Ovm3StoragePool ovm3sp, + Ovm3HypervisorNetwork ovm3hvn) { + c = conn; + config = ovm3config; + hypervisor = ovm3hyper; + pool = ovm3sp; + processor = ovm3stp; + network = ovm3hvn; + } + public Boolean createVifs(Xen.Vm vm, VirtualMachineTO spec) + throws Ovm3ResourceException { + if (spec.getNics() != null) { + NicTO[] nics = spec.getNics(); + return createVifs(vm, nics); + } else { + LOGGER.info("No nics for vm " + spec.getName()); + return false; + } + } + + private Boolean createVifs(Xen.Vm vm, NicTO[] nics) + throws Ovm3ResourceException { + for (NicTO nic : nics) { + if (!createVif(vm, nic)) { + return false; + } + } + return true; + } + + /* should add bitrates and latency... */ + private Boolean createVif(Xen.Vm vm, NicTO nic) + throws Ovm3ResourceException { + try { + String net = network.getNetwork(nic); + if (net != null) { + LOGGER.debug("Adding vif " + nic.getDeviceId() + " " + + nic.getMac() + " " + net + " to " + vm.getVmName()); + vm.addVif(nic.getDeviceId(), net, nic.getMac()); + } else { + LOGGER.debug("Unable to add vif " + nic.getDeviceId() + + " no network for " + vm.getVmName()); + return false; + } + } catch (Exception e) { + String msg = "Unable to add vif " + nic.getType() + " for " + + vm.getVmName() + " " + e.getMessage(); + LOGGER.debug(msg); + throw new Ovm3ResourceException(msg); + } + return true; + } + private Boolean deleteVif(Xen.Vm vm, NicTO nic) + throws Ovm3ResourceException { + /* here we should use the housekeeping of VLANs/Networks etc.. + * so we can clean after the last VM is gone + */ + try { + String net = network.getNetwork(nic); + if (net != null) { + LOGGER.debug("Removing vif " + nic.getDeviceId() + " " + " " + + nic.getMac() + " " + net + " from " + vm.getVmName()); + vm.removeVif(net, nic.getMac()); + } else { + LOGGER.debug("Unable to remove vif " + nic.getDeviceId() + + " no network for " + vm.getVmName()); + return false; + } + } catch (Exception e) { + String msg = "Unable to remove vif " + nic.getType() + " for " + + vm.getVmName() + " " + e.getMessage(); + LOGGER.debug(msg); + throw new Ovm3ResourceException(msg); + } + return true; + } +/* + public AttachVolumeAnswer execute(AttachVolumeCommand cmd) { + return new AttachVolumeAnswer(cmd, "You must stop " + cmd.getVmName() + + " first, Ovm3 doesn't support hotplug datadisk"); + } +*/ + /* Migration should make sure both HVs are the same ? */ + public PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) { + VirtualMachineTO vm = cmd.getVirtualMachine(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Preparing host for migrating " + vm.getName()); + } + NicTO[] nics = vm.getNics(); + try { + for (NicTO nic : nics) { + network.getNetwork(nic); + } + hypervisor.setVmState(vm.getName(), State.Migrating); + LOGGER.debug("VM " + vm.getName() + " is in Migrating state"); + return new PrepareForMigrationAnswer(cmd); + } catch (Ovm3ResourceException e) { + LOGGER.error("Catch Exception " + e.getClass().getName() + + " prepare for migration failed due to: " + e.getMessage()); + return new PrepareForMigrationAnswer(cmd, e); + } + } + + /* do migrations of VMs in a simple way just inside a cluster for now */ + public MigrateAnswer execute(final MigrateCommand cmd) { + final String vmName = cmd.getVmName(); + String destUuid = cmd.getHostGuid(); + String destIp = cmd.getDestinationIp(); + State state = State.Error; + /* + * TODO: figure out non pooled migration, works from CLI but not from + * the agent... perhaps pause the VM and then migrate it ? for now just + * stop the VM. + */ + String msg = "Migrating " + vmName + " to " + destIp; + LOGGER.info(msg); + if (!config.getAgentInOvm3Cluster() && !config.getAgentInOvm3Pool()) { + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getRunningVmConfig(vmName); + HostVO destHost = resourceMgr.findHostByGuid(destUuid); + if (destHost == null) { + msg = "Unable to find migration target host in DB " + + destUuid + " with ip " + destIp; + LOGGER.info(msg); + return new MigrateAnswer(cmd, false, msg, null); + } + xen.stopVm(ovmObject.deDash(vm.getVmRootDiskPoolId()), + vm.getVmUuid()); + msg = destHost.toString(); + state = State.Stopping; + return new MigrateAnswer(cmd, false, msg, null); + } catch (Ovm3ResourceException e) { + msg = "Unpooled VM Migrate of " + vmName + " to " + destUuid + + " failed due to: " + e.getMessage(); + LOGGER.debug(msg, e); + return new MigrateAnswer(cmd, false, msg, null); + } finally { + /* shouldn't we just reinitialize completely as a last resort ? */ + hypervisor.setVmState(vmName, state); + } + } else { + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getRunningVmConfig(vmName); + if (vm == null) { + state = State.Stopped; + msg = vmName + " is no running on " + config.getAgentHostname(); + return new MigrateAnswer(cmd, false, msg, null); + } + /* not a storage migration!!! */ + xen.migrateVm(ovmObject.deDash(vm.getVmRootDiskPoolId()), + vm.getVmUuid(), destIp); + state = State.Stopping; + msg = "Migration of " + vmName + " successfull"; + return new MigrateAnswer(cmd, true, msg, null); + } catch (Ovm3ResourceException e) { + msg = "Pooled VM Migrate" + ": Migration of " + vmName + " to " + + destIp + " failed due to " + e.getMessage(); + LOGGER.debug(msg, e); + return new MigrateAnswer(cmd, false, msg, null); + } finally { + hypervisor.setVmState(vmName, state); + } + } + } + + /* + */ + public GetVncPortAnswer execute(GetVncPortCommand cmd) { + try { + Xen host = new Xen(c); + Xen.Vm vm = host.getRunningVmConfig(cmd.getName()); + Integer vncPort = vm.getVncPort(); + LOGGER.debug("get vnc port for " + cmd.getName() + ": " + vncPort); + return new GetVncPortAnswer(cmd, c.getIp(), vncPort); + } catch (Ovm3ResourceException e) { + LOGGER.debug("get vnc port for " + cmd.getName() + " failed", e); + return new GetVncPortAnswer(cmd, e.getMessage()); + } + } + + private VmStatsEntry getVmStat(String vmName) { + CloudstackPlugin cSp = new CloudstackPlugin(c); + Map<String, String> oldVmStats = null; + Map<String, String> newVmStats = null; + VmStatsEntry stats = new VmStatsEntry(); + try { + if (vmStats.containsKey(vmName)) { + oldVmStats = new HashMap<String, String>(); + oldVmStats.putAll(vmStats.get(vmName)); + } + newVmStats = cSp.ovsDomUStats(vmName); + } catch (Ovm3ResourceException e) { + LOGGER.info("Unable to retrieve stats from " + vmName, e); + return stats; + } + if (oldVmStats == null) { + LOGGER.debug("No old stats retrieved stats from " + vmName); + stats.setNumCPUs(1); + stats.setNetworkReadKBs(0); + stats.setNetworkWriteKBs(0); + stats.setDiskReadKBs(0); + stats.setDiskWriteKBs(0); + stats.setDiskReadIOs(0); + stats.setDiskWriteIOs(0); + stats.setCPUUtilization(0); + stats.setEntityType("vm"); + } else { + LOGGER.debug("Retrieved new stats from " + vmName); + int cpus = Integer.parseInt(newVmStats.get("vcpus")); + stats.setNumCPUs(cpus); + stats.setNetworkReadKBs(doubleMin(newVmStats.get("rx_bytes"), oldVmStats.get("rx_bytes"))); + stats.setNetworkWriteKBs(doubleMin(newVmStats.get("tx_bytes"), oldVmStats.get("tx_bytes"))); + stats.setDiskReadKBs(doubleMin(newVmStats.get("rd_bytes"), oldVmStats.get("rd_bytes"))); + stats.setDiskWriteKBs(doubleMin(newVmStats.get("rw_bytes"), oldVmStats.get("rw_bytes"))); + stats.setDiskReadIOs(doubleMin(newVmStats.get("rd_ops"), oldVmStats.get("rd_ops"))); + stats.setDiskWriteIOs(doubleMin(newVmStats.get("rw_ops"), oldVmStats.get("rw_ops"))); + Double dCpu = doubleMin(newVmStats.get("cputime"), oldVmStats.get("cputime")); + Double dTime = doubleMin(newVmStats.get("uptime"), oldVmStats.get("uptime")); + Double cpupct = dCpu / dTime * 100 * cpus; + stats.setCPUUtilization(cpupct); + stats.setEntityType("vm"); + } + ((ConcurrentHashMap<String, Map<String, String>>) vmStats).put( + vmName, newVmStats); + return stats; + } + private Double doubleMin(String x, String y) { + try { + return (Double.parseDouble(x) - Double.parseDouble(y)); + } catch (NullPointerException e) { + return 0D; + } + } + + public GetVmStatsAnswer execute(GetVmStatsCommand cmd) { + List<String> vmNames = cmd.getVmNames(); + Map<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>(); + for (String vmName : vmNames) { + VmStatsEntry e = getVmStat(vmName); + vmStatsNameMap.put(vmName, e); + } + return new GetVmStatsAnswer(cmd, + (HashMap<String, VmStatsEntry>) vmStatsNameMap); + } + + /* This is not create for us, but really start */ +/* + public boolean startVm(String repoId, String vmId) throws XmlRpcException { + Xen host = new Xen(c); + try { + if (host.getRunningVmConfig(vmId) == null) { + LOGGER.error("Create VM " + vmId + " first on " + c.getIp()); + return false; + } else { + LOGGER.info("VM " + vmId + " exists on " + c.getIp()); + } + host.startVm(repoId, vmId); + } catch (Exception e) { + LOGGER.error("Failed to start VM " + vmId + " on " + c.getIp() + + " " + e.getMessage()); + return false; + } + return true; + } +*/ + /* + * TODO: OVM already cleans stuff up, just not the extra bridges which we + * don't want right now, as we'd have to keep a state table of which vlans + * need to stay on the host!? A map with vlanid -> list-o-hosts + */ + private void cleanupNetwork(List<String> vifs) throws XmlRpcException { + /* peel out vif info for vlan stuff */ + } + + public void cleanup(Xen.Vm vm) { + try { + cleanupNetwork(vm.getVmVifs()); + } catch (XmlRpcException e) { + LOGGER.info("Clean up network for " + vm.getVmName() + " failed", e); + } + String vmName = vm.getVmName(); + /* should become a single entity */ + vmStats.remove(vmName); + } + + /* + * Add rootdisk, datadisk and iso's + */ + public Boolean createVbds(Xen.Vm vm, VirtualMachineTO spec) { + if (spec.getDisks() == null) { + LOGGER.info("No disks defined for " + vm.getVmName()); + return false; + } + for (DiskTO disk : spec.getDisks()) { + try { + if (disk.getType() == Volume.Type.ROOT) { + VolumeObjectTO vol = (VolumeObjectTO) disk.getData(); + String diskFile = processor.getVirtualDiskPath(vol.getUuid(), vol.getDataStore().getUuid()); + vm.addRootDisk(diskFile); + vm.setPrimaryPoolUuid(vol.getDataStore().getUuid()); + LOGGER.debug("Adding root disk: " + diskFile); + } else if (disk.getType() == Volume.Type.ISO) { + DataTO isoTO = disk.getData(); + if (isoTO.getPath() != null) { + TemplateObjectTO template = (TemplateObjectTO) isoTO; + DataStoreTO store = template.getDataStore(); + if (!(store instanceof NfsTO)) { + throw new CloudRuntimeException( + "unsupported protocol"); + } + NfsTO nfsStore = (NfsTO) store; + String secPoolUuid = pool.setupSecondaryStorage(nfsStore + .getUrl()); + String isoPath = config.getAgentSecStoragePath() + File.separator + + secPoolUuid + File.separator + + template.getPath(); + vm.addIso(isoPath); + /* check if secondary storage is mounted */ + LOGGER.debug("Adding ISO: " + isoPath); + } + } else if (disk.getType() == Volume.Type.DATADISK) { + VolumeObjectTO vol = (VolumeObjectTO) disk.getData(); + String diskFile = processor.getVirtualDiskPath(vol.getUuid(), vol.getDataStore().getUuid()); + vm.addDataDisk(diskFile); + LOGGER.debug("Adding data disk: " + + diskFile); + } else { + throw new CloudRuntimeException("Unknown disk type: " + + disk.getType()); + } + } catch (Exception e) { + LOGGER.debug("CreateVbds failed", e); + throw new CloudRuntimeException("Exception" + e.getMessage(), e); + } + } + return true; + } + + /** + * Implements the unplug and plug feature for Nics, the boolan decides + * to either plug (true) or unplug (false) + * + * @param nic + * @param vmName + * @param plug + * @return + */ + private Answer plugNunplugNic(NicTO nic, String vmName, Boolean plug) { + try { + Xen xen = new Xen(c); + Xen.Vm vm = xen.getVmConfig(vmName); + /* check running */ + if (vm == null) { + return new Answer(null, false, + "Unable to execute command due to missing VM"); + } + // setup the NIC in the VM config. + if (plug) { + createVif(vm, nic); + vm.setupVifs(); + } else { + deleteVif(vm, nic); + } + // execute the change + xen.configureVm(ovmObject.deDash(vm.getPrimaryPoolUuid()), + vm.getVmUuid()); + } catch (Ovm3ResourceException e) { + String msg = "Unable to execute command due to " + e.toString(); + LOGGER.debug(msg); + return new Answer(null, false, msg); + } + return new Answer(null, true, "success"); + } + /** + * PlugNicAnswer: plug a network interface into a VM + * @param cmd + * @return + */ + public PlugNicAnswer execute(PlugNicCommand cmd) { + Answer ans = plugNunplugNic(cmd.getNic(), cmd.getVmName(), true); + return new PlugNicAnswer(cmd, ans.getResult(), ans.getDetails()); + } + + /** + * UnPlugNicAnswer: remove a nic from a VM + * @param cmd + * @return + */ + public UnPlugNicAnswer execute(UnPlugNicCommand cmd) { + Answer ans = plugNunplugNic(cmd.getNic(), cmd.getVmName(), false); + return new UnPlugNicAnswer(cmd, ans.getResult(), ans.getDetails()); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/module.properties ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/module.properties b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/module.properties new file mode 100644 index 0000000..69e6469 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/module.properties @@ -0,0 +1,18 @@ +# 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. +name=ovm3-compute +parent=compute http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml new file mode 100644 index 0000000..308015e --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-compute/spring-ovm3-compute-context.xml @@ -0,0 +1,41 @@ +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + > + + <bean id="Ovm3Fencer" class="com.cloud.hypervisor.ovm3.resources.Ovm3FenceBuilder"> + <property name="name" value="Ovm3FenceBuilder" /> + </bean> + + <bean id="Ovm3Guru" class="com.cloud.hypervisor.ovm3.resources.Ovm3HypervisorGuru"> + <property name="name" value="Ovm3Guru" /> + </bean> + + <bean id="Ovm3Investigator" class="com.cloud.ha.Ovm3Investigator"> + <property name="name" value="Ovm3Investigator" /> + </bean> +</beans> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/module.properties ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/module.properties b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/module.properties new file mode 100644 index 0000000..025d4cf --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/module.properties @@ -0,0 +1,18 @@ +# 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. +name=ovm3-discoverer +parent=discoverer http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml new file mode 100644 index 0000000..a28a2fc --- /dev/null +++ b/plugins/hypervisors/ovm3/src/main/resources/META-INF/cloudstack/ovm3-discoverer/spring-ovm3-discoverer-context.xml @@ -0,0 +1,34 @@ +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + > + + <bean id="Ovm3Discoverer" class="com.cloud.hypervisor.ovm3.resources.Ovm3Discoverer"> + <property name="name" value="Ovm3Discover" /> + </bean> + +</beans> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/test/java/com/cloud/hypervisor/ovm3/objects/CloudStackPluginTest.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/ovm3/src/test/java/com/cloud/hypervisor/ovm3/objects/CloudStackPluginTest.java b/plugins/hypervisors/ovm3/src/test/java/com/cloud/hypervisor/ovm3/objects/CloudStackPluginTest.java new file mode 100644 index 0000000..87e0580 --- /dev/null +++ b/plugins/hypervisors/ovm3/src/test/java/com/cloud/hypervisor/ovm3/objects/CloudStackPluginTest.java @@ -0,0 +1,323 @@ +/******************************************************************************* + * 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.ovm3.objects; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Map; + +import org.junit.Test; + +import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin.ReturnCode; + +public class CloudStackPluginTest { + private static final String VMNAME = "test"; + String domrIp = "169.254.3.2"; + public String getDomrIp() { + return domrIp; + } + + public String getDom0Ip() { + return dom0Ip; + } + + public Integer getDomrPort() { + return domrPort; + } + + String dom0Ip = "192.168.1.64"; + Integer domrPort = 3922; + String host = "ovm-1"; + String path = "/tmp"; + String dirpath = "/tmp/testing"; + String filename = "test.txt"; + String content = "This is some content"; + String bridge = "xenbr0"; + String vncPort = "5900"; + Integer port = 8899; + Integer retries = 1; + Integer interval = 1; + Integer timeout = 120; + + ConnectionTest con = new ConnectionTest(); + CloudstackPlugin cSp = new CloudstackPlugin(con); + XmlTestResultTest results = new XmlTestResultTest(); + + String domrExecXml = "<?xml version='1.0'?>" + + "<methodResponse>" + + "<params>" + + "<param>" + + "<value><struct>" + + "<member>" + + "<name>out</name>" + + "<value><string>clearUsageRules.sh func.sh hv-kvp-daemon_3.1_amd64.deb monitorServices.py reconfigLB.sh redundant_router</string></value>" + + "</member>" + + "<member>" + + "<name>err</name>" + + "<value><string></string></value>" + + "</member>" + + "<member>" + + "<name>rc</name>" + + "<value><i8>0</i8></value>" + + "</member>" + + "</struct></value>" + + "</param>" + + "</params>" + + "</methodResponse>"; + String dom0StatsXml = "<?xml version='1.0'?>\n" + + "<methodResponse>\n" + + "<params>\n" + + "<param>\n" + + "<value><struct>\n" + + "<member>\n" + + "<name>rx</name>\n" + + "<value><string>11631523\n" + + "</string></value>\n" + + "</member>\n" + + "<member>\n" + + "<name>total</name>\n" + + "<value><string>4293918720</string></value>\n" + + "</member>\n" + + "<member>\n" + + "<name>tx</name>\n" + + "<value><string>16927399\n" + + "</string></value>\n" + + "</member>\n" + + "<member>\n" + + "<name>cpu</name>\n" + + "<value><string>1.5</string></value>\n" + + "</member>\n" + + "<member>\n" + + "<name>free</name>\n" + + "<value><string>3162505216</string></value>\n" + + "</member>\n" + + "</struct></value>\n" + + "</param>\n" + + "</params>\n" + + "</methodResponse>"; + String domuStatsXml = "<?xml version='1.0'?>" + + "<methodResponse>" + + "<params>" + + "<param>" + + "<value><struct>" + + "<member>" + + "<name>uptime</name>" + + "<value><string>862195495455</string></value>" + + "</member>" + + "<member>" + + "<name>rx_bytes</name>" + + "<value><string>52654010</string></value>" + + "</member>" + + "<member>" + + "<name>wr_ops</name>" + + "<value><string>521674</string></value>" + + "</member>" + + "<member>" + + "<name>vcpus</name>" + + "<value><string>1</string></value>" + + "</member>" + + "<member>" + + "<name>cputime</name>" + + "<value><string>295303661496</string></value>" + + "</member>" + + "<member>" + + "<name>rd_ops</name>" + + "<value><string>14790</string></value>" + + "</member>" + + "<member>" + + "<name>rd_bytes</name>" + + "<value><string>250168320</string></value>" + + "</member>" + + "<member>" + + "<name>tx_bytes</name>" + + "<value><string>161389183</string></value>" + + "</member>" + + "<member>" + + "<name>wr_bytes</name>" + + "<value><string>1604468736</string></value>" + + "</member>" + + "</struct></value>" + + "</param>" + + "</params>" + + "</methodResponse>"; + private String dom0StorageCheckXml = "<?xml version='1.0'?>" + + "<methodResponse>" + + "<params>" + + "<param>" + + "<value><array><data>" + + "<value><boolean>1</boolean></value>" + + "<value><boolean>0</boolean></value>" + + "</data></array></value>" + + "</param>" + + "</params>" + + "</methodResponse>"; + public String getDom0StorageCheckXml() { + return dom0StorageCheckXml; + } + public String getDomrExecXml() { + return domrExecXml; + } + + public String getDom0StatsXml() { + return dom0StatsXml; + } + + public String getDomuStatsXml() { + return domuStatsXml; + } + + @Test + public void testDom0CheckStorageHealthCheck() throws Ovm3ResourceException { + con.setResult(dom0StorageCheckXml); + results.basicBooleanTest(cSp.dom0CheckStorageHealthCheck("", "", "", 120, 1)); + results.basicBooleanTest(cSp.dom0CheckStorageHealthCheck(), false); + } + @Test + public void testOvsUploadFile() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsUploadFile(path, filename, content)); + } + + @Test + public void testOvsUploadSshKey() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsUploadSshKey(path, content)); + } + + @Test + public void testOvsDomrUploadFile() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsDomrUploadFile(VMNAME, path, filename, content)); + } + + @Test + public void testGetVncPort() throws Ovm3ResourceException { + con.setResult(results.getString(vncPort)); + results.basicStringTest(cSp.getVncPort(VMNAME), vncPort); + } + + @Test + public void testDom0CheckPort() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.dom0CheckPort(host, port, retries, interval)); + /* test nothing */ + con.setNull(); + results.basicBooleanTest( + cSp.dom0CheckPort(host, port, retries, interval), false); + /* for the last test we need to fake the timeout... */ + } + + @Test + public void testDom0Ip() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.dom0HasIp(dom0Ip)); + con.setResult(results.getBoolean(false)); + results.basicBooleanTest(cSp.dom0HasIp(dom0Ip), false); + } + + @Test + public void testDomrExec() throws Ovm3ResourceException { + con.setResult(domrExecXml); + ReturnCode x = cSp.domrExec(domrIp, "ls"); + assertNotNull(x); + assertEquals(x.getExit(), (Integer) 0); + assertEquals(x.getRc(), true); + assertEquals(x.getExit(), (Integer) 0); + assertNotNull(x.getStdOut()); + + /* failed */ + domrExecXml = domrExecXml.replace("<i8>0</i8>", "<i8>1</i8>"); + domrExecXml = domrExecXml.replace("<value><string></string></value>", "<value><string>Something went wrong!</string></value>"); + con.setResult(domrExecXml); + ReturnCode y = cSp.domrExec(domrIp, "ls"); + assertNotNull(y); + assertEquals(y.getRc(), false); + assertEquals(y.getExit(), (Integer) 1); + assertNotNull(x.getStdErr()); + } + + @Test + public void testOvsDom0Stats() throws Ovm3ResourceException { + con.setResult(dom0StatsXml); + Map<String, String> stats = cSp.ovsDom0Stats(bridge); + results.basicStringTest(stats.get("cpu"), "1.5"); + } + + @Test + public void TestOvsDomUStats() throws Ovm3ResourceException { + con.setResult(domuStatsXml); + Map<String, String> stats = cSp.ovsDomUStats(VMNAME); + results.basicStringTest(stats.get("cputime"), "295303661496"); + } + + @Test + public void TestDomrCheckPort() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.domrCheckPort(domrIp, domrPort)); + } + + @Test + public void TestDomrCheckSsh() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.domrCheckSsh(domrIp)); + } + + @Test + public void TestOvsControlInterface() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsControlInterface("control0", "169.254.0.1/16")); + } + + @Test + public void TestPing() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ping(host)); + } + + @Test + public void TestOvsCheckFile() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsCheckFile(filename)); + } + + @Test + public void dom0CheckStorageHealth() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.dom0CheckStorageHealth("", "", "", 120)); + con.setResult(results.getBoolean(false)); + results.basicBooleanTest(cSp.dom0CheckStorageHealth("", "", "", 120), false); + } + @Test + public void TestovsMkdirs() throws Ovm3ResourceException { + con.setResult(results.getNil()); + results.basicBooleanTest(cSp.ovsMkdirs(dirpath)); + } + @Test + public void TestovsMkdirsDirExists() throws Ovm3ResourceException { + con.setResult(results.getBoolean(true)); + results.basicBooleanTest(cSp.ovsMkdirs(dirpath), false); + } + @Test + public void TestovsMkdirs2() throws Ovm3ResourceException { + con.setResult(results.getNil()); + results.basicBooleanTest(cSp.ovsMkdirs(dirpath, 755)); + } + +}
