private void updateNetworkLabels(HostVO host) {
    // check if networkLabels need to be updated in details
    // we send only private and storage network label to the resource.
    String privateNetworkLabel =
        _networkMgr.getDefaultManagementTrafficLabel(
            host.getDataCenterId(), host.getHypervisorType());
    String storageNetworkLabel =
        _networkMgr.getDefaultStorageTrafficLabel(host.getDataCenterId(), host.getHypervisorType());

    String privateDevice = host.getDetail("private.network.device");
    String storageDevice = host.getDetail("storage.network.device1");

    boolean update = false;

    if (privateNetworkLabel != null && !privateNetworkLabel.equalsIgnoreCase(privateDevice)) {
      host.setDetail("private.network.device", privateNetworkLabel);
      update = true;
    }
    if (storageNetworkLabel != null && !storageNetworkLabel.equalsIgnoreCase(storageDevice)) {
      host.setDetail("storage.network.device1", storageNetworkLabel);
      update = true;
    }
    if (update) {
      _hostDao.saveDetails(host);
    }
  }
 public void releaseIp(long ipId, long userId, Account caller) {
   s_logger.info("ELB: Release public IP for loadbalancing " + ipId);
   IPAddressVO ipvo = _ipAddressDao.findById(ipId);
   ipvo.setAssociatedWithNetworkId(null);
   _ipAddressDao.update(ipvo.getId(), ipvo);
   _networkMgr.disassociatePublicIpAddress(ipId, userId, caller);
   _ipAddressDao.unassignIpAddress(ipId);
 }
  @Override
  public boolean generateVMSetupCommand(Long ssAHostId) {
    HostVO ssAHost = _hostDao.findById(ssAHostId);
    if (ssAHost.getType() != Host.Type.SecondaryStorageVM) {
      return false;
    }
    SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findByInstanceName(ssAHost.getName());
    if (secStorageVm == null) {
      s_logger.warn("secondary storage VM " + ssAHost.getName() + " doesn't exist");
      return false;
    }

    SecStorageVMSetupCommand setupCmd = new SecStorageVMSetupCommand();
    if (_allowedInternalSites != null) {
      List<String> allowedCidrs = new ArrayList<String>();
      String[] cidrs = _allowedInternalSites.split(",");
      for (String cidr : cidrs) {
        if (NetUtils.isValidCIDR(cidr) || NetUtils.isValidIp(cidr)) {
          allowedCidrs.add(cidr);
        }
      }
      List<? extends Nic> nics =
          _networkMgr.getNicsForTraffic(secStorageVm.getId(), TrafficType.Management);
      Nic privateNic = nics.get(0);
      String privateCidr =
          NetUtils.ipAndNetMaskToCidr(privateNic.getIp4Address(), privateNic.getNetmask());
      String publicCidr =
          NetUtils.ipAndNetMaskToCidr(
              secStorageVm.getPublicIpAddress(), secStorageVm.getPublicNetmask());
      if (NetUtils.isNetworkAWithinNetworkB(privateCidr, publicCidr)
          || NetUtils.isNetworkAWithinNetworkB(publicCidr, privateCidr)) {
        s_logger.info(
            "private and public interface overlaps, add a default route through private interface. privateCidr: "
                + privateCidr
                + ", publicCidr: "
                + publicCidr);
        allowedCidrs.add(NetUtils.ALL_CIDRS);
      }
      setupCmd.setAllowedInternalSites(allowedCidrs.toArray(new String[allowedCidrs.size()]));
    }
    String copyPasswd = _configDao.getValue("secstorage.copy.password");
    setupCmd.setCopyPassword(copyPasswd);
    setupCmd.setCopyUserName(TemplateConstants.DEFAULT_HTTP_AUTH_USER);
    Answer answer = _agentMgr.easySend(ssAHostId, setupCmd);
    if (answer != null && answer.getResult()) {
      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Successfully programmed http auth into " + secStorageVm.getHostName());
      }
      return true;
    } else {
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "failed to program http auth into secondary storage vm : "
                + secStorageVm.getHostName());
      }
      return false;
    }
  }
  @DB
  protected boolean applyLoadBalancerRules(List<LoadBalancerVO> lbs)
      throws ResourceUnavailableException {
    Transaction txn = Transaction.currentTxn();
    List<LoadBalancingRule> rules = new ArrayList<LoadBalancingRule>();
    for (LoadBalancerVO lb : lbs) {
      List<LbDestination> dstList = getExistingDestinations(lb.getId());

      LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList);
      rules.add(loadBalancing);
    }

    if (!_networkMgr.applyRules(rules, false)) {
      s_logger.debug("LB rules are not completely applied");
      return false;
    }

    for (LoadBalancerVO lb : lbs) {
      txn.start();
      if (lb.getState() == FirewallRule.State.Revoke) {
        _lbDao.remove(lb.getId());
        s_logger.warn("LB " + lb.getId() + " is successfully removed");
      } else if (lb.getState() == FirewallRule.State.Add) {
        lb.setState(FirewallRule.State.Active);
        s_logger.warn("LB rule " + lb.getId() + " state is set to Active");
        _lbDao.persist(lb);
      }

      // remove LB-Vm mappings that were state to revoke
      List<LoadBalancerVMMapVO> lbVmMaps = _lb2VmMapDao.listByLoadBalancerId(lb.getId(), true);
      List<Long> instanceIds = new ArrayList<Long>();

      for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) {
        instanceIds.add(lbVmMap.getInstanceId());
      }

      if (!instanceIds.isEmpty()) {
        _lb2VmMapDao.remove(lb.getId(), instanceIds, null);
        s_logger.debug(
            "Load balancer rule id " + lb.getId() + " is removed for vms " + instanceIds);
      }

      if (_lb2VmMapDao.listByLoadBalancerId(lb.getId()).isEmpty()) {
        lb.setState(FirewallRule.State.Add);
        _lbDao.persist(lb);
        s_logger.debug(
            "LB rule "
                + lb.getId()
                + " state is set to Add as there are no more active LB-VM mappings");
      }

      txn.commit();
    }
    return true;
  }
  @Override
  public Network design(
      NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
    DataCenter dc = _dcDao.findById(plan.getDataCenterId());

    if (!canHandle(offering, dc)) {
      return null;
    }

    State state = State.Allocated;
    if (dc.getNetworkType() == NetworkType.Basic) {
      state = State.Setup;
    }

    NetworkVO config =
        new NetworkVO(
            offering.getTrafficType(),
            Mode.Dhcp,
            BroadcastDomainType.Vlan,
            offering.getId(),
            state,
            plan.getDataCenterId(),
            plan.getPhysicalNetworkId());

    if (userSpecified != null) {
      if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null)
          || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) {
        throw new InvalidParameterValueException("cidr and gateway must be specified together.");
      }

      if (userSpecified.getCidr() != null) {
        config.setCidr(userSpecified.getCidr());
        config.setGateway(userSpecified.getGateway());
      }

      if (userSpecified.getBroadcastUri() != null) {
        config.setBroadcastUri(userSpecified.getBroadcastUri());
        config.setState(State.Setup);
      }

      if (userSpecified.getBroadcastDomainType() != null) {
        config.setBroadcastDomainType(userSpecified.getBroadcastDomainType());
      }
    }

    boolean isSecurityGroupEnabled =
        _networkMgr.areServicesSupportedByNetworkOffering(offering.getId(), Service.SecurityGroup);
    if (isSecurityGroupEnabled) {
      config.setName("SecurityGroupEnabledNetwork");
      config.setDisplayText("SecurityGroupEnabledNetwork");
    }

    return config;
  }
 @Override
 public boolean isVmSecurityGroupEnabled(Long vmId) {
   VirtualMachine vm = _vmDao.findByIdIncludingRemoved(vmId);
   List<NicProfile> nics = _networkMgr.getNicProfiles(vm);
   for (NicProfile nic : nics) {
     if (nic.isSecurityGroupEnabled() && vm.getHypervisorType() != HypervisorType.VMware) {
       return true;
     }
   }
   return false;
 }
  private boolean canHandle(Network config) {
    DataCenter zone = _configMgr.getZone(config.getDataCenterId());
    if ((zone.getNetworkType() == NetworkType.Advanced
            && config.getGuestType() != Network.GuestType.Isolated)
        || (zone.getNetworkType() == NetworkType.Basic
            && config.getGuestType() != Network.GuestType.Shared)) {
      s_logger.trace("Not handling network type = " + config.getGuestType());
      return false;
    }

    return _networkManager.networkIsConfiguredForExternalNetworking(zone.getId(), config.getId());
  }
 @Override
 public void reserve(
     NicProfile nic,
     Network network,
     VirtualMachineProfile<? extends VirtualMachine> vm,
     DeployDestination dest,
     ReservationContext context)
     throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
         ConcurrentOperationException {
   if (nic.getIp4Address() == null) {
     _networkMgr.allocateDirectIp(nic, dest.getDataCenter(), vm, network, null);
     nic.setStrategy(ReservationStrategy.Create);
   }
 }
  @Override
  public void reserve(
      NicProfile nic,
      Network config,
      VirtualMachineProfile<? extends VirtualMachine> vm,
      DeployDestination dest,
      ReservationContext context)
      throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
    assert (nic.getReservationStrategy() == ReservationStrategy.Start)
        : "What can I do for nics that are not allocated at start? ";
    boolean _isEnabled = Boolean.parseBoolean(_configDao.getValue(Config.OvsTunnelNetwork.key()));
    if (_isEnabled) {
      return;
    }

    DataCenter dc = _dcDao.findById(config.getDataCenterId());

    if (_networkModel.networkIsConfiguredForExternalNetworking(
        config.getDataCenterId(), config.getId())) {
      nic.setBroadcastUri(config.getBroadcastUri());
      nic.setIsolationUri(config.getBroadcastUri());
      nic.setDns1(dc.getDns1());
      nic.setDns2(dc.getDns2());
      nic.setNetmask(NetUtils.cidr2Netmask(config.getCidr()));
      long cidrAddress = NetUtils.ip2Long(config.getCidr().split("/")[0]);
      int cidrSize = getGloballyConfiguredCidrSize();
      nic.setGateway(config.getGateway());

      if (nic.getIp4Address() == null) {
        String guestIp = _networkMgr.acquireGuestIpAddress(config, null);
        if (guestIp == null) {
          throw new InsufficientVirtualNetworkCapcityException(
              "Unable to acquire guest IP address for network " + config,
              DataCenter.class,
              dc.getId());
        }

        nic.setIp4Address(guestIp);
      } else {
        long ipMask =
            NetUtils.ip2Long(nic.getIp4Address()) & ~(0xffffffffffffffffl << (32 - cidrSize));
        nic.setIp4Address(NetUtils.long2Ip(cidrAddress | ipMask));
      }
    } else {
      super.reserve(nic, config, vm, dest, context);
    }
  }
  @Override
  @DB
  public void deallocate(
      Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug(
          "Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address());
    }

    IPAddressVO ip =
        _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address());
    if (ip != null) {
      Transaction txn = Transaction.currentTxn();
      txn.start();
      _networkMgr.markIpAsUnavailable(ip.getId());
      _ipAddressDao.unassignIpAddress(ip.getId());
      txn.commit();
    }
    nic.deallocate();
  }
  @Override
  public NicProfile allocate(
      Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
      throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
          ConcurrentOperationException {

    DataCenter dc = _dcDao.findById(network.getDataCenterId());

    if (nic == null) {
      nic = new NicProfile(ReservationStrategy.Create, null, null, null, null);
    } else if (nic.getIp4Address() == null) {
      nic.setStrategy(ReservationStrategy.Start);
    } else {
      nic.setStrategy(ReservationStrategy.Create);
    }

    _networkMgr.allocateDirectIp(nic, dc, vm, network, nic.getRequestedIp());
    nic.setStrategy(ReservationStrategy.Create);

    return nic;
  }
  protected void getIp(
      NicProfile nic,
      DataCenter dc,
      VirtualMachineProfile<? extends VirtualMachine> vm,
      Network network)
      throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException,
          ConcurrentOperationException {
    if (nic.getIp4Address() == null) {
      PublicIp ip =
          _networkMgr.assignPublicIpAddress(
              dc.getId(),
              vm.getOwner(),
              dc.getNetworkType().equals(NetworkType.Basic)
                  ? VlanType.DirectAttached
                  : VlanType.VirtualNetwork,
              null);
      nic.setIp4Address(ip.getAddress().toString());
      nic.setGateway(ip.getGateway());
      nic.setNetmask(ip.getNetmask());
      if (ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase("untagged")) {
        nic.setIsolationUri(URI.create("vlan://untagged"));
        nic.setBroadcastUri(URI.create("vlan://untagged"));
        nic.setBroadcastType(BroadcastDomainType.Native);
      } else if (ip.getVlanTag() != null) {
        nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag()));
        nic.setBroadcastUri(IsolationType.Vlan.toUri(ip.getVlanTag()));
        nic.setBroadcastType(BroadcastDomainType.Vlan);
      }

      nic.setFormat(AddressFormat.Ip4);
      nic.setReservationId(String.valueOf(ip.getVlanTag()));
      nic.setMacAddress(ip.getMacAddress());
    }
    nic.setDns1(dc.getDns1());
    nic.setDns2(dc.getDns2());
  }
  @DB
  public PublicIp allocDirectIp(Account account, long guestNetworkId)
      throws InsufficientAddressCapacityException {
    Network frontEndNetwork = _networkModel.getNetwork(guestNetworkId);
    Transaction txn = Transaction.currentTxn();
    txn.start();

    PublicIp ip =
        _networkMgr.assignPublicIpAddress(
            frontEndNetwork.getDataCenterId(),
            null,
            account,
            VlanType.DirectAttached,
            frontEndNetwork.getId(),
            null,
            true);
    IPAddressVO ipvo = _ipAddressDao.findById(ip.getId());
    ipvo.setAssociatedWithNetworkId(frontEndNetwork.getId());
    _ipAddressDao.update(ipvo.getId(), ipvo);
    txn.commit();
    s_logger.info("Acquired frontend IP for ELB " + ip);

    return ip;
  }
  protected Map<PortAndProto, Set<String>> generateRulesForVM(Long userVmId) {

    Map<PortAndProto, Set<String>> allowed = new TreeMap<PortAndProto, Set<String>>();

    List<SecurityGroupVMMapVO> groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVmId);
    for (SecurityGroupVMMapVO mapVO : groupsForVm) {
      List<IngressRuleVO> rules = _ingressRuleDao.listBySecurityGroupId(mapVO.getSecurityGroupId());
      for (IngressRuleVO rule : rules) {
        PortAndProto portAndProto =
            new PortAndProto(rule.getProtocol(), rule.getStartPort(), rule.getEndPort());
        Set<String> cidrs = allowed.get(portAndProto);
        if (cidrs == null) {
          cidrs = new TreeSet<String>(new CidrComparator());
        }
        if (rule.getAllowedNetworkId() != null) {
          List<SecurityGroupVMMapVO> allowedInstances =
              _securityGroupVMMapDao.listBySecurityGroup(rule.getAllowedNetworkId(), State.Running);
          for (SecurityGroupVMMapVO ngmapVO : allowedInstances) {
            Nic defaultNic = _networkMgr.getDefaultNic(ngmapVO.getInstanceId());
            if (defaultNic != null) {
              String cidr = defaultNic.getIp4Address();
              cidr = cidr + "/32";
              cidrs.add(cidr);
            }
          }
        } else if (rule.getAllowedSourceIpCidr() != null) {
          cidrs.add(rule.getAllowedSourceIpCidr());
        }
        if (cidrs.size() > 0) {
          allowed.put(portAndProto, cidrs);
        }
      }
    }

    return allowed;
  }
  protected Map<String, Object> createSecStorageVmInstance(
      long dataCenterId, SecondaryStorageVm.Role role) {
    HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId);
    if (secHost == null) {
      String msg =
          "No secondary storage available in zone "
              + dataCenterId
              + ", cannot create secondary storage vm";
      s_logger.warn(msg);
      throw new CloudRuntimeException(msg);
    }

    long id = _secStorageVmDao.getNextInSequence(Long.class, "id");
    String name = VirtualMachineName.getSystemVmName(id, _instance, "s").intern();
    Account systemAcct = _accountMgr.getSystemAccount();

    DataCenterDeployment plan = new DataCenterDeployment(dataCenterId);
    DataCenter dc = _dcDao.findById(plan.getDataCenterId());

    List<NetworkOfferingVO> defaultOffering =
        _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemPublicNetwork);

    if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) {
      defaultOffering =
          _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemGuestNetwork);
    }

    List<NetworkOfferingVO> offerings =
        _networkMgr.getSystemAccountNetworkOfferings(
            NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork);
    List<Pair<NetworkVO, NicProfile>> networks =
        new ArrayList<Pair<NetworkVO, NicProfile>>(offerings.size() + 1);
    NicProfile defaultNic = new NicProfile();
    defaultNic.setDefaultNic(true);
    defaultNic.setDeviceId(2);
    try {
      networks.add(
          new Pair<NetworkVO, NicProfile>(
              _networkMgr
                  .setupNetwork(systemAcct, defaultOffering.get(0), plan, null, null, false, false)
                  .get(0),
              defaultNic));
      for (NetworkOfferingVO offering : offerings) {
        networks.add(
            new Pair<NetworkVO, NicProfile>(
                _networkMgr
                    .setupNetwork(systemAcct, offering, plan, null, null, false, false)
                    .get(0),
                null));
      }
    } catch (ConcurrentOperationException e) {
      s_logger.info("Unable to setup due to concurrent operation. " + e);
      return new HashMap<String, Object>();
    }

    VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId);
    if (template == null) {
      s_logger.debug("Can't find a template to start");
      throw new CloudRuntimeException("Insufficient capacity exception");
    }

    SecondaryStorageVmVO secStorageVm =
        new SecondaryStorageVmVO(
            id,
            _serviceOffering.getId(),
            name,
            template.getId(),
            template.getHypervisorType(),
            template.getGuestOSId(),
            dataCenterId,
            systemAcct.getDomainId(),
            systemAcct.getId(),
            role,
            _serviceOffering.getOfferHA());
    try {
      secStorageVm =
          _itMgr.allocate(
              secStorageVm, template, _serviceOffering, networks, plan, null, systemAcct);
    } catch (InsufficientCapacityException e) {
      s_logger.warn("InsufficientCapacity", e);
      throw new CloudRuntimeException("Insufficient capacity exception", e);
    }

    Map<String, Object> context = new HashMap<String, Object>();
    context.put("secStorageVmId", secStorageVm.getId());
    return context;
  }
  @DB
  public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb, boolean openFirewall)
      throws NetworkRuleConflictException {
    long ipId = lb.getSourceIpAddressId();
    UserContext caller = UserContext.current();
    int srcPortStart = lb.getSourcePortStart();
    int defPortStart = lb.getDefaultPortStart();
    int srcPortEnd = lb.getSourcePortEnd();

    IPAddressVO ipAddr = _ipAddressDao.findById(lb.getSourceIpAddressId());
    Long networkId = ipAddr.getSourceNetworkId();
    // make sure ip address exists
    if (ipAddr == null || !ipAddr.readyToUse()) {
      throw new InvalidParameterValueException(
          "Unable to create load balancer rule, invalid IP address id" + ipId);
    }

    _firewallMgr.validateFirewallRule(
        caller.getCaller(),
        ipAddr,
        srcPortStart,
        srcPortEnd,
        lb.getProtocol(),
        Purpose.LoadBalancing);

    networkId = ipAddr.getAssociatedWithNetworkId();
    if (networkId == null) {
      throw new InvalidParameterValueException(
          "Unable to create load balancer rule ; ip id="
              + ipId
              + " is not associated with any network");
    }
    NetworkVO network = _networkDao.findById(networkId);

    _accountMgr.checkAccess(caller.getCaller(), null, ipAddr);

    // verify that lb service is supported by the network
    if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) {
      throw new InvalidParameterValueException(
          "LB service is not supported in network id= " + networkId);
    }

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

    LoadBalancerVO newRule =
        new LoadBalancerVO(
            lb.getXid(),
            lb.getName(),
            lb.getDescription(),
            lb.getSourceIpAddressId(),
            lb.getSourcePortEnd(),
            lb.getDefaultPortStart(),
            lb.getAlgorithm(),
            network.getId(),
            ipAddr.getAccountId(),
            ipAddr.getDomainId());

    newRule = _lbDao.persist(newRule);

    if (openFirewall) {
      _firewallMgr.createRuleForAllCidrs(
          ipId,
          caller.getCaller(),
          lb.getSourcePortStart(),
          lb.getSourcePortEnd(),
          lb.getProtocol(),
          null,
          null,
          newRule.getId());
    }

    boolean success = true;

    try {
      _firewallMgr.detectRulesConflict(newRule, ipAddr);
      if (!_firewallDao.setStateToAdd(newRule)) {
        throw new CloudRuntimeException("Unable to update the state to add for " + newRule);
      }
      s_logger.debug(
          "Load balancer "
              + newRule.getId()
              + " for Ip address id="
              + ipId
              + ", public port "
              + srcPortStart
              + ", private port "
              + defPortStart
              + " is added successfully.");
      UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId());
      UsageEventVO usageEvent =
          new UsageEventVO(
              EventTypes.EVENT_LOAD_BALANCER_CREATE,
              ipAddr.getAllocatedToAccountId(),
              ipAddr.getDataCenterId(),
              newRule.getId(),
              null);
      _usageEventDao.persist(usageEvent);
      txn.commit();

      return newRule;
    } catch (Exception e) {
      success = false;
      if (e instanceof NetworkRuleConflictException) {
        throw (NetworkRuleConflictException) e;
      }
      throw new CloudRuntimeException(
          "Unable to add rule for ip address id=" + newRule.getSourceIpAddressId(), e);
    } finally {
      if (!success && newRule != null) {

        txn.start();
        _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false);
        _lbDao.remove(newRule.getId());

        txn.commit();
      }
    }
  }
  @Override
  @DB
  @ActionEvent(
      eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE,
      eventDescription = "assigning to load balancer",
      async = true)
  public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds) {
    UserContext ctx = UserContext.current();
    Account caller = ctx.getCaller();

    LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId);
    if (loadBalancer == null) {
      throw new InvalidParameterValueException(
          "Failed to assign to load balancer "
              + loadBalancerId
              + ", the load balancer was not found.");
    }

    List<LoadBalancerVMMapVO> mappedInstances =
        _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false);
    Set<Long> mappedInstanceIds = new HashSet<Long>();
    for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
      mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId()));
    }

    List<UserVm> vmsToAdd = new ArrayList<UserVm>();

    for (Long instanceId : instanceIds) {
      if (mappedInstanceIds.contains(instanceId)) {
        throw new InvalidParameterValueException(
            "VM " + instanceId + " is already mapped to load balancer.");
      }

      UserVm vm = _vmDao.findById(instanceId);
      if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) {
        throw new InvalidParameterValueException("Invalid instance id: " + instanceId);
      }

      _rulesMgr.checkRuleAndUserVm(loadBalancer, vm, caller);

      if (vm.getAccountId() != loadBalancer.getAccountId()) {
        throw new PermissionDeniedException(
            "Cannot add virtual machines that do not belong to the same owner.");
      }

      // Let's check to make sure the vm has a nic in the same network as the load balancing rule.
      List<? extends Nic> nics = _networkMgr.getNics(vm.getId());
      Nic nicInSameNetwork = null;
      for (Nic nic : nics) {
        if (nic.getNetworkId() == loadBalancer.getNetworkId()) {
          nicInSameNetwork = nic;
          break;
        }
      }

      if (nicInSameNetwork == null) {
        throw new InvalidParameterValueException(
            "VM " + instanceId + " cannot be added because it doesn't belong in the same network.");
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Adding " + vm + " to the load balancer pool");
      }
      vmsToAdd.add(vm);
    }

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

    for (UserVm vm : vmsToAdd) {
      LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false);
      map = _lb2VmMapDao.persist(map);
    }
    txn.commit();

    try {
      loadBalancer.setState(FirewallRule.State.Add);
      _lbDao.persist(loadBalancer);
      applyLoadBalancerConfig(loadBalancerId);
    } catch (ResourceUnavailableException e) {
      s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e);
      return false;
    }

    return true;
  }
  @Override
  public Map<? extends ServerResource, Map<String, String>> find(
      long dcId,
      Long podId,
      Long clusterId,
      URI uri,
      String username,
      String password,
      List<String> hostTags)
      throws DiscoveryException {

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

    Map<KvmDummyResourceBase, Map<String, String>> resources =
        new HashMap<KvmDummyResourceBase, Map<String, String>>();
    Map<String, String> details = new HashMap<String, String>();
    if (!uri.getScheme().equals("http")) {
      String msg =
          "urlString is not http so we're not taking care of the discovery for this: " + uri;
      s_logger.debug(msg);
      return null;
    }
    com.trilead.ssh2.Connection sshConnection = null;
    String agentIp = null;
    try {

      String hostname = uri.getHost();
      InetAddress ia = InetAddress.getByName(hostname);
      agentIp = ia.getHostAddress();
      String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString();
      String guidWithTail = guid + "-LibvirtComputingResource"; /*tail added by agent.java*/
      if (_resourceMgr.findHostByGuid(guidWithTail) != null) {
        s_logger.debug(
            "Skipping " + agentIp + " because " + guidWithTail + " is already in the database.");
        return null;
      }

      sshConnection = new com.trilead.ssh2.Connection(agentIp, 22);

      sshConnection.connect(null, 60000, 60000);
      if (!sshConnection.authenticateWithPassword(username, password)) {
        s_logger.debug("Failed to authenticate");
        throw new DiscoveredWithErrorException("Authentication error");
      }

      if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm", 3)) {
        s_logger.debug("It's not a KVM enabled machine");
        return null;
      }

      List<PhysicalNetworkSetupInfo> netInfos =
          _networkMgr.getPhysicalNetworkInfo(dcId, HypervisorType.KVM);
      String kvmPrivateNic = _kvmPrivateNic;
      String kvmPublicNic = _kvmPublicNic;
      String kvmGuestNic = _kvmGuestNic;

      for (PhysicalNetworkSetupInfo info : netInfos) {
        if (info.getPrivateNetworkName() != null) {
          kvmPrivateNic = info.getPrivateNetworkName();
        }
        if (info.getPublicNetworkName() != null) {
          kvmPublicNic = info.getPublicNetworkName();
        }
        if (info.getGuestNetworkName() != null) {
          kvmGuestNic = info.getGuestNetworkName();
        }
      }

      String parameters =
          " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid
              + " -a";

      if (kvmPublicNic != null) {
        parameters += " --pubNic=" + kvmPublicNic;
      }

      if (kvmPrivateNic != null) {
        parameters += " --prvNic=" + kvmPrivateNic;
      }

      if (kvmGuestNic != null) {
        parameters += " --guestNic=" + kvmGuestNic;
      }

      SSHCmdHelper.sshExecuteCmd(sshConnection, "cloud-setup-agent " + parameters, 3);

      KvmDummyResourceBase kvmResource = new KvmDummyResourceBase();
      Map<String, Object> params = new HashMap<String, Object>();

      params.put("zone", Long.toString(dcId));
      params.put("pod", Long.toString(podId));
      params.put("cluster", Long.toString(clusterId));
      params.put("guid", guid);
      params.put("agentIp", agentIp);
      kvmResource.configure("kvm agent", params);
      resources.put(kvmResource, details);

      HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail);
      if (connectedHost == null) return null;

      details.put("guid", guidWithTail);

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

      // save user name and password
      _hostDao.loadDetails(connectedHost);
      Map<String, String> hostDetails = connectedHost.getDetails();
      hostDetails.put("password", password);
      hostDetails.put("username", username);
      _hostDao.saveDetails(connectedHost);
      return resources;
    } catch (DiscoveredWithErrorException e) {
      throw e;
    } catch (Exception e) {
      String msg = " can't setup agent, due to " + e.toString() + " - " + e.getMessage();
      s_logger.warn(msg);
    } finally {
      if (sshConnection != null) sshConnection.close();
    }

    return null;
  }
  public DomainRouterVO deployELBVm(
      Network guestNetwork, DeployDestination dest, Account owner, Map<Param, Object> params)
      throws ConcurrentOperationException, ResourceUnavailableException,
          InsufficientCapacityException {
    long dcId = dest.getDataCenter().getId();

    // lock guest network
    Long guestNetworkId = guestNetwork.getId();
    guestNetwork = _networkDao.acquireInLockTable(guestNetworkId);

    if (guestNetwork == null) {
      throw new ConcurrentOperationException("Unable to acquire network lock: " + guestNetworkId);
    }

    try {

      if (_networkModel.isNetworkSystem(guestNetwork)
          || guestNetwork.getGuestType() == Network.GuestType.Shared) {
        owner = _accountService.getSystemAccount();
      }

      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Starting a ELB vm for network configurations: " + guestNetwork + " in " + dest);
      }
      assert guestNetwork.getState() == Network.State.Implemented
              || guestNetwork.getState() == Network.State.Setup
              || guestNetwork.getState() == Network.State.Implementing
          : "Network is not yet fully implemented: " + guestNetwork;

      DataCenterDeployment plan = null;
      DomainRouterVO elbVm = null;

      plan = new DataCenterDeployment(dcId, dest.getPod().getId(), null, null, null, null);

      if (elbVm == null) {
        long id = _routerDao.getNextInSequence(Long.class, "id");
        if (s_logger.isDebugEnabled()) {
          s_logger.debug("Creating the ELB vm " + id);
        }

        List<? extends NetworkOffering> offerings =
            _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork);
        NetworkOffering controlOffering = offerings.get(0);
        NetworkVO controlConfig =
            _networkMgr.setupNetwork(_systemAcct, controlOffering, plan, null, null, false).get(0);

        List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>(2);
        NicProfile guestNic = new NicProfile();
        guestNic.setDefaultNic(true);
        networks.add(new Pair<NetworkVO, NicProfile>(controlConfig, null));
        networks.add(new Pair<NetworkVO, NicProfile>((NetworkVO) guestNetwork, guestNic));

        VMTemplateVO template = _templateDao.findSystemVMTemplate(dcId);

        String typeString = "ElasticLoadBalancerVm";
        Long physicalNetworkId = _networkModel.getPhysicalNetworkId(guestNetwork);
        PhysicalNetworkServiceProvider provider =
            _physicalProviderDao.findByServiceProvider(physicalNetworkId, typeString);
        if (provider == null) {
          throw new CloudRuntimeException(
              "Cannot find service provider "
                  + typeString
                  + " in physical network "
                  + physicalNetworkId);
        }
        VirtualRouterProvider vrProvider =
            _vrProviderDao.findByNspIdAndType(
                provider.getId(), VirtualRouterProviderType.ElasticLoadBalancerVm);
        if (vrProvider == null) {
          throw new CloudRuntimeException(
              "Cannot find virtual router provider "
                  + typeString
                  + " as service provider "
                  + provider.getId());
        }

        elbVm =
            new DomainRouterVO(
                id,
                _elasticLbVmOffering.getId(),
                vrProvider.getId(),
                VirtualMachineName.getSystemVmName(id, _instance, _elbVmNamePrefix),
                template.getId(),
                template.getHypervisorType(),
                template.getGuestOSId(),
                owner.getDomainId(),
                owner.getId(),
                false,
                0,
                false,
                RedundantState.UNKNOWN,
                _elasticLbVmOffering.getOfferHA(),
                false,
                VirtualMachine.Type.ElasticLoadBalancerVm,
                null);
        elbVm.setRole(Role.LB);
        elbVm = _itMgr.allocate(elbVm, template, _elasticLbVmOffering, networks, plan, null, owner);
        // TODO: create usage stats
      }

      State state = elbVm.getState();
      if (state != State.Running) {
        elbVm =
            this.start(
                elbVm, _accountService.getSystemUser(), _accountService.getSystemAccount(), params);
      }

      return elbVm;
    } finally {
      _networkDao.releaseFromLockTable(guestNetworkId);
    }
  }