Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 12855106E0 for ; Wed, 11 Dec 2013 12:40:02 +0000 (UTC) Received: (qmail 13634 invoked by uid 500); 11 Dec 2013 12:39:58 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 13576 invoked by uid 500); 11 Dec 2013 12:39:53 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 13569 invoked by uid 99); 11 Dec 2013 12:39:51 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 11 Dec 2013 12:39:51 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 249E28897F5; Wed, 11 Dec 2013 12:39:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: devdeep@apache.org To: commits@cloudstack.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: git commit: updated refs/heads/master to 2b1d997 Date: Wed, 11 Dec 2013 12:39:50 +0000 (UTC) Updated Branches: refs/heads/master ab025f026 -> 2b1d99772 CLOUDSTACK-5248: Fixed creation of mount point when running as non root (cloud) user. The systemvm iso file is copied only when a systemvm or router vm is to be started on a host. The file gets copied to the secondary storage. The mount point used is the one that has permissions for regular user to mount a share. CLOUDSTACK-5275: The failure was because a secondary storage wasn't available when the host was added. When a setup is done through wizard the hosts get added before the secondary storage. CS was tying to copy yhe systemvm iso to secondary and it used to fail if it wasn't available. Made a change to copy the iso only when a systemvm is being started on a host. CLOUDSTACK-5202: Made changes to clean up mount points on stop and start. All the three are related fixes; so putting a fix in one commit. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2b1d9977 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2b1d9977 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2b1d9977 Branch: refs/heads/master Commit: 2b1d9977282f9949791a005d601955355643e35c Parents: ab025f0 Author: Devdeep Singh Authored: Wed Dec 11 17:22:45 2013 +0530 Committer: Devdeep Singh Committed: Wed Dec 11 17:50:13 2013 +0530 ---------------------------------------------------------------------- core/src/com/cloud/agent/api/SetupCommand.java | 20 - core/src/com/cloud/agent/api/StartCommand.java | 10 + .../HypervResource/HypervResourceController.cs | 50 ++- .../ServerResource/HypervResource/WmiCallsV2.cs | 5 +- .../core/spring-hyperv-core-context.xml | 32 ++ .../discoverer/HypervServerDiscoverer.java | 200 ---------- .../hyperv/manager/HypervManager.java | 24 ++ .../hyperv/manager/HypervManagerImpl.java | 367 +++++++++++++++++++ .../resource/HypervDirectConnectResource.java | 63 +++- 9 files changed, 520 insertions(+), 251 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/core/src/com/cloud/agent/api/SetupCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/SetupCommand.java b/core/src/com/cloud/agent/api/SetupCommand.java index 65700e9..ee43c59 100644 --- a/core/src/com/cloud/agent/api/SetupCommand.java +++ b/core/src/com/cloud/agent/api/SetupCommand.java @@ -23,8 +23,6 @@ public class SetupCommand extends Command { HostEnvironment env; boolean multipath; boolean needSetup; - String secondaryStorage; - String systemVmIso; public boolean needSetup() { return needSetup; @@ -38,8 +36,6 @@ public class SetupCommand extends Command { this.env = env; this.multipath = false; this.needSetup = false; - secondaryStorage = null; - systemVmIso = null; } public HostEnvironment getEnvironment() { @@ -57,22 +53,6 @@ public class SetupCommand extends Command { return multipath; } - public void setSecondaryStorage(String secondaryStorage) { - this.secondaryStorage = secondaryStorage; - } - - public String getSecondaryStorage() { - return this.secondaryStorage; - } - - public void setSystemVmIso(String systemVmIso) { - this.systemVmIso = systemVmIso; - } - - public String getSystemVmIso() { - return this.systemVmIso; - } - @Override public boolean executeInSequence() { return true; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/core/src/com/cloud/agent/api/StartCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/StartCommand.java b/core/src/com/cloud/agent/api/StartCommand.java index 308730a..88810c6 100644 --- a/core/src/com/cloud/agent/api/StartCommand.java +++ b/core/src/com/cloud/agent/api/StartCommand.java @@ -25,6 +25,7 @@ public class StartCommand extends Command { VirtualMachineTO vm; String hostIp; boolean executeInSequence = false; + String secondaryStorage; public VirtualMachineTO getVirtualMachine() { return vm; @@ -42,9 +43,18 @@ public class StartCommand extends Command { this.vm = vm; this.hostIp = host.getPrivateIpAddress(); this.executeInSequence = executeInSequence; + this.secondaryStorage = null; } public String getHostIp() { return this.hostIp; } + + public String getSecondaryStorage() { + return this.secondaryStorage; + } + + public void setSecondaryStorage(String secondary) { + this.secondaryStorage = secondary; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs index f500812..7f9e68a 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs @@ -141,7 +141,7 @@ namespace HypervResource public static HypervResourceControllerConfig config = new HypervResourceControllerConfig(); private static ILog logger = LogManager.GetLogger(typeof(HypervResourceController)); - private static string systemVmIso; + private string systemVmIso = ""; Dictionary contextMap = new Dictionary(); public static void Initialize() @@ -179,19 +179,6 @@ namespace HypervResource try { - NFSTO share = new NFSTO(); - String uriStr = (String)cmd.secondaryStorage; - share.uri = new Uri(uriStr); - - string systemVmIso = (string)cmd.systemVmIso; - string defaultDataPath = wmiCallsV2.GetDefaultDataRoot(); - string isoPath = Path.Combine(defaultDataPath, Path.GetFileName(systemVmIso)); - if (!File.Exists(isoPath)) - { - logger.Info("File " + isoPath + " not found. Copying it from the secondary share."); - Utils.DownloadCifsFileToLocalFile(systemVmIso, share, isoPath); - } - HypervResourceController.systemVmIso = isoPath; result = true; } catch (Exception sysEx) @@ -957,7 +944,40 @@ namespace HypervResource try { - wmiCallsV2.DeployVirtualMachine(cmd, systemVmIso); + string systemVmIsoPath = systemVmIso; + lock (systemVmIso) + { + systemVmIsoPath = systemVmIso; + String uriStr = (String)cmd.secondaryStorage; + if (!String.IsNullOrEmpty(uriStr)) + { + if (String.IsNullOrEmpty(systemVmIsoPath) || !File.Exists(systemVmIsoPath)) + { + NFSTO share = new NFSTO(); + share.uri = new Uri(uriStr); + string defaultDataPath = wmiCallsV2.GetDefaultDataRoot(); + + string secondaryPath = Path.Combine(share.UncPath, "systemvm").Replace(@"/", @"\"); + string[] choices = choices = Directory.GetFiles(secondaryPath, "systemvm*.iso"); + if (choices.Length != 1) + { + String errMsg = "Couldn't locate the systemvm iso on " + secondaryPath; + logger.Debug(errMsg); + } + else + { + systemVmIsoPath = Path.Combine(defaultDataPath, Path.GetFileName(choices[0])); + if (!File.Exists(systemVmIsoPath)) + { + Utils.DownloadCifsFileToLocalFile(choices[0], share, systemVmIsoPath); + } + systemVmIso = systemVmIsoPath; + } + } + } + } + + wmiCallsV2.DeployVirtualMachine(cmd, systemVmIsoPath); result = true; } catch (Exception wmiEx) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs index c6c039a..b2feab3 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs @@ -453,7 +453,10 @@ namespace HypervResource // call patch systemvm iso only for systemvms if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-")) { - patchSystemVmIso(vmName, systemVmIso); + if (systemVmIso != null && systemVmIso.Length != 0) + { + patchSystemVmIso(vmName, systemVmIso); + } } logger.DebugFormat("Starting VM {0}", vmName); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/resources/META-INF/cloudstack/core/spring-hyperv-core-context.xml ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/resources/META-INF/cloudstack/core/spring-hyperv-core-context.xml b/plugins/hypervisors/hyperv/resources/META-INF/cloudstack/core/spring-hyperv-core-context.xml new file mode 100644 index 0000000..84d50ca --- /dev/null +++ b/plugins/hypervisors/hyperv/resources/META-INF/cloudstack/core/spring-hyperv-core-context.xml @@ -0,0 +1,32 @@ + + + + + + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/discoverer/HypervServerDiscoverer.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/discoverer/HypervServerDiscoverer.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/discoverer/HypervServerDiscoverer.java index 2a630c7..2b81fa6 100644 --- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/discoverer/HypervServerDiscoverer.java +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/discoverer/HypervServerDiscoverer.java @@ -114,8 +114,6 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer private HostPodDao _podDao; @Inject private DataCenterDao _dcDao; - @Inject - DataStoreManager _dataStoreMgr; // TODO: AgentManager and AlertManager not being used to transmit info, // may want to reconsider. @@ -172,17 +170,8 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer s_logger.debug("Setting up host " + agentId); } - String secondaryStorageUri = getSecondaryStorageStoreUrl(cluster.getDataCenterId()); - if (secondaryStorageUri == null) { - s_logger.debug("Secondary storage uri for dc " + cluster.getDataCenterId() + " couldn't be obtained"); - } else { - prepareSecondaryStorageStore(secondaryStorageUri); - } - HostEnvironment env = new HostEnvironment(); SetupCommand setup = new SetupCommand(env); - setup.setSecondaryStorage(secondaryStorageUri); - setup.setSystemVmIso("systemvm/" + getSystemVMIsoFileNameOnDatastore()); if (!host.isSetup()) { setup.setNeedSetup(true); } @@ -309,7 +298,6 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer params.put("cluster", Long.toString(clusterId)); params.put("guid", guidWithTail); params.put("ipaddress", agentIp); - params.put("sec.storage.url", getSecondaryStorageStoreUrl(dcId)); // Hyper-V specific settings Map details = new HashMap(); @@ -352,175 +340,6 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer return null; } - private void prepareSecondaryStorageStore(String storageUrl) { - String mountPoint = getMountPoint(storageUrl); - - GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm"); - try { - if (lock.lock(3600)) { - try { - File patchFolder = new File(mountPoint + "/systemvm"); - if (!patchFolder.exists()) { - if (!patchFolder.mkdirs()) { - String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString(); - s_logger.error(msg); - throw new CloudRuntimeException(msg); - } - } - - File srcIso = getSystemVMPatchIsoFile(); - File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore()); - if (!destIso.exists()) { - s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " + srcIso.getAbsolutePath() + ", destination: " + - destIso.getAbsolutePath()); - try { - FileUtil.copyfile(srcIso, destIso); - } catch (IOException e) { - s_logger.error("Unexpected exception ", e); - - String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso; - s_logger.error(msg); - throw new CloudRuntimeException(msg); - } - } else { - if (s_logger.isTraceEnabled()) { - s_logger.trace("SystemVM ISO file " + destIso.getPath() + " already exists"); - } - } - } finally { - lock.unlock(); - } - } - } finally { - lock.releaseRef(); - } - } - - private String getMountPoint(String storageUrl) { - String mountPoint = null; - synchronized (_storageMounts) { - mountPoint = _storageMounts.get(storageUrl); - if (mountPoint != null) { - return mountPoint; - } - - URI uri; - try { - uri = new URI(storageUrl); - } catch (URISyntaxException e) { - s_logger.error("Invalid storage URL format ", e); - throw new CloudRuntimeException("Unable to create mount point due to invalid storage URL format " + storageUrl); - } - - mountPoint = mount(File.separator + File.separator + uri.getHost() + uri.getPath(), _mountParent, uri.getScheme(), uri.getQuery()); - if (mountPoint == null) { - s_logger.error("Unable to create mount point for " + storageUrl); - return "/mnt/sec"; - } - - _storageMounts.put(storageUrl, mountPoint); - return mountPoint; - } - } - - protected String mount(String path, String parent, String scheme, String query) { - String mountPoint = setupMountPoint(parent); - if (mountPoint == null) { - s_logger.warn("Unable to create a mount point"); - return null; - } - - Script script = null; - String result = null; - if (scheme.equals("cifs")) { - Script command = new Script(true, "mount", _timeout, s_logger); - command.add("-t", "cifs"); - command.add(path); - command.add(mountPoint); - - if (query != null) { - query = query.replace('&', ','); - command.add("-o", query); - } - result = command.execute(); - } - - if (result != null) { - s_logger.warn("Unable to mount " + path + " due to " + result); - File file = new File(mountPoint); - if (file.exists()) { - file.delete(); - } - return null; - } - - // Change permissions for the mountpoint - script = new Script(true, "chmod", _timeout, s_logger); - script.add("-R", "777", mountPoint); - result = script.execute(); - if (result != null) { - s_logger.warn("Unable to set permissions for " + mountPoint + " due to " + result); - } - return mountPoint; - } - - private String setupMountPoint(String parent) { - String mountPoint = null; - long mshostId = ManagementServerNode.getManagementServerId(); - for (int i = 0; i < 10; i++) { - String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE)); - File file = new File(mntPt); - if (!file.exists()) { - if (_storage.mkdir(mntPt)) { - mountPoint = mntPt; - break; - } - } - s_logger.error("Unable to create mount: " + mntPt); - } - - return mountPoint; - } - - private String getSystemVMIsoFileNameOnDatastore() { - String version = this.getClass().getPackage().getImplementationVersion(); - String fileName = "systemvm-" + version + ".iso"; - return fileName.replace(':', '-'); - } - - private File getSystemVMPatchIsoFile() { - // locate systemvm.iso - URL url = this.getClass().getClassLoader().getResource("vms/systemvm.iso"); - File isoFile = null; - if (url != null) { - isoFile = new File(url.getPath()); - } - - if (isoFile == null || !isoFile.exists()) { - isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso"); - } - - assert (isoFile != null); - if (!isoFile.exists()) { - s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); - } - return isoFile; - } - - private String getSecondaryStorageStoreUrl(long zoneId) { - String secUrl = null; - DataStore secStore = _dataStoreMgr.getImageStore(zoneId); - if (secStore != null) { - secUrl = secStore.getUri(); - } - - if (secUrl == null) { - s_logger.warn("Secondary storage uri couldn't be retrieved"); - } - - return secUrl; - } - /** * Encapsulate GUID calculation in public method to allow access to test * programs. Works by converting a string to a GUID using @@ -545,25 +364,6 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer @Override public final boolean configure(final String name, final Map params) throws ConfigurationException { super.configure(name, params); - - _mountParent = (String)params.get(Config.MountParent.key()); - if (_mountParent == null) { - _mountParent = File.separator + "mnt"; - } - - if (_instance != null) { - _mountParent = _mountParent + File.separator + _instance; - } - - String value = (String)params.get("scripts.timeout"); - _timeout = NumbersUtil.parseInt(value, 30) * 1000; - - _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey); - if (_storage == null) { - _storage = new JavaStorageLayer(); - _storage.configure("StorageLayer", params); - } - // TODO: allow timeout on we HTTPRequests to be configured _agentMgr.registerForHostEvents(this, true, false, true); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManager.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManager.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManager.java new file mode 100644 index 0000000..9030e29 --- /dev/null +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManager.java @@ -0,0 +1,24 @@ +// 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.hyperv.manager; + +import com.cloud.utils.component.Manager; + +public interface HypervManager extends Manager { + public String prepareSecondaryStorageStore(long zoneId); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManagerImpl.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManagerImpl.java new file mode 100644 index 0000000..f21683d --- /dev/null +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/manager/HypervManagerImpl.java @@ -0,0 +1,367 @@ +// 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.hyperv.manager; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.utils.identity.ManagementServerNode; +import org.apache.log4j.Logger; + +import com.cloud.configuration.Config; +import com.cloud.storage.JavaStorageLayer; +import com.cloud.storage.StorageLayer; +import com.cloud.utils.FileUtil; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + +@Local(value = { HypervManager.class }) +public class HypervManagerImpl implements HypervManager { + public static final Logger s_logger = Logger.getLogger(HypervManagerImpl.class); + + private String name; + private int runLevel; + private Map params; + + private int _timeout; + Random _rand = new Random(System.currentTimeMillis()); + + Map _storageMounts = new HashMap(); + StorageLayer _storage; + + @Inject ConfigurationDao _configDao; + @Inject DataStoreManager _dataStoreMgr; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + if (params != null) { + String value = (String)params.get("scripts.timeout"); + _timeout = NumbersUtil.parseInt(value, 30) * 1000; + _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey); + } + + if (_storage == null) { + _storage = new JavaStorageLayer(); + _storage.configure("StorageLayer", params); + } + + return true; + } + + @Override + public boolean start() { + startupCleanup(getMountParent()); + return true; + } + + @Override + public boolean stop() { + shutdownCleanup(); + return true; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setConfigParams(Map params) { + this.params = params; + } + + @Override + public Map getConfigParams() { + return params; + } + + @Override + public int getRunLevel() { + return runLevel; + } + + @Override + public void setRunLevel(int level) { + runLevel = level; + } + + public String prepareSecondaryStorageStore(long zoneId) { + String secondaryStorageUri = getSecondaryStorageStoreUrl(zoneId); + if (secondaryStorageUri == null) { + s_logger.debug("Secondary storage uri for dc " + zoneId + " couldn't be obtained"); + } else { + prepareSecondaryStorageStore(secondaryStorageUri); + } + + return secondaryStorageUri; + } + + private String getSecondaryStorageStoreUrl(long zoneId) { + String secUrl = null; + DataStore secStore = _dataStoreMgr.getImageStore(zoneId); + if (secStore != null) { + secUrl = secStore.getUri(); + } + + if (secUrl == null) { + s_logger.warn("Secondary storage uri couldn't be retrieved"); + } + + return secUrl; + } + + private void prepareSecondaryStorageStore(String storageUrl) { + String mountPoint = getMountPoint(storageUrl); + + GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm"); + try { + if(lock.lock(3600)) { + try { + File patchFolder = new File(mountPoint + "/systemvm"); + if(!patchFolder.exists()) { + if(!patchFolder.mkdirs()) { + String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + File srcIso = getSystemVMPatchIsoFile(); + File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore()); + if(!destIso.exists()) { + s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " + + srcIso.getAbsolutePath() + ", destination: " + destIso.getAbsolutePath()); + try { + FileUtil.copyfile(srcIso, destIso); + } catch(IOException e) { + s_logger.error("Unexpected exception ", e); + + String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso; + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } else { + if(s_logger.isTraceEnabled()) { + s_logger.trace("SystemVM ISO file " + destIso.getPath() + " already exists"); + } + } + } finally { + lock.unlock(); + } + } + } finally { + lock.releaseRef(); + } + } + + private String getMountPoint(String storageUrl) { + String mountPoint = null; + synchronized(_storageMounts) { + mountPoint = _storageMounts.get(storageUrl); + if(mountPoint != null) { + return mountPoint; + } + + URI uri; + try { + uri = new URI(storageUrl); + } catch (URISyntaxException e) { + s_logger.error("Invalid storage URL format ", e); + throw new CloudRuntimeException("Unable to create mount point due to invalid storage URL format " + storageUrl); + } + + mountPoint = mount(File.separator + File.separator + uri.getHost() + uri.getPath(), getMountParent(), + uri.getScheme(), uri.getQuery()); + if(mountPoint == null) { + s_logger.error("Unable to create mount point for " + storageUrl); + return "/mnt/sec"; + } + + _storageMounts.put(storageUrl, mountPoint); + return mountPoint; + } + } + + protected String mount(String path, String parent, String scheme, String query) { + String mountPoint = setupMountPoint(parent); + if (mountPoint == null) { + s_logger.warn("Unable to create a mount point"); + return null; + } + + Script script = null; + String result = null; + if (scheme.equals("cifs")) { + Script command = new Script(true, "mount", _timeout, s_logger); + command.add("-t", "cifs"); + command.add(path); + command.add(mountPoint); + + if (query != null) { + query = query.replace('&', ','); + command.add("-o", query); + } + result = command.execute(); + } + + if (result != null) { + s_logger.warn("Unable to mount " + path + " due to " + result); + File file = new File(mountPoint); + if (file.exists()) { + file.delete(); + } + return null; + } + + // Change permissions for the mountpoint + script = new Script(true, "chmod", _timeout, s_logger); + script.add("-R", "777", mountPoint); + result = script.execute(); + if (result != null) { + s_logger.warn("Unable to set permissions for " + mountPoint + " due to " + result); + } + return mountPoint; + } + + private String setupMountPoint(String parent) { + String mountPoint = null; + long mshostId = ManagementServerNode.getManagementServerId(); + for (int i = 0; i < 10; i++) { + String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE)); + File file = new File(mntPt); + if (!file.exists()) { + if (_storage.mkdir(mntPt)) { + mountPoint = mntPt; + break; + } + } + s_logger.error("Unable to create mount: " + mntPt); + } + + return mountPoint; + } + + private String getSystemVMIsoFileNameOnDatastore() { + String version = this.getClass().getPackage().getImplementationVersion(); + String fileName = "systemvm-" + version + ".iso"; + return fileName.replace(':', '-'); + } + + private File getSystemVMPatchIsoFile() { + // locate systemvm.iso + URL url = this.getClass().getClassLoader().getResource("vms/systemvm.iso"); + File isoFile = null; + if (url != null) { + isoFile = new File(url.getPath()); + } + + if(isoFile == null || !isoFile.exists()) { + isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso"); + } + + assert(isoFile != null); + if(!isoFile.exists()) { + s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); + } + return isoFile; + } + + private String getMountParent() { + String mountParent = _configDao.getValue(Config.MountParent.key()); + if (mountParent == null) { + mountParent = File.separator + "mnt"; + } + + String instance = _configDao.getValue(Config.InstanceName.key()); + if (instance == null) { + instance = "DEFAULT"; + } + + if (instance != null) { + mountParent = mountParent + File.separator + instance; + } + + return mountParent; + } + + private void startupCleanup(String parent) { + s_logger.info("Cleanup mounted mount points used in previous session"); + + long mshostId = ManagementServerNode.getManagementServerId(); + + // cleanup left-over NFS mounts from previous session + String[] mounts = _storage.listFiles(parent + File.separator + String.valueOf(mshostId) + ".*"); + if(mounts != null && mounts.length > 0) { + for(String mountPoint : mounts) { + s_logger.info("umount NFS mount from previous session: " + mountPoint); + + String result = null; + Script command = new Script(true, "umount", _timeout, s_logger); + command.add(mountPoint); + result = command.execute(); + if (result != null) { + s_logger.warn("Unable to umount " + mountPoint + " due to " + result); + } + File file = new File(mountPoint); + if (file.exists()) { + file.delete(); + } + } + } + } + + private void shutdownCleanup() { + s_logger.info("Cleanup mounted mount points used in current session"); + + for(String mountPoint : _storageMounts.values()) { + s_logger.info("umount NFS mount: " + mountPoint); + + String result = null; + Script command = new Script(true, "umount", _timeout, s_logger); + command.add(mountPoint); + result = command.execute(); + if (result != null) { + s_logger.warn("Unable to umount " + mountPoint + " due to " + result); + } + File file = new File(mountPoint); + if (file.exists()) { + file.delete(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2b1d9977/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java index f61e5ff..6c4babd 100644 --- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java @@ -28,7 +28,9 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import javax.annotation.PostConstruct; import javax.ejb.Local; +import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.http.HttpResponse; @@ -57,6 +59,7 @@ import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupRoutingCommand.VmState; @@ -91,9 +94,11 @@ import com.cloud.agent.api.to.FirewallRuleTO; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.hyperv.manager.HypervManager; import com.cloud.network.HAProxyConfigurator; import com.cloud.network.LoadBalancerConfigurator; import com.cloud.network.Networks.RouterPrivateIpStrategy; @@ -105,7 +110,9 @@ import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SshHelper; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineName; +import com.google.gson.Gson; /** * Implementation of dummy resource to be returned from discoverer. @@ -137,6 +144,15 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S private String _username; private String _password; + private static HypervManager s_hypervMgr; + @Inject HypervManager _hypervMgr; + + @PostConstruct + void init() { + s_hypervMgr = _hypervMgr; + } + + @Override public final Type getType() { return Type.Routing; @@ -367,9 +383,23 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S } else if (clazz == CheckS2SVpnConnectionsCommand.class) { answer = execute((CheckS2SVpnConnectionsCommand)cmd); } else if (clazz == SetStaticRouteCommand.class) { - answer = execute((SetStaticRouteCommand)cmd); + answer = execute((SetStaticRouteCommand) cmd); } else { - // Else send the cmd to hyperv agent. + if (clazz == StartCommand.class) { + VirtualMachineTO vmSpec = ((StartCommand)cmd).getVirtualMachine(); + if (vmSpec.getType() != VirtualMachine.Type.User) { + if (s_hypervMgr != null) { + String secondary = s_hypervMgr.prepareSecondaryStorageStore(Long.parseLong(_zoneId)); + if (secondary != null) { + ((StartCommand)cmd).setSecondaryStorage(secondary); + } + } else { + s_logger.error("Hyperv manager isn't available. Couldn't check and copy the systemvm iso."); + } + } + } + + // Send the cmd to hyperv agent. String ansStr = postHttpRequest(s_gson.toJson(cmd), agentUri); if (ansStr == null) { return Answer.createUnsupportedCommandAnswer(cmd); @@ -1576,19 +1606,22 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S @Override public final boolean configure(final String name, final Map params) throws ConfigurationException { /* todo: update, make consistent with the xen server equivalent. */ - _guid = (String)params.get("guid"); - _zoneId = (String)params.get("zone"); - _podId = (String)params.get("pod"); - _clusterId = (String)params.get("cluster"); - _agentIp = (String)params.get("ipaddress"); // was agentIp - _name = name; - - _clusterGuid = (String)params.get("cluster.guid"); - _username = (String)params.get("url"); - _password = (String)params.get("password"); - _username = (String)params.get("username"); - - _configureCalled = true; + + if (params != null) { + _guid = (String) params.get("guid"); + _zoneId = (String) params.get("zone"); + _podId = (String) params.get("pod"); + _clusterId = (String) params.get("cluster"); + _agentIp = (String) params.get("ipaddress"); // was agentIp + _name = name; + + _clusterGuid = (String) params.get("cluster.guid"); + _username = (String) params.get("url"); + _password = (String) params.get("password"); + _username = (String) params.get("username"); + _configureCalled = true; + } + return true; }