You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cloudstack.apache.org by David Nalley <da...@gnsa.us> on 2013/03/04 06:41:26 UTC

Re: [1/2] CLOUDSTACK-24: mipn feature for isolated and vpc networks

Abhi, Jayapal:

Where are tests for this feature?
I asked about the tests on February 10 on the review itself, Chip
asked about tests on Feb 11th on the review as well. The patch has
subsequently had three revisions, yet nary a response to either my
Chip's questions or adding tests to the patch itself.
Why was this committed sans tests?

--David

On Mon, Mar 4, 2013 at 12:32 AM,  <ap...@apache.org> wrote:
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/rules/RulesManagerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java
> index 614d308..29ed5f3 100755
> --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
> +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
> @@ -78,10 +78,13 @@ import com.cloud.utils.db.Transaction;
>  import com.cloud.utils.exception.CloudRuntimeException;
>  import com.cloud.utils.net.Ip;
>  import com.cloud.vm.Nic;
> +import com.cloud.vm.NicSecondaryIp;
>  import com.cloud.vm.UserVmVO;
>  import com.cloud.vm.VirtualMachine;
>  import com.cloud.vm.VirtualMachine.Type;
>  import com.cloud.vm.dao.NicDao;
> +import com.cloud.vm.dao.NicSecondaryIpDao;
> +import com.cloud.vm.dao.NicSecondaryIpVO;
>  import com.cloud.vm.dao.UserVmDao;
>
>  @Component
> @@ -123,6 +126,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>      ResourceTagDao _resourceTagDao;
>      @Inject
>      VpcManager _vpcMgr;
> +    @Inject
> +    NicSecondaryIpDao _nicSecondaryDao;
>
>      @Override
>      public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) {
> @@ -172,7 +177,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>      @Override
>      @DB
>      @ActionEvent(eventType = EventTypes.EVENT_NET_RULE_ADD, eventDescription = "creating forwarding rule", create = true)
> -    public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean openFirewall)
> +    public PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, Ip vmIp, boolean openFirewall)
>              throws NetworkRuleConflictException {
>          UserContext ctx = UserContext.current();
>          Account caller = ctx.getCaller();
> @@ -192,6 +197,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>          Network network = _networkModel.getNetwork(networkId);
>          //associate ip address to network (if needed)
>          boolean performedIpAssoc = false;
> +        Nic guestNic;
>          if (ipAddress.getAssociatedWithNetworkId() == null) {
>              boolean assignToVpcNtwk =  network.getVpcId() != null
>                      && ipAddress.getVpcId() != null && ipAddress.getVpcId().longValue() == network.getVpcId();
> @@ -244,13 +250,26 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>
>              // Verify that vm has nic in the network
>              Ip dstIp = rule.getDestinationIpAddress();
> -            Nic guestNic = _networkModel.getNicInNetwork(vmId, networkId);
> +            guestNic = _networkModel.getNicInNetwork(vmId, networkId);
>              if (guestNic == null || guestNic.getIp4Address() == null) {
>                  throw new InvalidParameterValueException("Vm doesn't belong to network associated with ipAddress");
>              } else {
>                  dstIp = new Ip(guestNic.getIp4Address());
>              }
>
> +            if (vmIp != null) {
> +                //vm ip is passed so it can be primary or secondary ip addreess.
> +                if (!dstIp.equals(vmIp)) {
> +                    //the vm ip is secondary ip to the nic.
> +                    // is vmIp is secondary ip or not
> +                    NicSecondaryIp secondaryIp = _nicSecondaryDao.findByIp4AddressAndNicId(vmIp.toString(), guestNic.getId());
> +                    if (secondaryIp == null) {
> +                        throw new InvalidParameterValueException("IP Address is not in the VM nic's network ");
> +                    }
> +                    dstIp = vmIp;
> +                }
> +            }
> +
>              //if start port and end port are passed in, and they are not equal to each other, perform the validation
>              boolean validatePortRange = false;
>              if (rule.getSourcePortStart().intValue() != rule.getSourcePortEnd().intValue()
> @@ -350,8 +369,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              throw new InvalidParameterValueException("Can't create ip forwarding rules for the network where elasticIP service is enabled");
>          }
>
> -        String dstIp = _networkModel.getIpInNetwork(ipAddress.getAssociatedWithVmId(), networkId);
> -
> +        //String dstIp = _networkModel.getIpInNetwork(ipAddress.getAssociatedWithVmId(), networkId);
> +        String dstIp = ipAddress.getVmIp();
>          Transaction txn = Transaction.currentTxn();
>          txn.start();
>
> @@ -397,14 +416,13 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>
>      @Override
>      @ActionEvent(eventType = EventTypes.EVENT_ENABLE_STATIC_NAT, eventDescription = "enabling static nat")
> -    public boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm)
> +    public boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm, String vmGuestIp)
>              throws NetworkRuleConflictException, ResourceUnavailableException {
>          UserContext ctx = UserContext.current();
>          Account caller = ctx.getCaller();
>          UserContext.current().setEventDetails("Ip Id: " + ipId);
>
>          // Verify input parameters
> -
>          IPAddressVO ipAddress = _ipAddressDao.findById(ipId);
>          if (ipAddress == null) {
>              throw new InvalidParameterValueException("Unable to find ip address by id " + ipId);
> @@ -414,6 +432,10 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>          boolean performedIpAssoc = false;
>          boolean isOneToOneNat = ipAddress.isOneToOneNat();
>          Long associatedWithVmId = ipAddress.getAssociatedWithVmId();
> +        Nic guestNic;
> +        NicSecondaryIpVO nicSecIp = null;
> +        String dstIp = null;
> +
>          try {
>              Network network = _networkModel.getNetwork(networkId);
>              if (network == null) {
> @@ -421,11 +443,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              }
>
>              // Check that vm has a nic in the network
> -            Nic guestNic = _networkModel.getNicInNetwork(vmId, networkId);
> +            guestNic = _networkModel.getNicInNetwork(vmId, networkId);
>              if (guestNic == null) {
>                  throw new InvalidParameterValueException("Vm doesn't belong to the network with specified id");
>              }
> -
> +            dstIp = guestNic.getIp4Address();
>
>              if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.StaticNat)) {
>                  throw new InvalidParameterValueException("Unable to create static nat rule; StaticNat service is not " +
> @@ -466,13 +488,36 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>                  // Check permissions
>                  checkIpAndUserVm(ipAddress, vm, caller);
>
> +                //is static nat is for vm secondary ip
> +                //dstIp = guestNic.getIp4Address();
> +                if (vmGuestIp != null) {
> +                    //dstIp = guestNic.getIp4Address();
> +
> +                    if (!dstIp.equals(vmGuestIp)) {
> +                        //check whether the secondary ip set to the vm or not
> +                        boolean secondaryIpSet = _networkMgr.isSecondaryIpSetForNic(guestNic.getId());
> +                        if (!secondaryIpSet) {
> +                            throw new InvalidParameterValueException("VM ip " + vmGuestIp + " address not belongs to the vm");
> +                        }
> +                        //check the ip belongs to the vm or not
> +                        nicSecIp = _nicSecondaryDao.findByIp4AddressAndNicId(vmGuestIp, guestNic.getId());
> +                        if (nicSecIp == null) {
> +                            throw new InvalidParameterValueException("VM ip " + vmGuestIp + " address not belongs to the vm");
> +                        }
> +                        dstIp = nicSecIp.getIp4Address();
> +                         // Set public ip column with the vm ip
> +                    }
> +                }
> +
>                  // Verify ip address parameter
> -                isIpReadyForStaticNat(vmId, ipAddress, caller, ctx.getCallerUserId());
> +                // checking vm id is not sufficient, check for the vm ip
> +                isIpReadyForStaticNat(vmId, ipAddress, dstIp, caller, ctx.getCallerUserId());
>              }
>
>              ipAddress.setOneToOneNat(true);
>              ipAddress.setAssociatedWithVmId(vmId);
>
> +            ipAddress.setVmIp(dstIp);
>              if (_ipAddressDao.update(ipAddress.getId(), ipAddress)) {
>                  // enable static nat on the backend
>                  s_logger.trace("Enabling static nat for ip address " + ipAddress + " and vm id=" + vmId + " on the backend");
> @@ -483,6 +528,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>                      s_logger.warn("Failed to enable static nat rule for ip address " + ipId + " on the backend");
>                      ipAddress.setOneToOneNat(isOneToOneNat);
>                      ipAddress.setAssociatedWithVmId(associatedWithVmId);
> +                    ipAddress.setVmIp(null);
>                      _ipAddressDao.update(ipAddress.getId(), ipAddress);
>                  }
>              } else {
> @@ -490,16 +536,17 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>
>              }
>          } finally {
> -            if (performedIpAssoc) {
> -                //if the rule is the last one for the ip address assigned to VPC, unassign it from the network
> -                IpAddress ip = _ipAddressDao.findById(ipAddress.getId());
> -                _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), networkId);
> +                if (performedIpAssoc) {
> +                    //if the rule is the last one for the ip address assigned to VPC, unassign it from the network
> +                    IpAddress ip = _ipAddressDao.findById(ipAddress.getId());
> +                    _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), networkId);
>              }
>          }
>          return false;
>      }
>
> -    protected void isIpReadyForStaticNat(long vmId, IPAddressVO ipAddress, Account caller, long callerUserId)
> +    protected void isIpReadyForStaticNat(long vmId, IPAddressVO ipAddress,
> +            String vmIp, Account caller, long callerUserId)
>              throws NetworkRuleConflictException, ResourceUnavailableException {
>          if (ipAddress.isSourceNat()) {
>              throw new InvalidParameterValueException("Can't enable static, ip address " + ipAddress + " is a sourceNat ip address");
> @@ -519,7 +566,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              throw new NetworkRuleConflictException("Failed to enable static for the ip address " + ipAddress + " and vm id=" + vmId + " as it's already assigned to antoher vm");
>          }
>
> -        IPAddressVO oldIP = _ipAddressDao.findByAssociatedVmId(vmId);
> +        //check wether the vm ip is alreday associated with any public ip address
> +        IPAddressVO oldIP = _ipAddressDao.findByAssociatedVmIdAndVmIp(vmId, vmIp);
>
>          if (oldIP != null) {
>              // If elasticIP functionality is supported in the network, we always have to disable static nat on the old
> @@ -538,9 +586,9 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              if (!reassignStaticNat) {
>                  throw new InvalidParameterValueException("Failed to enable static nat for the ip address id=" + ipAddress.getId() + " as vm id=" + vmId + " is already associated with ip id=" + oldIP.getId());
>              }
> -            // unassign old static nat rule
> -            s_logger.debug("Disassociating static nat for ip " + oldIP);
> -            if (!disableStaticNat(oldIP.getId(), caller, callerUserId, true)) {
> +        // unassign old static nat rule
> +        s_logger.debug("Disassociating static nat for ip " + oldIP);
> +        if (!disableStaticNat(oldIP.getId(), caller, callerUserId, true)) {
>                  throw new CloudRuntimeException("Failed to disable old static nat rule for vm id=" + vmId + " and ip " + oldIP);
>              }
>          }
> @@ -890,8 +938,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>          List<StaticNat> staticNats = new ArrayList<StaticNat>();
>          for (IPAddressVO ip : ips) {
>              // Get nic IP4 address
> -            String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
> -            StaticNatImpl staticNat = new StaticNatImpl(ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(), networkId, ip.getId(), dstIp, false);
> +            //String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
> +            StaticNatImpl staticNat = new StaticNatImpl(ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(), networkId, ip.getId(), ip.getVmIp(), false);
>              staticNats.add(staticNat);
>          }
>
> @@ -1209,6 +1257,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              boolean isIpSystem = ipAddress.getSystem();
>              ipAddress.setOneToOneNat(false);
>              ipAddress.setAssociatedWithVmId(null);
> +            ipAddress.setVmIp(null);
>              if (isIpSystem && !releaseIpIfElastic) {
>                  ipAddress.setSystem(false);
>              }
> @@ -1248,11 +1297,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>              throw ex;
>          }
>
> -        String dstIp;
> -        if (forRevoke) {
> -            dstIp = _networkModel.getIpInNetworkIncludingRemoved(ip.getAssociatedWithVmId(), rule.getNetworkId());
> -        } else {
> -            dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), rule.getNetworkId());
> +        String dstIp = ip.getVmIp();
> +        if (dstIp == null) {
> +            InvalidParameterValueException ex = new InvalidParameterValueException("VM ip address of the specified public ip is not set ");
> +            ex.addProxyObject(ruleVO, rule.getId(), "ruleId");
> +            throw ex;
>          }
>
>          return new StaticNatRuleImpl(ruleVO, dstIp);
> @@ -1333,12 +1382,16 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>
>          // create new static nat rule
>          // Get nic IP4 address
> +        Nic guestNic = _networkModel.getNicInNetwork(vm.getId(), networkId);
> +        if (guestNic == null) {
> +            throw new InvalidParameterValueException("Vm doesn't belong to the network with specified id");
> +        }
>
>          String dstIp;
> -        if (forRevoke) {
> -            dstIp = _networkModel.getIpInNetworkIncludingRemoved(sourceIp.getAssociatedWithVmId(), networkId);
> -        } else {
> -            dstIp = _networkModel.getIpInNetwork(sourceIp.getAssociatedWithVmId(), networkId);
> +
> +        dstIp = sourceIp.getVmIp();
> +        if (dstIp == null) {
> +            throw new InvalidParameterValueException("Vm ip is not set as dnat ip for this public ip");
>          }
>
>          StaticNatImpl staticNat = new StaticNatImpl(sourceIp.getAllocatedToAccountId(), sourceIp.getAllocatedInDomainId(),
> @@ -1373,7 +1426,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
>
>                  boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm);
>                  try {
> -                    success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM);
> +                    success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM, null);
>                  } catch (NetworkRuleConflictException ex) {
>                      s_logger.warn("Failed to enable static nat as a part of enabling elasticIp and staticNat for vm " +
>                              vm + " in guest network " + guestNetwork + " due to exception ", ex);
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> index 91f08e7..682a941 100644
> --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> @@ -41,5 +41,7 @@ public interface PortForwardingRulesDao extends GenericDao<PortForwardingRuleVO,
>      List<PortForwardingRuleVO> listByNetwork(long networkId);
>
>      List<PortForwardingRuleVO> listByAccount(long accountId);
> +
> +    List<PortForwardingRuleVO> listByDestIpAddr(String ip4Address);
>
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
> index 5406ab6..1d2e991 100644
> --- a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
> +++ b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.java
> @@ -32,6 +32,7 @@ import com.cloud.utils.db.GenericDaoBase;
>  import com.cloud.utils.db.SearchBuilder;
>  import com.cloud.utils.db.SearchCriteria;
>  import com.cloud.utils.db.SearchCriteria.Op;
> +import com.cloud.vm.dao.NicSecondaryIpVO;
>
>  @Component
>  @Local(value=PortForwardingRulesDao.class)
> @@ -55,6 +56,7 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase<PortForwardingRul
>          AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
>          AllFieldsSearch.and("vmId", AllFieldsSearch.entity().getVirtualMachineId(), Op.EQ);
>          AllFieldsSearch.and("purpose", AllFieldsSearch.entity().getPurpose(), Op.EQ);
> +        AllFieldsSearch.and("dstIp", AllFieldsSearch.entity().getDestinationIpAddress(), Op.EQ);
>          AllFieldsSearch.done();
>
>          ApplicationSearch = createSearchBuilder();
> @@ -149,5 +151,11 @@ public class PortForwardingRulesDaoImpl extends GenericDaoBase<PortForwardingRul
>
>          return listBy(sc);
>      }
> +    @Override
> +    public List<PortForwardingRuleVO> listByDestIpAddr(String ip4Address) {
> +        SearchCriteria<PortForwardingRuleVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("address", ip4Address);
> +        return listBy(sc);
> +    }
>
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/server/ManagementServerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
> index e80d48c..95b2973 100755
> --- a/server/src/com/cloud/server/ManagementServerImpl.java
> +++ b/server/src/com/cloud/server/ManagementServerImpl.java
> @@ -2165,6 +2165,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
>          cmdList.add(CreateVMSnapshotCmd.class);
>          cmdList.add(RevertToSnapshotCmd.class);
>          cmdList.add(DeleteVMSnapshotCmd.class);
> +        cmdList.add(AddIpToVmNicCmd.class);
> +        cmdList.add(RemoveIpFromVmNicCmd.class);
> +        cmdList.add(ListNicsCmd.class);
>          return cmdList;
>      }
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/NicVO.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/NicVO.java b/server/src/com/cloud/vm/NicVO.java
> index 8e2edda..987596c 100644
> --- a/server/src/com/cloud/vm/NicVO.java
> +++ b/server/src/com/cloud/vm/NicVO.java
> @@ -122,6 +122,9 @@ public class NicVO implements Nic {
>      @Column(name = "uuid")
>      String uuid = UUID.randomUUID().toString();
>
> +    @Column(name = "secondary_ip")
> +    boolean secondaryIp;
> +
>      public NicVO(String reserver, Long instanceId, long configurationId, VirtualMachine.Type vmType) {
>          this.reserver = reserver;
>          this.instanceId = instanceId;
> @@ -349,4 +352,12 @@ public class NicVO implements Nic {
>         public void setIp6Cidr(String ip6Cidr) {
>                 this.ip6Cidr = ip6Cidr;
>         }
> +
> +    public boolean getSecondaryIp() {
> +        return secondaryIp;
> +    }
> +
> +    public void setSecondaryIp(boolean secondaryIp) {
> +        this.secondaryIp = secondaryIp;
> +    }
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/UserVmManagerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
> index ce53c45..ca9c13f 100755
> --- a/server/src/com/cloud/vm/UserVmManagerImpl.java
> +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
> @@ -360,6 +360,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
>      protected ProjectManager _projectMgr;
>      @Inject
>      protected ResourceManager _resourceMgr;
> +
>      @Inject
>      protected NetworkServiceMapDao _ntwkSrvcDao;
>      @Inject
> @@ -1359,6 +1360,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
>                      + " as a part of vm id=" + vmId
>                      + " expunge because resource is unavailable", e);
>          }
> +        //remove vm secondary ip addresses
> +        if (_networkMgr.removeVmSecondaryIps(vmId)) {
> +            s_logger.debug("Removed vm " + vmId + " secondary ip address of the VM Nics as a part of expunge process");
> +        } else {
> +            success = false;
> +            s_logger.warn("Fail to remove secondary ip address  of vm " + vmId + " Nics as a part of expunge process");
> +        }
>
>          return success;
>      }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/dao/NicDao.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/dao/NicDao.java b/server/src/com/cloud/vm/dao/NicDao.java
> index 762048b..794bacc 100644
> --- a/server/src/com/cloud/vm/dao/NicDao.java
> +++ b/server/src/com/cloud/vm/dao/NicDao.java
> @@ -58,4 +58,6 @@ public interface NicDao extends GenericDao<NicVO, Long> {
>      NicVO findByNetworkIdInstanceIdAndBroadcastUri(long networkId, long instanceId, String broadcastUri);
>
>      NicVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId, long instanceId, String ip4Address);
> +
> +    List<NicVO> listByVmIdAndNicId(Long vmId, Long nicId);
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/dao/NicDaoImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java b/server/src/com/cloud/vm/dao/NicDaoImpl.java
> index 5cf152f..4491174 100644
> --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java
> +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java
> @@ -53,8 +53,10 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
>          AllFieldsSearch.and("address", AllFieldsSearch.entity().getIp4Address(), Op.EQ);
>          AllFieldsSearch.and("isDefault", AllFieldsSearch.entity().isDefaultNic(), Op.EQ);
>          AllFieldsSearch.and("broadcastUri", AllFieldsSearch.entity().getBroadcastUri(), Op.EQ);
> +        AllFieldsSearch.and("secondaryip", AllFieldsSearch.entity().getSecondaryIp(), Op.EQ);
> +        AllFieldsSearch.and("nicid", AllFieldsSearch.entity().getId(), Op.EQ);
>          AllFieldsSearch.done();
> -
> +
>          IpSearch = createSearchBuilder(String.class);
>          IpSearch.select(null, Func.DISTINCT, IpSearch.entity().getIp4Address());
>          IpSearch.and("network", IpSearch.entity().getNetworkId(), Op.EQ);
> @@ -202,4 +204,12 @@ public class NicDaoImpl extends GenericDaoBase<NicVO, Long> implements NicDao {
>          sc.setParameters("address", ip4Address);
>          return findOneBy(sc);
>      }
> +
> +    @Override
> +    public List<NicVO> listByVmIdAndNicId(Long vmId, Long nicId) {
> +        SearchCriteria<NicVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("instance", vmId);
> +        sc.setParameters("nicid", nicId);
> +        return listBy(sc);
> +    }
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java b/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> new file mode 100644
> index 0000000..da96df4
> --- /dev/null
> +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> @@ -0,0 +1,53 @@
> +// Licensed to the Apache Software Foundation (ASF) under one
> +// or more contributor license agreements.  See the NOTICE file
> +// distributed with this work for additional information
> +// regarding copyright ownership.  The ASF licenses this file
> +// to you under the Apache License, Version 2.0 (the
> +// "License"); you may not use this file except in compliance
> +// with the License.  You may obtain a copy of the License at
> +//
> +//   http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing,
> +// software distributed under the License is distributed on an
> +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +// KIND, either express or implied.  See the License for the
> +// specific language governing permissions and limitations
> +// under the License.
> +package com.cloud.vm.dao;
> +
> +import java.util.List;
> +import com.cloud.utils.db.GenericDao;
> +
> +public interface NicSecondaryIpDao extends GenericDao<NicSecondaryIpVO, Long> {
> +    List<NicSecondaryIpVO> listByVmId(long instanceId);
> +
> +    List<String> listSecondaryIpAddressInNetwork(long networkConfigId);
> +    List<NicSecondaryIpVO> listByNetworkId(long networkId);
> +
> +    NicSecondaryIpVO findByInstanceIdAndNetworkId(long networkId, long instanceId);
> +
> +    //    void removeNicsForInstance(long instanceId);
> +    //    void removeSecondaryIpForNic(long nicId);
> +
> +    NicSecondaryIpVO findByIp4AddressAndNetworkId(String ip4Address, long networkId);
> +
> +    /**
> +     * @param networkId
> +     * @param instanceId
> +     * @return
> +     */
> +
> +    List<NicSecondaryIpVO> getSecondaryIpAddressesForVm(long vmId);
> +
> +    List<NicSecondaryIpVO> listByNicId(long nicId);
> +
> +    List<NicSecondaryIpVO> listByNicIdAndVmid(long nicId, long vmId);
> +
> +    NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long nicId);
> +
> +    NicSecondaryIpVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId,
> +            Long vmId, String vmIp);
> +
> +    List<String> getSecondaryIpAddressesForNic(long nicId);
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java b/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> new file mode 100644
> index 0000000..3befaf7
> --- /dev/null
> +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> @@ -0,0 +1,138 @@
> +// Licensed to the Apache Software Foundation (ASF) under one
> +// or more contributor license agreements.  See the NOTICE file
> +// distributed with this work for additional information
> +// regarding copyright ownership.  The ASF licenses this file
> +// to you under the Apache License, Version 2.0 (the
> +// "License"); you may not use this file except in compliance
> +// with the License.  You may obtain a copy of the License at
> +//
> +//   http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing,
> +// software distributed under the License is distributed on an
> +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +// KIND, either express or implied.  See the License for the
> +// specific language governing permissions and limitations
> +// under the License.
> +package com.cloud.vm.dao;
> +
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +import javax.ejb.Local;
> +
> +import org.springframework.stereotype.Component;
> +
> +import com.cloud.utils.db.GenericDaoBase;
> +import com.cloud.utils.db.GenericSearchBuilder;
> +import com.cloud.utils.db.SearchBuilder;
> +import com.cloud.utils.db.SearchCriteria;
> +import com.cloud.utils.db.SearchCriteria.Func;
> +import com.cloud.utils.db.SearchCriteria.Op;
> +
> +@Component
> +@Local(value=NicSecondaryIpDao.class)
> +public class NicSecondaryIpDaoImpl extends GenericDaoBase<NicSecondaryIpVO, Long> implements NicSecondaryIpDao {
> +    private final SearchBuilder<NicSecondaryIpVO> AllFieldsSearch;
> +    private final GenericSearchBuilder<NicSecondaryIpVO, String> IpSearch;
> +
> +    protected NicSecondaryIpDaoImpl() {
> +        super();
> +        AllFieldsSearch = createSearchBuilder();
> +        AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getVmId(), Op.EQ);
> +        AllFieldsSearch.and("network", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
> +        AllFieldsSearch.and("address", AllFieldsSearch.entity().getIp4Address(), Op.EQ);
> +        AllFieldsSearch.and("nicId", AllFieldsSearch.entity().getNicId(), Op.EQ);
> +        AllFieldsSearch.done();
> +
> +        IpSearch = createSearchBuilder(String.class);
> +        IpSearch.select(null, Func.DISTINCT, IpSearch.entity().getIp4Address());
> +        IpSearch.and("network", IpSearch.entity().getNetworkId(), Op.EQ);
> +        IpSearch.and("address", IpSearch.entity().getIp4Address(), Op.NNULL);
> +        IpSearch.done();
> +    }
> +
> +    @Override
> +    public List<NicSecondaryIpVO> listByVmId(long instanceId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("instanceId", instanceId);
> +        return listBy(sc);
> +    }
> +
> +    @Override
> +    public List<NicSecondaryIpVO> listByNicId(long nicId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("nicId", nicId);
> +        return listBy(sc);
> +    }
> +
> +    @Override
> +    public List<String> listSecondaryIpAddressInNetwork(long networkId) {
> +        SearchCriteria<String> sc = IpSearch.create();
> +        sc.setParameters("network", networkId);
> +        return customSearch(sc, null);
> +    }
> +
> +    @Override
> +    public List<NicSecondaryIpVO> listByNetworkId(long networkId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("network", networkId);
> +        return listBy(sc);
> +    }
> +
> +    @Override
> +    public List<NicSecondaryIpVO> listByNicIdAndVmid(long nicId, long vmId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("nicId", nicId);
> +        sc.setParameters("instanceId", vmId);
> +        return listBy(sc);
> +    }
> +
> +    @Override
> +    public List<NicSecondaryIpVO> getSecondaryIpAddressesForVm(long vmId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("instanceId", vmId);
> +        return listBy(sc);
> +    }
> +
> +    @Override
> +    public List<String> getSecondaryIpAddressesForNic(long nicId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("nicId", nicId);
> +        List<NicSecondaryIpVO> results = search(sc, null);
> +        List<String> ips = new ArrayList<String>(results.size());
> +        for (NicSecondaryIpVO result : results) {
> +            ips.add(result.getIp4Address());
> +        }
> +        return ips;
> +    }
> +
> +    @Override
> +    public NicSecondaryIpVO findByInstanceIdAndNetworkId(long networkId, long instanceId) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +    @Override
> +    public NicSecondaryIpVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +    @Override
> +    public NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long nicId) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("address", ip4Address);
> +        sc.setParameters("nicId", nicId);
> +        return findOneBy(sc);
> +    }
> +
> +    @Override
> +    public NicSecondaryIpVO findByIp4AddressAndNetworkIdAndInstanceId(
> +            long networkId, Long vmId, String vmIp) {
> +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> +        sc.setParameters("network", networkId);
> +        sc.setParameters("instanceId", vmId);
> +        sc.setParameters("address", vmIp);
> +        return findOneBy(sc);
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java b/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> new file mode 100644
> index 0000000..770e188
> --- /dev/null
> +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> @@ -0,0 +1,160 @@
> +// Licensed to the Apache Software Foundation (ASF) under one
> +// or more contributor license agreements.  See the NOTICE file
> +// distributed with this work for additional information
> +// regarding copyright ownership.  The ASF licenses this file
> +// to you under the Apache License, Version 2.0 (the
> +// "License"); you may not use this file except in compliance
> +// with the License.  You may obtain a copy of the License at
> +//
> +//   http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing,
> +// software distributed under the License is distributed on an
> +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +// KIND, either express or implied.  See the License for the
> +// specific language governing permissions and limitations
> +// under the License.
> +package com.cloud.vm.dao;
> +
> +import java.util.Date;
> +import java.util.UUID;
> +
> +import javax.persistence.Column;
> +import javax.persistence.Entity;
> +import javax.persistence.GeneratedValue;
> +import javax.persistence.GenerationType;
> +import javax.persistence.Id;
> +import javax.persistence.Table;
> +
> +import com.cloud.utils.db.GenericDao;
> +import com.cloud.vm.NicSecondaryIp;
> +
> +@Entity
> +@Table(name = "nic_secondary_ips")
> +public class NicSecondaryIpVO implements NicSecondaryIp {
> +
> +    public NicSecondaryIpVO(Long nicId, String ipaddr, Long vmId,
> +            Long accountId, Long domainId, Long networkId) {
> +        this.nicId = nicId;
> +        this.vmId = vmId;
> +        this.ip4Address = ipaddr;
> +        this.accountId = accountId;
> +        this.domainId = domainId;
> +        this.networkId = networkId;
> +    }
> +
> +    protected NicSecondaryIpVO() {
> +    }
> +
> +    @Id
> +    @GeneratedValue(strategy = GenerationType.IDENTITY)
> +    @Column(name = "id")
> +    long id;
> +
> +    @Column(name = "nicId")
> +    long nicId;
> +
> +    @Column(name="domain_id", updatable=false)
> +    long domainId;
> +
> +    @Column(name="account_id", updatable=false)
> +    private Long accountId;
> +
> +    @Column(name = "ip4_address")
> +    String ip4Address;
> +
> +    @Column(name = "ip6_address")
> +    String ip6Address;
> +
> +    @Column(name = "network_id")
> +    long networkId;
> +
> +    @Column(name = GenericDao.CREATED_COLUMN)
> +    Date created;
> +
> +    @Column(name = "uuid")
> +    String uuid = UUID.randomUUID().toString();
> +
> +    @Column(name = "vmId")
> +    Long vmId;
> +
> +    public long getId() {
> +        return id;
> +    }
> +
> +    public void setId(long id) {
> +        this.id = id;
> +    }
> +
> +    public long getNicId() {
> +        return nicId;
> +    }
> +
> +    public void setNicId(long nicId) {
> +        this.nicId = nicId;
> +    }
> +
> +    public long getDomainId() {
> +        return domainId;
> +    }
> +
> +    public void setDomainId(Long domainId) {
> +        this.domainId = domainId;
> +    }
> +
> +    public long getAccountId() {
> +        return accountId;
> +    }
> +
> +    public void setAccountId(Long accountId) {
> +        this.accountId = accountId;
> +    }
> +
> +    public String getIp4Address() {
> +        return ip4Address;
> +    }
> +
> +    public void setIp4Address(String ip4Address) {
> +        this.ip4Address = ip4Address;
> +    }
> +
> +    public String getIp6Address() {
> +        return ip6Address;
> +    }
> +
> +    public void setIp6Address(String ip6Address) {
> +        this.ip6Address = ip6Address;
> +    }
> +
> +    public long getNetworkId() {
> +        return networkId;
> +    }
> +
> +    public void setNetworkId(long networkId) {
> +        this.networkId = networkId;
> +    }
> +
> +    public Date getCreated() {
> +        return created;
> +    }
> +
> +    public void setCreated(Date created) {
> +        this.created = created;
> +    }
> +
> +    public String getUuid() {
> +        return uuid;
> +    }
> +
> +    public void setUuid(String uuid) {
> +        this.uuid = uuid;
> +    }
> +
> +    public long getVmId() {
> +        return vmId;
> +    }
> +
> +    public void setVmId(Long vmId) {
> +        this.vmId = vmId;
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/test/com/cloud/network/MockNetworkManagerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java
> index 3568da5..8004310 100755
> --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java
> +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java
> @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
>  import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
>  import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
>  import org.springframework.stereotype.Component;
> +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
>
>  import com.cloud.dc.DataCenter;
>  import com.cloud.dc.Vlan.VlanType;
> @@ -64,6 +65,7 @@ import com.cloud.utils.component.Manager;
>  import com.cloud.utils.component.ManagerBase;
>  import com.cloud.vm.Nic;
>  import com.cloud.vm.NicProfile;
> +import com.cloud.vm.NicSecondaryIp;
>  import com.cloud.vm.ReservationContext;
>  import com.cloud.vm.VMInstanceVO;
>  import com.cloud.vm.VirtualMachine;
> @@ -824,4 +826,49 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
>          // TODO Auto-generated method stub
>          return null;
>      }
> +
> +    @Override
> +    public boolean isSecondaryIpSetForNic(long nicId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +    @Override
> +    public boolean releaseSecondaryIpFromNic(long ipAddressId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +    @Override
> +    public String allocateSecondaryGuestIP(Account account, long zoneId,
> +            Long nicId, Long networkId, String ipaddress) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +    @Override
> +    public String allocateGuestIP(Account ipOwner, boolean isSystem,
> +            long zoneId, Long networkId, String requestedIp)
> +            throws InsufficientAddressCapacityException {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +    @Override
> +    public boolean removeVmSecondaryIps(long vmId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +    @Override
> +    public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +    @Override
> +    public List<? extends Nic> listNics(ListNicsCmd listNicsCmd) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/test/com/cloud/network/MockRulesManagerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/test/com/cloud/network/MockRulesManagerImpl.java b/server/test/com/cloud/network/MockRulesManagerImpl.java
> index ba3dd41..e5a6894 100644
> --- a/server/test/com/cloud/network/MockRulesManagerImpl.java
> +++ b/server/test/com/cloud/network/MockRulesManagerImpl.java
> @@ -39,6 +39,7 @@ import com.cloud.uservm.UserVm;
>  import com.cloud.utils.Pair;
>  import com.cloud.utils.component.Manager;
>  import com.cloud.utils.component.ManagerBase;
> +import com.cloud.utils.net.Ip;
>  import com.cloud.vm.VirtualMachine;
>
>  @Local(value = {RulesManager.class, RulesService.class})
> @@ -54,14 +55,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R
>         }
>
>         @Override
> -       public PortForwardingRule createPortForwardingRule(PortForwardingRule rule,
> -                       Long vmId, boolean openFirewall)
> -                       throws NetworkRuleConflictException {
> -               // TODO Auto-generated method stub
> -               return null;
> -       }
> -
> -       @Override
>         public boolean revokePortForwardingRule(long ruleId, boolean apply) {
>                 // TODO Auto-generated method stub
>                 return false;
> @@ -83,7 +76,7 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R
>
>         @Override
>         public boolean enableStaticNat(long ipAddressId, long vmId, long networkId,
> -                       boolean isSystemVm) throws NetworkRuleConflictException,
> +                       boolean isSystemVm, String ipAddr) throws NetworkRuleConflictException,
>                         ResourceUnavailableException {
>                 // TODO Auto-generated method stub
>                 return false;
> @@ -310,4 +303,12 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R
>                 return "MockRulesManagerImpl";
>         }
>
> +    @Override
> +    public PortForwardingRule createPortForwardingRule(PortForwardingRule rule,
> +            Long vmId, Ip vmIp, boolean openFirewall)
> +            throws NetworkRuleConflictException {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> ----------------------------------------------------------------------
> diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> index 828a555..63ef874 100644
> --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementors
>  import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
>  import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
>  import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
> +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
>  import org.apache.log4j.Logger;
>  import org.springframework.stereotype.Component;
>
> @@ -80,6 +81,7 @@ import com.cloud.utils.component.Manager;
>  import com.cloud.utils.component.ManagerBase;
>  import com.cloud.vm.Nic;
>  import com.cloud.vm.NicProfile;
> +import com.cloud.vm.NicSecondaryIp;
>  import com.cloud.vm.ReservationContext;
>  import com.cloud.vm.VMInstanceVO;
>  import com.cloud.vm.VirtualMachine;
> @@ -1317,4 +1319,75 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
>          // TODO Auto-generated method stub
>          return null;
>      }
> +
> +
> +
> +
> +
> +    @Override
> +    public boolean isSecondaryIpSetForNic(long nicId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +    @Override
> +    public String allocateSecondaryGuestIP(Account account, long zoneId,
> +            Long nicId, Long networkId, String ipaddress) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +
> +
> +
> +
> +
> +
> +    @Override
> +    public boolean releaseSecondaryIpFromNic(long ipAddressId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +
> +
> +
> +
> +    @Override
> +    public String allocateGuestIP(Account ipOwner, boolean isSystem,
> +            long zoneId, Long networkId, String requestedIp)
> +            throws InsufficientAddressCapacityException {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +
> +
> +
> +
> +    @Override
> +    public boolean removeVmSecondaryIps(long vmId) {
> +        // TODO Auto-generated method stub
> +        return false;
> +    }
> +
> +
> +
> +
> +
> +    @Override
> +    public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
> +
> +
> +
> +
> +
> +    @Override
> +    public List<? extends Nic> listNics(ListNicsCmd listNicsCmd) {
> +        // TODO Auto-generated method stub
> +        return null;
> +    }
>  }
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/setup/db/db/schema-410to420.sql
> ----------------------------------------------------------------------
> diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
> index 4349bd0..6f68e12 100644
> --- a/setup/db/db/schema-410to420.sql
> +++ b/setup/db/db/schema-410to420.sql
> @@ -112,3 +112,24 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'UserV
>
>  -- Re-enable foreign key checking, at the end of the upgrade path
>  SET foreign_key_checks = 1;
> +
> +
> +CREATE TABLE nic_secondary_ips (
> +  `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
> +  `uuid` varchar(40),
> +  `vmId` bigint unsigned COMMENT 'vm instance id',
> +  `nicId` bigint unsigned NOT NULL,
> +  `ip4_address` char(40) COMMENT 'ip4 address',
> +  `ip6_address` char(40) COMMENT 'ip6 address',
> +  `network_id` bigint unsigned NOT NULL COMMENT 'network configuration id',
> +  `created` datetime NOT NULL COMMENT 'date created',
> +  `account_id` bigint unsigned NOT NULL COMMENT 'owner.  foreign key to   account table',
> +  `domain_id` bigint unsigned NOT NULL COMMENT 'the domain that the owner belongs to',
> +   PRIMARY KEY (`id`),
> +   CONSTRAINT `fk_nic_secondary_ip__vmId` FOREIGN KEY `fk_nic_secondary_ip__vmId`(`vmId`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE,
> +   CONSTRAINT `fk_nic_secondary_ip__networks_id` FOREIGN KEY `fk_nic_secondary_ip__networks_id`(`network_id`) REFERENCES `networks`(`id`),
> +   CONSTRAINT `uc_nic_secondary_ip__uuid` UNIQUE (`uuid`)
> +) ENGINE=InnoDB DEFAULT CHARSET=utf8;
> +
> +ALTER TABLE `cloud`.`nics` ADD COLUMN secondary_ip SMALLINT DEFAULT '0' COMMENT 'secondary ips configured for the nic';
> +ALTER TABLE `cloud`.`user_ip_address` ADD COLUMN dnat_vmip VARCHAR(40);
>

Re: [1/2] CLOUDSTACK-24: mipn feature for isolated and vpc networks

Posted by David Nalley <da...@gnsa.us>.
On Mon, Mar 4, 2013 at 1:01 AM, Jayapal Reddy Uradi
<ja...@citrix.com> wrote:
> Hi David,
>
> The test cases for this feature are added in the AddIpToVmNicTest.java file.
> In review board after your comments uploaded a new patch (r2) with the test cases added.
> Please let me know If I miss any thing.
>


Jayapal:

Thanks for following up, not sure how I missed those late last night.

My apologies for missing them both in reviewboard and the patch.

--David

RE: [1/2] CLOUDSTACK-24: mipn feature for isolated and vpc networks

Posted by Jayapal Reddy Uradi <ja...@citrix.com>.
Hi David,

The test cases for this feature are added in the AddIpToVmNicTest.java file.
In review board after your comments uploaded a new patch (r2) with the test cases added.
Please let me know If I miss any thing.

Thanks,
Jayapal


> -----Original Message-----
> From: David Nalley [mailto:david@gnsa.us]
> Sent: Monday, March 04, 2013 11:11 AM
> To: cloudstack-dev@incubator.apache.org
> Cc: cloudstack-commits@incubator.apache.org
> Subject: Re: [1/2] CLOUDSTACK-24: mipn feature for isolated and vpc
> networks
>
> Abhi, Jayapal:
>
> Where are tests for this feature?
> I asked about the tests on February 10 on the review itself, Chip asked about
> tests on Feb 11th on the review as well. The patch has subsequently had
> three revisions, yet nary a response to either my Chip's questions or adding
> tests to the patch itself.
> Why was this committed sans tests?
>
> --David
>
> On Mon, Mar 4, 2013 at 12:32 AM,  <ap...@apache.org> wrote:
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/network/rules/RulesManagerImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java
> > b/server/src/com/cloud/network/rules/RulesManagerImpl.java
> > index 614d308..29ed5f3 100755
> > --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java
> > +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java
> > @@ -78,10 +78,13 @@ import com.cloud.utils.db.Transaction;  import
> > com.cloud.utils.exception.CloudRuntimeException;
> >  import com.cloud.utils.net.Ip;
> >  import com.cloud.vm.Nic;
> > +import com.cloud.vm.NicSecondaryIp;
> >  import com.cloud.vm.UserVmVO;
> >  import com.cloud.vm.VirtualMachine;
> >  import com.cloud.vm.VirtualMachine.Type;  import
> > com.cloud.vm.dao.NicDao;
> > +import com.cloud.vm.dao.NicSecondaryIpDao;
> > +import com.cloud.vm.dao.NicSecondaryIpVO;
> >  import com.cloud.vm.dao.UserVmDao;
> >
> >  @Component
> > @@ -123,6 +126,8 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >      ResourceTagDao _resourceTagDao;
> >      @Inject
> >      VpcManager _vpcMgr;
> > +    @Inject
> > +    NicSecondaryIpDao _nicSecondaryDao;
> >
> >      @Override
> >      public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm,
> > Account caller) { @@ -172,7 +177,7 @@ public class RulesManagerImpl
> extends ManagerBase implements RulesManager, Rules
> >      @Override
> >      @DB
> >      @ActionEvent(eventType = EventTypes.EVENT_NET_RULE_ADD,
> eventDescription = "creating forwarding rule", create = true)
> > -    public PortForwardingRule
> createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean
> openFirewall)
> > +    public PortForwardingRule
> > + createPortForwardingRule(PortForwardingRule rule, Long vmId, Ip
> > + vmIp, boolean openFirewall)
> >              throws NetworkRuleConflictException {
> >          UserContext ctx = UserContext.current();
> >          Account caller = ctx.getCaller(); @@ -192,6 +197,7 @@ public
> > class RulesManagerImpl extends ManagerBase implements RulesManager,
> Rules
> >          Network network = _networkModel.getNetwork(networkId);
> >          //associate ip address to network (if needed)
> >          boolean performedIpAssoc = false;
> > +        Nic guestNic;
> >          if (ipAddress.getAssociatedWithNetworkId() == null) {
> >              boolean assignToVpcNtwk =  network.getVpcId() != null
> >                      && ipAddress.getVpcId() != null &&
> > ipAddress.getVpcId().longValue() == network.getVpcId(); @@ -244,13
> > +250,26 @@ public class RulesManagerImpl extends ManagerBase
> > implements RulesManager, Rules
> >
> >              // Verify that vm has nic in the network
> >              Ip dstIp = rule.getDestinationIpAddress();
> > -            Nic guestNic = _networkModel.getNicInNetwork(vmId, networkId);
> > +            guestNic = _networkModel.getNicInNetwork(vmId,
> > + networkId);
> >              if (guestNic == null || guestNic.getIp4Address() == null) {
> >                  throw new InvalidParameterValueException("Vm doesn't belong
> to network associated with ipAddress");
> >              } else {
> >                  dstIp = new Ip(guestNic.getIp4Address());
> >              }
> >
> > +            if (vmIp != null) {
> > +                //vm ip is passed so it can be primary or secondary ip addreess.
> > +                if (!dstIp.equals(vmIp)) {
> > +                    //the vm ip is secondary ip to the nic.
> > +                    // is vmIp is secondary ip or not
> > +                    NicSecondaryIp secondaryIp =
> _nicSecondaryDao.findByIp4AddressAndNicId(vmIp.toString(),
> guestNic.getId());
> > +                    if (secondaryIp == null) {
> > +                        throw new InvalidParameterValueException("IP Address is
> not in the VM nic's network ");
> > +                    }
> > +                    dstIp = vmIp;
> > +                }
> > +            }
> > +
> >              //if start port and end port are passed in, and they are not equal to
> each other, perform the validation
> >              boolean validatePortRange = false;
> >              if (rule.getSourcePortStart().intValue() !=
> > rule.getSourcePortEnd().intValue()
> > @@ -350,8 +369,8 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >              throw new InvalidParameterValueException("Can't create ip
> forwarding rules for the network where elasticIP service is enabled");
> >          }
> >
> > -        String dstIp =
> _networkModel.getIpInNetwork(ipAddress.getAssociatedWithVmId(),
> networkId);
> > -
> > +        //String dstIp =
> _networkModel.getIpInNetwork(ipAddress.getAssociatedWithVmId(),
> networkId);
> > +        String dstIp = ipAddress.getVmIp();
> >          Transaction txn = Transaction.currentTxn();
> >          txn.start();
> >
> > @@ -397,14 +416,13 @@ public class RulesManagerImpl extends
> > ManagerBase implements RulesManager, Rules
> >
> >      @Override
> >      @ActionEvent(eventType = EventTypes.EVENT_ENABLE_STATIC_NAT,
> eventDescription = "enabling static nat")
> > -    public boolean enableStaticNat(long ipId, long vmId, long networkId,
> boolean isSystemVm)
> > +    public boolean enableStaticNat(long ipId, long vmId, long
> > + networkId, boolean isSystemVm, String vmGuestIp)
> >              throws NetworkRuleConflictException,
> ResourceUnavailableException {
> >          UserContext ctx = UserContext.current();
> >          Account caller = ctx.getCaller();
> >          UserContext.current().setEventDetails("Ip Id: " + ipId);
> >
> >          // Verify input parameters
> > -
> >          IPAddressVO ipAddress = _ipAddressDao.findById(ipId);
> >          if (ipAddress == null) {
> >              throw new InvalidParameterValueException("Unable to find
> > ip address by id " + ipId); @@ -414,6 +432,10 @@ public class
> RulesManagerImpl extends ManagerBase implements RulesManager, Rules
> >          boolean performedIpAssoc = false;
> >          boolean isOneToOneNat = ipAddress.isOneToOneNat();
> >          Long associatedWithVmId = ipAddress.getAssociatedWithVmId();
> > +        Nic guestNic;
> > +        NicSecondaryIpVO nicSecIp = null;
> > +        String dstIp = null;
> > +
> >          try {
> >              Network network = _networkModel.getNetwork(networkId);
> >              if (network == null) {
> > @@ -421,11 +443,11 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >              }
> >
> >              // Check that vm has a nic in the network
> > -            Nic guestNic = _networkModel.getNicInNetwork(vmId, networkId);
> > +            guestNic = _networkModel.getNicInNetwork(vmId,
> > + networkId);
> >              if (guestNic == null) {
> >                  throw new InvalidParameterValueException("Vm doesn't belong
> to the network with specified id");
> >              }
> > -
> > +            dstIp = guestNic.getIp4Address();
> >
> >              if
> (!_networkModel.areServicesSupportedInNetwork(network.getId(),
> Service.StaticNat)) {
> >                  throw new InvalidParameterValueException("Unable to
> > create static nat rule; StaticNat service is not " + @@ -466,13 +488,36 @@
> public class RulesManagerImpl extends ManagerBase implements
> RulesManager, Rules
> >                  // Check permissions
> >                  checkIpAndUserVm(ipAddress, vm, caller);
> >
> > +                //is static nat is for vm secondary ip
> > +                //dstIp = guestNic.getIp4Address();
> > +                if (vmGuestIp != null) {
> > +                    //dstIp = guestNic.getIp4Address();
> > +
> > +                    if (!dstIp.equals(vmGuestIp)) {
> > +                        //check whether the secondary ip set to the vm or not
> > +                        boolean secondaryIpSet =
> _networkMgr.isSecondaryIpSetForNic(guestNic.getId());
> > +                        if (!secondaryIpSet) {
> > +                            throw new InvalidParameterValueException("VM ip " +
> vmGuestIp + " address not belongs to the vm");
> > +                        }
> > +                        //check the ip belongs to the vm or not
> > +                        nicSecIp =
> _nicSecondaryDao.findByIp4AddressAndNicId(vmGuestIp, guestNic.getId());
> > +                        if (nicSecIp == null) {
> > +                            throw new InvalidParameterValueException("VM ip " +
> vmGuestIp + " address not belongs to the vm");
> > +                        }
> > +                        dstIp = nicSecIp.getIp4Address();
> > +                         // Set public ip column with the vm ip
> > +                    }
> > +                }
> > +
> >                  // Verify ip address parameter
> > -                isIpReadyForStaticNat(vmId, ipAddress, caller,
> ctx.getCallerUserId());
> > +                // checking vm id is not sufficient, check for the vm ip
> > +                isIpReadyForStaticNat(vmId, ipAddress, dstIp, caller,
> > + ctx.getCallerUserId());
> >              }
> >
> >              ipAddress.setOneToOneNat(true);
> >              ipAddress.setAssociatedWithVmId(vmId);
> >
> > +            ipAddress.setVmIp(dstIp);
> >              if (_ipAddressDao.update(ipAddress.getId(), ipAddress)) {
> >                  // enable static nat on the backend
> >                  s_logger.trace("Enabling static nat for ip address "
> > + ipAddress + " and vm id=" + vmId + " on the backend"); @@ -483,6 +528,7
> @@ public class RulesManagerImpl extends ManagerBase implements
> RulesManager, Rules
> >                      s_logger.warn("Failed to enable static nat rule for ip address " +
> ipId + " on the backend");
> >                      ipAddress.setOneToOneNat(isOneToOneNat);
> >
> > ipAddress.setAssociatedWithVmId(associatedWithVmId);
> > +                    ipAddress.setVmIp(null);
> >                      _ipAddressDao.update(ipAddress.getId(), ipAddress);
> >                  }
> >              } else {
> > @@ -490,16 +536,17 @@ public class RulesManagerImpl extends
> > ManagerBase implements RulesManager, Rules
> >
> >              }
> >          } finally {
> > -            if (performedIpAssoc) {
> > -                //if the rule is the last one for the ip address assigned to VPC,
> unassign it from the network
> > -                IpAddress ip = _ipAddressDao.findById(ipAddress.getId());
> > -                _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), networkId);
> > +                if (performedIpAssoc) {
> > +                    //if the rule is the last one for the ip address assigned to VPC,
> unassign it from the network
> > +                    IpAddress ip = _ipAddressDao.findById(ipAddress.getId());
> > +                    _vpcMgr.unassignIPFromVpcNetwork(ip.getId(),
> > + networkId);
> >              }
> >          }
> >          return false;
> >      }
> >
> > -    protected void isIpReadyForStaticNat(long vmId, IPAddressVO
> ipAddress, Account caller, long callerUserId)
> > +    protected void isIpReadyForStaticNat(long vmId, IPAddressVO
> ipAddress,
> > +            String vmIp, Account caller, long callerUserId)
> >              throws NetworkRuleConflictException,
> ResourceUnavailableException {
> >          if (ipAddress.isSourceNat()) {
> >              throw new InvalidParameterValueException("Can't enable
> > static, ip address " + ipAddress + " is a sourceNat ip address"); @@ -519,7
> +566,8 @@ public class RulesManagerImpl extends ManagerBase
> implements RulesManager, Rules
> >              throw new NetworkRuleConflictException("Failed to enable static
> for the ip address " + ipAddress + " and vm id=" + vmId + " as it's already
> assigned to antoher vm");
> >          }
> >
> > -        IPAddressVO oldIP = _ipAddressDao.findByAssociatedVmId(vmId);
> > +        //check wether the vm ip is alreday associated with any public ip
> address
> > +        IPAddressVO oldIP =
> > + _ipAddressDao.findByAssociatedVmIdAndVmIp(vmId, vmIp);
> >
> >          if (oldIP != null) {
> >              // If elasticIP functionality is supported in the
> > network, we always have to disable static nat on the old @@ -538,9 +586,9
> @@ public class RulesManagerImpl extends ManagerBase implements
> RulesManager, Rules
> >              if (!reassignStaticNat) {
> >                  throw new InvalidParameterValueException("Failed to enable
> static nat for the ip address id=" + ipAddress.getId() + " as vm id=" + vmId + "
> is already associated with ip id=" + oldIP.getId());
> >              }
> > -            // unassign old static nat rule
> > -            s_logger.debug("Disassociating static nat for ip " + oldIP);
> > -            if (!disableStaticNat(oldIP.getId(), caller, callerUserId, true)) {
> > +        // unassign old static nat rule
> > +        s_logger.debug("Disassociating static nat for ip " + oldIP);
> > +        if (!disableStaticNat(oldIP.getId(), caller, callerUserId,
> > + true)) {
> >                  throw new CloudRuntimeException("Failed to disable old static nat
> rule for vm id=" + vmId + " and ip " + oldIP);
> >              }
> >          }
> > @@ -890,8 +938,8 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >          List<StaticNat> staticNats = new ArrayList<StaticNat>();
> >          for (IPAddressVO ip : ips) {
> >              // Get nic IP4 address
> > -            String dstIp =
> _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
> > -            StaticNatImpl staticNat = new
> StaticNatImpl(ip.getAllocatedToAccountId(), ip.getAllocatedInDomainId(),
> networkId, ip.getId(), dstIp, false);
> > +            //String dstIp =
> _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), networkId);
> > +            StaticNatImpl staticNat = new
> > + StaticNatImpl(ip.getAllocatedToAccountId(),
> > + ip.getAllocatedInDomainId(), networkId, ip.getId(), ip.getVmIp(),
> > + false);
> >              staticNats.add(staticNat);
> >          }
> >
> > @@ -1209,6 +1257,7 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >              boolean isIpSystem = ipAddress.getSystem();
> >              ipAddress.setOneToOneNat(false);
> >              ipAddress.setAssociatedWithVmId(null);
> > +            ipAddress.setVmIp(null);
> >              if (isIpSystem && !releaseIpIfElastic) {
> >                  ipAddress.setSystem(false);
> >              }
> > @@ -1248,11 +1297,11 @@ public class RulesManagerImpl extends
> ManagerBase implements RulesManager, Rules
> >              throw ex;
> >          }
> >
> > -        String dstIp;
> > -        if (forRevoke) {
> > -            dstIp =
> _networkModel.getIpInNetworkIncludingRemoved(ip.getAssociatedWithV
> mId(), rule.getNetworkId());
> > -        } else {
> > -            dstIp =
> _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(),
> rule.getNetworkId());
> > +        String dstIp = ip.getVmIp();
> > +        if (dstIp == null) {
> > +            InvalidParameterValueException ex = new
> InvalidParameterValueException("VM ip address of the specified public ip is
> not set ");
> > +            ex.addProxyObject(ruleVO, rule.getId(), "ruleId");
> > +            throw ex;
> >          }
> >
> >          return new StaticNatRuleImpl(ruleVO, dstIp); @@ -1333,12
> > +1382,16 @@ public class RulesManagerImpl extends ManagerBase
> > implements RulesManager, Rules
> >
> >          // create new static nat rule
> >          // Get nic IP4 address
> > +        Nic guestNic = _networkModel.getNicInNetwork(vm.getId(),
> networkId);
> > +        if (guestNic == null) {
> > +            throw new InvalidParameterValueException("Vm doesn't belong to
> the network with specified id");
> > +        }
> >
> >          String dstIp;
> > -        if (forRevoke) {
> > -            dstIp =
> _networkModel.getIpInNetworkIncludingRemoved(sourceIp.getAssociated
> WithVmId(), networkId);
> > -        } else {
> > -            dstIp =
> _networkModel.getIpInNetwork(sourceIp.getAssociatedWithVmId(),
> networkId);
> > +
> > +        dstIp = sourceIp.getVmIp();
> > +        if (dstIp == null) {
> > +            throw new InvalidParameterValueException("Vm ip is not
> > + set as dnat ip for this public ip");
> >          }
> >
> >          StaticNatImpl staticNat = new
> > StaticNatImpl(sourceIp.getAllocatedToAccountId(),
> > sourceIp.getAllocatedInDomainId(),
> > @@ -1373,7 +1426,7 @@ public class RulesManagerImpl extends
> > ManagerBase implements RulesManager, Rules
> >
> >                  boolean isSystemVM = (vm.getType() == Type.ConsoleProxy ||
> vm.getType() == Type.SecondaryStorageVm);
> >                  try {
> > -                    success = enableStaticNat(ip.getId(), vm.getId(),
> guestNetwork.getId(), isSystemVM);
> > +                    success = enableStaticNat(ip.getId(), vm.getId(),
> > + guestNetwork.getId(), isSystemVM, null);
> >                  } catch (NetworkRuleConflictException ex) {
> >                      s_logger.warn("Failed to enable static nat as a part of enabling
> elasticIp and staticNat for vm " +
> >                              vm + " in guest network " + guestNetwork
> > + " due to exception ", ex);
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> >
> c47/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> > ----------------------------------------------------------------------
> > diff --git
> > a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> > b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> > index 91f08e7..682a941 100644
> > ---
> > a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.java
> > +++
> b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDao.ja
> > +++ va
> > @@ -41,5 +41,7 @@ public interface PortForwardingRulesDao extends
> GenericDao<PortForwardingRuleVO,
> >      List<PortForwardingRuleVO> listByNetwork(long networkId);
> >
> >      List<PortForwardingRuleVO> listByAccount(long accountId);
> > +
> > +    List<PortForwardingRuleVO> listByDestIpAddr(String ip4Address);
> >
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> >
> c47/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl
> .
> > java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.ja
> > va
> >
> b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.ja
> > va
> > index 5406ab6..1d2e991 100644
> > ---
> >
> a/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImpl.ja
> > va
> > +++
> b/server/src/com/cloud/network/rules/dao/PortForwardingRulesDaoImp
> > +++ l.java
> > @@ -32,6 +32,7 @@ import com.cloud.utils.db.GenericDaoBase;
> >  import com.cloud.utils.db.SearchBuilder;  import
> > com.cloud.utils.db.SearchCriteria;
> >  import com.cloud.utils.db.SearchCriteria.Op;
> > +import com.cloud.vm.dao.NicSecondaryIpVO;
> >
> >  @Component
> >  @Local(value=PortForwardingRulesDao.class)
> > @@ -55,6 +56,7 @@ public class PortForwardingRulesDaoImpl extends
> GenericDaoBase<PortForwardingRul
> >          AllFieldsSearch.and("networkId",
> AllFieldsSearch.entity().getNetworkId(), Op.EQ);
> >          AllFieldsSearch.and("vmId",
> AllFieldsSearch.entity().getVirtualMachineId(), Op.EQ);
> >          AllFieldsSearch.and("purpose",
> > AllFieldsSearch.entity().getPurpose(), Op.EQ);
> > +        AllFieldsSearch.and("dstIp",
> > + AllFieldsSearch.entity().getDestinationIpAddress(), Op.EQ);
> >          AllFieldsSearch.done();
> >
> >          ApplicationSearch = createSearchBuilder(); @@ -149,5 +151,11
> > @@ public class PortForwardingRulesDaoImpl extends
> > GenericDaoBase<PortForwardingRul
> >
> >          return listBy(sc);
> >      }
> > +    @Override
> > +    public List<PortForwardingRuleVO> listByDestIpAddr(String ip4Address)
> {
> > +        SearchCriteria<PortForwardingRuleVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("address", ip4Address);
> > +        return listBy(sc);
> > +    }
> >
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/server/ManagementServerImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/server/ManagementServerImpl.java
> > b/server/src/com/cloud/server/ManagementServerImpl.java
> > index e80d48c..95b2973 100755
> > --- a/server/src/com/cloud/server/ManagementServerImpl.java
> > +++ b/server/src/com/cloud/server/ManagementServerImpl.java
> > @@ -2165,6 +2165,9 @@ public class ManagementServerImpl extends
> ManagerBase implements ManagementServe
> >          cmdList.add(CreateVMSnapshotCmd.class);
> >          cmdList.add(RevertToSnapshotCmd.class);
> >          cmdList.add(DeleteVMSnapshotCmd.class);
> > +        cmdList.add(AddIpToVmNicCmd.class);
> > +        cmdList.add(RemoveIpFromVmNicCmd.class);
> > +        cmdList.add(ListNicsCmd.class);
> >          return cmdList;
> >      }
> >
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/NicVO.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/NicVO.java
> > b/server/src/com/cloud/vm/NicVO.java
> > index 8e2edda..987596c 100644
> > --- a/server/src/com/cloud/vm/NicVO.java
> > +++ b/server/src/com/cloud/vm/NicVO.java
> > @@ -122,6 +122,9 @@ public class NicVO implements Nic {
> >      @Column(name = "uuid")
> >      String uuid = UUID.randomUUID().toString();
> >
> > +    @Column(name = "secondary_ip")
> > +    boolean secondaryIp;
> > +
> >      public NicVO(String reserver, Long instanceId, long configurationId,
> VirtualMachine.Type vmType) {
> >          this.reserver = reserver;
> >          this.instanceId = instanceId; @@ -349,4 +352,12 @@ public
> > class NicVO implements Nic {
> >         public void setIp6Cidr(String ip6Cidr) {
> >                 this.ip6Cidr = ip6Cidr;
> >         }
> > +
> > +    public boolean getSecondaryIp() {
> > +        return secondaryIp;
> > +    }
> > +
> > +    public void setSecondaryIp(boolean secondaryIp) {
> > +        this.secondaryIp = secondaryIp;
> > +    }
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/UserVmManagerImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java
> > b/server/src/com/cloud/vm/UserVmManagerImpl.java
> > index ce53c45..ca9c13f 100755
> > --- a/server/src/com/cloud/vm/UserVmManagerImpl.java
> > +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
> > @@ -360,6 +360,7 @@ public class UserVmManagerImpl extends
> ManagerBase implements UserVmManager, Use
> >      protected ProjectManager _projectMgr;
> >      @Inject
> >      protected ResourceManager _resourceMgr;
> > +
> >      @Inject
> >      protected NetworkServiceMapDao _ntwkSrvcDao;
> >      @Inject
> > @@ -1359,6 +1360,13 @@ public class UserVmManagerImpl extends
> ManagerBase implements UserVmManager, Use
> >                      + " as a part of vm id=" + vmId
> >                      + " expunge because resource is unavailable", e);
> >          }
> > +        //remove vm secondary ip addresses
> > +        if (_networkMgr.removeVmSecondaryIps(vmId)) {
> > +            s_logger.debug("Removed vm " + vmId + " secondary ip address of
> the VM Nics as a part of expunge process");
> > +        } else {
> > +            success = false;
> > +            s_logger.warn("Fail to remove secondary ip address  of vm " + vmId
> + " Nics as a part of expunge process");
> > +        }
> >
> >          return success;
> >      }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/dao/NicDao.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/dao/NicDao.java
> > b/server/src/com/cloud/vm/dao/NicDao.java
> > index 762048b..794bacc 100644
> > --- a/server/src/com/cloud/vm/dao/NicDao.java
> > +++ b/server/src/com/cloud/vm/dao/NicDao.java
> > @@ -58,4 +58,6 @@ public interface NicDao extends GenericDao<NicVO,
> Long> {
> >      NicVO findByNetworkIdInstanceIdAndBroadcastUri(long networkId,
> > long instanceId, String broadcastUri);
> >
> >      NicVO findByIp4AddressAndNetworkIdAndInstanceId(long networkId,
> > long instanceId, String ip4Address);
> > +
> > +    List<NicVO> listByVmIdAndNicId(Long vmId, Long nicId);
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/dao/NicDaoImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/dao/NicDaoImpl.java
> > b/server/src/com/cloud/vm/dao/NicDaoImpl.java
> > index 5cf152f..4491174 100644
> > --- a/server/src/com/cloud/vm/dao/NicDaoImpl.java
> > +++ b/server/src/com/cloud/vm/dao/NicDaoImpl.java
> > @@ -53,8 +53,10 @@ public class NicDaoImpl extends
> GenericDaoBase<NicVO, Long> implements NicDao {
> >          AllFieldsSearch.and("address",
> AllFieldsSearch.entity().getIp4Address(), Op.EQ);
> >          AllFieldsSearch.and("isDefault", AllFieldsSearch.entity().isDefaultNic(),
> Op.EQ);
> >          AllFieldsSearch.and("broadcastUri",
> > AllFieldsSearch.entity().getBroadcastUri(), Op.EQ);
> > +        AllFieldsSearch.and("secondaryip",
> AllFieldsSearch.entity().getSecondaryIp(), Op.EQ);
> > +        AllFieldsSearch.and("nicid",
> > + AllFieldsSearch.entity().getId(), Op.EQ);
> >          AllFieldsSearch.done();
> > -
> > +
> >          IpSearch = createSearchBuilder(String.class);
> >          IpSearch.select(null, Func.DISTINCT,
> IpSearch.entity().getIp4Address());
> >          IpSearch.and("network", IpSearch.entity().getNetworkId(),
> > Op.EQ); @@ -202,4 +204,12 @@ public class NicDaoImpl extends
> GenericDaoBase<NicVO, Long> implements NicDao {
> >          sc.setParameters("address", ip4Address);
> >          return findOneBy(sc);
> >      }
> > +
> > +    @Override
> > +    public List<NicVO> listByVmIdAndNicId(Long vmId, Long nicId) {
> > +        SearchCriteria<NicVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("instance", vmId);
> > +        sc.setParameters("nicid", nicId);
> > +        return listBy(sc);
> > +    }
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> > b/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> > new file mode 100644
> > index 0000000..da96df4
> > --- /dev/null
> > +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpDao.java
> > @@ -0,0 +1,53 @@
> > +// Licensed to the Apache Software Foundation (ASF) under one // or
> > +more contributor license agreements.  See the NOTICE file //
> > +distributed with this work for additional information // regarding
> > +copyright ownership.  The ASF licenses this file // to you under the
> > +Apache License, Version 2.0 (the // "License"); you may not use this
> > +file except in compliance // with the License.  You may obtain a copy
> > +of the License at //
> > +//   http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, //
> > +software distributed under the License is distributed on an // "AS
> > +IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND,
> either
> > +express or implied.  See the License for the // specific language
> > +governing permissions and limitations // under the License.
> > +package com.cloud.vm.dao;
> > +
> > +import java.util.List;
> > +import com.cloud.utils.db.GenericDao;
> > +
> > +public interface NicSecondaryIpDao extends
> GenericDao<NicSecondaryIpVO, Long> {
> > +    List<NicSecondaryIpVO> listByVmId(long instanceId);
> > +
> > +    List<String> listSecondaryIpAddressInNetwork(long networkConfigId);
> > +    List<NicSecondaryIpVO> listByNetworkId(long networkId);
> > +
> > +    NicSecondaryIpVO findByInstanceIdAndNetworkId(long networkId,
> > + long instanceId);
> > +
> > +    //    void removeNicsForInstance(long instanceId);
> > +    //    void removeSecondaryIpForNic(long nicId);
> > +
> > +    NicSecondaryIpVO findByIp4AddressAndNetworkId(String ip4Address,
> > + long networkId);
> > +
> > +    /**
> > +     * @param networkId
> > +     * @param instanceId
> > +     * @return
> > +     */
> > +
> > +    List<NicSecondaryIpVO> getSecondaryIpAddressesForVm(long vmId);
> > +
> > +    List<NicSecondaryIpVO> listByNicId(long nicId);
> > +
> > +    List<NicSecondaryIpVO> listByNicIdAndVmid(long nicId, long vmId);
> > +
> > +    NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address, long
> > + nicId);
> > +
> > +    NicSecondaryIpVO findByIp4AddressAndNetworkIdAndInstanceId(long
> networkId,
> > +            Long vmId, String vmIp);
> > +
> > +    List<String> getSecondaryIpAddressesForNic(long nicId); }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> > b/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> > new file mode 100644
> > index 0000000..3befaf7
> > --- /dev/null
> > +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpDaoImpl.java
> > @@ -0,0 +1,138 @@
> > +// Licensed to the Apache Software Foundation (ASF) under one // or
> > +more contributor license agreements.  See the NOTICE file //
> > +distributed with this work for additional information // regarding
> > +copyright ownership.  The ASF licenses this file // to you under the
> > +Apache License, Version 2.0 (the // "License"); you may not use this
> > +file except in compliance // with the License.  You may obtain a copy
> > +of the License at //
> > +//   http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, //
> > +software distributed under the License is distributed on an // "AS
> > +IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND,
> either
> > +express or implied.  See the License for the // specific language
> > +governing permissions and limitations // under the License.
> > +package com.cloud.vm.dao;
> > +
> > +import java.util.ArrayList;
> > +import java.util.List;
> > +
> > +import javax.ejb.Local;
> > +
> > +import org.springframework.stereotype.Component;
> > +
> > +import com.cloud.utils.db.GenericDaoBase;
> > +import com.cloud.utils.db.GenericSearchBuilder;
> > +import com.cloud.utils.db.SearchBuilder; import
> > +com.cloud.utils.db.SearchCriteria;
> > +import com.cloud.utils.db.SearchCriteria.Func;
> > +import com.cloud.utils.db.SearchCriteria.Op;
> > +
> > +@Component
> > +@Local(value=NicSecondaryIpDao.class)
> > +public class NicSecondaryIpDaoImpl extends
> GenericDaoBase<NicSecondaryIpVO, Long> implements NicSecondaryIpDao
> {
> > +    private final SearchBuilder<NicSecondaryIpVO> AllFieldsSearch;
> > +    private final GenericSearchBuilder<NicSecondaryIpVO, String>
> > +IpSearch;
> > +
> > +    protected NicSecondaryIpDaoImpl() {
> > +        super();
> > +        AllFieldsSearch = createSearchBuilder();
> > +        AllFieldsSearch.and("instanceId", AllFieldsSearch.entity().getVmId(),
> Op.EQ);
> > +        AllFieldsSearch.and("network",
> AllFieldsSearch.entity().getNetworkId(), Op.EQ);
> > +        AllFieldsSearch.and("address",
> AllFieldsSearch.entity().getIp4Address(), Op.EQ);
> > +        AllFieldsSearch.and("nicId", AllFieldsSearch.entity().getNicId(),
> Op.EQ);
> > +        AllFieldsSearch.done();
> > +
> > +        IpSearch = createSearchBuilder(String.class);
> > +        IpSearch.select(null, Func.DISTINCT,
> IpSearch.entity().getIp4Address());
> > +        IpSearch.and("network", IpSearch.entity().getNetworkId(), Op.EQ);
> > +        IpSearch.and("address", IpSearch.entity().getIp4Address(),
> Op.NNULL);
> > +        IpSearch.done();
> > +    }
> > +
> > +    @Override
> > +    public List<NicSecondaryIpVO> listByVmId(long instanceId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("instanceId", instanceId);
> > +        return listBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public List<NicSecondaryIpVO> listByNicId(long nicId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("nicId", nicId);
> > +        return listBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public List<String> listSecondaryIpAddressInNetwork(long networkId) {
> > +        SearchCriteria<String> sc = IpSearch.create();
> > +        sc.setParameters("network", networkId);
> > +        return customSearch(sc, null);
> > +    }
> > +
> > +    @Override
> > +    public List<NicSecondaryIpVO> listByNetworkId(long networkId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("network", networkId);
> > +        return listBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public List<NicSecondaryIpVO> listByNicIdAndVmid(long nicId, long
> vmId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("nicId", nicId);
> > +        sc.setParameters("instanceId", vmId);
> > +        return listBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public List<NicSecondaryIpVO> getSecondaryIpAddressesForVm(long
> vmId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("instanceId", vmId);
> > +        return listBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public List<String> getSecondaryIpAddressesForNic(long nicId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("nicId", nicId);
> > +        List<NicSecondaryIpVO> results = search(sc, null);
> > +        List<String> ips = new ArrayList<String>(results.size());
> > +        for (NicSecondaryIpVO result : results) {
> > +            ips.add(result.getIp4Address());
> > +        }
> > +        return ips;
> > +    }
> > +
> > +    @Override
> > +    public NicSecondaryIpVO findByInstanceIdAndNetworkId(long
> networkId, long instanceId) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +    @Override
> > +    public NicSecondaryIpVO findByIp4AddressAndNetworkId(String
> ip4Address, long networkId) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +    @Override
> > +    public NicSecondaryIpVO findByIp4AddressAndNicId(String ip4Address,
> long nicId) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("address", ip4Address);
> > +        sc.setParameters("nicId", nicId);
> > +        return findOneBy(sc);
> > +    }
> > +
> > +    @Override
> > +    public NicSecondaryIpVO
> findByIp4AddressAndNetworkIdAndInstanceId(
> > +            long networkId, Long vmId, String vmIp) {
> > +        SearchCriteria<NicSecondaryIpVO> sc = AllFieldsSearch.create();
> > +        sc.setParameters("network", networkId);
> > +        sc.setParameters("instanceId", vmId);
> > +        sc.setParameters("address", vmIp);
> > +        return findOneBy(sc);
> > +    }
> > +}
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> > ----------------------------------------------------------------------
> > diff --git a/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> > b/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> > new file mode 100644
> > index 0000000..770e188
> > --- /dev/null
> > +++ b/server/src/com/cloud/vm/dao/NicSecondaryIpVO.java
> > @@ -0,0 +1,160 @@
> > +// Licensed to the Apache Software Foundation (ASF) under one // or
> > +more contributor license agreements.  See the NOTICE file //
> > +distributed with this work for additional information // regarding
> > +copyright ownership.  The ASF licenses this file // to you under the
> > +Apache License, Version 2.0 (the // "License"); you may not use this
> > +file except in compliance // with the License.  You may obtain a copy
> > +of the License at //
> > +//   http://www.apache.org/licenses/LICENSE-2.0
> > +//
> > +// Unless required by applicable law or agreed to in writing, //
> > +software distributed under the License is distributed on an // "AS
> > +IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND,
> either
> > +express or implied.  See the License for the // specific language
> > +governing permissions and limitations // under the License.
> > +package com.cloud.vm.dao;
> > +
> > +import java.util.Date;
> > +import java.util.UUID;
> > +
> > +import javax.persistence.Column;
> > +import javax.persistence.Entity;
> > +import javax.persistence.GeneratedValue; import
> > +javax.persistence.GenerationType;
> > +import javax.persistence.Id;
> > +import javax.persistence.Table;
> > +
> > +import com.cloud.utils.db.GenericDao; import
> > +com.cloud.vm.NicSecondaryIp;
> > +
> > +@Entity
> > +@Table(name = "nic_secondary_ips")
> > +public class NicSecondaryIpVO implements NicSecondaryIp {
> > +
> > +    public NicSecondaryIpVO(Long nicId, String ipaddr, Long vmId,
> > +            Long accountId, Long domainId, Long networkId) {
> > +        this.nicId = nicId;
> > +        this.vmId = vmId;
> > +        this.ip4Address = ipaddr;
> > +        this.accountId = accountId;
> > +        this.domainId = domainId;
> > +        this.networkId = networkId;
> > +    }
> > +
> > +    protected NicSecondaryIpVO() {
> > +    }
> > +
> > +    @Id
> > +    @GeneratedValue(strategy = GenerationType.IDENTITY)
> > +    @Column(name = "id")
> > +    long id;
> > +
> > +    @Column(name = "nicId")
> > +    long nicId;
> > +
> > +    @Column(name="domain_id", updatable=false)
> > +    long domainId;
> > +
> > +    @Column(name="account_id", updatable=false)
> > +    private Long accountId;
> > +
> > +    @Column(name = "ip4_address")
> > +    String ip4Address;
> > +
> > +    @Column(name = "ip6_address")
> > +    String ip6Address;
> > +
> > +    @Column(name = "network_id")
> > +    long networkId;
> > +
> > +    @Column(name = GenericDao.CREATED_COLUMN)
> > +    Date created;
> > +
> > +    @Column(name = "uuid")
> > +    String uuid = UUID.randomUUID().toString();
> > +
> > +    @Column(name = "vmId")
> > +    Long vmId;
> > +
> > +    public long getId() {
> > +        return id;
> > +    }
> > +
> > +    public void setId(long id) {
> > +        this.id = id;
> > +    }
> > +
> > +    public long getNicId() {
> > +        return nicId;
> > +    }
> > +
> > +    public void setNicId(long nicId) {
> > +        this.nicId = nicId;
> > +    }
> > +
> > +    public long getDomainId() {
> > +        return domainId;
> > +    }
> > +
> > +    public void setDomainId(Long domainId) {
> > +        this.domainId = domainId;
> > +    }
> > +
> > +    public long getAccountId() {
> > +        return accountId;
> > +    }
> > +
> > +    public void setAccountId(Long accountId) {
> > +        this.accountId = accountId;
> > +    }
> > +
> > +    public String getIp4Address() {
> > +        return ip4Address;
> > +    }
> > +
> > +    public void setIp4Address(String ip4Address) {
> > +        this.ip4Address = ip4Address;
> > +    }
> > +
> > +    public String getIp6Address() {
> > +        return ip6Address;
> > +    }
> > +
> > +    public void setIp6Address(String ip6Address) {
> > +        this.ip6Address = ip6Address;
> > +    }
> > +
> > +    public long getNetworkId() {
> > +        return networkId;
> > +    }
> > +
> > +    public void setNetworkId(long networkId) {
> > +        this.networkId = networkId;
> > +    }
> > +
> > +    public Date getCreated() {
> > +        return created;
> > +    }
> > +
> > +    public void setCreated(Date created) {
> > +        this.created = created;
> > +    }
> > +
> > +    public String getUuid() {
> > +        return uuid;
> > +    }
> > +
> > +    public void setUuid(String uuid) {
> > +        this.uuid = uuid;
> > +    }
> > +
> > +    public long getVmId() {
> > +        return vmId;
> > +    }
> > +
> > +    public void setVmId(Long vmId) {
> > +        this.vmId = vmId;
> > +    }
> > +}
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/test/com/cloud/network/MockNetworkManagerImpl.java
> > ----------------------------------------------------------------------
> > diff --git
> a/server/test/com/cloud/network/MockNetworkManagerImpl.java
> > b/server/test/com/cloud/network/MockNetworkManagerImpl.java
> > index 3568da5..8004310 100755
> > --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java
> > +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java
> > @@ -29,6 +29,7 @@ import
> > org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
> >  import
> > org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
> >  import
> > org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
> >  import org.springframework.stereotype.Component;
> > +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
> >
> >  import com.cloud.dc.DataCenter;
> >  import com.cloud.dc.Vlan.VlanType;
> > @@ -64,6 +65,7 @@ import com.cloud.utils.component.Manager;
> >  import com.cloud.utils.component.ManagerBase;
> >  import com.cloud.vm.Nic;
> >  import com.cloud.vm.NicProfile;
> > +import com.cloud.vm.NicSecondaryIp;
> >  import com.cloud.vm.ReservationContext;  import
> > com.cloud.vm.VMInstanceVO;  import com.cloud.vm.VirtualMachine; @@
> > -824,4 +826,49 @@ public class MockNetworkManagerImpl extends
> ManagerBase implements NetworkManage
> >          // TODO Auto-generated method stub
> >          return null;
> >      }
> > +
> > +    @Override
> > +    public boolean isSecondaryIpSetForNic(long nicId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +    @Override
> > +    public boolean releaseSecondaryIpFromNic(long ipAddressId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +    @Override
> > +    public String allocateSecondaryGuestIP(Account account, long zoneId,
> > +            Long nicId, Long networkId, String ipaddress) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +    @Override
> > +    public String allocateGuestIP(Account ipOwner, boolean isSystem,
> > +            long zoneId, Long networkId, String requestedIp)
> > +            throws InsufficientAddressCapacityException {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +    @Override
> > +    public boolean removeVmSecondaryIps(long vmId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +    @Override
> > +    public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +    @Override
> > +    public List<? extends Nic> listNics(ListNicsCmd listNicsCmd) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/test/com/cloud/network/MockRulesManagerImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/test/com/cloud/network/MockRulesManagerImpl.java
> > b/server/test/com/cloud/network/MockRulesManagerImpl.java
> > index ba3dd41..e5a6894 100644
> > --- a/server/test/com/cloud/network/MockRulesManagerImpl.java
> > +++ b/server/test/com/cloud/network/MockRulesManagerImpl.java
> > @@ -39,6 +39,7 @@ import com.cloud.uservm.UserVm;  import
> > com.cloud.utils.Pair;  import com.cloud.utils.component.Manager;
> >  import com.cloud.utils.component.ManagerBase;
> > +import com.cloud.utils.net.Ip;
> >  import com.cloud.vm.VirtualMachine;
> >
> >  @Local(value = {RulesManager.class, RulesService.class}) @@ -54,14
> > +55,6 @@ public class MockRulesManagerImpl extends ManagerBase
> implements RulesManager, R
> >         }
> >
> >         @Override
> > -       public PortForwardingRule
> createPortForwardingRule(PortForwardingRule rule,
> > -                       Long vmId, boolean openFirewall)
> > -                       throws NetworkRuleConflictException {
> > -               // TODO Auto-generated method stub
> > -               return null;
> > -       }
> > -
> > -       @Override
> >         public boolean revokePortForwardingRule(long ruleId, boolean apply) {
> >                 // TODO Auto-generated method stub
> >                 return false;
> > @@ -83,7 +76,7 @@ public class MockRulesManagerImpl extends
> > ManagerBase implements RulesManager, R
> >
> >         @Override
> >         public boolean enableStaticNat(long ipAddressId, long vmId, long
> networkId,
> > -                       boolean isSystemVm) throws NetworkRuleConflictException,
> > +                       boolean isSystemVm, String ipAddr) throws
> > + NetworkRuleConflictException,
> >                         ResourceUnavailableException {
> >                 // TODO Auto-generated method stub
> >                 return false;
> > @@ -310,4 +303,12 @@ public class MockRulesManagerImpl extends
> ManagerBase implements RulesManager, R
> >                 return "MockRulesManagerImpl";
> >         }
> >
> > +    @Override
> > +    public PortForwardingRule
> createPortForwardingRule(PortForwardingRule rule,
> > +            Long vmId, Ip vmIp, boolean openFirewall)
> > +            throws NetworkRuleConflictException {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> > ----------------------------------------------------------------------
> > diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> > b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> > index 828a555..63ef874 100644
> > --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> > +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
> > @@ -29,6 +29,7 @@ import
> >
> org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplement
> > ors  import
> > org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
> >  import
> > org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
> >  import
> > org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
> > +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
> >  import org.apache.log4j.Logger;
> >  import org.springframework.stereotype.Component;
> >
> > @@ -80,6 +81,7 @@ import com.cloud.utils.component.Manager;
> >  import com.cloud.utils.component.ManagerBase;
> >  import com.cloud.vm.Nic;
> >  import com.cloud.vm.NicProfile;
> > +import com.cloud.vm.NicSecondaryIp;
> >  import com.cloud.vm.ReservationContext;  import
> > com.cloud.vm.VMInstanceVO;  import com.cloud.vm.VirtualMachine; @@
> > -1317,4 +1319,75 @@ public class MockNetworkManagerImpl extends
> ManagerBase implements NetworkManage
> >          // TODO Auto-generated method stub
> >          return null;
> >      }
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public boolean isSecondaryIpSetForNic(long nicId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +    @Override
> > +    public String allocateSecondaryGuestIP(Account account, long zoneId,
> > +            Long nicId, Long networkId, String ipaddress) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public boolean releaseSecondaryIpFromNic(long ipAddressId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public String allocateGuestIP(Account ipOwner, boolean isSystem,
> > +            long zoneId, Long networkId, String requestedIp)
> > +            throws InsufficientAddressCapacityException {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public boolean removeVmSecondaryIps(long vmId) {
> > +        // TODO Auto-generated method stub
> > +        return false;
> > +    }
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> > +
> > +
> > +
> > +
> > +
> > +    @Override
> > +    public List<? extends Nic> listNics(ListNicsCmd listNicsCmd) {
> > +        // TODO Auto-generated method stub
> > +        return null;
> > +    }
> >  }
> >
> > http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8
> > c47/setup/db/db/schema-410to420.sql
> > ----------------------------------------------------------------------
> > diff --git a/setup/db/db/schema-410to420.sql
> > b/setup/db/db/schema-410to420.sql index 4349bd0..6f68e12 100644
> > --- a/setup/db/db/schema-410to420.sql
> > +++ b/setup/db/db/schema-410to420.sql
> > @@ -112,3 +112,24 @@ INSERT IGNORE INTO `cloud`.`configuration`
> VALUES
> > ('Advanced', 'DEFAULT', 'UserV
> >
> >  -- Re-enable foreign key checking, at the end of the upgrade path
> > SET foreign_key_checks = 1;
> > +
> > +
> > +CREATE TABLE nic_secondary_ips (
> > +  `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
> > +  `uuid` varchar(40),
> > +  `vmId` bigint unsigned COMMENT 'vm instance id',
> > +  `nicId` bigint unsigned NOT NULL,
> > +  `ip4_address` char(40) COMMENT 'ip4 address',
> > +  `ip6_address` char(40) COMMENT 'ip6 address',
> > +  `network_id` bigint unsigned NOT NULL COMMENT 'network
> > +configuration id',
> > +  `created` datetime NOT NULL COMMENT 'date created',
> > +  `account_id` bigint unsigned NOT NULL COMMENT 'owner.  foreign key
> to   account table',
> > +  `domain_id` bigint unsigned NOT NULL COMMENT 'the domain that the
> owner belongs to',
> > +   PRIMARY KEY (`id`),
> > +   CONSTRAINT `fk_nic_secondary_ip__vmId` FOREIGN KEY
> `fk_nic_secondary_ip__vmId`(`vmId`) REFERENCES `vm_instance`(`id`) ON
> DELETE CASCADE,
> > +   CONSTRAINT `fk_nic_secondary_ip__networks_id` FOREIGN KEY
> `fk_nic_secondary_ip__networks_id`(`network_id`) REFERENCES
> `networks`(`id`),
> > +   CONSTRAINT `uc_nic_secondary_ip__uuid` UNIQUE (`uuid`)
> > +) ENGINE=InnoDB DEFAULT CHARSET=utf8;
> > +
> > +ALTER TABLE `cloud`.`nics` ADD COLUMN secondary_ip SMALLINT
> DEFAULT
> > +'0' COMMENT 'secondary ips configured for the nic'; ALTER TABLE
> > +`cloud`.`user_ip_address` ADD COLUMN dnat_vmip VARCHAR(40);
> >