cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bfede...@apache.org
Subject [21/50] [abbrv] git commit: refs/heads/ui-multiple-nics - CLOUDSTACK-24: mipn feature for isolated and vpc networks
Date Tue, 05 Mar 2013 18:37:40 GMT
CLOUDSTACK-24: mipn feature for isolated and vpc networks

 https://cwiki.apache.org/confluence/display/CLOUDSTACK/Multiple+IP+address+per+NIC
 https://issues.apache.org/jira/browse/CLOUDSTACK-24


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/aedb8c47
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/aedb8c47
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/aedb8c47

Branch: refs/heads/ui-multiple-nics
Commit: aedb8c478e88ad393246b9fa08a7fdac53e8e2d9
Parents: fe649f6
Author: Jayapal Uradi <jayapalreddy.uradi@citrix.com>
Authored: Mon Mar 4 11:02:09 2013 +0530
Committer: Abhinandan Prateek <aprateek@apache.org>
Committed: Mon Mar 4 11:02:09 2013 +0530

----------------------------------------------------------------------
 api/src/com/cloud/network/IpAddress.java           |    3 +
 api/src/com/cloud/network/NetworkService.java      |   15 +-
 api/src/com/cloud/network/rules/RulesService.java  |    5 +-
 api/src/com/cloud/vm/Nic.java                      |    1 +
 api/src/com/cloud/vm/NicSecondaryIp.java           |   36 +++
 .../org/apache/cloudstack/api/ApiConstants.java    |    1 +
 .../apache/cloudstack/api/ResponseGenerator.java   |    7 +
 .../user/firewall/CreatePortForwardingRuleCmd.java |   19 ++-
 .../api/command/user/nat/EnableStaticNatCmd.java   |   12 +-
 .../api/command/user/vm/AddIpToVmNicCmd.java       |  176 +++++++++++++++
 .../api/command/user/vm/ListNicsCmd.java           |  133 +++++++++++
 .../api/command/user/vm/RemoveIpFromVmNicCmd.java  |  123 ++++++++++
 .../api/response/AddIpToVmNicResponse.java         |   85 +++++++
 .../cloudstack/api/response/IPAddressResponse.java |    8 +
 .../cloudstack/api/response/NicResponse.java       |   12 +-
 .../api/response/NicSecondaryIpResponse.java       |   85 +++++++
 .../api/command/test/AddIpToVmNicTest.java         |  132 +++++++++++
 client/tomcatconf/commands.properties.in           |    5 +
 server/src/com/cloud/api/ApiDBUtils.java           |   10 +
 server/src/com/cloud/api/ApiResponseHelper.java    |   56 +++++
 server/src/com/cloud/network/NetworkManager.java   |   12 +
 .../src/com/cloud/network/NetworkManagerImpl.java  |   76 ++++++-
 server/src/com/cloud/network/NetworkModelImpl.java |    5 +
 .../src/com/cloud/network/NetworkServiceImpl.java  |  170 ++++++++++++++
 server/src/com/cloud/network/addr/PublicIp.java    |   34 ++-
 server/src/com/cloud/network/dao/IPAddressDao.java |    7 +-
 .../com/cloud/network/dao/IPAddressDaoImpl.java    |   17 ++-
 server/src/com/cloud/network/dao/IPAddressVO.java  |   16 ++-
 .../router/VirtualNetworkApplianceManagerImpl.java |    3 +-
 .../com/cloud/network/rules/RulesManagerImpl.java  |  113 +++++++---
 .../network/rules/dao/PortForwardingRulesDao.java  |    2 +
 .../rules/dao/PortForwardingRulesDaoImpl.java      |    8 +
 .../src/com/cloud/server/ManagementServerImpl.java |    3 +
 server/src/com/cloud/vm/NicVO.java                 |   11 +
 server/src/com/cloud/vm/UserVmManagerImpl.java     |    8 +
 server/src/com/cloud/vm/dao/NicDao.java            |    2 +
 server/src/com/cloud/vm/dao/NicDaoImpl.java        |   12 +-
 server/src/com/cloud/vm/dao/NicSecondaryIpDao.java |   53 +++++
 .../com/cloud/vm/dao/NicSecondaryIpDaoImpl.java    |  138 +++++++++++
 server/src/com/cloud/vm/dao/NicSecondaryIpVO.java  |  160 +++++++++++++
 .../com/cloud/network/MockNetworkManagerImpl.java  |   47 ++++
 .../com/cloud/network/MockRulesManagerImpl.java    |   19 +-
 .../test/com/cloud/vpc/MockNetworkManagerImpl.java |   73 ++++++
 setup/db/db/schema-410to420.sql                    |   21 ++
 44 files changed, 1866 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/com/cloud/network/IpAddress.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/IpAddress.java b/api/src/com/cloud/network/IpAddress.java
index 47df4d6..fce8f38 100644
--- a/api/src/com/cloud/network/IpAddress.java
+++ b/api/src/com/cloud/network/IpAddress.java
@@ -87,4 +87,7 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity
      * @param vpcId
      */
     void setVpcId(Long vpcId);
+    String getVmIp();
+    void setVmIp(String vmIp);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/com/cloud/network/NetworkService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java
index 95bcc42..ab6d7bf 100755
--- a/api/src/com/cloud/network/NetworkService.java
+++ b/api/src/com/cloud/network/NetworkService.java
@@ -19,9 +19,10 @@ package com.cloud.network;
 import java.util.List;
 
 import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
+import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
 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 com.cloud.exception.ConcurrentOperationException;
 import com.cloud.exception.InsufficientAddressCapacityException;
@@ -33,6 +34,8 @@ import com.cloud.network.Networks.TrafficType;
 import com.cloud.user.Account;
 import com.cloud.user.User;
 import com.cloud.utils.Pair;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicSecondaryIp;
 
 /**
  * The NetworkService interface is the "public" api to entities that make requests to the orchestration engine
@@ -153,5 +156,13 @@ public interface NetworkService {
     Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan,
             String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId)
                     throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException;
- 
+
+    /* Requests an IP address for the guest nic */
+    String allocateSecondaryGuestIP(Account account, long zoneId, Long nicId,
+            Long networkId, String ipaddress) throws InsufficientAddressCapacityException;
+
+    boolean releaseSecondaryIpFromNic(long ipAddressId);
+
+    /* lists the nic informaton */
+    List<? extends Nic> listNics(ListNicsCmd listNicsCmd);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/com/cloud/network/rules/RulesService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/rules/RulesService.java b/api/src/com/cloud/network/rules/RulesService.java
index 921a86e..d47b38f 100644
--- a/api/src/com/cloud/network/rules/RulesService.java
+++ b/api/src/com/cloud/network/rules/RulesService.java
@@ -25,6 +25,7 @@ import com.cloud.exception.NetworkRuleConflictException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.user.Account;
 import com.cloud.utils.Pair;
+import com.cloud.utils.net.Ip;
 
 public interface RulesService {
     Pair<List<? extends FirewallRule>, Integer> searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId, Long projectId, boolean isRecursive, boolean listAll);
