private boolean sendCommandsToRouter(final DomainRouterVO elbVm, Commands cmds)
      throws AgentUnavailableException {
    Answer[] answers = null;
    try {
      answers = _agentMgr.send(elbVm.getHostId(), cmds);
    } catch (OperationTimedoutException e) {
      s_logger.warn("ELB: Timed Out", e);
      throw new AgentUnavailableException(
          "Unable to send commands to virtual elbVm ", elbVm.getHostId(), e);
    }

    if (answers == null) {
      return false;
    }

    if (answers.length != cmds.size()) {
      return false;
    }

    // FIXME: Have to return state for individual command in the future
    if (answers.length > 0) {
      Answer ans = answers[0];
      return ans.getResult();
    }
    return true;
  }
  @Override
  protected void finalizeNetworkRulesForNetwork(
      final Commands cmds,
      final DomainRouterVO domainRouterVO,
      final Provider provider,
      final Long guestNetworkId) {

    super.finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNetworkId);

    if (domainRouterVO.getVpcId() != null) {

      if (domainRouterVO.getState() == State.Starting
          || domainRouterVO.getState() == State.Running) {
        if (_networkModel.isProviderSupportServiceInNetwork(
            guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) {
          final List<NetworkACLItemVO> networkACLs =
              _networkACLMgr.listNetworkACLItems(guestNetworkId);
          if (networkACLs != null && !networkACLs.isEmpty()) {
            s_logger.debug(
                "Found "
                    + networkACLs.size()
                    + " network ACLs to apply as a part of VPC VR "
                    + domainRouterVO
                    + " start for guest network id="
                    + guestNetworkId);
            _commandSetupHelper.createNetworkACLsCommands(
                networkACLs, domainRouterVO, cmds, guestNetworkId, false);
          }
        }
      }
    }
  }
  protected boolean shutdownRouterVM(DomainRouterVO router) {
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Try to shutdown router VM " + router.getInstanceName() + " directly.");
    }

    Pair<Boolean, String> result;
    try {
      result =
          SshHelper.sshExecute(
              router.getPrivateIpAddress(),
              DEFAULT_DOMR_SSHPORT,
              "root",
              getSystemVMKeyFile(),
              null,
              "poweroff -f");

      if (!result.first()) {
        s_logger.debug("Unable to shutdown " + router.getInstanceName() + " directly");
        return false;
      }
    } catch (Throwable e) {
      s_logger.warn("Unable to shutdown router " + router.getInstanceName() + " directly.");
      return false;
    }
    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Shutdown router " + router.getInstanceName() + " successful.");
    }
    return true;
  }
  @Override
  public List<DomainRouterVO> startRouters(
      final RouterDeploymentDefinition routerDeploymentDefinition)
      throws StorageUnavailableException, InsufficientCapacityException,
          ConcurrentOperationException, ResourceUnavailableException {

    final List<DomainRouterVO> runningRouters = new ArrayList<DomainRouterVO>();

    for (DomainRouterVO router : routerDeploymentDefinition.getRouters()) {
      boolean skip = false;
      final State state = router.getState();
      if (router.getHostId() != null && state != State.Running) {
        final HostVO host = _hostDao.findById(router.getHostId());
        if (host == null || host.getState() != Status.Up) {
          skip = true;
        }
      }
      if (!skip) {
        if (state != State.Running) {
          router =
              startVirtualRouter(
                  router,
                  _accountMgr.getSystemUser(),
                  _accountMgr.getSystemAccount(),
                  routerDeploymentDefinition.getParams());
        }
        if (router != null) {
          runningRouters.add(router);
        }
      }
    }
    return runningRouters;
  }
 @Override
 public boolean processDisconnect(long agentId, Status state) {
   UserContext context = UserContext.current();
   context.setAccountId(1);
   /* Stopped VMware Host's virtual routers */
   HostVO host = _hostDao.findById(agentId);
   if (host.getHypervisorType() != HypervisorType.VMware) {
     return true;
   }
   List<DomainRouterVO> routers = _routerDao.listByHostId(agentId);
   for (DomainRouterVO router : routers) {
     try {
       State oldState = router.getState();
       _routerMgr.stopRouter(router.getId(), true);
       // In case only vCenter is disconnected, we want to shut down router directly
       if (oldState == State.Running) {
         shutdownRouterVM(router);
       }
     } catch (ResourceUnavailableException e) {
       s_logger.warn(
           "Fail to stop router " + router.getInstanceName() + " when host disconnected!", e);
     } catch (ConcurrentOperationException e) {
       s_logger.warn(
           "Fail to stop router " + router.getInstanceName() + " when host disconnected!", e);
     }
   }
   return true;
 }
  private DomainRouterVO getVirtualRouter(Network network) {
    List<DomainRouterVO> routers =
        _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER);

    if (routers.isEmpty()) {
      throw new CloudRuntimeException(
          String.format(
              "cannot find any running virtual router on network[id:%s, uuid:%s]",
              network.getId(), network.getUuid()));
    }

    if (routers.size() > 1) {
      throw new CloudRuntimeException(
          String.format("baremetal hasn't supported redundant router yet"));
    }

    DomainRouterVO vr = routers.get(0);
    if (!Hypervisor.HypervisorType.VMware.equals(vr.getHypervisorType())) {
      throw new CloudRuntimeException(
          String.format(
              "baremetal only support vmware virtual router, but get %s", vr.getHypervisorType()));
    }

    return vr;
  }
  /** @param network */
  private void mockDAOs(final NetworkVO network, final NetworkOfferingVO offering) {
    when(_networkDao.acquireInLockTable(
            network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value()))
        .thenReturn(network);
    when(_networksDao.acquireInLockTable(
            network.getId(), NetworkOrchestrationService.NetworkLockTimeout.value()))
        .thenReturn(network);
    when(_physicalProviderDao.findByServiceProvider(0L, "VirtualRouter"))
        .thenReturn(new PhysicalNetworkServiceProviderVO());
    when(_vrProviderDao.findByNspIdAndType(0L, Type.VirtualRouter))
        .thenReturn(new VirtualRouterProviderVO());
    when(_networkOfferingDao.findById(0L)).thenReturn(offering);
    // watchit: (in this test) there can be only one
    when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(0L);
    final ServiceOfferingVO svcoff =
        new ServiceOfferingVO(
            "name",
            /* cpu */ 1,
            /* ramsize */ 1024 * 1024,
            /* (clock?)speed */ 1024 * 1024 * 1024,
            /* rateMbps */ 1,
            /* multicastRateMbps */ 0,
            /* offerHA */ false,
            "displayText",
            ProvisioningType.THIN,
            /* useLocalStorage */ false,
            /* recreatable */ false,
            "tags",
            /* systemUse */ false,
            VirtualMachine.Type.DomainRouter,
            /* defaultUse */ false);
    when(_serviceOfferingDao.findById(0L)).thenReturn(svcoff);
    final DomainRouterVO router =
        new DomainRouterVO(
            /* id */ 1L,
            /* serviceOfferingId */ 1L,
            /* elementId */ 0L,
            "name",
            /* templateId */ 0L,
            HypervisorType.XenServer,
            /* guestOSId */ 0L,
            /* domainId */ 0L,
            /* accountId */ 1L,
            /* userId */ 1L,
            /* isRedundantRouter */ false,
            RedundantState.UNKNOWN,
            /* haEnabled */ false,
            /* stopPending */ false,
            /* vpcId */ null);

    when(_routerDao.getNextInSequence(Long.class, "id")).thenReturn(1L);
    when(_templateDao.findRoutingTemplate(
            HypervisorType.XenServer, "SystemVM Template (XenServer)"))
        .thenReturn(new VMTemplateVO());
    when(_routerDao.persist(any(DomainRouterVO.class))).thenReturn(router);
    when(_routerDao.findById(router.getId())).thenReturn(router);
  }
 @Override
 public void finalizeStop(final VirtualMachineProfile profile, final Answer answer) {
   super.finalizeStop(profile, answer);
   // Mark VPN connections as Disconnected
   final DomainRouterVO router = _routerDao.findById(profile.getId());
   final Long vpcId = router.getVpcId();
   if (vpcId != null) {
     _s2sVpnMgr.markDisconnectVpnConnByVpc(vpcId);
   }
 }
  protected DomainRouterVO waitRouter(final DomainRouterVO router) {
    DomainRouterVO vm = _routerDao.findById(router.getId());

    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Router " + router.getInstanceName() + " is not fully up yet, we will wait");
    }
    while (vm.getState() == State.Starting) {
      try {
        Thread.sleep(1000);
      } catch (final InterruptedException e) {
      }

      // reload to get the latest state info
      vm = _routerDao.findById(router.getId());
    }

    if (vm.getState() == State.Running) {
      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Router " + router.getInstanceName() + " is now fully up");
      }

      return router;
    }

    s_logger.warn(
        "Router " + router.getInstanceName() + " failed to start. current state: " + vm.getState());
    return null;
  }
  @Override
  public boolean finalizeVirtualMachineProfile(
      final VirtualMachineProfile profile,
      final DeployDestination dest,
      final ReservationContext context) {
    final DomainRouterVO domainRouterVO = _routerDao.findById(profile.getId());

    final Long vpcId = domainRouterVO.getVpcId();

    if (vpcId != null) {
      if (domainRouterVO.getState() == State.Starting
          || domainRouterVO.getState() == State.Running) {
        String defaultDns1 = null;
        String defaultDns2 = null;
        // remove public and guest nics as we will plug them later
        final Iterator<NicProfile> it = profile.getNics().iterator();
        while (it.hasNext()) {
          final NicProfile nic = it.next();
          if (nic.getTrafficType() == TrafficType.Public
              || nic.getTrafficType() == TrafficType.Guest) {
            // save dns information
            if (nic.getTrafficType() == TrafficType.Public) {
              defaultDns1 = nic.getIPv4Dns1();
              defaultDns2 = nic.getIPv4Dns2();
            }
            s_logger.debug(
                "Removing nic "
                    + nic
                    + " of type "
                    + nic.getTrafficType()
                    + " from the nics passed on vm start. "
                    + "The nic will be plugged later");
            it.remove();
          }
        }

        // add vpc cidr/dns/networkdomain to the boot load args
        final StringBuilder buf = profile.getBootArgsBuilder();
        final Vpc vpc = _entityMgr.findById(Vpc.class, vpcId);
        buf.append(" vpccidr=" + vpc.getCidr() + " domain=" + vpc.getNetworkDomain());

        buf.append(" dns1=").append(defaultDns1);
        if (defaultDns2 != null) {
          buf.append(" dns2=").append(defaultDns2);
        }
      }
    }

    return super.finalizeVirtualMachineProfile(profile, dest, context);
  }
 @Override
 public List<DomainRouterVO> listByStateAndNetworkType(
     State state, Network.GuestType type, long mgmtSrvrId) {
   SearchCriteria<DomainRouterVO> sc = StateNetworkTypeSearch.create();
   sc.setParameters("state", state);
   sc.setJoinParameters("networkRouter", "type", type);
   sc.setJoinParameters("host", "mgmtServerId", mgmtSrvrId);
   List<DomainRouterVO> routerIds = listBy(sc);
   List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
   for (DomainRouterVO router : routerIds) {
     routers.add(findById(router.getId()));
   }
   return routers;
 }
 private DomainRouterVO findELBVmWithCapacity(Network guestNetwork, IPAddressVO ipAddr) {
   List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
   if (unusedElbVms.size() > 0) {
     List<DomainRouterVO> candidateVms = new ArrayList<DomainRouterVO>();
     for (DomainRouterVO candidateVm : unusedElbVms) {
       if (candidateVm.getPodIdToDeployIn() == getPodIdForDirectIp(ipAddr))
         candidateVms.add(candidateVm);
     }
     return candidateVms.size() == 0
         ? null
         : candidateVms.get(new Random().nextInt(candidateVms.size()));
   }
   return null;
 }
  @Override
  public boolean remove(Long id) {
    TransactionLegacy txn = TransactionLegacy.currentTxn();
    txn.start();
    DomainRouterVO router = createForUpdate();
    router.setPublicIpAddress(null);
    UpdateBuilder ub = getUpdateBuilder(router);
    ub.set(router, "state", State.Destroyed);
    update(id, ub, router);

    boolean result = super.remove(id);
    txn.commit();
    return result;
  }
 @Override
 public List<DomainRouterVO> listIsolatedByHostId(Long hostId) {
   SearchCriteria<DomainRouterVO> sc = HostUpSearch.create();
   if (hostId != null) {
     sc.setParameters("host", hostId);
   }
   sc.setJoinParameters("networkRouter", "type", Network.GuestType.Isolated);
   List<DomainRouterVO> routerIds = listBy(sc);
   List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
   for (DomainRouterVO router : routerIds) {
     routers.add(findById(router.getId()));
   }
   return routers;
 }
  @Override
  public void handleSingleWorkingRedundantRouter(
      final List<? extends VirtualRouter> connectedRouters,
      final List<? extends VirtualRouter> disconnectedRouters,
      final String reason)
      throws ResourceUnavailableException {
    if (connectedRouters.isEmpty() || disconnectedRouters.isEmpty()) {
      return;
    }

    for (final VirtualRouter virtualRouter : connectedRouters) {
      if (!virtualRouter.getIsRedundantRouter()) {
        throw new ResourceUnavailableException(
            "Who is calling this with non-redundant router or non-domain router?",
            DataCenter.class,
            virtualRouter.getDataCenterId());
      }
    }

    for (final VirtualRouter virtualRouter : disconnectedRouters) {
      if (!virtualRouter.getIsRedundantRouter()) {
        throw new ResourceUnavailableException(
            "Who is calling this with non-redundant router or non-domain router?",
            DataCenter.class,
            virtualRouter.getDataCenterId());
      }
    }

    final DomainRouterVO connectedRouter = (DomainRouterVO) connectedRouters.get(0);
    DomainRouterVO disconnectedRouter = (DomainRouterVO) disconnectedRouters.get(0);

    if (s_logger.isDebugEnabled()) {
      s_logger.debug(
          "About to stop the router "
              + disconnectedRouter.getInstanceName()
              + " due to: "
              + reason);
    }
    final String title =
        "Virtual router "
            + disconnectedRouter.getInstanceName()
            + " would be stopped after connecting back, due to "
            + reason;
    final String context =
        "Virtual router (name: "
            + disconnectedRouter.getInstanceName()
            + ", id: "
            + disconnectedRouter.getId()
            + ") would be stopped after connecting back, due to: "
            + reason;
    _alertMgr.sendAlert(
        AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER,
        disconnectedRouter.getDataCenterId(),
        disconnectedRouter.getPodIdToDeployIn(),
        title,
        context);
    disconnectedRouter.setStopPending(true);
    disconnectedRouter = _routerDao.persist(disconnectedRouter);
  }
 protected DomainRouterVO start(
     DomainRouterVO router,
     final User user,
     final Account caller,
     final Map<Param, Object> params,
     final DeploymentPlan planToDeploy)
     throws StorageUnavailableException, InsufficientCapacityException,
         ConcurrentOperationException, ResourceUnavailableException {
   s_logger.debug("Starting router " + router);
   try {
     _itMgr.advanceStart(router.getUuid(), params, planToDeploy, null);
   } catch (final OperationTimedoutException e) {
     throw new ResourceUnavailableException(
         "Starting router " + router + " failed! " + e.toString(),
         DataCenter.class,
         router.getDataCenterId());
   }
   if (router.isStopPending()) {
     s_logger.info(
         "Clear the stop pending flag of router "
             + router.getHostName()
             + " after start router successfully!");
     router.setStopPending(false);
     router = _routerDao.persist(router);
   }
   // We don't want the failure of VPN Connection affect the status of
   // router, so we try to make connection
   // only after router start successfully
   final Long vpcId = router.getVpcId();
   if (vpcId != null) {
     _s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId);
   }
   return _routerDao.findById(router.getId());
 }
  @Override
  public boolean finalizeDeployment(
      Commands cmds,
      VirtualMachineProfile<DomainRouterVO> profile,
      DeployDestination dest,
      ReservationContext context)
      throws ResourceUnavailableException {
    DomainRouterVO elbVm = profile.getVirtualMachine();

    List<NicProfile> nics = profile.getNics();
    for (NicProfile nic : nics) {
      if (nic.getTrafficType() == TrafficType.Public) {
        elbVm.setPublicIpAddress(nic.getIp4Address());
        elbVm.setPublicNetmask(nic.getNetmask());
        elbVm.setPublicMacAddress(nic.getMacAddress());
      } else if (nic.getTrafficType() == TrafficType.Control) {
        elbVm.setPrivateIpAddress(nic.getIp4Address());
        elbVm.setPrivateMacAddress(nic.getMacAddress());
      }
    }
    _routerDao.update(elbVm.getId(), elbVm);

    finalizeCommandsOnStart(cmds, profile);
    return true;
  }
  @Override
  public void CheckAndDestroyTunnel(VirtualMachine vm) {
    if (!_isEnabled) {
      return;
    }

    List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getAccountId(), vm.getHostId());
    if (vm.getType() == VirtualMachine.Type.User) {
      if (userVms.size() > 1) {
        return;
      }

      List<DomainRouterVO> routers =
          _routerDao.findBy(vm.getAccountId(), vm.getDataCenterIdToDeployIn());
      for (DomainRouterVO router : routers) {
        if (router.getHostId() == vm.getHostId()) {
          return;
        }
      }
    } else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
      return;
    }

    try {
      /* Now we are last one on host, destroy all tunnels of my account */
      Command cmd = new OvsDestroyTunnelCommand(vm.getAccountId(), "[]");
      Answer ans = _agentMgr.send(vm.getHostId(), cmd);
      handleDestroyTunnelAnswer(ans, vm.getHostId(), 0, vm.getAccountId());

      /* Then ask hosts have peer tunnel with me to destroy them */
      List<OvsTunnelAccountVO> peers =
          _tunnelAccountDao.listByToAccount(vm.getHostId(), vm.getAccountId());
      for (OvsTunnelAccountVO p : peers) {
        cmd = new OvsDestroyTunnelCommand(p.getAccount(), p.getPortName());
        ans = _agentMgr.send(p.getFrom(), cmd);
        handleDestroyTunnelAnswer(ans, p.getFrom(), p.getTo(), p.getAccount());
      }
    } catch (Exception e) {
      s_logger.warn(
          String.format(
              "Destroy tunnel(account:%1$s, hostId:%2$s) failed",
              vm.getAccountId(), vm.getHostId()),
          e);
    }
  }
  @Override
  public VirtualRouter destroyRouter(
      final long routerId, final Account caller, final Long callerUserId)
      throws ResourceUnavailableException, ConcurrentOperationException {

    if (s_logger.isDebugEnabled()) {
      s_logger.debug("Attempting to destroy router " + routerId);
    }

    final DomainRouterVO router = _routerDao.findById(routerId);
    if (router == null) {
      return null;
    }

    _accountMgr.checkAccess(caller, null, true, router);

    _itMgr.expunge(router.getUuid());
    _routerDao.remove(router.getId());
    return router;
  }
  protected boolean sendNetworkRulesToRouter(final long routerId, final long networkId)
      throws ResourceUnavailableException {
    final DomainRouterVO router = _routerDao.findById(routerId);
    final Commands cmds = new Commands(OnError.Continue);

    final VirtualRouterProvider vrProvider = _vrProviderDao.findById(router.getElementId());
    if (vrProvider == null) {
      throw new CloudRuntimeException(
          "Cannot find related virtual router provider of router: " + router.getHostName());
    }
    final Provider provider = Network.Provider.getProvider(vrProvider.getType().toString());
    if (provider == null) {
      throw new CloudRuntimeException(
          "Cannot find related provider of virtual router provider: "
              + vrProvider.getType().toString());
    }

    finalizeNetworkRulesForNetwork(cmds, router, provider, networkId);
    return _nwHelper.sendCommandsToRouter(router, cmds);
  }
 private DomainRouterVO start(
     DomainRouterVO elbVm, User user, Account caller, Map<Param, Object> params)
     throws StorageUnavailableException, InsufficientCapacityException,
         ConcurrentOperationException, ResourceUnavailableException {
   s_logger.debug("Starting ELB VM " + elbVm);
   if (_itMgr.start(elbVm, params, user, caller) != null) {
     return _routerDao.findById(elbVm.getId());
   } else {
     return null;
   }
 }
  void garbageCollectUnusedElbVms() {
    List<DomainRouterVO> unusedElbVms = _elbVmMapDao.listUnusedElbVms();
    if (unusedElbVms != null && unusedElbVms.size() > 0)
      s_logger.info("Found " + unusedElbVms.size() + " unused ELB vms");
    Set<Long> currentGcCandidates = new HashSet<Long>();
    for (DomainRouterVO elbVm : unusedElbVms) {
      currentGcCandidates.add(elbVm.getId());
    }
    _gcCandidateElbVmIds.retainAll(currentGcCandidates);
    currentGcCandidates.removeAll(_gcCandidateElbVmIds);
    User user = _accountService.getSystemUser();
    for (Long elbVmId : _gcCandidateElbVmIds) {
      DomainRouterVO elbVm = _routerDao.findById(elbVmId);
      boolean gceed = false;

      try {
        s_logger.info("Attempting to stop ELB VM: " + elbVm);
        stop(elbVm, true, user, _systemAcct);
        gceed = true;
      } catch (ConcurrentOperationException e) {
        s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
      } catch (ResourceUnavailableException e) {
        s_logger.warn("Unable to stop unused ELB vm " + elbVm + " due to ", e);
        continue;
      }
      if (gceed) {
        try {
          s_logger.info("Attempting to destroy ELB VM: " + elbVm);
          _itMgr.expunge(elbVm, user, _systemAcct);
        } catch (ResourceUnavailableException e) {
          s_logger.warn("Unable to destroy unused ELB vm " + elbVm + " due to ", e);
          gceed = false;
        }
      }
      if (!gceed) {
        currentGcCandidates.add(elbVm.getId());
      }
    }
    _gcCandidateElbVmIds = currentGcCandidates;
  }
  private void createApplyLoadBalancingRulesCommands(
      List<LoadBalancingRule> rules, DomainRouterVO elbVm, Commands cmds, long guestNetworkId) {

    LoadBalancerTO[] lbs = new LoadBalancerTO[rules.size()];
    int i = 0;
    for (LoadBalancingRule rule : rules) {
      boolean revoked = (rule.getState().equals(FirewallRule.State.Revoke));
      String protocol = rule.getProtocol();
      String algorithm = rule.getAlgorithm();

      String elbIp = _networkModel.getIp(rule.getSourceIpAddressId()).getAddress().addr();
      int srcPort = rule.getSourcePortStart();
      String uuid = rule.getUuid();
      List<LbDestination> destinations = rule.getDestinations();
      LoadBalancerTO lb =
          new LoadBalancerTO(
              uuid, elbIp, srcPort, protocol, algorithm, revoked, false, false, destinations);
      lbs[i++] = lb;
    }

    LoadBalancerConfigCommand cmd =
        new LoadBalancerConfigCommand(
            lbs,
            elbVm.getPublicIpAddress(),
            _nicDao.getIpAddress(guestNetworkId, elbVm.getId()),
            elbVm.getPrivateIpAddress(),
            null,
            null);
    cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, elbVm.getPrivateIpAddress());
    cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, elbVm.getInstanceName());
    // FIXME: why are we setting attributes directly? Ick!! There should be accessors and
    // the constructor should set defaults.
    cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
    cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());
    cmd.lbStatsAuth = _configDao.getValue(Config.NetworkLBHaproxyStatsAuth.key());
    cmd.lbStatsPort = _configDao.getValue(Config.NetworkLBHaproxyStatsPort.key());

    cmds.addCommand(cmd);
  }
 private DomainRouterVO stop(DomainRouterVO elbVm, boolean forced, User user, Account caller)
     throws ConcurrentOperationException, ResourceUnavailableException {
   s_logger.debug("Stopping ELB vm " + elbVm);
   try {
     if (_itMgr.advanceStop(elbVm, forced, user, caller)) {
       return _routerDao.findById(elbVm.getId());
     } else {
       return null;
     }
   } catch (OperationTimedoutException e) {
     throw new CloudRuntimeException("Unable to stop " + elbVm, e);
   }
 }
  @Override
  public boolean applyLoadBalancerRules(Network network, List<? extends FirewallRule> rules)
      throws ResourceUnavailableException {
    if (rules == null || rules.isEmpty()) {
      return true;
    }
    if (rules.get(0).getPurpose() != Purpose.LoadBalancing) {
      s_logger.warn("ELB: Not handling non-LB firewall rules");
      return false;
    }

    DomainRouterVO elbVm = findElbVmForLb(rules.get(0));

    if (elbVm == null) {
      s_logger.warn(
          "Unable to apply lb rules, ELB vm  doesn't exist in the network " + network.getId());
      throw new ResourceUnavailableException(
          "Unable to apply lb rules", DataCenter.class, network.getDataCenterId());
    }

    if (elbVm.getState() == State.Running) {
      // resend all rules for the public ip
      List<LoadBalancerVO> lbs = _lbDao.listByIpAddress(rules.get(0).getSourceIpAddressId());
      List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
      for (LoadBalancerVO lb : lbs) {
        List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
        List<LbStickinessPolicy> policyList = _lbMgr.getStickinessPolicies(lb.getId());
        List<LbHealthCheckPolicy> hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId());
        LoadBalancingRule loadBalancing =
            new LoadBalancingRule(lb, dstList, policyList, hcPolicyList);
        lbRules.add(loadBalancing);
      }
      return applyLBRules(elbVm, lbRules, network.getId());
    } else if (elbVm.getState() == State.Stopped || elbVm.getState() == State.Stopping) {
      s_logger.debug(
          "ELB VM is in "
              + elbVm.getState()
              + ", so not sending apply LoadBalancing rules commands to the backend");
      return true;
    } else {
      s_logger.warn(
          "Unable to apply loadbalancing rules, ELB VM is not in the right state "
              + elbVm.getState());
      throw new ResourceUnavailableException(
          "Unable to apply loadbalancing rules, ELB VM is not in the right state",
          VirtualRouter.class,
          elbVm.getId());
    }
  }
  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);
    }
  }
  @Override
  @DB
  public LoadBalancer handleCreateLoadBalancerRule(
      CreateLoadBalancerRuleCmd lb, Account account, long networkId)
      throws InsufficientAddressCapacityException, NetworkRuleConflictException {
    // this part of code is executed when the LB provider is Elastic Load Balancer vm
    if (!_networkModel.isProviderSupportServiceInNetwork(
        lb.getNetworkId(), Service.Lb, Provider.ElasticLoadBalancerVm)) {
      return null;
    }

    Long ipId = lb.getSourceIpAddressId();
    if (ipId != null) {
      return null;
    }
    boolean newIp = false;
    account = _accountDao.acquireInLockTable(account.getId());
    if (account == null) {
      s_logger.warn("ELB: CreateLoadBalancer: Failed to acquire lock on account");
      throw new CloudRuntimeException("Failed to acquire lock on account");
    }
    try {
      List<LoadBalancerVO> existingLbs =
          findExistingLoadBalancers(
              lb.getName(),
              lb.getSourceIpAddressId(),
              lb.getAccountId(),
              lb.getDomainId(),
              lb.getSourcePortStart());
      if (existingLbs == null) {
        existingLbs =
            findExistingLoadBalancers(
                lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), null);
        if (existingLbs == null) {
          if (lb.getSourceIpAddressId() != null) {
            existingLbs =
                findExistingLoadBalancers(
                    lb.getName(), null, lb.getAccountId(), lb.getDomainId(), null);
            if (existingLbs != null) {
              throw new InvalidParameterValueException(
                  "Supplied LB name "
                      + lb.getName()
                      + " is not associated with IP "
                      + lb.getSourceIpAddressId());
            }
          } else {
            s_logger.debug(
                "Could not find any existing frontend ips for this account for this LB rule, acquiring a new frontent IP for ELB");
            PublicIp ip = allocDirectIp(account, networkId);
            ipId = ip.getId();
            newIp = true;
          }
        } else {
          ipId = existingLbs.get(0).getSourceIpAddressId();
          s_logger.debug(
              "ELB: Found existing frontend ip for this account for this LB rule " + ipId);
        }
      } else {
        s_logger.warn("ELB: Found existing load balancers matching requested new LB");
        throw new NetworkRuleConflictException(
            "ELB: Found existing load balancers matching requested new LB");
      }

      Network network = _networkModel.getNetwork(networkId);
      IPAddressVO ipAddr = _ipAddressDao.findById(ipId);

      LoadBalancer result = null;
      try {
        lb.setSourceIpAddressId(ipId);
        result = _lbMgr.createLoadBalancer(lb, false);
      } catch (NetworkRuleConflictException e) {
        s_logger.warn("Failed to create LB rule, not continuing with ELB deployment");
        if (newIp) {
          releaseIp(ipId, UserContext.current().getCallerUserId(), account);
        }
        throw e;
      }

      DomainRouterVO elbVm = null;

      if (existingLbs == null) {
        elbVm = findELBVmWithCapacity(network, ipAddr);
        if (elbVm == null) {
          elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId());
          if (elbVm == null) {
            s_logger.warn(
                "Failed to deploy a new ELB vm for ip "
                    + ipAddr
                    + " in network "
                    + network
                    + "lb name="
                    + lb.getName());
            if (newIp) releaseIp(ipId, UserContext.current().getCallerUserId(), account);
          }
        }

      } else {
        ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(ipId);
        if (elbVmMap != null) {
          elbVm = _routerDao.findById(elbVmMap.getElbVmId());
        }
      }

      if (elbVm == null) {
        s_logger.warn("No ELB VM can be found or deployed");
        s_logger.warn("Deleting LB since we failed to deploy ELB VM");
        _lbDao.remove(result.getId());
        return null;
      }

      ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId(), result.getId());
      _elbVmMapDao.persist(mapping);
      return result;

    } finally {
      if (account != null) {
        _accountDao.releaseFromLockTable(account.getId());
      }
    }
  }
  @Override
  public DomainRouterVO deployRouter(
      final RouterDeploymentDefinition routerDeploymentDefinition, final boolean startRouter)
      throws InsufficientAddressCapacityException, InsufficientServerCapacityException,
          InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException {

    final ServiceOfferingVO routerOffering =
        _serviceOfferingDao.findById(routerDeploymentDefinition.getServiceOfferingId());
    final Account owner = routerDeploymentDefinition.getOwner();

    // Router is the network element, we don't know the hypervisor type yet.
    // Try to allocate the domR twice using diff hypervisors, and when
    // failed both times, throw the exception up
    final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition);

    int allocateRetry = 0;
    int startRetry = 0;
    DomainRouterVO router = null;
    for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext(); ) {
      final HypervisorType hType = iter.next();
      try {
        final long id = _routerDao.getNextInSequence(Long.class, "id");
        if (s_logger.isDebugEnabled()) {
          s_logger.debug(
              String.format(
                  "Allocating the VR with id=%s in datacenter %s with the hypervisor type %s",
                  id, routerDeploymentDefinition.getDest().getDataCenter(), hType));
        }

        final String templateName =
            retrieveTemplateName(
                hType, routerDeploymentDefinition.getDest().getDataCenter().getId());
        final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);

        if (template == null) {
          s_logger.debug(hType + " won't support system vm, skip it");
          continue;
        }

        final boolean offerHA = routerOffering.getOfferHA();

        // routerDeploymentDefinition.getVpc().getId() ==> do not use
        // VPC because it is not a VPC offering.
        final Long vpcId =
            routerDeploymentDefinition.getVpc() != null
                ? routerDeploymentDefinition.getVpc().getId()
                : null;

        long userId = CallContext.current().getCallingUserId();
        if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
          final List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
          if (!userVOs.isEmpty()) {
            userId = userVOs.get(0).getId();
          }
        }

        router =
            new DomainRouterVO(
                id,
                routerOffering.getId(),
                routerDeploymentDefinition.getVirtualProvider().getId(),
                VirtualMachineName.getRouterName(id, s_vmInstanceName),
                template.getId(),
                template.getHypervisorType(),
                template.getGuestOSId(),
                owner.getDomainId(),
                owner.getId(),
                userId,
                routerDeploymentDefinition.isRedundant(),
                RedundantState.UNKNOWN,
                offerHA,
                false,
                vpcId);

        router.setDynamicallyScalable(template.isDynamicallyScalable());
        router.setRole(Role.VIRTUAL_ROUTER);
        router = _routerDao.persist(router);

        reallocateRouterNetworks(routerDeploymentDefinition, router, template, null);
        router = _routerDao.findById(router.getId());
      } catch (final InsufficientCapacityException ex) {
        if (allocateRetry < 2 && iter.hasNext()) {
          s_logger.debug(
              "Failed to allocate the VR with hypervisor type "
                  + hType
                  + ", retrying one more time");
          continue;
        } else {
          throw ex;
        }
      } finally {
        allocateRetry++;
      }

      if (startRouter) {
        try {
          router =
              startVirtualRouter(
                  router,
                  _accountMgr.getSystemUser(),
                  _accountMgr.getSystemAccount(),
                  routerDeploymentDefinition.getParams());
          break;
        } catch (final InsufficientCapacityException ex) {
          if (startRetry < 2 && iter.hasNext()) {
            s_logger.debug(
                "Failed to start the VR  "
                    + router
                    + " with hypervisor type "
                    + hType
                    + ", "
                    + "destroying it and recreating one more time");
            // destroy the router
            destroyRouter(
                router.getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM), User.UID_SYSTEM);
            continue;
          } else {
            throw ex;
          }
        } finally {
          startRetry++;
        }
      } else {
        // return stopped router
        return router;
      }
    }

    return router;
  }
  @Override
  public DomainRouterVO startVirtualRouter(
      final DomainRouterVO router,
      final User user,
      final Account caller,
      final Map<Param, Object> params)
      throws StorageUnavailableException, InsufficientCapacityException,
          ConcurrentOperationException, ResourceUnavailableException {

    if (router.getRole() != Role.VIRTUAL_ROUTER || !router.getIsRedundantRouter()) {
      return start(router, user, caller, params, null);
    }

    if (router.getState() == State.Running) {
      s_logger.debug("Redundant router " + router.getInstanceName() + " is already running!");
      return router;
    }

    //
    // If another thread has already requested a VR start, there is a
    // transition period for VR to transit from
    // Starting to Running, there exist a race conditioning window here
    // We will wait until VR is up or fail
    if (router.getState() == State.Starting) {
      return waitRouter(router);
    }

    final DataCenterDeployment plan = new DataCenterDeployment(0, null, null, null, null, null);
    DomainRouterVO result = null;
    assert router.getIsRedundantRouter();
    final List<Long> networkIds = _routerDao.getRouterNetworks(router.getId());

    DomainRouterVO routerToBeAvoid = null;
    if (networkIds.size() != 0) {
      final List<DomainRouterVO> routerList = _routerDao.findByNetwork(networkIds.get(0));
      for (final DomainRouterVO rrouter : routerList) {
        if (rrouter.getHostId() != null
            && rrouter.getIsRedundantRouter()
            && rrouter.getState() == State.Running) {
          if (routerToBeAvoid != null) {
            throw new ResourceUnavailableException(
                "Try to start router "
                    + router.getInstanceName()
                    + "("
                    + router.getId()
                    + ")"
                    + ", but there are already two redundant routers with IP "
                    + router.getPublicIpAddress()
                    + ", they are "
                    + rrouter.getInstanceName()
                    + "("
                    + rrouter.getId()
                    + ") and "
                    + routerToBeAvoid.getInstanceName()
                    + "("
                    + routerToBeAvoid.getId()
                    + ")",
                DataCenter.class,
                rrouter.getDataCenterId());
          }
          routerToBeAvoid = rrouter;
        }
      }
    }
    if (routerToBeAvoid == null) {
      return start(router, user, caller, params, null);
    }
    // We would try best to deploy the router to another place
    final int retryIndex = 5;
    final ExcludeList[] avoids = new ExcludeList[5];
    avoids[0] = new ExcludeList();
    avoids[0].addPod(routerToBeAvoid.getPodIdToDeployIn());
    avoids[1] = new ExcludeList();
    avoids[1].addCluster(_hostDao.findById(routerToBeAvoid.getHostId()).getClusterId());
    avoids[2] = new ExcludeList();
    final List<VolumeVO> volumes =
        _volumeDao.findByInstanceAndType(routerToBeAvoid.getId(), Volume.Type.ROOT);
    if (volumes != null && volumes.size() != 0) {
      avoids[2].addPool(volumes.get(0).getPoolId());
    }
    avoids[2].addHost(routerToBeAvoid.getHostId());
    avoids[3] = new ExcludeList();
    avoids[3].addHost(routerToBeAvoid.getHostId());
    avoids[4] = new ExcludeList();

    for (int i = 0; i < retryIndex; i++) {
      if (s_logger.isTraceEnabled()) {
        s_logger.trace(
            "Try to deploy redundant virtual router:"
                + router.getHostName()
                + ", for "
                + i
                + " time");
      }
      plan.setAvoids(avoids[i]);
      try {
        result = start(router, user, caller, params, plan);
      } catch (final InsufficientServerCapacityException ex) {
        result = null;
      }
      if (result != null) {
        break;
      }
    }
    return result;
  }
  @Override
  public boolean finalizeCommandsOnStart(
      Commands cmds, VirtualMachineProfile<DomainRouterVO> profile) {
    DomainRouterVO elbVm = profile.getVirtualMachine();
    DataCenterVO dcVo = _dcDao.findById(elbVm.getDataCenterId());

    NicProfile controlNic = null;
    Long guestNetworkId = null;

    if (profile.getHypervisorType() == HypervisorType.VMware
        && dcVo.getNetworkType() == NetworkType.Basic) {
      // TODO this is a ugly to test hypervisor type here
      // for basic network mode, we will use the guest NIC for control NIC
      for (NicProfile nic : profile.getNics()) {
        if (nic.getTrafficType() == TrafficType.Guest && nic.getIp4Address() != null) {
          controlNic = nic;
          guestNetworkId = nic.getNetworkId();
        }
      }
    } else {
      for (NicProfile nic : profile.getNics()) {
        if (nic.getTrafficType() == TrafficType.Control && nic.getIp4Address() != null) {
          controlNic = nic;
        } else if (nic.getTrafficType() == TrafficType.Guest) {
          guestNetworkId = nic.getNetworkId();
        }
      }
    }

    if (controlNic == null) {
      s_logger.error("Control network doesn't exist for the ELB vm " + elbVm);
      return false;
    }

    cmds.addCommand(
        "checkSsh",
        new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922));

    // Re-apply load balancing rules
    List<LoadBalancerVO> lbs = _elbVmMapDao.listLbsForElbVm(elbVm.getId());
    List<LoadBalancingRule> lbRules = new ArrayList<LoadBalancingRule>();
    for (LoadBalancerVO lb : lbs) {
      List<LbDestination> dstList = _lbMgr.getExistingDestinations(lb.getId());
      List<LbStickinessPolicy> policyList = _lbMgr.getStickinessPolicies(lb.getId());
      List<LbHealthCheckPolicy> hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId());
      LoadBalancingRule loadBalancing =
          new LoadBalancingRule(lb, dstList, policyList, hcPolicyList);
      lbRules.add(loadBalancing);
    }

    s_logger.debug(
        "Found "
            + lbRules.size()
            + " load balancing rule(s) to apply as a part of ELB vm "
            + elbVm
            + " start.");
    if (!lbRules.isEmpty()) {
      createApplyLoadBalancingRulesCommands(lbRules, elbVm, cmds, guestNetworkId);
    }

    return true;
  }