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 05F8E9507 for ; Thu, 23 May 2013 07:25:27 +0000 (UTC) Received: (qmail 41073 invoked by uid 500); 23 May 2013 07:25:18 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 40857 invoked by uid 500); 23 May 2013 07:25:16 -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 38366 invoked by uid 99); 23 May 2013 07:25:07 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 23 May 2013 07:25:07 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8151E8942AD; Thu, 23 May 2013 07:25:07 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sateesh@apache.org To: commits@cloudstack.apache.org Date: Thu, 23 May 2013 07:25:52 -0000 Message-Id: <4ef0c3059637476e98d4e5c318ddedc8@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [47/50] [abbrv] git commit: updated refs/heads/vmware-datamodel to f1a5d70 CLOUDSTACK-1963 New mapping model for CloudStack zone and Vmware datacenter Introduced 2 new API command classes AddVmwareDcCmd & RemoveVmwareDcCmd. The new APIs are addVmwareDc & removeVmwareDc, these APIs will associate a Vmware datacenter to a cloudstack zone & dis-associate a Vmware datacenter from a cloudstack zone. Constraint checks are added for infrastructure change operations in zone that encompass resources like clusters. Constraint checks are added in discoverer and manager classes. Added a service 'VmwareDatacenterService' to expose methods that will have API implementation for 2 APIs addVmwareDc & removeVmwareDc Signed-off-by: Sateesh Chodapuneedi Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/03d6a043 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/03d6a043 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/03d6a043 Branch: refs/heads/vmware-datamodel Commit: 03d6a043e42622ec7f713fd73bafaa17d60bac55 Parents: e838059 Author: Sateesh Chodapuneedi Authored: Thu May 23 12:34:19 2013 +0530 Committer: Sateesh Chodapuneedi Committed: Thu May 23 12:53:21 2013 +0530 ---------------------------------------------------------------------- .../hypervisor/vmware/VmwareDatacenterService.java | 32 ++ .../hypervisor/vmware/VmwareServerDiscoverer.java | 80 ++++- .../vmware/manager/VmwareManagerImpl.java | 282 ++++++++++++++- .../api/command/admin/zone/AddVmwareDcCmd.java | 122 +++++++ .../api/command/admin/zone/RemoveVmwareDcCmd.java | 99 +++++ .../api/response/VmwareDatacenterResponse.java | 51 +++ 6 files changed, 662 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java new file mode 100644 index 0000000..5e80e18 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java @@ -0,0 +1,32 @@ +// 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.vmware; + +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; + +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.utils.component.PluggableService; + +public interface VmwareDatacenterService extends PluggableService { + + public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws IllegalArgumentException, DiscoveryException, ResourceInUseException; + + public boolean removeVmwareDatacenter(RemoveVmwareDcCmd cmd) throws IllegalArgumentException, ResourceInUseException; +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index 2f82b53..aec44b3 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -30,6 +30,7 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.apache.cloudstack.api.ApiConstants; +import org.springframework.beans.NullValueInNestedPathException; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; @@ -51,6 +52,8 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.mo.ClusterMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -107,11 +110,16 @@ public class VmwareServerDiscoverer extends DiscovererBase implements @Inject CiscoNexusVSMDeviceDao _nexusDao; @Inject - CiscoNexusVSMElementService _nexusElement; + CiscoNexusVSMElement _nexusElement; @Inject NetworkModel _netmgr; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; + @Inject + VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao; + @Inject + VmwareDatacenterDao _vmwareDcDao; + protected Map _urlParams; protected boolean useDVS = false; protected boolean nexusDVS = false; @@ -140,6 +148,18 @@ public class VmwareServerDiscoverer extends DiscovererBase implements return null; } + Map clusterDetails = _clusterDetailsDao.findDetails(clusterId); + boolean legacyZone = false; + //Check if NOT a legacy zone. + if (!legacyZone) { + String updatedInventoryPath = validateCluster(dcId, url, username, password); + if (url.getPath() != updatedInventoryPath) { + // If url from API doesn't specifiy DC then update url in database with DC assocaited with this zone. + clusterDetails.put("url", url.getScheme() + "://" + url.getHost() + updatedInventoryPath); + _clusterDetailsDao.persist(clusterId, clusterDetails); + } + } + List hosts = _resourceMgr.listAllHostsInCluster(clusterId); if (hosts != null && hosts.size() > 0) { int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(hosts.get(0).getHypervisorType(), hosts.get(0).getHypervisorVersion()); @@ -164,7 +184,6 @@ public class VmwareServerDiscoverer extends DiscovererBase implements VmwareTrafficLabel guestTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Guest); VmwareTrafficLabel publicTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Public); - Map clusterDetails = _clusterDetailsDao.findDetails(clusterId); DataCenterVO zone = _dcDao.findById(dcId); NetworkType zoneType = zone.getNetworkType(); _readGlobalConfigParameters(); @@ -395,6 +414,63 @@ public class VmwareServerDiscoverer extends DiscovererBase implements } } + private String validateCluster(Long dcId, URI url, String username, String password) throws DiscoveryException { + String msg; + long vmwareDcId; + VmwareDatacenterVO vmwareDc; + String vmwareDcNameFromDb; + String vmwareDcNameFromApi; + String vCenterHost; + String updatedInventoryPath = url.getPath(); + String clusterName = null; + + // Check if zone is associated with DC + VmwareDatacenterZoneMapVO vmwareDcZone = _vmwareDcZoneMapDao.findByZoneId(dcId); + if (vmwareDcZone == null) { + msg = "Zone " + dcId + " is not associated with any VMware DC yet. " + + "Please add VMware DC to this zone first and then try to add clusters."; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + + // Retrieve DC added to this zone from database + vmwareDcId = vmwareDcZone.getVmwareDcId(); + vmwareDc = _vmwareDcDao.findById(vmwareDcId); + vmwareDcNameFromApi = vmwareDcNameFromDb = vmwareDc.getVmwareDatacenterName(); + vCenterHost = vmwareDc.getVcenterHost(); + String inventoryPath = url.getPath(); + + assert (inventoryPath != null); + + String[] pathTokens = inventoryPath.split("/"); + if (pathTokens.length == 2) { + // DC name is not present in url. + // Using DC name read from database. + clusterName = pathTokens[1]; + updatedInventoryPath = "/" + vmwareDcNameFromDb + "/" + clusterName; + } else if (pathTokens.length == 3) { + vmwareDcNameFromApi = pathTokens[1]; + clusterName = pathTokens[2]; + } + + if (!vCenterHost.equalsIgnoreCase(url.getHost())) { + msg = "This cluster " + clusterName + " belongs to vCenter " + url.getHost() + + " .But this zone is associated with VMware DC from vCenter " + vCenterHost + + ". Make sure the cluster being added belongs to vCenter " + vCenterHost + + " and DC " + vmwareDcNameFromDb; + s_logger.error(msg); + throw new DiscoveryException(msg); + } else if (!vmwareDcNameFromDb.equalsIgnoreCase(vmwareDcNameFromApi)) { + msg = "This cluster " + clusterName + " belongs to VMware DC " + vmwareDcNameFromApi + + " .But this zone is associated with VMware DC " + vmwareDcNameFromDb + + ". Make sure the cluster being added belongs to DC " + vmwareDcNameFromDb + + " in vCenter " + vCenterHost; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + return updatedInventoryPath; + } + private boolean validateDiscoveredHosts(VmwareContext context, ManagedObjectReference morCluster, List morHosts) throws Exception { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index 9f260f1..3718762 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,6 +36,8 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -51,15 +54,28 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVSMMapVO; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterVSMMapDao; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.DiscoveredWithErrorException; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.hypervisor.vmware.VmwareCleanupMaid; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMapVO; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; +import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO; +import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.vmware.mo.DiskControllerType; import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -68,8 +84,10 @@ import com.cloud.hypervisor.vmware.mo.TaskMO; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.hypervisor.vmware.mo.VmwareHostType; import com.cloud.utils.ssh.SshHelper; +import com.cloud.hypervisor.vmware.resource.VmwareContextFactory; import com.cloud.hypervisor.vmware.util.VmwareClient; import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.network.CiscoNexusVSMDeviceVO; import com.cloud.network.NetworkModel; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; @@ -83,11 +101,13 @@ import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.UriUtils; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SshHelper; @@ -98,8 +118,8 @@ import com.vmware.vim25.HostConnectSpec; import com.vmware.vim25.ManagedObjectReference; -@Local(value = {VmwareManager.class}) -public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener { +@Local(value = {VmwareManager.class, VmwareDatacenterService.class}) +public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService { private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class); private static final int STARTUP_DELAY = 60000; // 60 seconds @@ -124,6 +144,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Inject ConfigurationDao _configDao; @Inject ConfigurationServer _configServer; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; + @Inject DataCenterDao _dcDao; + @Inject VmwareDatacenterDao _vmwareDcDao; + @Inject VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao; String _mountParent; StorageLayer _storage; @@ -865,4 +888,259 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw public String getRootDiskController() { return _rootDiskController; } + + @Override + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddVmwareDcCmd.class); + cmdList.add(RemoveVmwareDcCmd.class); + return cmdList; + } + + @Override + @DB + public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException { + VmwareDatacenterVO vmwareDc = null; + Long zoneId = cmd.getZoneId(); + String url = cmd.getUrl(); + String userName = cmd.getUsername(); + String password = cmd.getPassword(); + String vmwareDcName = cmd.getName(); + + // Zone validation + validateZone(zoneId, "add VMware datacenter to zone"); + + VmwareDatacenterZoneMapVO vmwareDcZoneMap = _vmwareDcZoneMapDao.findByZoneId(zoneId); + // Check if zone is associated with VMware DC + if (vmwareDcZoneMap != null) { + throw new CloudRuntimeException("Zone " + zoneId + " is already associated with a VMware datacenter."); + } + + // Validate url and get uri + URI uri = getUri(url); + + // Validate username and password and DC name + if (userName == null) { + throw new InvalidParameterValueException("Invalid parameter username."); + } + + if (password == null) { + throw new InvalidParameterValueException("Invalid parameter password."); + } + + if (vmwareDcName == null) { + throw new InvalidParameterValueException("Invalid parameter name. Please provide valid VMware datacenter name."); + } + + // Check if DC is already part of zone + // In that case vmware_data_center table should have the DC + String vCenterHost = uri.getHost(); + List vmwareDcs = _vmwareDcDao.getVmwareDatacenterByNameAndVcenter(vmwareDcName, vCenterHost); + if (vmwareDcs != null && vmwareDcs.size() != 0) { + throw new ResourceInUseException("This DC is already part of other CloudStack zone(s). Cannot add this DC to more zones."); + } + + VmwareContext context = null; + DatacenterMO dcMo = null; + String dcCustomFieldValue; + boolean addDcCustomFieldDef = false; + boolean dcInUse = false; + String guid; + ManagedObjectReference dcMor; + try { + context = VmwareContextFactory.create(vCenterHost, userName, password); + + // Check if DC exists on vCenter + try { + dcMo = new DatacenterMO(context, vmwareDcName); + } catch(Throwable t) { + String msg = "Unable to find DC " + vmwareDcName + " in vCenter " + vCenterHost; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + assert (dcMo != null); + + // Check if DC is already associated with another cloudstack deployment + // Get custom field property cloud.zone over this DC + guid = vmwareDcName + "@" + vCenterHost; + + dcCustomFieldValue = dcMo.getCustomFieldValue(CustomFieldConstants.CLOUD_ZONE); + if (dcCustomFieldValue == null) { + addDcCustomFieldDef = true; + } + dcInUse = Boolean.parseBoolean(dcCustomFieldValue); + if (dcInUse) { + throw new ResourceInUseException("This DC is being managed by other CloudStack deployment. Cannot add this DC to zone."); + } + + // Add DC to database into vmware_data_center table + vmwareDc = new VmwareDatacenterVO(guid, vmwareDcName, vCenterHost, userName, password); + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + vmwareDc = _vmwareDcDao.persist(vmwareDc); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to persist VMware datacenter details to database. Exception: " + e.getMessage()); + throw new CloudRuntimeException(e.getMessage()); + } + + // Map zone with vmware datacenter + vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId()); + + txn = Transaction.currentTxn(); + try { + txn.start(); + vmwareDcZoneMap = _vmwareDcZoneMapDao.persist(vmwareDcZoneMap); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to associate VMware datacenter with zone " + zoneId + ". Exception: " + e.getMessage()); + // Removing VMware datacenter from vmware_data_center table because association with zone failed. + _vmwareDcDao.remove(vmwareDcZoneMap.getId()); + throw new CloudRuntimeException(e.getMessage()); + } + + // Set custom field for this DC + if (addDcCustomFieldDef) { + dcMo.ensureCustomFieldDef(CustomFieldConstants.CLOUD_ZONE); + } + dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "true"); + + } catch (Exception e) { + String msg = "VMware DC discovery failed due to : " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } finally { + if (context != null) + context.close(); + context = null; + } + return vmwareDc; + } + + @Override + public boolean removeVmwareDatacenter(RemoveVmwareDcCmd cmd) throws ResourceInUseException { + Long zoneId = cmd.getZoneId(); + // Validate zone + validateZone(zoneId, "remove VMware datacenter from zone"); + + // Get DC associated with this zone + VmwareDatacenterZoneMapVO vmwareDcZoneMap; + VmwareDatacenterVO vmwareDatacenter; + String vmwareDcName; + long vmwareDcId; + String vCenterHost; + String userName; + String password; + DatacenterMO dcMo = null; + Transaction txn; + + vmwareDcZoneMap = _vmwareDcZoneMapDao.findByZoneId(zoneId); + // Check if zone is associated with VMware DC + if (vmwareDcZoneMap == null) { + throw new CloudRuntimeException("Zone " + zoneId + " is not associated with any VMware datacenter."); + } + + vmwareDcId = vmwareDcZoneMap.getVmwareDcId(); + vmwareDatacenter = _vmwareDcDao.findById(vmwareDcId); + vmwareDcName = vmwareDatacenter.getVmwareDatacenterName(); + vCenterHost = vmwareDatacenter.getVcenterHost(); + userName = vmwareDatacenter.getUser(); + password = vmwareDatacenter.getPassword(); + txn = Transaction.currentTxn(); + try { + txn.start(); + // Remove the VMware datacenter entry in table vmware_data_center + _vmwareDcDao.remove(vmwareDcId); + // Remove the map entry in table vmware_data_center_zone_map + _vmwareDcZoneMapDao.remove(vmwareDcZoneMap.getId()); + txn.commit(); + } catch (Exception e) { + s_logger.info("Caught exception when trying to delete VMware datacenter record.." + e.getMessage()); + throw new CloudRuntimeException("Failed to delete VMware datacenter "); + } + + // Construct context + VmwareContext context = null; + try { + context = VmwareContextFactory.create(vCenterHost, userName, password); + + // Check if DC exists on vCenter + try { + dcMo = new DatacenterMO(context, vmwareDcName); + } catch(Throwable t) { + String msg = "able to find DC " + vmwareDcName + " in vCenter " + vCenterHost; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + + assert (dcMo != null); + + // Reset custom field property cloud.zone over this DC + dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "false"); + s_logger.info("Sucessfully reset custom field property cloud.zone over DC " + vmwareDcName); + } catch (Exception e) { + String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + + " due to : " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } finally { + if (context != null) + context.close(); + context = null; + } + return true; + } + + private void validateZone(Long zoneId, String errStr) throws ResourceInUseException { + // Check if zone with specified id exists + DataCenterVO zone = _dcDao.findById(zoneId); + if (zone == null) { + InvalidParameterValueException ex = new InvalidParameterValueException( + "Can't find zone by the id specified"); + throw ex; + } + + // Check if zone has resources? - For now look for clusters + List clusters = _clusterDao.listByZoneId(zoneId); + if (clusters != null && clusters.size() > 0) { + // Look for VMware hypervisor. + for (ClusterVO cluster : clusters) { + if (cluster.getHypervisorType().equals(HypervisorType.VMware)) { + throw new ResourceInUseException("Zone has one or more clusters." + + " Can't " + errStr + " which already has clusters."); + } + } + } + } + + private URI getUri(String url) throws InvalidParameterValueException { + if (url == null) { + throw new InvalidParameterValueException("Invalid url."); + } + + URI uri = null; + try { + uri = new URI(UriUtils.encodeURIComponent(url)); + if (uri.getScheme() == null) { + throw new InvalidParameterValueException( + "uri.scheme is null " + url + + ", add http:// as a prefix"); + } else if (uri.getScheme().equalsIgnoreCase("http")) { + if (uri.getHost() == null + || uri.getHost().equalsIgnoreCase("") + || uri.getPath() == null + || uri.getPath().equalsIgnoreCase("")) { + throw new InvalidParameterValueException( + "Your host and/or path is wrong. Make sure it's of the format http://hostname/path"); + } + } + } catch (URISyntaxException e) { + throw new InvalidParameterValueException(url + + " is not a valid uri"); + } + return uri; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java new file mode 100644 index 0000000..7168c7f --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java @@ -0,0 +1,122 @@ +// 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 org.apache.cloudstack.api.command.admin.zone; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VmwareDatacenterResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "addVmwareDc", description="Adds a VMware datacenter to specified zone", responseObject=VmwareDatacenterResponse.class) +public class AddVmwareDcCmd extends BaseCmd { + + @Inject public VmwareDatacenterService _vmwareDatacenterService; + + public static final Logger s_logger = Logger.getLogger(AddVmwareDcCmd.class.getName()); + + private static final String s_name = "addvmwaredcresponse"; + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of VMware datacenter to be added to specified zone.") + private String name; + + @Parameter(name=ApiConstants.URL, type=CommandType.STRING, required=false, description="The URL of vCenter.") + private String url; + + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required=false, description="The Username required to connect to resource.") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=false, description="The password for specified username.") + private String password; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, required=true, description="The Zone ID.") + private Long zoneId; + + public String getName() { + return name; + } + + public String getUrl() { + return url; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public Long getZoneId() { + return zoneId; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + try { + VmwareDatacenterResponse response = new VmwareDatacenterResponse(); + VmwareDatacenterVO result = _vmwareDatacenterService.addVmwareDatacenter(this); + if (result != null){ + response.setId(result.getUuid()); + response.setName(result.getVmwareDatacenterName()); + response.setResponseName(getCommandName()); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add VMware Datacenter to zone."); + } + this.setResponseObject(response); + } catch (DiscoveryException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (ResourceInUseException ex) { + s_logger.warn("Exception: ", ex); + ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + for (String proxyObj : ex.getIdProxyList()) { + e.addProxyObject(proxyObj); + } + throw e; + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } catch (CloudRuntimeException runtimeEx) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeEx.getMessage()); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java new file mode 100644 index 0000000..a74c91b --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java @@ -0,0 +1,99 @@ +// 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 org.apache.cloudstack.api.command.admin.zone; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.BaseCmd.CommandType; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.network.element.CiscoNexusVSMElementService; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "removeVmwareDc", responseObject=SuccessResponse.class, description="Remove a VMware datacenter from a zone.") +public class RemoveVmwareDcCmd extends BaseCmd { + + @Inject public VmwareDatacenterService _vmwareDatacenterService; + + public static final Logger s_logger = Logger.getLogger(AddVmwareDcCmd.class.getName()); + + private static final String s_name = "removevmwaredcresponse"; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, required=true, + description="The id of Zone from which VMware datacenter has to be removed.") + + private Long zoneId; + + public Long getZoneId() { + return zoneId; + } + + @Override + public void execute() { + SuccessResponse response = new SuccessResponse(); + try { + boolean result = _vmwareDatacenterService.removeVmwareDatacenter(this); + if (result) { + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VMware datacenter from zone"); + } + } catch (ResourceInUseException ex) { + s_logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone." + + " Please remove all resource from zone, and retry. Exception: ", ex); + ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + for (String proxyObj : ex.getIdProxyList()) { + e.addProxyObject(proxyObj); + } + throw e; + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } catch (CloudRuntimeException runtimeEx) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeEx.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/03d6a043/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java new file mode 100644 index 0000000..420320b --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java @@ -0,0 +1,51 @@ +// 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 org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.hypervisor.vmware.VmwareDatacenter; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = VmwareDatacenter.class) +public class VmwareDatacenterResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description="The VMware Datacenter ID") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description="The VMware Datacenter name") + private String name; + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public void setId(String id) { + this.id = id; + } +}