@@ -43,7 +44,7 @@ public interface RulesService {
      * @throws NetworkRuleConflictException
      *             if conflicts in the network rules are detected.
      */
-    PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean openFirewall) throws NetworkRuleConflictException;
+    PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, Ip vmIp, boolean openFirewall) throws NetworkRuleConflictException;
 
     /**
      * Revokes a port forwarding rule
@@ -66,7 +67,7 @@ public interface RulesService {
 
     boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
 
-    boolean enableStaticNat(long ipAddressId, long vmId, long networkId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException;
+    boolean enableStaticNat(long ipAddressId, long vmId, long networkId, boolean isSystemVm, String vmGuestIp) throws NetworkRuleConflictException, ResourceUnavailableException;
 
     PortForwardingRule getPortForwardigRule(long ruleId);
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/com/cloud/vm/Nic.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/Nic.java b/api/src/com/cloud/vm/Nic.java
index 9d21130..b2f6976 100644
--- a/api/src/com/cloud/vm/Nic.java
+++ b/api/src/com/cloud/vm/Nic.java
@@ -151,4 +151,5 @@ public interface Nic extends Identity, InternalIdentity {
 	String getIp6Cidr();
 
 	String getIp6Address();
+    boolean getSecondaryIp();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/com/cloud/vm/NicSecondaryIp.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/NicSecondaryIp.java b/api/src/com/cloud/vm/NicSecondaryIp.java
new file mode 100644
index 0000000..655d172
--- /dev/null
+++ b/api/src/com/cloud/vm/NicSecondaryIp.java
@@ -0,0 +1,36 @@
+// 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;
+
+import org.apache.cloudstack.acl.ControlledEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+
+/**
+ * Nic represents one nic on the VM.
+ */
+public interface NicSecondaryIp  extends ControlledEntity, Identity, InternalIdentity {
+    /**
+     * @return id in the CloudStack database
+     */
+    long getId();
+    long getNicId();
+    String getIp4Address();
+    long getNetworkId();
+    long getVmId();
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 4fdc91e..1b544fd 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -458,6 +458,7 @@ public class ApiConstants {
     public static final String UCS_PROFILE_DN = "profiledn";
     public static final String UCS_BLADE_DN = "bladedn";
     public static final String UCS_BLADE_ID = "bladeid";
+    public static final String VM_GUEST_IP = "vmguestip";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/ResponseGenerator.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index 267238a..a602514 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -53,6 +53,8 @@ import org.apache.cloudstack.api.response.LoadBalancerResponse;
 import org.apache.cloudstack.api.response.NetworkACLResponse;
 import org.apache.cloudstack.api.response.NetworkOfferingResponse;
 import org.apache.cloudstack.api.response.NetworkResponse;
+import org.apache.cloudstack.api.response.NicResponse;
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
 import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
 import org.apache.cloudstack.api.response.PodResponse;
 import org.apache.cloudstack.api.response.PrivateGatewayResponse;
@@ -163,6 +165,8 @@ import com.cloud.user.User;
 import com.cloud.user.UserAccount;
 import com.cloud.uservm.UserVm;
 import com.cloud.vm.InstanceGroup;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.snapshot.VMSnapshot;
 
@@ -385,4 +389,7 @@ public interface ResponseGenerator {
 
     TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor);
     VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot);
+    NicSecondaryIpResponse createSecondaryIPToNicResponse(String ip,
+            Long nicId, Long networkId);
+    public NicResponse createNicResponse(Nic result);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
index 39ab812..4012852 100644
--- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java
@@ -94,6 +94,9 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
             description="The network of the vm the Port Forwarding rule will be created for. " +
                 "Required when public Ip address is not associated with any Guest network yet (VPC case)")
     private Long networkId;
+    @Parameter(name = ApiConstants.VM_GUEST_IP, type = CommandType.STRING, required = false,
+    description = "VM guest nic Secondary ip address for the port forwarding rule")
+    private String vmSecondaryIp;
 
     // ///////////////////////////////////////////////////
     // ///////////////// Accessors ///////////////////////
@@ -104,6 +107,13 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
         return ipAddressId;
     }
 
+    public Ip getVmSecondaryIp() {
+        if (vmSecondaryIp == null) {
+            return null;
+        }
+        return new Ip(vmSecondaryIp);
+    }
+
     @Override
     public String getProtocol() {
         return protocol.trim();
@@ -300,8 +310,15 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
             throw new InvalidParameterValueException("Parameter cidrList is deprecated; if you need to open firewall rule for the specific cidr, please refer to createFirewallRule command");
         }
 
+        Ip privateIp = getVmSecondaryIp();
+        if (privateIp != null) {
+            if ( !privateIp.isIp4()) {
+                throw new InvalidParameterValueException("Invalid vm ip address");
+            }
+        }
+
         try {
-            PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, getOpenFirewall());
+            PortForwardingRule result = _rulesService.createPortForwardingRule(this, virtualMachineId, privateIp, getOpenFirewall());
             setEntityId(result.getId());
             setEntityUuid(result.getUuid());
         } catch (NetworkRuleConflictException ex) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java
index ce6ea16..a0ec68e 100644
--- a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java
@@ -59,6 +59,9 @@ public class EnableStaticNatCmd extends BaseCmd{
         description="The network of the vm the static nat will be enabled for." +
                 " Required when public Ip address is not associated with any Guest network yet (VPC case)")
     private Long networkId;
+    @Parameter(name = ApiConstants.VM_GUEST_IP, type = CommandType.STRING, required = false,
+    description = "VM guest nic Secondary ip address for the port forwarding rule")
+    private String vmSecondaryIp;
 
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
@@ -72,6 +75,13 @@ public class EnableStaticNatCmd extends BaseCmd{
         return virtualMachineId;
     }
 
