/** Get a list of security group ids for the slave */
  private List<String> getEc2SecurityGroups(AmazonEC2 ec2) throws AmazonClientException {
    List<String> groupIds = new ArrayList<String>();

    DescribeSecurityGroupsResult groupResult =
        getSecurityGroupsBy("group-name", securityGroupSet, ec2);
    if (groupResult.getSecurityGroups().size() == 0) {
      groupResult = getSecurityGroupsBy("group-id", securityGroupSet, ec2);
    }

    for (SecurityGroup group : groupResult.getSecurityGroups()) {
      if (group.getVpcId() != null && !group.getVpcId().isEmpty()) {
        List<Filter> filters = new ArrayList<Filter>();
        filters.add(new Filter("vpc-id").withValues(group.getVpcId()));
        filters.add(new Filter("state").withValues("available"));
        filters.add(new Filter("subnet-id").withValues(getSubnetId()));

        DescribeSubnetsRequest subnetReq = new DescribeSubnetsRequest();
        subnetReq.withFilters(filters);
        DescribeSubnetsResult subnetResult = ec2.describeSubnets(subnetReq);

        List<Subnet> subnets = subnetResult.getSubnets();
        if (subnets != null && !subnets.isEmpty()) {
          groupIds.add(group.getGroupId());
        }
      }
    }

    if (securityGroupSet.size() != groupIds.size()) {
      throw new AmazonClientException(
          "Security groups must all be VPC security groups to work in a VPC context");
    }

    return groupIds;
  }
 @Override
 public boolean isVmMappedToDefaultSecurityGroup(long vmId) {
   UserVmVO vm = _userVmMgr.getVirtualMachine(vmId);
   SecurityGroup defaultGroup = getDefaultSecurityGroup(vm.getAccountId());
   if (defaultGroup == null) {
     s_logger.warn("Unable to find default security group for account id=" + vm.getAccountId());
     return false;
   }
   SecurityGroupVMMapVO map = _securityGroupVMMapDao.findByVmIdGroupId(vmId, defaultGroup.getId());
   if (map == null) {
     return false;
   } else {
     return true;
   }
 }
  @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());
      }
    }
  }