private VmwareTrafficLabel getTrafficInfo(
      TrafficType trafficType,
      String zoneWideTrafficLabel,
      VirtualSwitchType defaultVirtualSwitchType,
      String vSwitchType,
      String vSwitchName,
      Long clusterId) {
    VmwareTrafficLabel trafficLabelObj = null;
    Map<String, String> clusterDetails = null;
    try {
      trafficLabelObj =
          new VmwareTrafficLabel(zoneWideTrafficLabel, trafficType, defaultVirtualSwitchType);
    } catch (InvalidParameterValueException e) {
      s_logger.error(
          "Failed to recognize virtual switch type specified for "
              + trafficType
              + " traffic due to "
              + e.getMessage());
      throw e;
    }

    if (defaultVirtualSwitchType.equals(VirtualSwitchType.StandardVirtualSwitch)
        || (vSwitchType == null && vSwitchName == null)) {
      // Case of no cluster level override configuration defined.
      // Depend only on zone wide traffic label
      // If global param for dvSwitch is false return default traffic info object with vmware
      // standard vswitch
      return trafficLabelObj;
    } else {
      // Need to persist cluster level override configuration to db
      clusterDetails = _clusterDetailsDao.findDetails(clusterId);
    }

    if (vSwitchName != null) {
      trafficLabelObj.setVirtualSwitchName(vSwitchName);
      if (trafficType == TrafficType.Guest) {
        clusterDetails.put(ApiConstants.VSWITCH_NAME_GUEST_TRAFFIC, vSwitchName);
      } else {
        clusterDetails.put(ApiConstants.VSWITCH_NAME_PUBLIC_TRAFFIC, vSwitchName);
      }
    }

    if (vSwitchType != null) {
      validateVswitchType(vSwitchType);
      trafficLabelObj.setVirtualSwitchType(VirtualSwitchType.getType(vSwitchType));
      if (trafficType == TrafficType.Guest) {
        clusterDetails.put(ApiConstants.VSWITCH_TYPE_GUEST_TRAFFIC, vSwitchType);
      } else {
        clusterDetails.put(ApiConstants.VSWITCH_TYPE_PUBLIC_TRAFFIC, vSwitchType);
      }
    }

    // Save cluster level override configuration to cluster details
    _clusterDetailsDao.persist(clusterId, clusterDetails);

    return trafficLabelObj;
  }
  @DB
  private void updateClusterNativeHAState(Host host, StartupCommand cmd) {
    ClusterVO cluster = _clusterDao.findById(host.getClusterId());
    if (cluster.getClusterType() == ClusterType.ExternalManaged) {
      if (cmd instanceof StartupRoutingCommand) {
        StartupRoutingCommand hostStartupCmd = (StartupRoutingCommand) cmd;
        Map<String, String> details = hostStartupCmd.getHostDetails();

        if (details.get("NativeHA") != null && details.get("NativeHA").equalsIgnoreCase("true")) {
          _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "true");
        } else {
          _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "false");
        }
      }
    }
  }
  @Override
  protected HashMap<String, Object> buildConfigParams(HostVO host) {
    HashMap<String, Object> params = super.buildConfigParams(host);

    Map<String, String> clusterDetails = _clusterDetailsDao.findDetails(host.getClusterId());
    // Get zone wide traffic labels from guest traffic and public traffic
    String guestTrafficLabel =
        _netmgr.getDefaultGuestTrafficLabel(host.getDataCenterId(), HypervisorType.VMware);
    String publicTrafficLabel =
        _netmgr.getDefaultPublicTrafficLabel(host.getDataCenterId(), HypervisorType.VMware);
    _readGlobalConfigParameters();
    VirtualSwitchType defaultVirtualSwitchType = getDefaultVirtualSwitchType();

    params.put(
        "guestTrafficInfo",
        getTrafficInfo(
            TrafficType.Guest, guestTrafficLabel, clusterDetails, defaultVirtualSwitchType));
    params.put(
        "publicTrafficInfo",
        getTrafficInfo(
            TrafficType.Public, publicTrafficLabel, clusterDetails, defaultVirtualSwitchType));

    return params;
  }
  // TODO: Get rid of this case once we've determined that the capacity listeners above have all the
  // changes
  // create capacity entries if none exist for this server
  private void createCapacityEntry(StartupCommand startup, HostVO server) {
    SearchCriteria<CapacityVO> capacitySC = _capacityDao.createSearchCriteria();
    capacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, server.getId());
    capacitySC.addAnd("dataCenterId", SearchCriteria.Op.EQ, server.getDataCenterId());
    capacitySC.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId());

    if (startup instanceof StartupRoutingCommand) {
      SearchCriteria<CapacityVO> capacityCPU = _capacityDao.createSearchCriteria();
      capacityCPU.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, server.getId());
      capacityCPU.addAnd("dataCenterId", SearchCriteria.Op.EQ, server.getDataCenterId());
      capacityCPU.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId());
      capacityCPU.addAnd("capacityType", SearchCriteria.Op.EQ, CapacityVO.CAPACITY_TYPE_CPU);
      List<CapacityVO> capacityVOCpus = _capacityDao.search(capacitySC, null);
      Float cpuovercommitratio =
          Float.parseFloat(
              _clusterDetailsDao
                  .findDetail(server.getClusterId(), "cpuOvercommitRatio")
                  .getValue());
      Float memoryOvercommitRatio =
          Float.parseFloat(
              _clusterDetailsDao
                  .findDetail(server.getClusterId(), "memoryOvercommitRatio")
                  .getValue());

      if (capacityVOCpus != null && !capacityVOCpus.isEmpty()) {
        CapacityVO CapacityVOCpu = capacityVOCpus.get(0);
        long newTotalCpu =
            (long)
                (server.getCpus().longValue() * server.getSpeed().longValue() * cpuovercommitratio);
        if ((CapacityVOCpu.getTotalCapacity() <= newTotalCpu)
            || ((CapacityVOCpu.getUsedCapacity() + CapacityVOCpu.getReservedCapacity())
                <= newTotalCpu)) {
          CapacityVOCpu.setTotalCapacity(newTotalCpu);
        } else if ((CapacityVOCpu.getUsedCapacity() + CapacityVOCpu.getReservedCapacity()
                > newTotalCpu)
            && (CapacityVOCpu.getUsedCapacity() < newTotalCpu)) {
          CapacityVOCpu.setReservedCapacity(0);
          CapacityVOCpu.setTotalCapacity(newTotalCpu);
        } else {
          s_logger.debug(
              "What? new cpu is :"
                  + newTotalCpu
                  + ", old one is "
                  + CapacityVOCpu.getUsedCapacity()
                  + ","
                  + CapacityVOCpu.getReservedCapacity()
                  + ","
                  + CapacityVOCpu.getTotalCapacity());
        }
        _capacityDao.update(CapacityVOCpu.getId(), CapacityVOCpu);
      } else {
        CapacityVO capacity =
            new CapacityVO(
                server.getId(),
                server.getDataCenterId(),
                server.getPodId(),
                server.getClusterId(),
                0L,
                (long) (server.getCpus().longValue() * server.getSpeed().longValue()),
                CapacityVO.CAPACITY_TYPE_CPU);
        _capacityDao.persist(capacity);
      }

      SearchCriteria<CapacityVO> capacityMem = _capacityDao.createSearchCriteria();
      capacityMem.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, server.getId());
      capacityMem.addAnd("dataCenterId", SearchCriteria.Op.EQ, server.getDataCenterId());
      capacityMem.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId());
      capacityMem.addAnd("capacityType", SearchCriteria.Op.EQ, CapacityVO.CAPACITY_TYPE_MEMORY);
      List<CapacityVO> capacityVOMems = _capacityDao.search(capacityMem, null);

      if (capacityVOMems != null && !capacityVOMems.isEmpty()) {
        CapacityVO CapacityVOMem = capacityVOMems.get(0);
        long newTotalMem = (long) ((server.getTotalMemory()) * memoryOvercommitRatio);
        if (CapacityVOMem.getTotalCapacity() <= newTotalMem
            || (CapacityVOMem.getUsedCapacity() + CapacityVOMem.getReservedCapacity()
                <= newTotalMem)) {
          CapacityVOMem.setTotalCapacity(newTotalMem);
        } else if (CapacityVOMem.getUsedCapacity() + CapacityVOMem.getReservedCapacity()
                > newTotalMem
            && CapacityVOMem.getUsedCapacity() < newTotalMem) {
          CapacityVOMem.setReservedCapacity(0);
          CapacityVOMem.setTotalCapacity(newTotalMem);
        } else {
          s_logger.debug(
              "What? new cpu is :"
                  + newTotalMem
                  + ", old one is "
                  + CapacityVOMem.getUsedCapacity()
                  + ","
                  + CapacityVOMem.getReservedCapacity()
                  + ","
                  + CapacityVOMem.getTotalCapacity());
        }
        _capacityDao.update(CapacityVOMem.getId(), CapacityVOMem);
      } else {
        CapacityVO capacity =
            new CapacityVO(
                server.getId(),
                server.getDataCenterId(),
                server.getPodId(),
                server.getClusterId(),
                0L,
                server.getTotalMemory(),
                CapacityVO.CAPACITY_TYPE_MEMORY);
        _capacityDao.persist(capacity);
      }
    }
  }
  @DB
  @Override
  public void allocateVmCapacity(VirtualMachine vm, boolean fromLastHost) {

    long hostId = vm.getHostId();
    HostVO host = _hostDao.findById(hostId);
    long clusterId = host.getClusterId();
    float cpuOvercommitRatio =
        Float.parseFloat(_clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue());
    float memoryOvercommitRatio =
        Float.parseFloat(
            _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue());

    ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId());

    CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU);
    CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY);

    if (capacityCpu == null || capacityMem == null || svo == null) {
      return;
    }

    int cpu = (int) (svo.getCpu() * svo.getSpeed());
    long ram = (long) (svo.getRamSize() * 1024L * 1024L);

    Transaction txn = Transaction.currentTxn();

    try {
      txn.start();
      capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
      capacityMem = _capacityDao.lockRow(capacityMem.getId(), true);

      long usedCpu = capacityCpu.getUsedCapacity();
      long usedMem = capacityMem.getUsedCapacity();
      long reservedCpu = capacityCpu.getReservedCapacity();
      long reservedMem = capacityMem.getReservedCapacity();
      long actualTotalCpu = capacityCpu.getTotalCapacity();
      long actualTotalMem = capacityMem.getTotalCapacity();
      long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio);
      long totalMem = (long) (actualTotalMem * memoryOvercommitRatio);
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Hosts's actual total CPU: "
                + actualTotalCpu
                + " and CPU after applying overprovisioning: "
                + totalCpu);
      }

      long freeCpu = totalCpu - (reservedCpu + usedCpu);
      long freeMem = totalMem - (reservedMem + usedMem);

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("We are allocating VM, increasing the used capacity of this host:" + hostId);
        s_logger.debug(
            "Current Used CPU: " + usedCpu + " , Free CPU:" + freeCpu + " ,Requested CPU: " + cpu);
        s_logger.debug(
            "Current Used RAM: " + usedMem + " , Free RAM:" + freeMem + " ,Requested RAM: " + ram);
      }
      capacityCpu.setUsedCapacity(usedCpu + cpu);
      capacityMem.setUsedCapacity(usedMem + ram);

      if (fromLastHost) {
        /* alloc from reserved */
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              "We are allocating VM to the last host again, so adjusting the reserved capacity if it is not less than required");
          s_logger.debug("Reserved CPU: " + reservedCpu + " , Requested CPU: " + cpu);
          s_logger.debug("Reserved RAM: " + reservedMem + " , Requested RAM: " + ram);
        }
        if (reservedCpu >= cpu && reservedMem >= ram) {
          capacityCpu.setReservedCapacity(reservedCpu - cpu);
          capacityMem.setReservedCapacity(reservedMem - ram);
        }
      } else {
        /* alloc from free resource */
        if (!((reservedCpu + usedCpu + cpu <= totalCpu)
            && (reservedMem + usedMem + ram <= totalMem))) {
          if (s_logger.isDebugEnabled()) {
            s_logger.debug(
                "Host doesnt seem to have enough free capacity, but increasing the used capacity anyways, since the VM is already starting on this host ");
          }
        }
      }

      s_logger.debug(
          "CPU STATS after allocation: for host: "
              + hostId
              + ", old used: "
              + usedCpu
              + ", old reserved: "
              + reservedCpu
              + ", actual total: "
              + actualTotalCpu
              + ", total with overprovisioning: "
              + totalCpu
              + "; new used:"
              + capacityCpu.getUsedCapacity()
              + ", reserved:"
              + capacityCpu.getReservedCapacity()
              + "; requested cpu:"
              + cpu
              + ",alloc_from_last:"
              + fromLastHost);

      s_logger.debug(
          "RAM STATS after allocation: for host: "
              + hostId
              + ", old used: "
              + usedMem
              + ", old reserved: "
              + reservedMem
              + ", total: "
              + totalMem
              + "; new used: "
              + capacityMem.getUsedCapacity()
              + ", reserved: "
              + capacityMem.getReservedCapacity()
              + "; requested mem: "
              + ram
              + ",alloc_from_last:"
              + fromLastHost);

      _capacityDao.update(capacityCpu.getId(), capacityCpu);
      _capacityDao.update(capacityMem.getId(), capacityMem);
      txn.commit();
    } catch (Exception e) {
      txn.rollback();
      return;
    }
  }
  @DB
  @Override
  public boolean releaseVmCapacity(
      VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId) {
    ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId());
    CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU);
    CapacityVO capacityMemory =
        _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY);
    Long clusterId = null;
    if (hostId != null) {
      HostVO host = _hostDao.findById(hostId);
      clusterId = host.getClusterId();
    }
    if (capacityCpu == null || capacityMemory == null || svo == null) {
      return false;
    }

    Transaction txn = Transaction.currentTxn();
    try {
      txn.start();

      capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
      capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true);

      long usedCpu = capacityCpu.getUsedCapacity();
      long usedMem = capacityMemory.getUsedCapacity();
      long reservedCpu = capacityCpu.getReservedCapacity();
      long reservedMem = capacityMemory.getReservedCapacity();
      long actualTotalCpu = capacityCpu.getTotalCapacity();
      float cpuOvercommitRatio =
          Float.parseFloat(
              _clusterDetailsDao.findDetail(clusterId, "cpuOvercommitRatio").getValue());
      float memoryOvercommitRatio =
          Float.parseFloat(
              _clusterDetailsDao.findDetail(clusterId, "memoryOvercommitRatio").getValue());
      int vmCPU = (int) (svo.getCpu() * svo.getSpeed());
      long vmMem = (long) (svo.getRamSize() * 1024L * 1024L);
      long actualTotalMem = capacityMemory.getTotalCapacity();
      long totalMem = (long) (actualTotalMem * memoryOvercommitRatio);
      long totalCpu = (long) (actualTotalCpu * cpuOvercommitRatio);
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Hosts's actual total CPU: "
                + actualTotalCpu
                + " and CPU after applying overprovisioning: "
                + totalCpu);
        s_logger.debug(
            "Hosts's actual total RAM: "
                + actualTotalMem
                + " and RAM after applying overprovisioning: "
                + totalMem);
      }

      if (!moveFromReserved) {
        /* move resource from used */
        if (usedCpu >= vmCPU) {
          capacityCpu.setUsedCapacity(usedCpu - vmCPU);
        }
        if (usedMem >= vmMem) {
          capacityMemory.setUsedCapacity(usedMem - vmMem);
        }

        if (moveToReservered) {
          if (reservedCpu + vmCPU <= totalCpu) {
            capacityCpu.setReservedCapacity(reservedCpu + vmCPU);
          }
          if (reservedMem + vmMem <= totalMem) {
            capacityMemory.setReservedCapacity(reservedMem + vmMem);
          }
        }
      } else {
        if (reservedCpu >= vmCPU) {
          capacityCpu.setReservedCapacity(reservedCpu - vmCPU);
        }
        if (reservedMem >= vmMem) {
          capacityMemory.setReservedCapacity(reservedMem - vmMem);
        }
      }

      s_logger.debug(
          "release cpu from host: "
              + hostId
              + ", old used: "
              + usedCpu
              + ",reserved: "
              + reservedCpu
              + ", actual total: "
              + actualTotalCpu
              + ", total with overprovisioning: "
              + totalCpu
              + "; new used: "
              + capacityCpu.getUsedCapacity()
              + ",reserved:"
              + capacityCpu.getReservedCapacity()
              + "; movedfromreserved: "
              + moveFromReserved
              + ",moveToReservered"
              + moveToReservered);

      s_logger.debug(
          "release mem from host: "
              + hostId
              + ", old used: "
              + usedMem
              + ",reserved: "
              + reservedMem
              + ", total: "
              + totalMem
              + "; new used: "
              + capacityMemory.getUsedCapacity()
              + ",reserved:"
              + capacityMemory.getReservedCapacity()
              + "; movedfromreserved: "
              + moveFromReserved
              + ",moveToReservered"
              + moveToReservered);

      _capacityDao.update(capacityCpu.getId(), capacityCpu);
      _capacityDao.update(capacityMemory.getId(), capacityMemory);
      txn.commit();
      return true;
    } catch (Exception e) {
      s_logger.debug("Failed to transit vm's state, due to " + e.getMessage());
      txn.rollback();
      return false;
    }
  }
  @Override
  public Map<? extends ServerResource, Map<String, String>> find(
      long dcId,
      Long podId,
      Long clusterId,
      URI url,
      String username,
      String password,
      List<String> hostTags)
      throws DiscoveryException {

    if (s_logger.isInfoEnabled())
      s_logger.info(
          "Discover host. dc: "
              + dcId
              + ", pod: "
              + podId
              + ", cluster: "
              + clusterId
              + ", uri host: "
              + url.getHost());

    if (podId == null) {
      if (s_logger.isInfoEnabled())
        s_logger.info(
            "No pod is assigned, assuming that it is not for vmware and skip it to next discoverer");
      return null;
    }

    ClusterVO cluster = _clusterDao.findById(clusterId);
    if (cluster == null || cluster.getHypervisorType() != HypervisorType.VMware) {
      if (s_logger.isInfoEnabled())
        s_logger.info("invalid cluster id or cluster is not for VMware hypervisors");
      return null;
    }

    List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(clusterId);
    if (hosts != null && hosts.size() > 0) {
      int maxHostsPerCluster =
          _hvCapabilitiesDao.getMaxHostsPerCluster(
              hosts.get(0).getHypervisorType(), hosts.get(0).getHypervisorVersion());
      if (hosts.size() > maxHostsPerCluster) {
        String msg =
            "VMware cluster "
                + cluster.getName()
                + " is too big to add new host now. (current configured cluster size: "
                + maxHostsPerCluster
                + ")";
        s_logger.error(msg);
        throw new DiscoveredWithErrorException(msg);
      }
    }

    String privateTrafficLabel = null;
    String publicTrafficLabel = null;
    String guestTrafficLabel = null;
    Map<String, String> vsmCredentials = null;

    VirtualSwitchType defaultVirtualSwitchType = VirtualSwitchType.StandardVirtualSwitch;

    String paramGuestVswitchType = null;
    String paramGuestVswitchName = null;
    String paramPublicVswitchType = null;
    String paramPublicVswitchName = null;

    VmwareTrafficLabel guestTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Guest);
    VmwareTrafficLabel publicTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Public);
    Map<String, String> clusterDetails = _clusterDetailsDao.findDetails(clusterId);
    DataCenterVO zone = _dcDao.findById(dcId);
    NetworkType zoneType = zone.getNetworkType();
    _readGlobalConfigParameters();

    // Set default physical network end points for public and guest traffic
    // Private traffic will be only on standard vSwitch for now.
    if (useDVS) {
      // Parse url parameters for type of vswitch and name of vswitch specified at cluster level
      paramGuestVswitchType = _urlParams.get(ApiConstants.VSWITCH_TYPE_GUEST_TRAFFIC);
      paramGuestVswitchName = _urlParams.get(ApiConstants.VSWITCH_NAME_GUEST_TRAFFIC);
      paramPublicVswitchType = _urlParams.get(ApiConstants.VSWITCH_TYPE_PUBLIC_TRAFFIC);
      paramPublicVswitchName = _urlParams.get(ApiConstants.VSWITCH_NAME_PUBLIC_TRAFFIC);
      defaultVirtualSwitchType = getDefaultVirtualSwitchType();
    }

    // Zone level vSwitch Type depends on zone level traffic labels
    //
    // User can override Zone wide vswitch type (for public and guest) by providing following
    // optional parameters in addClusterCmd
    // param "guestvswitchtype" with valid values vmwaredvs, vmwaresvs, nexusdvs
    // param "publicvswitchtype" with valid values vmwaredvs, vmwaresvs, nexusdvs
    //
    // Format of label is <VSWITCH>,<VLANID>,<VSWITCHTYPE>
    // If a field <VLANID> OR <VSWITCHTYPE> is not present leave it empty.
    // Ex: 1) vswitch0
    // 2) dvswitch0,200,vmwaredvs
    // 3) nexusepp0,300,nexusdvs
    // 4) vswitch1,400,vmwaresvs
    // 5) vswitch0
    // default vswitchtype is 'vmwaresvs'.
    // <VSWITCHTYPE> 'vmwaresvs' is for vmware standard vswitch
    // <VSWITCHTYPE> 'vmwaredvs' is for vmware distributed virtual switch
    // <VSWITCHTYPE> 'nexusdvs' is for cisco nexus distributed virtual switch
    // Get zone wide traffic labels for Guest traffic and Public traffic
    guestTrafficLabel = _netmgr.getDefaultGuestTrafficLabel(dcId, HypervisorType.VMware);

    // Process traffic label information provided at zone level and cluster level
    guestTrafficLabelObj =
        getTrafficInfo(
            TrafficType.Guest,
            guestTrafficLabel,
            defaultVirtualSwitchType,
            paramGuestVswitchType,
            paramGuestVswitchName,
            clusterId);

    if (zoneType == NetworkType.Advanced) {
      // Get zone wide traffic label for Public traffic
      publicTrafficLabel = _netmgr.getDefaultPublicTrafficLabel(dcId, HypervisorType.VMware);

      // Process traffic label information provided at zone level and cluster level
      publicTrafficLabelObj =
          getTrafficInfo(
              TrafficType.Public,
              publicTrafficLabel,
              defaultVirtualSwitchType,
              paramPublicVswitchType,
              paramPublicVswitchName,
              clusterId);

      // Configuration Check: A physical network cannot be shared by different types of virtual
      // switches.
      //
      // Check if different vswitch types are chosen for same physical network
      // 1. Get physical network for guest traffic - multiple networks
      // 2. Get physical network for public traffic - single network
      // See if 2 is in 1
      //  if no - pass
      //  if yes - compare publicTrafficLabelObj.getVirtualSwitchType() ==
      // guestTrafficLabelObj.getVirtualSwitchType()
      //      true  - pass
      //      false - throw exception - fail cluster add operation

      List<? extends PhysicalNetwork> pNetworkListGuestTraffic =
          _netmgr.getPhysicalNtwksSupportingTrafficType(dcId, TrafficType.Guest);
      List<? extends PhysicalNetwork> pNetworkListPublicTraffic =
          _netmgr.getPhysicalNtwksSupportingTrafficType(dcId, TrafficType.Public);
      // Public network would be on single physical network hence getting first object of the list
      // would suffice.
      PhysicalNetwork pNetworkPublic = pNetworkListPublicTraffic.get(0);
      if (pNetworkListGuestTraffic.contains(pNetworkPublic)) {
        if (publicTrafficLabelObj.getVirtualSwitchType()
            != guestTrafficLabelObj.getVirtualSwitchType()) {
          String msg =
              "Both public traffic and guest traffic is over same physical network "
                  + pNetworkPublic
                  + ". And virtual switch type chosen for each traffic is different"
                  + ". A physical network cannot be shared by different types of virtual switches.";
          s_logger.error(msg);
          throw new InvalidParameterValueException(msg);
        }
      }
    } else {
      // Distributed virtual switch is not supported in Basic zone for now.
      // Private / Management network traffic is not yet supported over distributed virtual switch.
      if (guestTrafficLabelObj.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) {
        String msg =
            "Detected that Guest traffic is over Distributed virtual switch in Basic zone. Only Standard vSwitch is supported in Basic zone.";
        s_logger.error(msg);
        throw new DiscoveredWithErrorException(msg);
      }
    }

    privateTrafficLabel = _netmgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.VMware);
    if (privateTrafficLabel != null) {
      s_logger.info("Detected private network label : " + privateTrafficLabel);
    }

    if (nexusDVS) {
      if (zoneType != NetworkType.Basic) {
        publicTrafficLabel = _netmgr.getDefaultPublicTrafficLabel(dcId, HypervisorType.VMware);
        if (publicTrafficLabel != null) {
          s_logger.info("Detected public network label : " + publicTrafficLabel);
        }
      }
      // Get physical network label
      guestTrafficLabel = _netmgr.getDefaultGuestTrafficLabel(dcId, HypervisorType.VMware);
      if (guestTrafficLabel != null) {
        s_logger.info("Detected guest network label : " + guestTrafficLabel);
      }
      vsmCredentials = _vmwareMgr.getNexusVSMCredentialsByClusterId(clusterId);
    }

    VmwareContext context = null;
    try {
      context = VmwareContextFactory.create(url.getHost(), username, password);
      if (privateTrafficLabel != null)
        context.registerStockObject("privateTrafficLabel", privateTrafficLabel);

      if (nexusDVS) {
        if (vsmCredentials != null) {
          s_logger.info("Stocking credentials of Nexus VSM");
          context.registerStockObject("vsmcredentials", vsmCredentials);
        }
      }
      List<ManagedObjectReference> morHosts =
          _vmwareMgr.addHostToPodCluster(
              context, dcId, podId, clusterId, URLDecoder.decode(url.getPath()));
      if (morHosts == null) s_logger.info("Found 0 hosts.");
      if (privateTrafficLabel != null) context.uregisterStockObject("privateTrafficLabel");

      if (morHosts == null) {
        s_logger.error(
            "Unable to find host or cluster based on url: " + URLDecoder.decode(url.getPath()));
        return null;
      }

      ManagedObjectReference morCluster = null;
      clusterDetails = _clusterDetailsDao.findDetails(clusterId);
      if (clusterDetails.get("url") != null) {
        URI uriFromCluster = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url")));
        morCluster = context.getHostMorByPath(URLDecoder.decode(uriFromCluster.getPath()));

        if (morCluster == null
            || !morCluster.getType().equalsIgnoreCase("ClusterComputeResource")) {
          s_logger.warn(
              "Cluster url does not point to a valid vSphere cluster, url: "
                  + clusterDetails.get("url"));
          return null;
        } else {
          ClusterMO clusterMo = new ClusterMO(context, morCluster);
          ClusterDasConfigInfo dasConfig = clusterMo.getDasConfig();
          if (dasConfig != null
              && dasConfig.isEnabled() != null
              && dasConfig.isEnabled().booleanValue()) {
            clusterDetails.put("NativeHA", "true");
            _clusterDetailsDao.persist(clusterId, clusterDetails);
          }
        }
      }

      if (!validateDiscoveredHosts(context, morCluster, morHosts)) {
        if (morCluster == null)
          s_logger.warn(
              "The discovered host is not standalone host, can not be added to a standalone cluster");
        else s_logger.warn("The discovered host does not belong to the cluster");
        return null;
      }

      Map<VmwareResource, Map<String, String>> resources =
          new HashMap<VmwareResource, Map<String, String>>();
      for (ManagedObjectReference morHost : morHosts) {
        Map<String, String> details = new HashMap<String, String>();
        Map<String, Object> params = new HashMap<String, Object>();

        HostMO hostMo = new HostMO(context, morHost);
        details.put("url", hostMo.getHostName());
        details.put("username", username);
        details.put("password", password);
        String guid = morHost.getType() + ":" + morHost.getValue() + "@" + url.getHost();
        details.put("guid", guid);

        params.put("url", hostMo.getHostName());
        params.put("username", username);
        params.put("password", password);
        params.put("zone", Long.toString(dcId));
        params.put("pod", Long.toString(podId));
        params.put("cluster", Long.toString(clusterId));
        params.put("guid", guid);
        if (privateTrafficLabel != null) {
          params.put("private.network.vswitch.name", privateTrafficLabel);
        }
        params.put("guestTrafficInfo", guestTrafficLabelObj);
        params.put("publicTrafficInfo", publicTrafficLabelObj);

        VmwareResource resource = new VmwareResource();
        try {
          resource.configure("VMware", params);
        } catch (ConfigurationException e) {
          _alertMgr.sendAlert(
              AlertManager.ALERT_TYPE_HOST,
              dcId,
              podId,
              "Unable to add " + url.getHost(),
              "Error is " + e.getMessage());
          s_logger.warn("Unable to instantiate " + url.getHost(), e);
        }
        resource.start();

        resources.put(resource, details);
      }

      // place a place holder guid derived from cluster ID
      cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
      _clusterDao.update(clusterId, cluster);

      return resources;
    } catch (DiscoveredWithErrorException e) {
      throw e;
    } catch (Exception e) {
      s_logger.warn(
          "Unable to connect to Vmware vSphere server. service address: " + url.getHost());
      return null;
    } finally {
      if (context != null) context.close();
    }
  }
  protected void loadResource(Long hostId) {
    HostVO host = hostDao.findById(hostId);
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("guid", host.getGuid());
    params.put("ipaddress", host.getPrivateIpAddress());
    params.put("username", "root");
    params.put("password", "password");
    params.put("zone", String.valueOf(host.getDataCenterId()));
    params.put("pod", String.valueOf(host.getPodId()));

    ServerResource resource = null;
    if (host.getHypervisorType() == HypervisorType.XenServer) {
      resource = new XcpOssResource();
      try {
        resource.configure(host.getName(), params);

      } catch (ConfigurationException e) {
        logger.debug("Failed to load resource:" + e.toString());
      }
    } else if (host.getHypervisorType() == HypervisorType.KVM) {
      resource = new LibvirtComputingResource();
      try {
        params.put("public.network.device", "cloudbr0");
        params.put("private.network.device", "cloudbr0");
        resource.configure(host.getName(), params);
      } catch (ConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } else if (host.getHypervisorType() == HypervisorType.VMware) {
      ClusterVO cluster = clusterDao.findById(host.getClusterId());
      String url = clusterDetailsDao.findDetail(cluster.getId(), "url").getValue();
      URI uri;
      try {
        uri = new URI(url);
        String userName = clusterDetailsDao.findDetail(cluster.getId(), "username").getValue();
        String password = clusterDetailsDao.findDetail(cluster.getId(), "password").getValue();
        VmwareServerDiscoverer discover = new VmwareServerDiscoverer();

        Map<? extends ServerResource, Map<String, String>> resources =
            discover.find(
                host.getDataCenterId(),
                host.getPodId(),
                host.getClusterId(),
                uri,
                userName,
                password,
                null);
        for (Map.Entry<? extends ServerResource, Map<String, String>> entry :
            resources.entrySet()) {
          resource = entry.getKey();
        }
        if (resource == null) {
          throw new CloudRuntimeException("can't find resource");
        }
      } catch (DiscoveryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (URISyntaxException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    hostResourcesMap.put(hostId, resource);
    HostEnvironment env = new HostEnvironment();
    SetupCommand cmd = new SetupCommand(env);
    cmd.setNeedSetup(true);

    resource.executeRequest(cmd);
  }