+    public String getVmSecondaryIp() {
+        if (vmSecondaryIp == null) {
+            return null;
+        }
+        return vmSecondaryIp;
+    }
+
     public long getNetworkId() {
         IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
         Long ntwkId = null;
@@ -110,7 +120,7 @@ public class EnableStaticNatCmd extends BaseCmd{
     @Override
     public void execute() throws ResourceUnavailableException{
         try {
-            boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), false);
+            boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), false, getVmSecondaryIp());
             if (result) {
                 SuccessResponse response = new SuccessResponse(getCommandName());
                 this.setResponseObject(response);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java
new file mode 100644
index 0000000..0f99274
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java
@@ -0,0 +1,176 @@
+// 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 org.apache.cloudstack.api.command.user.vm;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.NicResponse;
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
+
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.utils.net.NetUtils;
+import com.cloud.vm.Nic;
+
+@APICommand(name = "addIpToNic", description = "Assigns secondary IP to NIC", responseObject = NicSecondaryIpResponse.class)
+public class AddIpToVmNicCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(AddIpToVmNicCmd.class.getName());
+    private static final String s_name = "addiptovmnicresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+    @Parameter(name=ApiConstants.NIC_ID, type=CommandType.UUID, entityType = NicResponse.class, required = true,
+            description="the ID of the nic to which you want to assign private IP")
+            private Long nicId;
+
+    @Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, required = false,
+            description = "Secondary IP Address")
+            private String ipAddr;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "nic_secondary_ips";
+    }
+
+    public String getAccountName() {
+        return UserContext.current().getCaller().getAccountName();
+    }
+
+    public long getDomainId() {
+        return UserContext.current().getCaller().getDomainId();
+    }
+
+    private long getZoneId() {
+        Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
+        if (ntwk == null) {
+            throw new InvalidParameterValueException("Can't find zone id for specified");
+        }
+        return ntwk.getDataCenterId();
+    }
+
+    public Long getNetworkId() {
+        Nic nic = _entityMgr.findById(Nic.class, nicId);
+        Long networkId = nic.getNetworkId();
+        return networkId;
+    }
+
+    public Long getNicId() {
+        return nicId;
+    }
+
+    public String getIpaddress () {
+        if (ipAddr != null) {
+            return ipAddr;
+        } else {
+            return null;
+        }
+    }
+    @Override
+    public long getEntityOwnerId() {
+        Account caller = UserContext.current().getCaller();
+        return caller.getAccountId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_NET_IP_ASSIGN;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  "associating ip to nic id: " + getNetworkId() + " in zone " + getZoneId();
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "addressinfo";
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException, ResourceAllocationException,
+    ConcurrentOperationException, InsufficientCapacityException {
+
+        UserContext.current().setEventDetails("Nic Id: " + getNicId() );
+        String ip;
+        String SecondaryIp = null;
+        if ((ip = getIpaddress()) != null) {
+            if (!NetUtils.isValidIp(ip)) {
+                throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid ip address " + ip);
+            }
+        }
+
+        try {
+            SecondaryIp =  _networkService.allocateSecondaryGuestIP(_accountService.getAccount(getEntityOwnerId()),  getZoneId(), getNicId(), getNetworkId(), getIpaddress());
+        } catch (InsufficientAddressCapacityException e) {
+            throw new InvalidParameterValueException("Allocating guest ip for nic failed");
+        }
+
+        if (SecondaryIp != null) {
+            s_logger.info("Associated ip address to NIC : " + SecondaryIp);
+            NicSecondaryIpResponse response = new NicSecondaryIpResponse();
+            response = _responseGenerator.createSecondaryIPToNicResponse(ip, getNicId(), getNetworkId());
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign secondary ip to nic");
+        }
+    }
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public Long getSyncObjId() {
+        return getNetworkId();
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.IpAddress;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
new file mode 100644
index 0000000..9af044e
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java
@@ -0,0 +1,133 @@
+// 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 org.apache.cloudstack.api.command.user.vm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.NicResponse;
+import org.apache.cloudstack.api.response.UserVmResponse;
+
+import com.cloud.async.AsyncJob;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicSecondaryIp;
+
+@APICommand(name = "listNics", description = "list the vm nics  IP to NIC", responseObject = NicResponse.class)
+public class ListNicsCmd extends BaseListCmd {
+    public static final Logger s_logger = Logger.getLogger(ListNicsCmd.class.getName());
+    private static final String s_name = "listnics";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.NIC_ID, type=CommandType.UUID, entityType = NicResponse.class, required = false,
+            description="the ID of the nic to to list IPs")
+            private Long nicId;
+
+    @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = UserVmResponse.class, required = true,
+            description="the ID of the vm")
+            private Long vmId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "nics";
+    }
+
+    public String getAccountName() {
+        return UserContext.current().getCaller().getAccountName();
+    }
+
+    public long getDomainId() {
+        return UserContext.current().getCaller().getDomainId();
+    }
+
+    public Long getNicId() {
+        return nicId;
+    }
+
+    public Long getVmId() {
+        return vmId;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account caller = UserContext.current().getCaller();
+        return caller.getAccountId();
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "addressinfo";
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException, ResourceAllocationException,
+    ConcurrentOperationException, InsufficientCapacityException {
+
+        try {
+            List<? extends Nic> results = _networkService.listNics(this);
+            ListResponse<NicResponse> response = new ListResponse<NicResponse>();
+            List<NicResponse> resList = new ArrayList<NicResponse>(results.size());
+            for (Nic r : results) {
+                NicResponse resp = _responseGenerator.createNicResponse(r);
+                resp.setObjectName("nic");
+                resList.add(resp);
+            }
+            response.setResponses(resList);
+            response.setResponseName(getCommandName());
+            this.setResponseObject(response);
+
+        } catch (Exception e) {
+            s_logger.warn("Failed to list secondary ip address per nic ");
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
+        }
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.IpAddress;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
new file mode 100644
index 0000000..cb5e085
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java
@@ -0,0 +1,123 @@
+// 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 org.apache.cloudstack.api.command.user.vm;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import com.cloud.async.AsyncJob;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.user.Account;
+import com.cloud.user.UserContext;
+
+@APICommand(name = "removeIpFromNic", description="Assigns secondary IP to NIC.", responseObject=SuccessResponse.class)
+public class RemoveIpFromVmNicCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = Logger.getLogger(RemoveIpFromVmNicCmd.class.getName());
+    private static final String s_name = "unassignsecondaryipaddrtonicresponse";
+
+    /////////////////////////////////////////////////////
+    //////////////// API parameters /////////////////////
+    /////////////////////////////////////////////////////
+
+    @Parameter(name=ApiConstants.ID, type=CommandType.UUID, required = true, entityType = NicSecondaryIpResponse.class,
+            description="the ID of the secondary ip address to nic")
+            private long id;
+
+    // unexposed parameter needed for events logging
+    @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, expose=false)
+    private Long ownerId;
+
+    /////////////////////////////////////////////////////
+    /////////////////// Accessors ///////////////////////
+    /////////////////////////////////////////////////////
+
+    public String getEntityTable() {
+        return "nic_secondary_ips";
+    }
+
+    public long getIpAddressId() {
+        return id;
+    }
+
+    public String getAccountName() {
+        return UserContext.current().getCaller().getAccountName();
+    }
+
+    public long getDomainId() {
+        return UserContext.current().getCaller().getDomainId();
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        Account caller = UserContext.current().getCaller();
+        return caller.getAccountId();
+    }
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_NET_IP_ASSIGN;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return  ("Disassociating ip address with id=" + id);
+    }
+
+    /////////////////////////////////////////////////////
+    /////////////// API Implementation///////////////////
+    /////////////////////////////////////////////////////
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    public static String getResultObjectName() {
+        return "addressinfo";
+    }
+
+    @Override
+    public void execute() throws InvalidParameterValueException {
+        UserContext.current().setEventDetails("Ip Id: " + getIpAddressId());
+        boolean result = _networkService.releaseSecondaryIpFromNic(getIpAddressId());
+        if (result) {
+            SuccessResponse response = new SuccessResponse(getCommandName());
+            this.setResponseObject(response);
+        } else {
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove secondary  ip address for the nic");
+        }
+    }
+
+    @Override
+    public String getSyncObjType() {
+        return BaseAsyncCmd.networkSyncObject;
+    }
+
+    @Override
+    public AsyncJob.Type getInstanceType() {
+        return AsyncJob.Type.IpAddress;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/response/AddIpToVmNicResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/AddIpToVmNicResponse.java b/api/src/org/apache/cloudstack/api/response/AddIpToVmNicResponse.java
new file mode 100644
index 0000000..9af20b2
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/AddIpToVmNicResponse.java
@@ -0,0 +1,85 @@
+// 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 org.apache.cloudstack.api.response;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@SuppressWarnings("unused")
+public class AddIpToVmNicResponse extends BaseResponse {
+    @SerializedName(ApiConstants.ID) @Param(description="the ID of the secondary private IP addr")
+    private Long id;
+
+    @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="Secondary IP address")
+    private String ipAddr;
+
+    @SerializedName(ApiConstants.NIC_ID) @Param(description="the ID of the nic")
+    private Long nicId;
+
+    @SerializedName(ApiConstants.NETWORK_ID) @Param(description="the ID of the network")
+    private  Long nwId;
+
+    @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) @Param(description="the ID of the vm")
+    private Long vmId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getIpAddr() {
+        return ipAddr;
+    }
+
+    public void setIpAddr(String ipAddr) {
+        this.ipAddr = ipAddr;
+    }
+
+    public Long getNicId() {
+        return nicId;
+    }
+
+    public void setNicId(Long nicId) {
+        this.nicId = nicId;
+    }
+
+    public Long getNwId() {
+        return nwId;
+    }
+
+    public void setNwId(Long nwId) {
+        this.nwId = nwId;
+    }
+
+    public Long getVmId() {
+        return vmId;
+    }
+
+    public void setVmId(Long vmId) {
+        this.vmId = vmId;
+    }
+
+    public Long setId(Long id) {
+        return id;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
index 251b2dd..cede84f 100644
--- a/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/IPAddressResponse.java
@@ -82,6 +82,10 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
     @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) @Param(description="virutal machine id the ip address is assigned to (not null only for static nat Ip)")
     private String virtualMachineId;
 
