// Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. // reserves all rights not expressly granted by 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. // // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.network; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import com.cloud.agent.api.StartupCommand; import com.cloud.api.ApiConstants; import com.cloud.dc.ClusterDetailsDao; 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.exception.InvalidParameterValueException; import com.cloud.host.DetailVO; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.resource.ResourceManager; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; import com.cloud.network.dao.PortProfileDao; import com.cloud.exception.ResourceInUseException; import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper; public abstract class CiscoNexusVSMDeviceManagerImpl extends AdapterBase { @Inject CiscoNexusVSMDeviceDao _ciscoNexusVSMDeviceDao; @Inject ClusterDao _clusterDao; @Inject ClusterVSMMapDao _clusterVSMDao; @Inject ResourceManager _resourceMgr; @Inject VmwareManager _vmwareMgr; @Inject ClusterDetailsDao _clusterDetailsDao; @Inject HostDetailsDao _hostDetailDao; @Inject PortProfileDao _ppDao; private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class); @DB //public CiscoNexusVSMDeviceVO addCiscoNexusVSM(long clusterId, String ipaddress, String username, String password, ServerResource resource, String vsmName) { public CiscoNexusVSMDeviceVO addCiscoNexusVSM(long clusterId, String ipaddress, String username, String password, String vCenterIpaddr, String vCenterDcName) { // In this function, we associate this VSM with each host // in the clusterId specified. // First check if the cluster is of type vmware. If not, // throw an exception. VSMs are tightly integrated with vmware clusters. ClusterVO cluster = _clusterDao.findById(clusterId); if (cluster == null) { throw new InvalidParameterValueException("Cluster with specified ID not found!"); } if (cluster.getHypervisorType() != HypervisorType.VMware) { InvalidParameterValueException ex = new InvalidParameterValueException("Cluster with specified id is not a VMWare hypervisor cluster"); throw ex; } // Next, check if the cluster already has a VSM associated with it. // If so, throw an exception disallowing this operation. The user must first // delete the current VSM and then only attempt to add the new one. if (_clusterVSMDao.findByClusterId(clusterId) != null) { // We can't have two VSMs for the same cluster. Throw exception. throw new InvalidParameterValueException("Cluster with specified id already has a VSM tied to it. Please remove that first and retry the operation."); } // TODO: Confirm whether we should be checking for VSM reachability here. // Next, check if this VSM is reachable. Use the XML-RPC VSM API Java bindings to talk to // the VSM. //NetconfHelper (String ip, String username, String password) NetconfHelper netconfClient; try { netconfClient = new NetconfHelper(ipaddress, username, password); } catch(CloudRuntimeException e) { String msg = "Failed to connect to Nexus VSM " + ipaddress + " with credentials of user " + username; s_logger.error(msg); throw new CloudRuntimeException(msg); } // Disconnect from the VSM. A VSM has a default of 8 maximum parallel connections that it allows. netconfClient.disconnect(); // Now, go ahead and associate the cluster with this VSM. // First, check if VSM already exists in the table "virtual_supervisor_module". // If it's not there already, create it. // If it's there already, return success. // TODO - Right now, we only check if the ipaddress matches for both requests. // We must really check whether every field of the VSM matches. Anyway, the // advantage of our approach for now is that existing infrastructure using // the existing VSM won't be affected if the new request to add the VSM // assumed different information on the VSM (mgmt vlan, username, password etc). CiscoNexusVSMDeviceVO VSMObj; try { VSMObj = _ciscoNexusVSMDeviceDao.getVSMbyIpaddress(ipaddress); } catch (Exception e) { throw new CloudRuntimeException(e.getMessage()); } if (VSMObj == null) { // Create the VSM record. For now, we aren't using the vsmName field. VSMObj = new CiscoNexusVSMDeviceVO(ipaddress, username, password); Transaction txn = Transaction.currentTxn(); try { txn.start(); _ciscoNexusVSMDeviceDao.persist(VSMObj); txn.commit(); } catch (Exception e) { txn.rollback(); throw new CloudRuntimeException(e.getMessage()); } } // At this stage, we have a VSM record for sure. Connect the VSM to the cluster Id. long vsmId = _ciscoNexusVSMDeviceDao.getVSMbyIpaddress(ipaddress).getId(); ClusterVSMMapVO connectorObj = new ClusterVSMMapVO(clusterId, vsmId); Transaction txn = Transaction.currentTxn(); try { txn.start(); _clusterVSMDao.persist(connectorObj); txn.commit(); } catch (Exception e) { txn.rollback(); throw new CloudRuntimeException(e.getMessage()); } // Now, get a list of all the ESXi servers in this cluster. // This is effectively a select * from host where cluster_id=clusterId; // All ESXi servers are stored in the host table, and their resource // type is vmwareresource. //List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(clusterId); //TODO: Activate the code below if we make the Nexus VSM a separate resource. // Iterate through each of the hosts in this list. Each host has a host id. // Given this host id, we can reconfigure the in-memory resource representing // the host via the agent manager. Thus we inject VSM related information // into each host's resource. Also, we first configure each resource's // entries in the database to contain this VSM information before the injection. //for (HostVO host : hosts) { // Create a host details VO object and write it out for this hostid. //Long hostid = new Long(vsmId); //DetailVO vsmDetail = new DetailVO(host.getId(), "vsmId", hostid.toString()); //Transaction tx = Transaction.currentTxn(); //try { //tx.start(); //_hostDetailDao.persist(vsmDetail); //tx.commit(); //} catch (Exception e) { //tx.rollback(); //throw new CloudRuntimeException(e.getMessage()); //} //} // Reconfigure the resource. //Map hostDetails = new HashMap<String, String>(); //hostDetails.put(ApiConstants.ID, vsmId); //hostDetails.put(ApiConstants.IP_ADDRESS, ipaddress); //hostDetails.put(ApiConstants.USERNAME, username); //hostDetails.put(ApiConstants.PASSWORD, password); //_agentMrg.send(host.getId(), ) return VSMObj; } @DB public boolean deleteCiscoNexusVSM(long vsmId) throws ResourceInUseException { CiscoNexusVSMDeviceVO cisconexusvsm = _ciscoNexusVSMDeviceDao.findById(vsmId); if (cisconexusvsm == null) { // This entry is already not present. Return success. return true; } // First, check whether this VSM is part of any non-empty cluster. // Search ClusterVSMMap's table for a list of clusters using this vsmId. List<ClusterVSMMapVO> clusterList = _clusterVSMDao.listByVSMId(vsmId); if (clusterList != null) { for (ClusterVSMMapVO record : clusterList) { // If this cluster id has any hosts in it, fail this operation. Long clusterId = record.getClusterId(); List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(clusterId); if (hosts != null && hosts.size() > 0) { for (Host host: hosts) { if (host.getType() == Host.Type.Routing) { s_logger.info("Non-empty cluster with id" + clusterId + "still has a host that uses this VSM. Please empty the cluster first"); throw new ResourceInUseException("Non-empty cluster with id" + clusterId + "still has a host that uses this VSM. Please empty the cluster first"); } } } } } // Iterate through the cluster list again, this time, delete the VSM. Transaction txn = Transaction.currentTxn(); try { txn.start(); // Remove the VSM entry in CiscoNexusVSMDeviceVO's table. _ciscoNexusVSMDeviceDao.remove(vsmId); // Remove the current record as well from ClusterVSMMapVO's table. _clusterVSMDao.removeByVsmId(vsmId); // There are no hosts at this stage in the cluster, so we don't need // to notify any resources or remove host details. txn.commit(); } catch (Exception e) { s_logger.info("Caught exception when trying to delete VSM record.." + e.getMessage()); throw new CloudRuntimeException("Failed to delete VSM"); } return true; } @DB public CiscoNexusVSMDeviceVO enableCiscoNexusVSM(long vsmId) { CiscoNexusVSMDeviceVO cisconexusvsm = _ciscoNexusVSMDeviceDao.findById(vsmId); if (cisconexusvsm == null) { throw new InvalidParameterValueException("Invalid vsm Id specified"); } // Else, check if this db record shows that this VSM is enabled or not. if (cisconexusvsm.getvsmDeviceState() == CiscoNexusVSMDeviceVO.VSMDeviceState.Disabled) { // it's currently disabled. So change it to enabled and write it out to the db. cisconexusvsm.setVsmDeviceState(CiscoNexusVSMDeviceVO.VSMDeviceState.Enabled); Transaction txn = Transaction.currentTxn(); try { txn.start(); _ciscoNexusVSMDeviceDao.persist(cisconexusvsm); txn.commit(); } catch (Exception e) { txn.rollback(); throw new CloudRuntimeException(e.getMessage()); } } return cisconexusvsm; } @DB public CiscoNexusVSMDeviceVO disableCiscoNexusVSM(long vsmId) { CiscoNexusVSMDeviceVO cisconexusvsm = _ciscoNexusVSMDeviceDao.findById(vsmId); if (cisconexusvsm == null) { throw new InvalidParameterValueException("Invalid vsm Id specified"); } // Else, check if this db record shows that this VSM is enabled or not. if (cisconexusvsm.getvsmDeviceState() == CiscoNexusVSMDeviceVO.VSMDeviceState.Enabled) { // it's currently disabled. So change it to enabled and write it out to the db. cisconexusvsm.setVsmDeviceState(CiscoNexusVSMDeviceVO.VSMDeviceState.Disabled); Transaction txn = Transaction.currentTxn(); try { txn.start(); _ciscoNexusVSMDeviceDao.persist(cisconexusvsm); txn.commit(); } catch (Exception e) { txn.rollback(); throw new CloudRuntimeException(e.getMessage()); } } return cisconexusvsm; } @DB public CiscoNexusVSMDeviceVO getCiscoVSMbyVSMId(long vsmId) { return _ciscoNexusVSMDeviceDao.findById(vsmId); } @DB public CiscoNexusVSMDeviceVO getCiscoVSMbyClusId(long clusterId) { ClusterVSMMapVO mapVO = _clusterVSMDao.findByClusterId(clusterId); if (mapVO == null) { s_logger.info("Couldn't find a VSM associated with the specified cluster Id"); return null; } // Else, pull out the VSM associated with the VSM id in mapVO. CiscoNexusVSMDeviceVO result = _ciscoNexusVSMDeviceDao.findById(mapVO.getVsmId()); return result; } public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { // TODO Auto-generated method stub return null; } }