From 2c386c61ef48a7cf9b282952152ecb7cedd21977 Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Fri, 22 Mar 2013 13:50:52 +0530 Subject: [PATCH] Nexus 1000v fix --- .../vmware/VmwareServerDiscoverer.java | 15 +++ .../CiscoNexusVSMDeviceManagerImpl.java | 96 ----------------- .../network/element/CiscoNexusVSMElement.java | 100 +++++++++++++++++- .../element/CiscoNexusVSMElementService.java | 7 ++ 4 files changed, 121 insertions(+), 97 deletions(-) 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 94ba97d96a1..de6dfbe6e39 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -45,6 +45,7 @@ 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.dao.HostDao; import com.cloud.hypervisor.Hypervisor; @@ -62,6 +63,8 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.VmwareTrafficLabel; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; +import com.cloud.network.element.CiscoNexusVSMElement; +import com.cloud.network.element.CiscoNexusVSMElementService; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; import com.cloud.resource.ResourceManager; @@ -104,6 +107,8 @@ public class VmwareServerDiscoverer extends DiscovererBase implements @Inject CiscoNexusVSMDeviceDao _nexusDao; @Inject + CiscoNexusVSMElementService _nexusElement; + @Inject NetworkModel _netmgr; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; @@ -256,6 +261,16 @@ public class VmwareServerDiscoverer extends DiscovererBase implements if (guestTrafficLabel != null) { s_logger.info("Detected guest network label : " + guestTrafficLabel); } + String vsmIp = _urlParams.get("vsmipaddress"); + String vsmUser = _urlParams.get("vsmusername"); + String vsmPassword = _urlParams.get("vsmpassword"); + String clusterName = cluster.getName(); + try { + _nexusElement.validateVsmCluster(vsmIp, vsmUser, vsmPassword, clusterId, clusterName); + } catch(ResourceInUseException ex) { + DiscoveryException discEx = new DiscoveryException(ex.getLocalizedMessage() + ". The resource is " + ex.getResourceName()); + throw discEx; + } vsmCredentials = _vmwareMgr.getNexusVSMCredentialsByClusterId(clusterId); } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java index e17d99d3184..9ec64ffce9d 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/CiscoNexusVSMDeviceManagerImpl.java @@ -23,8 +23,6 @@ import javax.inject.Inject; import org.apache.log4j.Logger; import com.cloud.agent.api.StartupCommand; -import com.cloud.configuration.Config; -import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVSMMapVO; @@ -64,8 +62,6 @@ public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase { HostDetailsDao _hostDetailDao; @Inject PortProfileDao _ppDao; - @Inject - ConfigurationDao _configDao; private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class); @@ -315,96 +311,4 @@ public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase { // TODO Auto-generated method stub return null; } - - @DB - public boolean vliadateVsmCluster(String vsmIp, String vsmUser, String vsmPassword, long clusterId, String clusterName) throws ResourceInUseException { - // Check if we're associating a Cisco Nexus VSM with a vmware cluster. - if (Boolean.parseBoolean(_configDao.getValue(Config.VmwareUseNexusVSwitch.toString()))) { - - if(vsmIp != null && vsmUser != null && vsmPassword != null) { - NetconfHelper netconfClient; - try { - netconfClient = new NetconfHelper(vsmIp, vsmUser, vsmPassword); - netconfClient.disconnect(); - } catch (CloudRuntimeException e) { - String msg = "Invalid credentials supplied for user " + vsmUser + " for Cisco Nexus 1000v VSM at " + vsmIp; - s_logger.error(msg); - _clusterDao.remove(clusterId); - throw new CloudRuntimeException(msg); - } - - Transaction txn; - - // If VSM already exists and is mapped to a cluster, fail this operation. - CiscoNexusVSMDeviceVO vsm = _ciscoNexusVSMDeviceDao.getVSMbyIpaddress(vsmIp); - if(vsm != null) { - List clusterList = _clusterVSMDao.listByVSMId(vsm.getId()); - if (clusterList != null && !clusterList.isEmpty()) { - s_logger.error("Failed to add cluster: specified Nexus VSM is already associated with another cluster"); - _clusterDao.remove(clusterId); - ResourceInUseException ex = new ResourceInUseException("Failed to add cluster: specified Nexus VSM is already associated with another cluster with specified Id"); - // get clusterUuid to report error - ClusterVO cluster = _clusterDao.findById(clusterList.get(0).getClusterId()); - ex.addProxyObject(cluster.getUuid()); - throw ex; - } - } - // persist credentials to database if the VSM entry is not already in the db. - if (_ciscoNexusVSMDeviceDao.getVSMbyIpaddress(vsmIp) == null) { - vsm = new CiscoNexusVSMDeviceVO(vsmIp, vsmUser, vsmPassword); - txn = Transaction.currentTxn(); - try { - txn.start(); - vsm = _ciscoNexusVSMDeviceDao.persist(vsm); - txn.commit(); - } catch (Exception e) { - txn.rollback(); - s_logger.error("Failed to persist Cisco Nexus 1000v VSM details to database. Exception: " + e.getMessage()); - // Removing the cluster record which was added already because the persistence of Nexus VSM credentials has failed. - _clusterDao.remove(clusterId); - throw new CloudRuntimeException(e.getMessage()); - } - } - // Create a mapping between the cluster and the vsm. - vsm = _ciscoNexusVSMDeviceDao.getVSMbyIpaddress(vsmIp); - if (vsm != null) { - ClusterVSMMapVO connectorObj = new ClusterVSMMapVO(clusterId, vsm.getId()); - txn = Transaction.currentTxn(); - try { - txn.start(); - _clusterVSMDao.persist(connectorObj); - txn.commit(); - } catch (Exception e) { - txn.rollback(); - s_logger.error("Failed to associate Cisco Nexus 1000v VSM with cluster: " + clusterName + ". Exception: " + e.getMessage()); - _clusterDao.remove(clusterId); - throw new CloudRuntimeException(e.getMessage()); - } - } - } else { - String msg; - msg = "The global parameter " + Config.VmwareUseNexusVSwitch.toString() + - " is set to \"true\". Following mandatory parameters are not specified. "; - if(vsmIp == null) { - msg += "vsmipaddress: Management IP address of Cisco Nexus 1000v dvSwitch. "; - } - if(vsmUser == null) { - msg += "vsmusername: Name of a user account with admin privileges over Cisco Nexus 1000v dvSwitch. "; - } - if(vsmPassword == null) { - if(vsmUser != null) { - msg += "vsmpassword: Password of user account " + vsmUser + ". "; - } else { - msg += "vsmpassword: Password of user account with admin privileges over Cisco Nexus 1000v dvSwitch. "; - } - } - s_logger.error(msg); - // Cleaning up the cluster record as addCluster operation failed because Nexus dvSwitch credentials are supplied. - _clusterDao.remove(clusterId); - throw new CloudRuntimeException(msg); - } - return true; - } - return false; - } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java index daf7dd6bd40..e86ae23a6ba 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElement.java @@ -34,6 +34,11 @@ import com.cloud.api.commands.EnableCiscoNexusVSMCmd; import com.cloud.api.commands.DisableCiscoNexusVSMCmd; import com.cloud.api.commands.ListCiscoNexusVSMsCmd; import com.cloud.api.response.CiscoNexusVSMResponse; +import com.cloud.configuration.Config; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.ClusterVSMMapVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.ClusterVSMMapDao; import com.cloud.deploy.DeployDestination; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -55,7 +60,10 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.offering.NetworkOffering; import com.cloud.org.Cluster; +import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper; import com.cloud.utils.component.Manager; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; import com.cloud.exception.ResourceInUseException; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.server.ManagementService; @@ -66,7 +74,11 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme private static final Logger s_logger = Logger.getLogger(CiscoNexusVSMElement.class); @Inject - CiscoNexusVSMDeviceDao _vsmDao; + CiscoNexusVSMDeviceDao _vsmDao; + @Inject + ClusterDao _clusterDao; + @Inject + ClusterVSMMapDao _clusterVSMDao; @Override public Map> getCapabilities() { @@ -247,4 +259,90 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme cmdList.add(DeleteCiscoNexusVSMCmd.class); return cmdList; } + + @DB + public boolean validateVsmCluster(String vsmIp, String vsmUser, String vsmPassword, long clusterId, String clusterName) throws ResourceInUseException { + if(vsmIp != null && vsmUser != null && vsmPassword != null) { + NetconfHelper netconfClient; + try { + netconfClient = new NetconfHelper(vsmIp, vsmUser, vsmPassword); + netconfClient.disconnect(); + } catch (CloudRuntimeException e) { + String msg = "Invalid credentials supplied for user " + vsmUser + " for Cisco Nexus 1000v VSM at " + vsmIp; + s_logger.error(msg); + _clusterDao.remove(clusterId); + throw new CloudRuntimeException(msg); + } + + Transaction txn; + + // If VSM already exists and is mapped to a cluster, fail this operation. + CiscoNexusVSMDeviceVO vsm = _vsmDao.getVSMbyIpaddress(vsmIp); + if(vsm != null) { + List clusterList = _clusterVSMDao.listByVSMId(vsm.getId()); + if (clusterList != null && !clusterList.isEmpty()) { + s_logger.error("Failed to add cluster: specified Nexus VSM is already associated with another cluster"); + ResourceInUseException ex = new ResourceInUseException("Failed to add cluster: specified Nexus VSM is already associated with another cluster with specified Id"); + // get clusterUuid to report error + ClusterVO cluster = _clusterDao.findById(clusterList.get(0).getClusterId()); + ex.addProxyObject(cluster.getUuid()); + _clusterDao.remove(clusterId); + throw ex; + } + } + // persist credentials to database if the VSM entry is not already in the db. + if (_vsmDao.getVSMbyIpaddress(vsmIp) == null) { + vsm = new CiscoNexusVSMDeviceVO(vsmIp, vsmUser, vsmPassword); + txn = Transaction.currentTxn(); + try { + txn.start(); + vsm = _vsmDao.persist(vsm); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to persist Cisco Nexus 1000v VSM details to database. Exception: " + e.getMessage()); + throw new CloudRuntimeException(e.getMessage()); + } + } + // Create a mapping between the cluster and the vsm. + vsm = _vsmDao.getVSMbyIpaddress(vsmIp); + if (vsm != null) { + ClusterVSMMapVO connectorObj = new ClusterVSMMapVO(clusterId, vsm.getId()); + txn = Transaction.currentTxn(); + try { + txn.start(); + _clusterVSMDao.persist(connectorObj); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to associate Cisco Nexus 1000v VSM with cluster: " + clusterName + ". Exception: " + e.getMessage()); + _vsmDao.remove(vsm.getId()); // Removing VSM from virtual_supervisor_module table because association with cluster failed. + // Cluster would be deleted from cluster table by callee. + throw new CloudRuntimeException(e.getMessage()); + } + } + } else { + String msg; + msg = "The global parameter " + Config.VmwareUseNexusVSwitch.toString() + + " is set to \"true\". Following mandatory parameters are not specified. "; + if(vsmIp == null) { + msg += "vsmipaddress: Management IP address of Cisco Nexus 1000v dvSwitch. "; + } + if(vsmUser == null) { + msg += "vsmusername: Name of a user account with admin privileges over Cisco Nexus 1000v dvSwitch. "; + } + if(vsmPassword == null) { + if(vsmUser != null) { + msg += "vsmpassword: Password of user account " + vsmUser + ". "; + } else { + msg += "vsmpassword: Password of user account with admin privileges over Cisco Nexus 1000v dvSwitch. "; + } + } + s_logger.error(msg); + // Cleaning up the cluster record as addCluster operation failed because Nexus dvSwitch credentials are supplied. + _clusterDao.remove(clusterId); + throw new CloudRuntimeException(msg); + } + return true; + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElementService.java b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElementService.java index 1cc9fafb052..e90581ae56c 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElementService.java +++ b/plugins/hypervisors/vmware/src/com/cloud/network/element/CiscoNexusVSMElementService.java @@ -24,6 +24,7 @@ import com.cloud.api.commands.EnableCiscoNexusVSMCmd; import com.cloud.api.commands.DisableCiscoNexusVSMCmd; import com.cloud.api.commands.ListCiscoNexusVSMsCmd; import com.cloud.api.response.CiscoNexusVSMResponse; +import com.cloud.exception.ResourceInUseException; import com.cloud.network.CiscoNexusVSMDeviceVO; import com.cloud.network.CiscoNexusVSMDevice; import com.cloud.utils.component.PluggableService; @@ -68,4 +69,10 @@ public interface CiscoNexusVSMElementService extends PluggableService { * @return CiscoNexusVSMResponse */ public CiscoNexusVSMResponse createCiscoNexusVSMDetailedResponse(CiscoNexusVSMDevice vsmDeviceVO); + + /** + * Validate Cisco Nexus VSM before associating with cluster + * + */ + public boolean validateVsmCluster(String vsmIp, String vsmUser, String vsmPassword, long clusterId, String clusterName) throws ResourceInUseException; }