+    @SerializedName("vmipaddress") @Param(description="virutal machine (dnat) ip address (not null only for static nat Ip)")
+    private String virtualMachineIp;
+
+
     @SerializedName("virtualmachinename") @Param(description="virutal machine name the ip address is assigned to (not null only for static nat Ip)")
     private String virtualMachineName;
 
@@ -185,6 +189,10 @@ public class IPAddressResponse extends BaseResponse implements ControlledEntityR
         this.virtualMachineId = virtualMachineId;
     }
 
+    public void setVirtualMachineIp(String virtualMachineIp) {
+        this.virtualMachineIp = virtualMachineIp;
+    }
+
     public void setVirtualMachineName(String virtualMachineName) {
         this.virtualMachineName = virtualMachineName;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/response/NicResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NicResponse.java b/api/src/org/apache/cloudstack/api/response/NicResponse.java
index a7d1a0d..a1ceaf6 100644
--- a/api/src/org/apache/cloudstack/api/response/NicResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NicResponse.java
@@ -16,6 +16,8 @@
 // under the License.
 package org.apache.cloudstack.api.response;
 
+import java.util.List;
+
 import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.BaseResponse;
 
@@ -75,7 +77,10 @@ public class NicResponse extends BaseResponse {
     
     @SerializedName(ApiConstants.IP6_ADDRESS) @Param(description="the IPv6 address of network")
     private String ip6Address;
-    
+
+    @SerializedName("secondaryip") @Param(description="the Secondary ipv4 addr of nic")
+    private List<NicSecondaryIpResponse> secondaryIps;
+
     public String getId() {
         return id;
     }
@@ -167,4 +172,9 @@ public class NicResponse extends BaseResponse {
             return false;
         return true;
     }
+
+    public void setSecondaryIps(List<NicSecondaryIpResponse> ipList) {
+        this.secondaryIps = ipList;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/src/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java b/api/src/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java
new file mode 100644
index 0000000..3464a63
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/NicSecondaryIpResponse.java
@@ -0,0 +1,85 @@
+// 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 org.apache.cloudstack.api.response;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@SuppressWarnings("unused")
+public class NicSecondaryIpResponse extends BaseResponse {
+    @SerializedName(ApiConstants.ID) @Param(description="the ID of the secondary private IP addr")
+    private Long id;
+
+    @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="Secondary IP address")
+    private String ipAddr;
+
+    @SerializedName(ApiConstants.NIC_ID) @Param(description="the ID of the nic")
+    private Long nicId;
+
+    @SerializedName(ApiConstants.NETWORK_ID) @Param(description="the ID of the network")
+    private  Long nwId;
+
+    @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) @Param(description="the ID of the vm")
+    private Long vmId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public String getIpAddr() {
+        return ipAddr;
+    }
+
+    public void setIpAddr(String ipAddr) {
+        this.ipAddr = ipAddr;
+    }
+
+    public Long getNicId() {
+        return nicId;
+    }
+
+    public void setNicId(Long nicId) {
+        this.nicId = nicId;
+    }
+
+    public Long getNwId() {
+        return nwId;
+    }
+
+    public void setNwId(Long nwId) {
+        this.nwId = nwId;
+    }
+
+    public Long getVmId() {
+        return vmId;
+    }
+
+    public void setVmId(Long vmId) {
+        this.vmId = vmId;
+    }
+
+    public Long setId(Long id) {
+        return id;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/api/test/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java
----------------------------------------------------------------------
diff --git a/api/test/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java b/api/test/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java
new file mode 100644
index 0000000..106589d
--- /dev/null
+++ b/api/test/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java
@@ -0,0 +1,132 @@
+// 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 org.apache.cloudstack.api.command.test;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.cloudstack.api.ResponseGenerator;
+import org.apache.cloudstack.api.command.user.vm.AddIpToVmNicCmd;
+import org.apache.cloudstack.api.command.user.vm.RemoveIpFromVmNicCmd;
+import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mockito;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.NetworkService;
+import com.cloud.user.Account;
+
+public class AddIpToVmNicTest extends TestCase {
+
+    private AddIpToVmNicCmd addIpToVmNicCmd;
+    private RemoveIpFromVmNicCmd removeIpFromVmNicCmd;
+    private ResponseGenerator responseGenerator;
+    private SuccessResponse successResponseGenerator;
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Before
+    public void setUp() {
+        addIpToVmNicCmd = new AddIpToVmNicCmd() {
+        };
+        removeIpFromVmNicCmd = new RemoveIpFromVmNicCmd();
+    }
+
+    @Test
+    public void testCreateSuccess() throws ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException {
+
+        NetworkService networkService = Mockito.mock(NetworkService.class);
+        AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class);
+
+        Mockito.when(
+                networkService.allocateSecondaryGuestIP(Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn("10.1.1.2");
+
+        ipTonicCmd._networkService = networkService;
+        responseGenerator = Mockito.mock(ResponseGenerator.class);
+
+        NicSecondaryIpResponse ipres = Mockito.mock(NicSecondaryIpResponse.class);
+        Mockito.when(responseGenerator.createSecondaryIPToNicResponse(Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong())).thenReturn(ipres);
+
+        ipTonicCmd._responseGenerator = responseGenerator;
+        ipTonicCmd.execute();
+    }
+
+    @Test
+    public void testCreateFailure() throws ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException {
+
+        NetworkService networkService = Mockito.mock(NetworkService.class);
+        AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class);
+
+        Mockito.when(
+                networkService.allocateSecondaryGuestIP(Mockito.any(Account.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn(null);
+
+        ipTonicCmd._networkService = networkService;
+
+        try {
+            ipTonicCmd.execute();
+        } catch (InsufficientAddressCapacityException e) {
+            throw new InvalidParameterValueException("Allocating guest ip for nic failed");
+        }
+    }
+
+    @Test
+    public void testRemoveIpFromVmNicSuccess() throws ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException, InsufficientCapacityException {
+
+        NetworkService networkService = Mockito.mock(NetworkService.class);
+        RemoveIpFromVmNicCmd removeIpFromNic = Mockito.mock(RemoveIpFromVmNicCmd.class);
+
+        Mockito.when(
+                networkService.releaseSecondaryIpFromNic(Mockito.anyInt())).thenReturn(true);
+
+        removeIpFromNic._networkService = networkService;
+        successResponseGenerator = Mockito.mock(SuccessResponse.class);
+
+        removeIpFromNic.execute();
+    }
+
+    @Test
+    public void testRemoveIpFromVmNicFailure() throws InsufficientAddressCapacityException {
+        NetworkService networkService = Mockito.mock(NetworkService.class);
+        RemoveIpFromVmNicCmd removeIpFromNic = Mockito.mock(RemoveIpFromVmNicCmd.class);
+
+        Mockito.when(
+                networkService.releaseSecondaryIpFromNic(Mockito.anyInt())).thenReturn(false);
+
+        removeIpFromNic._networkService = networkService;
+        successResponseGenerator = Mockito.mock(SuccessResponse.class);
+
+        try {
+            removeIpFromNic.execute();
+        } catch (InvalidParameterValueException exception) {
+            Assert.assertEquals("Failed to remove secondary  ip address for the nic",
+                    exception.getLocalizedMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index f03e8d5..bbb3d30 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -326,6 +326,11 @@ addNicToVirtualMachine=15
 removeNicFromVirtualMachine=15
 updateDefaultNicForVirtualMachine=15
 
+####
+addIpToNic=15;
+removeIpFromNic=15;
+listNics=15;
+
 #### SSH key pair commands
 registerSSHKeyPair=15
 createSSHKeyPair=15

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/api/ApiDBUtils.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index ffee22f..95879ee 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -201,6 +201,7 @@ import com.cloud.vm.DomainRouterVO;
 import com.cloud.vm.InstanceGroup;
 import com.cloud.vm.InstanceGroupVO;
 import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.UserVmDetailVO;
 import com.cloud.vm.UserVmManager;
 import com.cloud.vm.UserVmVO;
@@ -209,6 +210,8 @@ import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VmStats;
 import com.cloud.vm.dao.ConsoleProxyDao;
 import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
@@ -319,6 +322,7 @@ public class ApiDBUtils {
     static HostDetailsDao _hostDetailsDao;
     static VMSnapshotDao _vmSnapshotDao;
     static ClusterDetailsDao _clusterDetailsDao;
+    static NicSecondaryIpDao _nicSecondaryIpDao;
 
     @Inject private ManagementServer ms;
     @Inject public AsyncJobManager asyncMgr;
@@ -421,6 +425,7 @@ public class ApiDBUtils {
     @Inject private HostDetailsDao hostDetailsDao;
     @Inject private ClusterDetailsDao clusterDetailsDao;
     @Inject private VMSnapshotDao vmSnapshotDao;
+    @Inject private NicSecondaryIpDao nicSecondaryIpDao;
     @PostConstruct
     void init() {
         _ms = ms;
@@ -521,6 +526,7 @@ public class ApiDBUtils {
         _hostDetailsDao = hostDetailsDao;
         _clusterDetailsDao = clusterDetailsDao;
         _vmSnapshotDao = vmSnapshotDao;
+        _nicSecondaryIpDao = nicSecondaryIpDao;
         // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned
         _statsCollector = StatsCollector.getInstance();
     }
@@ -1519,4 +1525,8 @@ public class ApiDBUtils {
    public static Map<String, String> findHostDetailsById(long hostId){
 	   return _hostDetailsDao.findDetails(hostId);
    }
+
+   public static List<NicSecondaryIpVO> findNicSecondaryIps(long nicId) {
+       return _nicSecondaryIpDao.listByNicId(nicId);
+   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java
index eafee8a..fbfc955 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -19,6 +19,7 @@ package com.cloud.api;
 import com.cloud.api.query.ViewResponseHelper;
 import com.cloud.api.query.vo.*;
 import com.cloud.api.response.ApiResponseSerializer;
+
 import org.apache.cloudstack.api.response.AsyncJobResponse;
 import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
 import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
@@ -52,6 +53,7 @@ import org.apache.cloudstack.api.response.LoadBalancerResponse;
 import org.apache.cloudstack.api.response.NetworkACLResponse;
 import org.apache.cloudstack.api.response.NetworkOfferingResponse;
 import org.apache.cloudstack.api.response.NetworkResponse;
+import org.apache.cloudstack.api.response.NicResponse;
 import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
 import org.apache.cloudstack.api.response.PodResponse;
 import org.apache.cloudstack.api.response.PrivateGatewayResponse;
@@ -180,10 +182,14 @@ import com.cloud.utils.StringUtils;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.ConsoleProxyVO;
 import com.cloud.vm.InstanceGroup;
+import com.cloud.vm.Nic;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.NicSecondaryIp;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.Type;
+import com.cloud.vm.dao.NicSecondaryIpVO;
+
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
@@ -551,6 +557,9 @@ public class ApiResponseHelper implements ResponseGenerator {
                 }
             }
         }
+        if (ipAddr.getVmIp() != null) {
+            ipResponse.setVirtualMachineIp(ipAddr.getVmIp());
+        }
 
         if (ipAddr.getAssociatedWithNetworkId() != null) {
             Network ntwk = ApiDBUtils.findNetworkById(ipAddr.getAssociatedWithNetworkId());
@@ -3435,4 +3444,51 @@ public class ApiResponseHelper implements ResponseGenerator {
         response.setTimeout(tmDetails.get("timeout"));
         return response;
     }
+
+    public NicSecondaryIpResponse createSecondaryIPToNicResponse(String ipAddr, Long nicId, Long networkId) {
+        NicSecondaryIpResponse response = new NicSecondaryIpResponse();
+        response.setIpAddr(ipAddr);
+        response.setNicId(nicId);
+        response.setNwId(networkId);
+        response.setObjectName("nicsecondaryip");
+        return response;
+    }
+
+    public NicResponse createNicResponse(Nic result) {
+        NicResponse response = new NicResponse();
+        response.setId(result.getUuid());
+        response.setIpaddress(result.getIp4Address());
+
+        if (result.getSecondaryIp()) {
+            List<NicSecondaryIpVO> secondaryIps = ApiDBUtils.findNicSecondaryIps(result.getId());
+            if (secondaryIps != null) {
+                List<NicSecondaryIpResponse> ipList = new ArrayList<NicSecondaryIpResponse>();
+                for (NicSecondaryIpVO ip: secondaryIps) {
+                    NicSecondaryIpResponse ipRes = new NicSecondaryIpResponse();
+                    ipRes.setId(ip.getId());
+                    ipRes.setIpAddr(ip.getIp4Address());
+                    ipList.add(ipRes);
+                }
+                response.setSecondaryIps(ipList);
+            }
+        }
+
+        response.setGateway(result.getGateway());
+        response.setId(result.getUuid());
+        response.setGateway(result.getGateway());
+        response.setNetmask(result.getNetmask());
+        response.setMacAddress(result.getMacAddress());
+        if (result.getBroadcastUri() != null) {
+            response.setBroadcastUri(result.getBroadcastUri().toString());
+        }
+        if (result.getIsolationUri() != null) {
+            response.setIsolationUri(result.getIsolationUri().toString());
+        }
+        if (result.getIp6Address() != null) {
+            response.setId(result.getIp6Address());
+        }
+
+        response.setIsDefault(result.isDefaultNic());
+        return response;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/NetworkManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java
index 2904183..8b6bf9a 100755
--- a/server/src/com/cloud/network/NetworkManager.java
+++ b/server/src/com/cloud/network/NetworkManager.java
@@ -49,6 +49,7 @@ import com.cloud.user.User;
 import com.cloud.utils.Pair;
 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;
@@ -331,4 +332,15 @@ public interface NetworkManager  {
     int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
 
     LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network);
+
+
+    boolean isSecondaryIpSetForNic(long nicId);
+
+     public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp)
+     throws InsufficientAddressCapacityException;
+
+     boolean removeVmSecondaryIps(long vmId);
+
+    List<? extends Nic> listVmNics(Long vmId, Long nicId);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index f527b73..a575183 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -140,8 +140,19 @@ import com.cloud.utils.fsm.StateMachine2;
 import com.cloud.utils.net.Ip;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.*;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicSecondaryIp;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.ReservationContextImpl;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VMInstanceVO;
+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;
 import com.cloud.vm.dao.VMInstanceDao;
 
@@ -240,6 +251,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
     UsageEventDao _usageEventDao;
     @Inject
     NetworkModel _networkModel;
+   @Inject
+    NicSecondaryIpDao _nicSecondaryIpDao;
     @Inject
     UserIpv6AddressDao _ipv6Dao;
     @Inject
@@ -1750,6 +1763,14 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
         guru.deallocate(network, profile, vm);
         _nicDao.remove(nic.getId());
         s_logger.debug("Removed nic id=" + nic.getId());
+        //remove the secondary ip addresses corresponding to to this nic
+        List<NicSecondaryIpVO> secondaryIps = _nicSecondaryIpDao.listByNicId(nic.getId());
+        if (secondaryIps != null) {
+            for (NicSecondaryIpVO ip : secondaryIps) {
+                _nicSecondaryIpDao.remove(ip.getId());
+            }
+            s_logger.debug("Removed nic " + nic.getId() + " secondary ip addreses");
+        }
     }
 
     @Override
@@ -2792,6 +2813,33 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
 
     Random _rand = new Random(System.currentTimeMillis());
 
+    public List<? extends Nic> listVmNics(Long vmId, Long nicId) {
+        List<NicVO> result = null;
+        if (nicId == null) {
+            result = _nicDao.listByVmId(vmId);
+        } else {
+            result = _nicDao.listByVmIdAndNicId(vmId, nicId);
+        }
+        return result;
+    }
+
+    public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp)
+    throws InsufficientAddressCapacityException {
+        String ipaddr = null;
+        Account caller = UserContext.current().getCaller();
+        long callerUserId = UserContext.current().getCallerUserId();
+        // check permissions
+        DataCenter zone = _configMgr.getZone(zoneId);
+        Network network = _networksDao.findById(networkId);
+
+        _accountMgr.checkAccess(caller, null, false, network);
+
+        //return acquireGuestIpAddress(network, requestedIp);
+        ipaddr = acquireGuestIpAddress(network, requestedIp);
+        return ipaddr;
+    }
+
+
     @Override
     @DB
     public String acquireGuestIpAddress(Network network, String requestedIp) {
@@ -2802,7 +2850,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
 
         Set<Long> availableIps = _networkModel.getAvailableIps(network, requestedIp);
 
-        if (availableIps.isEmpty()) {
+        if (availableIps == null || availableIps.isEmpty()) {
             return null;
         }
 
@@ -3032,9 +3080,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
                 throw new InvalidParameterValueException("Source ip address of the rule id=" + firewallStaticNatRule.getId() + " is not static nat enabled");
             }
 
-            String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), firewallStaticNatRule.getNetworkId());
+            //String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), firewallStaticNatRule.getNetworkId());
             ruleVO.setState(FirewallRule.State.Revoke);
-            staticNatRules.add(new StaticNatRuleImpl(ruleVO, dstIp));
+            staticNatRules.add(new StaticNatRuleImpl(ruleVO, ip.getVmIp()));
         }
 
         try {
@@ -3598,4 +3646,26 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
         }
         return rules.size();
     }
+
+         @Override
+    public boolean isSecondaryIpSetForNic(long nicId) {
+        NicVO nic = _nicDao.findById(nicId);
+        return nic.getSecondaryIp();
+    }
+
+        @Override
+        public boolean removeVmSecondaryIps(long vmId) {
+           Transaction txn = Transaction.currentTxn();
+           txn.start();
+           List <NicSecondaryIpVO> ipList = _nicSecondaryIpDao.listByVmId(vmId);
+           if (ipList != null) {
+               for (NicSecondaryIpVO ip: ipList) {
+                   _nicSecondaryIpDao.remove(ip.getId());
+               }
+               s_logger.debug("Revoving nic secondary ip entry ...");
+           }
+           txn.commit();
+           return true;
+        }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/NetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java
index ac1bc87..0525888 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -109,6 +109,7 @@ import com.cloud.vm.VMInstanceVO;
 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.VMInstanceDao;
 
 @Component
@@ -170,6 +171,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
     PrivateIpDao _privateIpDao;
     @Inject
     UserIpv6AddressDao _ipv6Dao;
+    @Inject
+    NicSecondaryIpDao _nicSecondaryIpDao;;
 
 
     private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
@@ -1624,6 +1627,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
     public Set<Long> getAvailableIps(Network network, String requestedIp) {
         String[] cidr = network.getCidr().split("/");
         List<String> ips = _nicDao.listIpAddressInNetwork(network.getId());
+        List<String> secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(network.getId());
+        ips.addAll(secondaryIps);
         Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1]));
         Set<Long> usedIps = new TreeSet<Long>(); 
         

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/NetworkServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 1708224..4c61aec 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -37,23 +37,28 @@ import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
 import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
 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.log4j.Logger;
 import org.springframework.stereotype.Component;
+import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
+import org.bouncycastle.util.IPAddress;
 
 import com.cloud.configuration.Config;
 import com.cloud.configuration.ConfigurationManager;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.dc.DataCenter;
+import com.cloud.dc.Pod;
 import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.Vlan.VlanType;
 import com.cloud.dc.VlanVO;
 import com.cloud.dc.dao.AccountVlanMapDao;
 import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.HostPodDao;
 import com.cloud.dc.dao.VlanDao;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.domain.Domain;
@@ -65,6 +70,8 @@ import com.cloud.event.UsageEventUtils;
 import com.cloud.event.dao.EventDao;
 import com.cloud.event.dao.UsageEventDao;
 import com.cloud.exception.*;
+import com.cloud.host.Host;
+import com.cloud.host.dao.HostDao;
 import com.cloud.network.IpAddress.State;
 import com.cloud.vm.Nic;
 import com.cloud.network.Network.Capability;
@@ -82,7 +89,9 @@ import com.cloud.network.element.VirtualRouterElement;
 import com.cloud.network.element.VpcVirtualRouterElement;
 import com.cloud.network.guru.NetworkGuru;
 import com.cloud.network.rules.FirewallRule.Purpose;
+import com.cloud.network.rules.dao.PortForwardingRulesDao;
 import com.cloud.network.rules.FirewallRuleVO;
+import com.cloud.network.rules.PortForwardingRuleVO;
 import com.cloud.network.rules.RulesManager;
 import com.cloud.network.vpc.PrivateIpVO;
 import com.cloud.network.vpc.VpcManager;
@@ -112,6 +121,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.*;
 import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.NicSecondaryIpDao;
+import com.cloud.vm.dao.NicSecondaryIpVO;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
 import java.util.*;
@@ -203,6 +214,16 @@ public class NetworkServiceImpl extends ManagerBase implements  NetworkService {
     @Inject
     NetworkModel _networkModel;
 
+    @Inject
+    NicSecondaryIpDao _nicSecondaryIpDao;
+
+    @Inject
+    PortForwardingRulesDao _portForwardingDao;
+    @Inject
+    HostDao _hostDao;
+    @Inject
+    HostPodDao _hostPodDao;
+
     int _cidrLimit;
     boolean _allowSubdomainNetworkAccess;
 
@@ -449,6 +470,138 @@ public class NetworkServiceImpl extends ManagerBase implements  NetworkService {
     }
 
 
+    public String allocateSecondaryGuestIP (Account ipOwner, long zoneId, Long nicId, Long networkId, String requestedIp) throws InsufficientAddressCapacityException {
+
+        Long accountId = null;
+        Long domainId = null;
+        Long vmId = null;
+        String ipaddr = null;
+
+        if (networkId == null) {
+            throw new InvalidParameterValueException("Invalid network id is given");
+        }
+
+        Network network = _networksDao.findById(networkId);
+        if (network == null) {
+            throw new InvalidParameterValueException("Invalid network id is given");
+        }
+        accountId = network.getAccountId();
+        domainId = network.getDomainId();
+
+        // verify permissions
+        _accountMgr.checkAccess(ipOwner, null, true, network);
+
+        //check whether the nic belongs to user vm.
+        NicVO nicVO = _nicDao.findById(nicId);
+        if (nicVO == null) {
+            throw new InvalidParameterValueException("There is no nic for the " + nicId);
+        }
+
+        if (nicVO.getVmType() != VirtualMachine.Type.User) {
+            throw new InvalidParameterValueException("The nic is not belongs to user vm");
+        }
+
+        DataCenter dc = _dcDao.findById(network.getDataCenterId());
+        Long id = nicVO.getInstanceId();
+
+        DataCenter zone = _configMgr.getZone(zoneId);
+        if (zone == null) {
+            throw new InvalidParameterValueException("Invalid zone Id is given");
+        }
+
+        s_logger.debug("Calling the ip allocation ...");
+        if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) {
+            try {
+                ipaddr = _networkMgr.allocateGuestIP(ipOwner, false,  zoneId, networkId, requestedIp);
+            } catch (InsufficientAddressCapacityException e) {
+                throw new InvalidParameterValueException("Allocating guest ip for nic failed");
+            }
+        } else {
+            throw new InvalidParameterValueException("AddIpToVMNic is not supported in this network...");
+        }
+
+        if (ipaddr != null) {
+            // we got the ip addr so up the nics table and secodary ip
+            Transaction txn = Transaction.currentTxn();
+            txn.start();
+
+            boolean nicSecondaryIpSet = nicVO.getSecondaryIp();
+            if (!nicSecondaryIpSet) {
+                nicVO.setSecondaryIp(true);
+                // commit when previously set ??
+                s_logger.debug("Setting nics table ...");
+                _nicDao.update(nicId, nicVO);
+            }
+
+            s_logger.debug("Setting nic_secondary_ip table ...");
+            vmId = nicVO.getInstanceId();
+            NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, ipaddr, vmId, accountId, domainId, networkId);
+            _nicSecondaryIpDao.persist(secondaryIpVO);
+            txn.commit();
+        }
+        return ipaddr;
+    }
+
+    @DB
+    public boolean releaseSecondaryIpFromNic (long ipAddressId) {
+        Account caller = UserContext.current().getCaller();
+        boolean success = false;
+
+        // Verify input parameters
+        NicSecondaryIpVO ipVO= _nicSecondaryIpDao.findById(ipAddressId);
+        if (ipVO == null) {
+            throw new InvalidParameterValueException("Unable to find ip address by id");
+        }
+
+        Network network = _networksDao.findById(ipVO.getNetworkId());
+
+        // verify permissions
+        _accountMgr.checkAccess(caller, null, true, network);
+
+        Long nicId = ipVO.getNicId();
+        s_logger.debug("ip id and nic id" + ipAddressId + "..." + nicId);
+        //check is this the last secondary ip for NIC
+        List<NicSecondaryIpVO> ipList = _nicSecondaryIpDao.listByNicId(nicId);
+        boolean lastIp = false;
+        if (ipList.size() == 1) {
+            // this is the last secondary ip to nic
+            lastIp = true;
+        }
+        //check PF or static NAT is configured on this ip address
+        String secondaryIp = ipVO.getIp4Address();
+        List<PortForwardingRuleVO> pfRuleList = _portForwardingDao.listByDestIpAddr(secondaryIp);
+        if (pfRuleList.size() != 0) {
+            s_logger.debug("VM nic IP " + secondaryIp + " is associated with the port forwarding rule");
+            throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is associate with the port forwarding rule");
+        }
+        //check if the secondary ip associated with any static nat rule
+        IPAddressVO publicIpVO = _ipAddressDao.findByVmIp(secondaryIp);
+        if (publicIpVO != null) {
+            s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId());
+            throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId());
+        }
+        success = removeNicSecondaryIP(ipVO, lastIp);
+        return success;
+    }
+
+    boolean removeNicSecondaryIP(NicSecondaryIpVO ipVO, boolean lastIp) {
+        Transaction txn = Transaction.currentTxn();
+        long nicId = ipVO.getNicId();
+        NicVO nic = _nicDao.findById(nicId);
+
+        txn.start();
+
+        if (lastIp) {
+            nic.setSecondaryIp(false);
+            s_logger.debug("Setting nics secondary ip to false ...");
+            _nicDao.update(nicId, nic);
+        }
+
+        s_logger.debug("Revoving nic secondary ip entry ...");
+        _nicSecondaryIpDao.remove(ipVO.getId());
+        txn.commit();
+        return true;
+    }
 
     @Override
     @DB
@@ -3025,4 +3178,21 @@ public class NetworkServiceImpl extends ManagerBase implements  NetworkService {
     public Network getNetwork(String networkUuid) {
        return _networksDao.findByUuid(networkUuid);
     }
+
+    @Override
+    public List<? extends Nic> listNics(ListNicsCmd cmd) {
+        Account caller = UserContext.current().getCaller();
+        Long nicId = cmd.getNicId();
+        Long vmId = cmd.getVmId();
+
+        UserVmVO  userVm = _userVmDao.findById(vmId);
+
+        if (userVm == null) {
+                InvalidParameterValueException ex = new InvalidParameterValueException("Virtual mahine id does not exist");
+                ex.addProxyObject(userVm, vmId, "vmId");
+                throw ex;
+            }
+        _accountMgr.checkAccess(caller, null, true, userVm);
+        return _networkMgr.listVmNics(vmId, nicId);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/addr/PublicIp.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/addr/PublicIp.java b/server/src/com/cloud/network/addr/PublicIp.java
index 61351a6..8217e4e 100644
--- a/server/src/com/cloud/network/addr/PublicIp.java
+++ b/server/src/com/cloud/network/addr/PublicIp.java
@@ -211,18 +211,28 @@ public class PublicIp implements PublicIpAddress {
         _addr.setVpcId(vpcId);
     }
 
-	@Override
-	public String getIp6Gateway() {
-		return _vlan.getIp6Gateway();
-	}
+    @Override
+    public String getIp6Gateway() {
+        return _vlan.getIp6Gateway();
+    }
 
-	@Override
-	public String getIp6Cidr() {
-		return _vlan.getIp6Cidr();
-	}
+    @Override
+    public String getIp6Cidr() {
+        return _vlan.getIp6Cidr();
+    }
 
-	@Override
-	public String getIp6Range() {
-		return _vlan.getIp6Range();
-	}
+    @Override
+    public String getIp6Range() {
+        return _vlan.getIp6Range();
+    }
+
+    @Override
+    public String getVmIp() {
+        return _addr.getVmIp();
+    }
+
+    @Override
+    public void setVmIp(String vmIp) {
+        _addr.setVmIp(vmIp);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/dao/IPAddressDao.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/IPAddressDao.java b/server/src/com/cloud/network/dao/IPAddressDao.java
index 9cdb975..1052639 100755
--- a/server/src/com/cloud/network/dao/IPAddressDao.java
+++ b/server/src/com/cloud/network/dao/IPAddressDao.java
@@ -62,5 +62,8 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
 
 	long countFreePublicIPs();
 	
-	long countFreeIPsInNetwork(long networkId);
-}
+    long countFreeIPsInNetwork(long networkId);
+    IPAddressVO findByVmIp(String vmIp);
+
+    IPAddressVO findByAssociatedVmIdAndVmIp(long vmId, String vmIp);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
index e7067d9..691e460 100755
--- a/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
+++ b/server/src/com/cloud/network/dao/IPAddressDaoImpl.java
@@ -80,6 +80,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
         AllFieldsSearch.and("sourcenetwork", AllFieldsSearch.entity().getSourceNetworkId(), Op.EQ);
         AllFieldsSearch.and("physicalNetworkId", AllFieldsSearch.entity().getPhysicalNetworkId(), Op.EQ);
         AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), Op.EQ);
+        AllFieldsSearch.and("associatedVmIp", AllFieldsSearch.entity().getVmIp(), Op.EQ);
         AllFieldsSearch.done();
 
         VlanDbIdSearchUnallocated = createSearchBuilder();
@@ -233,6 +234,12 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
     }
 
     @Override
+    public IPAddressVO findByVmIp(String vmIp) {
+        SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
+        sc.setParameters("associatedVmIp", vmIp);
+        return findOneBy(sc);
+    }
+    @Override
     public int countIPs(long dcId, long vlanId, boolean onlyCountAllocated) {
         SearchCriteria<Integer> sc = onlyCountAllocated ? AllocatedIpCount.create() : AllIpCount.create();
         sc.setParameters("dc", dcId);
@@ -347,5 +354,13 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
         boolean result = super.remove(id);
         txn.commit();
         return result;
-    }   
+    }
+
+    @Override
+    public IPAddressVO findByAssociatedVmIdAndVmIp(long vmId, String vmIp) {
+        SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
+        sc.setParameters("associatedWithVmId", vmId);
+        sc.setParameters("associatedVmIp", vmIp);
+        return findOneBy(sc);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/dao/IPAddressVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/IPAddressVO.java b/server/src/com/cloud/network/dao/IPAddressVO.java
index 00da5eb..8ce8d33 100644
--- a/server/src/com/cloud/network/dao/IPAddressVO.java
+++ b/server/src/com/cloud/network/dao/IPAddressVO.java
@@ -112,6 +112,10 @@ public class IPAddressVO implements IpAddress {
     @Column(name="vpc_id")
     private Long vpcId;
 
+    @Column(name="dnat_vmip")
+    private String vmIp;
+
+
 	protected IPAddressVO() {
 		this.uuid = UUID.randomUUID().toString();
 	}
@@ -288,8 +292,18 @@ public class IPAddressVO implements IpAddress {
         return vpcId;
     }
 
-	@Override
+    @Override
     public void setVpcId(Long vpcId) {
         this.vpcId = vpcId;
     }
+
+    @Override
+    public String getVmIp() {
+        return vmIp;
+    }
+
+    @Override
+    public void setVmIp(String vmIp) {
+        this.vmIp = vmIp;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/aedb8c47/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 0e2eb63..b387ab5 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -2318,8 +2318,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
       
                 if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.StaticNat, provider)) {
                     if (ip.isOneToOneNat()) {
-                            String dstIp = _networkModel.getIpInNetwork(ip.getAssociatedWithVmId(), guestNetworkId);
-                            StaticNatImpl staticNat = new StaticNatImpl(ip.getAccountId(), ip.getDomainId(), guestNetworkId, ip.getId(), dstIp, false);
+                            StaticNatImpl staticNat = new StaticNatImpl(ip.getAccountId(), ip.getDomainId(), guestNetworkId, ip.getId(), ip.getVmIp(), false);
                         staticNats.add(staticNat);
                     }
                 }


Mime
View raw message