@Override
  public void deployVirtualMachine(
      String reservationId, String caller, Map<VirtualMachineProfile.Param, Object> params)
      throws InsufficientCapacityException, ResourceUnavailableException {
    // grab the VM Id and destination using the reservationId.

    VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId);
    long vmId = vmReservation.getVmId();

    VMInstanceVO vm = _vmDao.findById(vmId);
    // Pass it down
    Long poolId = null;
    Map<Long, Long> storage = vmReservation.getVolumeReservation();
    if (storage != null) {
      List<Long> volIdList = new ArrayList<Long>(storage.keySet());
      if (volIdList != null && !volIdList.isEmpty()) {
        poolId = storage.get(volIdList.get(0));
      }
    }

    DataCenterDeployment reservedPlan =
        new DataCenterDeployment(
            vm.getDataCenterId(),
            vmReservation.getPodId(),
            vmReservation.getClusterId(),
            vmReservation.getHostId(),
            null,
            null);
    try {
      VMInstanceVO vmDeployed =
          _itMgr.start(
              vm,
              params,
              _userDao.findById(new Long(caller)),
              _accountDao.findById(vm.getAccountId()),
              reservedPlan);
    } catch (Exception ex) {
      // Retry the deployment without using the reservation plan
      DataCenterDeployment plan =
          new DataCenterDeployment(vm.getDataCenterId(), null, null, null, null, null);
      _itMgr.start(
          vm,
          params,
          _userDao.findById(new Long(caller)),
          _accountDao.findById(vm.getAccountId()),
          plan);
    }
  }
 @Override
 public List<? extends VpnUser> listVpnUsers(long vpnOwnerId, String userName) {
   Account caller = CallContext.current().getCallingAccount();
   Account owner = _accountDao.findById(vpnOwnerId);
   _accountMgr.checkAccess(caller, null, true, owner);
   return _vpnUsersDao.listByAccount(vpnOwnerId);
 }
  public SslCertResponse createCertResponse(SslCertVO cert, List<LoadBalancerCertMapVO> lbCertMap) {
    SslCertResponse response = new SslCertResponse();

    Account account = _accountDao.findByIdIncludingRemoved(cert.getAccountId());

    response.setObjectName("sslcert");
    response.setId(cert.getUuid());
    response.setCertificate(cert.getCertificate());
    response.setPrivatekey(cert.getKey());
    response.setFingerprint(cert.getFingerPrint());
    response.setAccountName(account.getAccountName());

    if (cert.getChain() != null) response.setCertchain(cert.getChain());

    if (lbCertMap != null && !lbCertMap.isEmpty()) {
      List<String> lbIds = new ArrayList<String>();
      for (LoadBalancerCertMapVO mapVO : lbCertMap) {
        LoadBalancer lb = _entityMgr.findById(LoadBalancerVO.class, mapVO.getLbId());
        lbIds.add(lb.getUuid());
      }
      response.setLbIds(lbIds);
    }

    return response;
  }
  @Override
  public boolean destroyVirtualMachine(VMEntityVO vmEntityVO, String caller)
      throws AgentUnavailableException, OperationTimedoutException, ConcurrentOperationException {

    VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
    return _itMgr.destroy(
        vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()));
  }
  @Override
  public boolean stopvirtualmachine(VMEntityVO vmEntityVO, String caller)
      throws ResourceUnavailableException {

    VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid());
    return _itMgr.stop(
        vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()));
  }
  @Override
  public void createAsync(
      DataStore dataStore,
      DataObject dataObject,
      AsyncCompletionCallback<CreateCmdResult> callback) {
    String iqn = null;
    String errMsg = null;

    if (dataObject.getType() == DataObjectType.VOLUME) {
      VolumeInfo volumeInfo = (VolumeInfo) dataObject;
      AccountVO account = _accountDao.findById(volumeInfo.getAccountId());
      String sfAccountName = getSfAccountName(account.getUuid(), account.getAccountId());

      long storagePoolId = dataStore.getId();
      SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);

      if (!sfAccountExists(sfAccountName, sfConnection)) {
        SolidFireUtil.SolidFireAccount sfAccount =
            createSolidFireAccount(sfAccountName, sfConnection);

        updateCsDbWithAccountInfo(account.getId(), sfAccount);
      }

      SolidFireUtil.SolidFireVolume sfVolume = createSolidFireVolume(volumeInfo, sfConnection);

      iqn = sfVolume.getIqn();

      VolumeVO volume = this._volumeDao.findById(volumeInfo.getId());

      volume.set_iScsiName(iqn);
      volume.setFolder(String.valueOf(sfVolume.getId()));
      volume.setPoolType(StoragePoolType.IscsiLUN);
      volume.setPoolId(storagePoolId);

      _volumeDao.update(volume.getId(), volume);

      StoragePoolVO storagePool = _storagePoolDao.findById(dataStore.getId());

      long capacityBytes = storagePool.getCapacityBytes();
      long usedBytes = storagePool.getUsedBytes();

      usedBytes += volumeInfo.getSize();

      storagePool.setUsedBytes(usedBytes > capacityBytes ? capacityBytes : usedBytes);

      _storagePoolDao.update(storagePoolId, storagePool);
    } else {
      errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to createAsync";
    }

    // path = iqn
    // size is pulled from DataObject instance, if errMsg is null
    CreateCmdResult result = new CreateCmdResult(iqn, new Answer(null, errMsg == null, errMsg));

    result.setResult(errMsg);

    callback.complete(result);
  }
  @Override
  public void deleteAsync(
      DataStore dataStore, DataObject dataObject, AsyncCompletionCallback<CommandResult> callback) {
    String errMsg = null;

    if (dataObject.getType() == DataObjectType.VOLUME) {
      VolumeInfo volumeInfo = (VolumeInfo) dataObject;
      AccountVO account = _accountDao.findById(volumeInfo.getAccountId());
      AccountDetailVO accountDetails =
          _accountDetailsDao.findDetail(account.getAccountId(), SolidFireUtil.ACCOUNT_ID);
      long sfAccountId = Long.parseLong(accountDetails.getValue());

      long storagePoolId = dataStore.getId();
      SolidFireConnection sfConnection = getSolidFireConnection(storagePoolId);

      deleteSolidFireVolume(volumeInfo, sfConnection);

      _volumeDao.deleteVolumesByInstance(volumeInfo.getId());

      //            if (!sfAccountHasVolume(sfAccountId, sfConnection)) {
      //                // delete the account from the SolidFire SAN
      //                deleteSolidFireAccount(sfAccountId, sfConnection);
      //
      //                // delete the info in the account_details table
      //                // that's related to the SolidFire account
      //                _accountDetailsDao.deleteDetails(account.getAccountId());
      //            }

      StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId);

      long usedBytes = storagePool.getUsedBytes();

      usedBytes -= volumeInfo.getSize();

      storagePool.setUsedBytes(usedBytes < 0 ? 0 : usedBytes);

      _storagePoolDao.update(storagePoolId, storagePool);
    } else {
      errMsg = "Invalid DataObjectType (" + dataObject.getType() + ") passed to deleteAsync";
    }

    CommandResult result = new CommandResult();

    result.setResult(errMsg);

    callback.complete(result);
  }
  @Override
  @DB
  public VpnUser addVpnUser(long vpnOwnerId, String username, String password) {
    Account caller = UserContext.current().getCaller();

    if (!username.matches("^[a-zA-Z0-9][a-zA-Z0-9@._-]{2,63}$")) {
      throw new InvalidParameterValueException(
          "Username has to be begin with an alphabet have 3-64 characters including alphabets, numbers and the set '@.-_'");
    }
    if (!password.matches("^[a-zA-Z0-9][a-zA-Z0-9@#+=._-]{2,31}$")) {
      throw new InvalidParameterValueException(
          "Password has to be 3-32 characters including alphabets, numbers and the set '@#+=.-_'");
    }
    Transaction txn = Transaction.currentTxn();
    txn.start();
    Account owner = _accountDao.lockRow(vpnOwnerId, true);
    if (owner == null) {
      throw new InvalidParameterValueException("Unable to add vpn user: Another operation active");
    }
    _accountMgr.checkAccess(caller, null, true, owner);

    // don't allow duplicated user names for the same account
    VpnUserVO vpnUser = _vpnUsersDao.findByAccountAndUsername(owner.getId(), username);
    if (vpnUser != null) {
      throw new InvalidParameterValueException(
          "VPN User with name " + username + " is already added for account " + owner);
    }

    long userCount = _vpnUsersDao.getVpnUserCount(owner.getId());
    if (userCount >= _userLimit) {
      throw new AccountLimitException(
          "Cannot add more than " + _userLimit + " remote access vpn users");
    }

    VpnUser user =
        _vpnUsersDao.persist(new VpnUserVO(vpnOwnerId, owner.getDomainId(), username, password));
    UsageEventUtils.publishUsageEvent(
        EventTypes.EVENT_VPN_USER_ADD,
        user.getAccountId(),
        0,
        user.getId(),
        user.getUsername(),
        user.getClass().getName(),
        user.getUuid());
    txn.commit();
    return user;
  }
 @Override
 public SecurityGroupVO createDefaultSecurityGroup(Long accountId) {
   SecurityGroupVO groupVO =
       _securityGroupDao.findByAccountAndName(accountId, SecurityGroupManager.DEFAULT_GROUP_NAME);
   if (groupVO == null) {
     Account accVO = _accountDao.findById(accountId);
     if (accVO != null) {
       return createSecurityGroup(
           SecurityGroupManager.DEFAULT_GROUP_NAME,
           SecurityGroupManager.DEFAULT_GROUP_DESCRIPTION,
           accVO.getDomainId(),
           accVO.getId(),
           accVO.getAccountName());
     }
   }
   return groupVO;
 }
  private Long accountAndUserValidation(
      Account account, Long userId, UserVmVO vmInstanceCheck, VMTemplateVO template, String msg)
      throws PermissionDeniedException {

    if (account != null) {
      if (!isAdmin(account.getType())) {
        if ((vmInstanceCheck != null) && (account.getId() != vmInstanceCheck.getAccountId())) {
          throw new PermissionDeniedException(msg + ". Permission denied.");
        }

        if ((template != null)
            && (!template.isPublicTemplate()
                && (account.getId() != template.getAccountId())
                && (template.getTemplateType() != TemplateType.PERHOST))) {
          throw new PermissionDeniedException(msg + ". Permission denied.");
        }

      } else {
        if ((vmInstanceCheck != null)
            && !_domainDao.isChildDomain(account.getDomainId(), vmInstanceCheck.getDomainId())) {
          throw new PermissionDeniedException(msg + ". Permission denied.");
        }
        // FIXME: if template/ISO owner is null we probably need to
        // throw some kind of exception

        if (template != null) {
          Account templateOwner = _accountDao.findById(template.getAccountId());
          if ((templateOwner != null)
              && !_domainDao.isChildDomain(account.getDomainId(), templateOwner.getDomainId())) {
            throw new PermissionDeniedException(msg + ". Permission denied.");
          }
        }
      }
    }
    // If command is executed via 8096 port, set userId to the id of System
    // account (1)
    if (userId == null) {
      userId = new Long(1);
    }

    return userId;
  }
 @Bean
 public EntityManager entityManager() {
   EntityManager mock = Mockito.mock(EntityManager.class);
   try {
     Mockito.when(mock.findById(Matchers.same(Account.class), Matchers.anyLong()))
         .thenReturn(_accountDao.findById(Account.ACCOUNT_ID_SYSTEM));
     Mockito.when(mock.findById(Matchers.same(User.class), Matchers.anyLong()))
         .thenReturn(_userDao.findById(User.UID_SYSTEM));
     Mockito.when(mock.findById(Matchers.same(NetworkOffering.class), Matchers.any(Long.class)))
         .thenAnswer(
             new Answer<NetworkOffering>() {
               @Override
               public NetworkOffering answer(final InvocationOnMock invocation) throws Throwable {
                 Long id = (Long) invocation.getArguments()[1];
                 return _networkOfferingDao.findById(id);
               }
             });
     Mockito.when(mock.findById(Matchers.same(IpAddress.class), Matchers.any(Long.class)))
         .thenAnswer(
             new Answer<IpAddress>() {
               @Override
               public IpAddress answer(final InvocationOnMock invocation) throws Throwable {
                 Long id = (Long) invocation.getArguments()[1];
                 return _ipAddressDao.findById(id);
               }
             });
     Mockito.when(mock.findById(Matchers.same(DataCenter.class), Matchers.any(Long.class)))
         .thenAnswer(
             new Answer<DataCenter>() {
               @Override
               public DataCenter answer(final InvocationOnMock invocation) throws Throwable {
                 Long id = (Long) invocation.getArguments()[1];
                 return _zoneDao.findById(id);
               }
             });
   } catch (Exception e) {
     e.printStackTrace();
   }
   CallContext.init(mock);
   return mock;
 }
  @DB
  @Override
  public boolean applyVpnUsers(long vpnOwnerId, String userName) {
    Account caller = CallContext.current().getCallingAccount();
    Account owner = _accountDao.findById(vpnOwnerId);
    _accountMgr.checkAccess(caller, null, true, owner);

    s_logger.debug("Applying vpn users for " + owner);
    List<RemoteAccessVpnVO> vpns = _remoteAccessVpnDao.findByAccount(vpnOwnerId);

    List<VpnUserVO> users = _vpnUsersDao.listByAccount(vpnOwnerId);

    // If user is in Active state, we still have to resend them therefore their status has to be Add
    for (VpnUserVO user : users) {
      if (user.getState() == State.Active) {
        user.setState(State.Add);
        _vpnUsersDao.update(user.getId(), user);
      }
    }

    boolean success = true;

    boolean[] finals = new boolean[users.size()];
    for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) {
      s_logger.debug("Applying vpn access to " + element.getName());
      for (RemoteAccessVpnVO vpn : vpns) {
        try {
          String[] results = element.applyVpnUsers(vpn, users);
          if (results != null) {
            for (int i = 0; i < results.length; i++) {
              s_logger.debug(
                  "VPN User "
                      + users.get(i)
                      + (results[i] == null
                          ? " is set on "
                          : (" couldn't be set due to " + results[i]) + " on ")
                      + vpn);
              if (results[i] == null) {
                if (!finals[i]) {
                  finals[i] = true;
                }
              } else {
                finals[i] = false;
                success = false;
              }
            }
          }
        } catch (Exception e) {
          s_logger.warn("Unable to apply vpn users ", e);
          success = false;

          for (int i = 0; i < finals.length; i++) {
            finals[i] = false;
          }
        }
      }
    }

    for (int i = 0; i < finals.length; i++) {
      final VpnUserVO user = users.get(i);
      if (finals[i]) {
        if (user.getState() == State.Add) {
          user.setState(State.Active);
          _vpnUsersDao.update(user.getId(), user);
        } else if (user.getState() == State.Revoke) {
          _vpnUsersDao.remove(user.getId());
        }
      } else {
        if (user.getState() == State.Add && (user.getUsername()).equals(userName)) {
          Transaction.execute(
              new TransactionCallbackNoReturn() {
                @Override
                public void doInTransactionWithoutResult(TransactionStatus status) {
                  _vpnUsersDao.remove(user.getId());
                  UsageEventUtils.publishUsageEvent(
                      EventTypes.EVENT_VPN_USER_REMOVE,
                      user.getAccountId(),
                      0,
                      user.getId(),
                      user.getUsername(),
                      user.getClass().getName(),
                      user.getUuid());
                }
              });
        }
        s_logger.warn(
            "Failed to apply vpn for user "
                + user.getUsername()
                + ", accountId="
                + user.getAccountId());
      }
    }

    return success;
  }
  @Override
  @DB
  @SuppressWarnings("rawtypes")
  public List<IngressRuleVO> authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd) {
    Long securityGroupId = cmd.getSecurityGroupId();
    String protocol = cmd.getProtocol();
    Integer startPort = cmd.getStartPort();
    Integer endPort = cmd.getEndPort();
    Integer icmpType = cmd.getIcmpType();
    Integer icmpCode = cmd.getIcmpCode();
    List<String> cidrList = cmd.getCidrList();
    Map groupList = cmd.getUserSecurityGroupList();
    Integer startPortOrType = null;
    Integer endPortOrCode = null;

    // Validate parameters
    SecurityGroup securityGroup = _securityGroupDao.findById(securityGroupId);
    if (securityGroup == null) {
      throw new InvalidParameterValueException(
          "Unable to find security group by id " + securityGroupId);
    }

    if (cidrList == null && groupList == null) {
      throw new InvalidParameterValueException(
          "At least one cidr or at least one security group needs to be specified");
    }

    Account caller = UserContext.current().getCaller();
    Account owner = _accountMgr.getAccount(securityGroup.getAccountId());

    if (owner == null) {
      throw new InvalidParameterValueException(
          "Unable to find security group owner by id=" + securityGroup.getAccountId());
    }

    // Verify permissions
    _accountMgr.checkAccess(caller, null, securityGroup);
    Long domainId = owner.getDomainId();

    if (protocol == null) {
      protocol = NetUtils.ALL_PROTO;
    }

    if (!NetUtils.isValidSecurityGroupProto(protocol)) {
      throw new InvalidParameterValueException("Invalid protocol " + protocol);
    }
    if ("icmp".equalsIgnoreCase(protocol)) {
      if ((icmpType == null) || (icmpCode == null)) {
        throw new InvalidParameterValueException(
            "Invalid ICMP type/code specified, icmpType = "
                + icmpType
                + ", icmpCode = "
                + icmpCode);
      }
      if (icmpType == -1 && icmpCode != -1) {
        throw new InvalidParameterValueException("Invalid icmp type range");
      }
      if (icmpCode > 255) {
        throw new InvalidParameterValueException("Invalid icmp code ");
      }
      startPortOrType = icmpType;
      endPortOrCode = icmpCode;
    } else if (protocol.equals(NetUtils.ALL_PROTO)) {
      if ((startPort != null) || (endPort != null)) {
        throw new InvalidParameterValueException(
            "Cannot specify startPort or endPort without specifying protocol");
      }
      startPortOrType = 0;
      endPortOrCode = 0;
    } else {
      if ((startPort == null) || (endPort == null)) {
        throw new InvalidParameterValueException(
            "Invalid port range specified, startPort = " + startPort + ", endPort = " + endPort);
      }
      if (startPort == 0 && endPort == 0) {
        endPort = 65535;
      }
      if (startPort > endPort) {
        throw new InvalidParameterValueException("Invalid port range " + startPort + ":" + endPort);
      }
      if (startPort > 65535 || endPort > 65535 || startPort < -1 || endPort < -1) {
        throw new InvalidParameterValueException(
            "Invalid port numbers " + startPort + ":" + endPort);
      }

      if (startPort < 0 || endPort < 0) {
        throw new InvalidParameterValueException("Invalid port range " + startPort + ":" + endPort);
      }
      startPortOrType = startPort;
      endPortOrCode = endPort;
    }

    protocol = protocol.toLowerCase();

    List<SecurityGroupVO> authorizedGroups = new ArrayList<SecurityGroupVO>();
    if (groupList != null) {
      Collection userGroupCollection = groupList.values();
      Iterator iter = userGroupCollection.iterator();
      while (iter.hasNext()) {
        HashMap userGroup = (HashMap) iter.next();
        String group = (String) userGroup.get("group");
        String authorizedAccountName = (String) userGroup.get("account");

        if ((group == null) || (authorizedAccountName == null)) {
          throw new InvalidParameterValueException(
              "Invalid user group specified, fields 'group' and 'account' cannot be null, please specify groups in the form:  userGroupList[0].group=XXX&userGroupList[0].account=YYY");
        }

        Account authorizedAccount = _accountDao.findActiveAccount(authorizedAccountName, domainId);
        if (authorizedAccount == null) {
          throw new InvalidParameterValueException(
              "Nonexistent account: "
                  + authorizedAccountName
                  + " when trying to authorize ingress for "
                  + securityGroupId
                  + ":"
                  + protocol
                  + ":"
                  + startPortOrType
                  + ":"
                  + endPortOrCode);
        }

        SecurityGroupVO groupVO =
            _securityGroupDao.findByAccountAndName(authorizedAccount.getId(), group);
        if (groupVO == null) {
          throw new InvalidParameterValueException(
              "Nonexistent group "
                  + group
                  + " for account "
                  + authorizedAccountName
                  + "/"
                  + domainId
                  + " is given, unable to authorize ingress.");
        }

        // Check permissions
        if (domainId != groupVO.getDomainId()) {
          throw new PermissionDeniedException(
              "Can't add security group id="
                  + groupVO.getDomainId()
                  + " as it belongs to different domain");
        }

        authorizedGroups.add(groupVO);
      }
    }

    final Transaction txn = Transaction.currentTxn();
    final Set<SecurityGroupVO> authorizedGroups2 =
        new TreeSet<SecurityGroupVO>(new SecurityGroupVOComparator());

    authorizedGroups2.addAll(authorizedGroups); // Ensure we don't re-lock the same row
    txn.start();

    // Prevents other threads/management servers from creating duplicate ingress rules
    securityGroup = _securityGroupDao.acquireInLockTable(securityGroupId);
    if (securityGroup == null) {
      s_logger.warn("Could not acquire lock on network security group: id= " + securityGroupId);
      return null;
    }
    List<IngressRuleVO> newRules = new ArrayList<IngressRuleVO>();
    try {
      for (final SecurityGroupVO ngVO : authorizedGroups2) {
        final Long ngId = ngVO.getId();
        // Don't delete the referenced group from under us
        if (ngVO.getId() != securityGroup.getId()) {
          final SecurityGroupVO tmpGrp = _securityGroupDao.lockRow(ngId, false);
          if (tmpGrp == null) {
            s_logger.warn("Failed to acquire lock on security group: " + ngId);
            txn.rollback();
            return null;
          }
        }
        IngressRuleVO ingressRule =
            _ingressRuleDao.findByProtoPortsAndAllowedGroupId(
                securityGroup.getId(), protocol, startPortOrType, endPortOrCode, ngVO.getId());
        if (ingressRule != null) {
          continue; // rule already exists.
        }
        ingressRule =
            new IngressRuleVO(
                securityGroup.getId(), startPortOrType, endPortOrCode, protocol, ngVO.getId());
        ingressRule = _ingressRuleDao.persist(ingressRule);
        newRules.add(ingressRule);
      }
      if (cidrList != null) {
        for (String cidr : cidrList) {
          IngressRuleVO ingressRule =
              _ingressRuleDao.findByProtoPortsAndCidr(
                  securityGroup.getId(), protocol, startPortOrType, endPortOrCode, cidr);
          if (ingressRule != null) {
            continue;
          }
          ingressRule =
              new IngressRuleVO(
                  securityGroup.getId(), startPortOrType, endPortOrCode, protocol, cidr);
          ingressRule = _ingressRuleDao.persist(ingressRule);
          newRules.add(ingressRule);
        }
      }
      if (s_logger.isDebugEnabled()) {
        s_logger.debug(
            "Added " + newRules.size() + " rules to security group " + securityGroup.getName());
      }
      txn.commit();
      final ArrayList<Long> affectedVms = new ArrayList<Long>();
      affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId()));
      scheduleRulesetUpdateToHosts(affectedVms, true, null);
      return newRules;
    } catch (Exception e) {
      s_logger.warn("Exception caught when adding ingress rules ", e);
      throw new CloudRuntimeException("Exception caught when adding ingress rules", e);
    } finally {
      if (securityGroup != null) {
        _securityGroupDao.releaseFromLockTable(securityGroup.getId());
      }
    }
  }
  @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());
      }
    }
  }
  public TemplateProfile prepare(
      boolean isIso,
      Long userId,
      String name,
      String displayText,
      Integer bits,
      Boolean passwordEnabled,
      Boolean requiresHVM,
      String url,
      Boolean isPublic,
      Boolean featured,
      Boolean isExtractable,
      String format,
      Long guestOSId,
      Long zoneId,
      HypervisorType hypervisorType,
      String chksum,
      Boolean bootable,
      String templateTag,
      Account templateOwner,
      Map details)
      throws ResourceAllocationException {
    // Long accountId = null;
    // parameters verification

    if (isPublic == null) {
      isPublic = Boolean.FALSE;
    }

    if (zoneId.longValue() == -1) {
      zoneId = null;
    }

    if (isIso) {
      if (bootable == null) {
        bootable = Boolean.TRUE;
      }
      GuestOS noneGuestOs = ApiDBUtils.findGuestOSByDisplayName(ApiConstants.ISO_GUEST_OS_NONE);
      if ((guestOSId == null || guestOSId == noneGuestOs.getId()) && bootable == true) {
        throw new InvalidParameterValueException("Please pass a valid GuestOS Id");
      }
      if (bootable == false) {
        guestOSId = noneGuestOs.getId(); // Guest os id of None.
      }
    } else {
      if (bits == null) {
        bits = Integer.valueOf(64);
      }
      if (passwordEnabled == null) {
        passwordEnabled = false;
      }
      if (requiresHVM == null) {
        requiresHVM = true;
      }
    }

    if (isExtractable == null) {
      isExtractable = Boolean.FALSE;
    }

    boolean isAdmin =
        _accountDao.findById(templateOwner.getId()).getType() == Account.ACCOUNT_TYPE_ADMIN;

    if (!isAdmin && zoneId == null) {
      throw new InvalidParameterValueException("Please specify a valid zone Id.");
    }

    if (url.toLowerCase().contains("file://")) {
      throw new InvalidParameterValueException("File:// type urls are currently unsupported");
    }

    boolean allowPublicUserTemplates =
        Boolean.parseBoolean(_configDao.getValue("allow.public.user.templates"));
    if (!isAdmin && !allowPublicUserTemplates && isPublic) {
      throw new InvalidParameterValueException("Only private templates/ISO can be created.");
    }

    if (!isAdmin || featured == null) {
      featured = Boolean.FALSE;
    }

    // If command is executed via 8096 port, set userId to the id of System
    // account (1)
    if (userId == null) {
      userId = Long.valueOf(1);
    }

    ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase());
    if (imgfmt == null) {
      throw new IllegalArgumentException(
          "Image format is incorrect "
              + format
              + ". Supported formats are "
              + EnumUtils.listValues(ImageFormat.values()));
    }

    // Check that the resource limit for templates/ISOs won't be exceeded
    UserVO user = _userDao.findById(userId);
    if (user == null) {
      throw new IllegalArgumentException("Unable to find user with id " + userId);
    }

    _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template);

    if (templateOwner.getType() != Account.ACCOUNT_TYPE_ADMIN && zoneId == null) {
      throw new IllegalArgumentException("Only admins can create templates in all zones");
    }

    // If a zoneId is specified, make sure it is valid
    if (zoneId != null) {
      DataCenterVO zone = _dcDao.findById(zoneId);
      if (zone == null) {
        throw new IllegalArgumentException("Please specify a valid zone.");
      }
      Account caller = UserContext.current().getCaller();
      if (Grouping.AllocationState.Disabled == zone.getAllocationState()
          && !_accountMgr.isRootAdmin(caller.getType())) {
        throw new PermissionDeniedException(
            "Cannot perform this operation, Zone is currently disabled: " + zoneId);
      }
    }

    List<VMTemplateVO> systemvmTmplts = _tmpltDao.listAllSystemVMTemplates();
    for (VMTemplateVO template : systemvmTmplts) {
      if (template.getName().equalsIgnoreCase(name)
          || template.getDisplayText().equalsIgnoreCase(displayText)) {
        throw new IllegalArgumentException("Cannot use reserved names for templates");
      }
    }

    Long id = _tmpltDao.getNextInSequence(Long.class, "id");
    UserContext.current().setEventDetails("Id: " + id + " name: " + name);
    return new TemplateProfile(
        id,
        userId,
        name,
        displayText,
        bits,
        passwordEnabled,
        requiresHVM,
        url,
        isPublic,
        featured,
        isExtractable,
        imgfmt,
        guestOSId,
        zoneId,
        hypervisorType,
        templateOwner.getAccountName(),
        templateOwner.getDomainId(),
        templateOwner.getAccountId(),
        chksum,
        bootable,
        templateTag,
        details);
  }