Package com.cloud.network

Source Code of com.cloud.network.CiscoNexusVSMDeviceManagerImpl

// 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.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.configuration.Config;
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.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;
    @Inject
    ConfigurationDao _configDao;
   
    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;
    }
   
    @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<ClusterVSMMapVO> 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");
                        ex.addProxyObject("cluster", clusterList.get(0).getClusterId(), "clusterId");
                        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;
    }
}
TOP

Related Classes of com.cloud.network.CiscoNexusVSMDeviceManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.