Return-Path: X-Original-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-cloudstack-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6E47FD69C for ; Mon, 4 Mar 2013 13:43:04 +0000 (UTC) Received: (qmail 83498 invoked by uid 500); 4 Mar 2013 13:43:03 -0000 Delivered-To: apmail-incubator-cloudstack-commits-archive@incubator.apache.org Received: (qmail 83305 invoked by uid 500); 4 Mar 2013 13:43:03 -0000 Mailing-List: contact cloudstack-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: cloudstack-dev@incubator.apache.org Delivered-To: mailing list cloudstack-commits@incubator.apache.org Received: (qmail 82593 invoked by uid 99); 4 Mar 2013 13:43:00 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Mar 2013 13:43:00 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8E22F31453F; Mon, 4 Mar 2013 13:43:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tsp@apache.org To: cloudstack-commits@incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: [39/44] git commit: refs/heads/marvin-refactor - CLOUDSTACK-24: mipn feature for isolated and vpc networks Message-Id: <20130304134300.8E22F31453F@tyr.zones.apache.org> Date: Mon, 4 Mar 2013 13:43:00 +0000 (UTC) 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/marvin-refactor Commit: aedb8c478e88ad393246b9fa08a7fdac53e8e2d9 Parents: fe649f6 Author: Jayapal Uradi Authored: Mon Mar 4 11:02:09 2013 +0530 Committer: Abhinandan Prateek 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 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, 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 results = _networkService.listNics(this); + ListResponse response = new ListResponse(); + List resList = new ArrayList(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 secondaryIps; + public String getId() { return id; } @@ -167,4 +172,9 @@ public class NicResponse extends BaseResponse { return false; return true; } + + public void setSecondaryIps(List 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 findHostDetailsById(long hostId){ return _hostDetailsDao.findDetails(hostId); } + + public static List 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 secondaryIps = ApiDBUtils.findNicSecondaryIps(result.getId()); + if (secondaryIps != null) { + List ipList = new ArrayList(); + 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 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 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 listVmNics(Long vmId, Long nicId) { + List 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 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 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 _systemNetworks = new HashMap(5); @@ -1624,6 +1627,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public Set getAvailableIps(Network network, String requestedIp) { String[] cidr = network.getCidr().split("/"); List ips = _nicDao.listIpAddressInNetwork(network.getId()); + List secondaryIps = _nicSecondaryIpDao.listSecondaryIpAddressInNetwork(network.getId()); + ips.addAll(secondaryIps); Set allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1])); Set usedIps = new TreeSet(); 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 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 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 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 { 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 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 implemen } @Override + public IPAddressVO findByVmIp(String vmIp) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("associatedVmIp", vmIp); + return findOneBy(sc); + } + @Override public int countIPs(long dcId, long vlanId, boolean onlyCountAllocated) { SearchCriteria sc = onlyCountAllocated ? AllocatedIpCount.create() : AllIpCount.create(); sc.setParameters("dc", dcId); @@ -347,5 +354,13 @@ public class IPAddressDaoImpl extends GenericDaoBase implemen boolean result = super.remove(id); txn.commit(); return result; - } + } + + @Override + public IPAddressVO findByAssociatedVmIdAndVmIp(long vmId, String vmIp) { + SearchCriteria 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); } }