diff --git a/api/src/com/cloud/agent/api/routing/SetSourceNatCommand.java b/api/src/com/cloud/agent/api/routing/SetSourceNatCommand.java index 9a88554b402..5f2f7c0e6fd 100644 --- a/api/src/com/cloud/agent/api/routing/SetSourceNatCommand.java +++ b/api/src/com/cloud/agent/api/routing/SetSourceNatCommand.java @@ -13,7 +13,6 @@ package com.cloud.agent.api.routing; import com.cloud.agent.api.to.IpAddressTO; -import com.cloud.agent.api.to.NicTO; /** * @author Alena Prokharchyk @@ -21,15 +20,13 @@ import com.cloud.agent.api.to.NicTO; public class SetSourceNatCommand extends NetworkElementCommand{ IpAddressTO ipAddress; boolean add; - NicTO nic; - + protected SetSourceNatCommand() { } - public SetSourceNatCommand(IpAddressTO ip, boolean add, NicTO nic) { + public SetSourceNatCommand(IpAddressTO ip, boolean add) { this.ipAddress = ip; this.add = add; - this.nic = nic; } @Override @@ -41,7 +38,4 @@ public class SetSourceNatCommand extends NetworkElementCommand{ return ipAddress; } - public NicTO getNic() { - return nic; - } } diff --git a/api/src/com/cloud/agent/api/to/IpAddressTO.java b/api/src/com/cloud/agent/api/to/IpAddressTO.java index 583892df8eb..f8a837a9086 100644 --- a/api/src/com/cloud/agent/api/to/IpAddressTO.java +++ b/api/src/com/cloud/agent/api/to/IpAddressTO.java @@ -18,7 +18,6 @@ package com.cloud.agent.api.to; import com.cloud.network.Networks.TrafficType; - public class IpAddressTO { private long accountId; diff --git a/api/src/com/cloud/api/ResponseGenerator.java b/api/src/com/cloud/api/ResponseGenerator.java index 201883d1e84..2095f8fb5b2 100755 --- a/api/src/com/cloud/api/ResponseGenerator.java +++ b/api/src/com/cloud/api/ResponseGenerator.java @@ -50,6 +50,7 @@ import com.cloud.api.response.NetworkOfferingResponse; import com.cloud.api.response.NetworkResponse; import com.cloud.api.response.PhysicalNetworkResponse; import com.cloud.api.response.PodResponse; +import com.cloud.api.response.PrivateGatewayResponse; import com.cloud.api.response.ProjectAccountResponse; import com.cloud.api.response.ProjectInvitationResponse; import com.cloud.api.response.ProjectResponse; @@ -113,6 +114,7 @@ import com.cloud.network.security.SecurityGroupRules; import com.cloud.network.security.SecurityRule; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcOffering; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -304,4 +306,10 @@ public interface ResponseGenerator { * @return */ NetworkACLResponse createNetworkACLResponse(NetworkACL networkACL); + + /** + * @param result + * @return + */ + PrivateGatewayResponse createPrivateGatewayResponseResponse(PrivateGateway result); } diff --git a/api/src/com/cloud/api/commands/CreatePrivateGatewayCmd.java b/api/src/com/cloud/api/commands/CreatePrivateGatewayCmd.java new file mode 100644 index 00000000000..8cb7a6d47de --- /dev/null +++ b/api/src/com/cloud/api/commands/CreatePrivateGatewayCmd.java @@ -0,0 +1,158 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCreateCmd; +import com.cloud.api.BaseCmd; +import com.cloud.api.IdentityMapper; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.PrivateGatewayResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.user.Account; + +/** + * @author Alena Prokharchyk + */ +@Implementation(description="Creates a private gateway", responseObject=PrivateGatewayResponse.class) +public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd { + public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayCmd.class.getName()); + + private static final String s_name = "createprivategatewayresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="physical_network") + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, description="the Physical Network ID the network belongs to") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.GATEWAY, type=CommandType.STRING, required=true, description="the gateway of the Private gateway") + private String gateway; + + @Parameter(name=ApiConstants.NETMASK, type=CommandType.STRING, required=true, description="the netmask of the Private gateway") + private String netmask; + + @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, required=true, description="the IP address of the Private gateaway") + private String ipAddress; + + @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, required=true, description="the Vlan for the private gateway") + private String vlan; + + @IdentityMapper(entityTableName="vpc") + @Parameter(name=ApiConstants.VPC_ID, type=CommandType.LONG, required=true, description="the VPC network belongs to") + private Long vpcId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getGateway() { + return gateway; + } + + public String getVlan() { + return vlan; + } + + public String getNetmask() { + return netmask; + } + + public String getStartIp() { + return ipAddress; + } + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public Long getVpcId() { + return vpcId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public String getCommandName() { + return s_name; + } + + + @Override + public void create() throws ResourceAllocationException { + PrivateGateway result = null; + try { + result = _vpcService.createVpcPrivateGateway(getVpcId(), getPhysicalNetworkId(), + getVlan(), getStartIp(), getGateway(), getNetmask(), getEntityOwnerId()); + } catch (InsufficientCapacityException ex){ + s_logger.info(ex); + s_logger.trace(ex); + throw new ServerApiException(BaseCmd.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); + } catch (ConcurrentOperationException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, ex.getMessage()); + } + + if (result != null) { + this.setEntityId(result.getId()); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create private gateway"); + } + } + + @Override + public void execute() throws InsufficientCapacityException, ConcurrentOperationException, + ResourceAllocationException, ResourceUnavailableException { + PrivateGateway result = _vpcService.applyVpcGateway(getEntityId()); + if (result != null) { + PrivateGatewayResponse response = _responseGenerator.createPrivateGatewayResponseResponse(result); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to create private gateway"); + } + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PRIVATE_GATEWAY_CREATE; + } + + @Override + public String getEventDescription() { + return "creating private gateway"; + + } + + @Override + public String getEntityTable() { + return "vpc_gateways"; + } +} diff --git a/api/src/com/cloud/api/commands/DeletePrivateGatewayCmd.java b/api/src/com/cloud/api/commands/DeletePrivateGatewayCmd.java new file mode 100644 index 00000000000..2d3a3e21510 --- /dev/null +++ b/api/src/com/cloud/api/commands/DeletePrivateGatewayCmd.java @@ -0,0 +1,113 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.BaseCmd; +import com.cloud.api.IdentityMapper; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.SuccessResponse; +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.VpcGateway; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +/** + * @author Alena Prokharchyk + */ +@Implementation(description="Deletes a Private gateway", responseObject=SuccessResponse.class) +public class DeletePrivateGatewayCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeletePrivateGatewayCmd.class.getName()); + private static final String s_name = "deleteprivategatewayresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @IdentityMapper(entityTableName="vpc_gateways") + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the private gateway") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public String getCommandName() { + return s_name; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PRIVATE_GATEWAY_DELETE; + } + + @Override + public String getEventDescription() { + return ("Deleting private gateway id=" + id); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() throws ResourceUnavailableException, ConcurrentOperationException { + UserContext.current().setEventDetails("Network ACL Id: " + id); + boolean result = _vpcService.deleteVpcPrivateGateway(id); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete private gateway"); + } + } + + + @Override + public String getSyncObjType() { + return BaseAsyncCmd.networkSyncObject; + } + + @Override + public Long getSyncObjId() { + VpcGateway gateway = _vpcService.getVpcPrivateGateway(getId()); + if (gateway == null) { + throw new InvalidParameterValueException("Invalid private gateway id"); + } + return gateway.getVpcId(); + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.Vpc; + } + +} \ No newline at end of file diff --git a/api/src/com/cloud/api/response/PrivateGatewayResponse.java b/api/src/com/cloud/api/response/PrivateGatewayResponse.java new file mode 100644 index 00000000000..621442ab711 --- /dev/null +++ b/api/src/com/cloud/api/response/PrivateGatewayResponse.java @@ -0,0 +1,90 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.api.response; + +/** + * @author Alena Prokharchyk + */ +import com.cloud.api.ApiConstants; +import com.cloud.serializer.Param; +import com.cloud.utils.IdentityProxy; +import com.google.gson.annotations.SerializedName; + +@SuppressWarnings("unused") +public class PrivateGatewayResponse extends BaseResponse{ + + @SerializedName(ApiConstants.ID) @Param(description="the id of the private gateway") + private IdentityProxy id = new IdentityProxy("vpc_gateways"); + + @SerializedName(ApiConstants.GATEWAY) @Param(description="the gateway") + private String gateway; + + @SerializedName(ApiConstants.NETMASK) @Param(description="the private gateway's netmask") + private String netmask; + + @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the private gateway's ip address") + private String address; + + @SerializedName(ApiConstants.ZONE_ID) @Param(description="zone id of the private gateway") + private IdentityProxy zoneId = new IdentityProxy("data_center"); + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the name of the zone the private gateway belongs to") + private String zoneName; + + @SerializedName(ApiConstants.VLAN) @Param(description="the vlan of the private gateway") + private String vlan; + + @SerializedName(ApiConstants.VPC_ID) @Param(description="VPC the private gateaway belongs to") + private IdentityProxy vpcId = new IdentityProxy("vpc"); + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network id") + private IdentityProxy physicalNetworkId = new IdentityProxy("physical_network"); + + + public void setId(Long id) { + this.id.setValue(id); + } + + public void setGateway(String gateway) { + this.gateway = gateway; + } + + public void setNetmask(String netmask) { + this.netmask = netmask; + } + + public void setZoneId(Long zoneId) { + this.zoneId.setValue(zoneId); + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public void setVpcId(Long vpcId) { + this.vpcId.setValue(vpcId); + } + + public void setAddress(String address) { + this.address = address; + } + + public void setPhysicalNetworkId(Long physicalNetworkId) { + this.physicalNetworkId.setValue(physicalNetworkId); + } +} + diff --git a/api/src/com/cloud/async/AsyncJob.java b/api/src/com/cloud/async/AsyncJob.java index 0e294ce1716..12cf2a5c6ba 100644 --- a/api/src/com/cloud/async/AsyncJob.java +++ b/api/src/com/cloud/async/AsyncJob.java @@ -40,7 +40,8 @@ public interface AsyncJob extends Identity { PhysicalNetworkServiceProvider, FirewallRule, Account, - User + User, + Vpc } Long getId(); diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 713a7ee3180..f478e4c1c23 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -266,8 +266,12 @@ public class EventTypes { public static final String EVENT_VPC_DELETE = "VPC.DELETE"; public static final String EVENT_VPC_RESTART = "VPC.RESTART"; - + // VPC offerings public static final String EVENT_VPC_OFFERING_CREATE = "VPC.OFFERING.CREATE"; public static final String EVENT_VPC_OFFERING_UPDATE = "VPC.OFFERING.UPDATE"; public static final String EVENT_VPC_OFFERING_DELETE = "VPC.OFFERING.DELETE"; + + // Private gateway + public static final String EVENT_PRIVATE_GATEWAY_CREATE = "PRIVATE.GATEWAY.CREATE"; + public static final String EVENT_PRIVATE_GATEWAY_DELETE = "PRIVATE.GATEWAY.DELETE"; } diff --git a/api/src/com/cloud/network/element/VpcProvider.java b/api/src/com/cloud/network/element/VpcProvider.java index bd55ff47c77..4188fb6101d 100644 --- a/api/src/com/cloud/network/element/VpcProvider.java +++ b/api/src/com/cloud/network/element/VpcProvider.java @@ -17,6 +17,7 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.Vpc; import com.cloud.vm.ReservationContext; @@ -40,11 +41,8 @@ public interface VpcProvider extends NetworkElement{ */ boolean shutdownVpc(Vpc vpc) throws ConcurrentOperationException, ResourceUnavailableException; - boolean createPrivateGateway(); - - boolean createVpnGateway(); + boolean createPrivateGateway(PrivateGateway gateway) throws ConcurrentOperationException, ResourceUnavailableException; - boolean deletePrivateGateway(); - - boolean deleteVpnGateway(); + boolean deletePrivateGateway(PrivateGateway privateGateway) throws ConcurrentOperationException, ResourceUnavailableException; + } diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index f7b0f9d3ffa..d556844da2c 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -45,4 +45,5 @@ public interface NetworkACLService { List listNetworkACLs(ListNetworkACLsCmd cmd); List listNetworkACLs(long guestNtwkId); + } diff --git a/api/src/com/cloud/network/vpc/PrivateGateway.java b/api/src/com/cloud/network/vpc/PrivateGateway.java new file mode 100644 index 00000000000..3ecc75a90db --- /dev/null +++ b/api/src/com/cloud/network/vpc/PrivateGateway.java @@ -0,0 +1,23 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +/** + * @author Alena Prokharchyk + */ +public interface PrivateGateway extends VpcGateway{ + String getVlanTag(); + String getGateway(); + String getNetmask(); + long getPhysicalNetworkId(); +} diff --git a/api/src/com/cloud/network/vpc/PrivateIp.java b/api/src/com/cloud/network/vpc/PrivateIp.java new file mode 100644 index 00000000000..771a2aa6386 --- /dev/null +++ b/api/src/com/cloud/network/vpc/PrivateIp.java @@ -0,0 +1,45 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +/** + * @author Alena Prokharchyk + */ +public interface PrivateIp { + + /** + * @return + */ + String getIpAddress(); + + /** + * @return + */ + String getVlanTag(); + + /** + * @return + */ + String getGateway(); + + /** + * @return + */ + String getNetmask(); + + /** + * @return + */ + String getMacAddress(); + +} diff --git a/api/src/com/cloud/network/vpc/VpcGateway.java b/api/src/com/cloud/network/vpc/VpcGateway.java new file mode 100644 index 00000000000..e3b532a1cb5 --- /dev/null +++ b/api/src/com/cloud/network/vpc/VpcGateway.java @@ -0,0 +1,53 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +import com.cloud.api.Identity; + +/** + * @author Alena Prokharchyk + */ +public interface VpcGateway extends Identity { + public enum Type { + Private, + Public, + Vpn + } + + long getId(); + + /** + * @return + */ + String getIp4Address(); + + /** + * @return + */ + Type getType(); + + /** + * @return + */ + Long getVpcId(); + + /** + * @return + */ + long getZoneId(); + + /** + * @return + */ + Long getNetworkId(); +} diff --git a/api/src/com/cloud/network/vpc/VpcService.java b/api/src/com/cloud/network/vpc/VpcService.java index 9473d180867..e8c9e86babb 100644 --- a/api/src/com/cloud/network/vpc/VpcService.java +++ b/api/src/com/cloud/network/vpc/VpcService.java @@ -18,6 +18,7 @@ import java.util.Set; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.Network.Provider; @@ -133,6 +134,41 @@ public interface VpcService { * @return * @throws InsufficientCapacityException */ - boolean restartVpc(Long id) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + boolean restartVpc(long id) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + + PrivateGateway getVpcPrivateGateway(long id); + + /** + * @param vpcId TODO + * @param physicalNetworkId + * @param vlan + * @param ipAddress + * @param gateway + * @param netmask + * @param gatewayOwnerId + * @return + * @throws InsufficientCapacityException + * @throws ConcurrentOperationException + * @throws ResourceAllocationException + */ + public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, + String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException, + ConcurrentOperationException, InsufficientCapacityException; + + /** + * @param gatewayId + * @return + * @throws ResourceUnavailableException + * @throws ConcurrentOperationException + */ + public PrivateGateway applyVpcGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException; + + /** + * @param id + * @return + * @throws ResourceUnavailableException + * @throws ConcurrentOperationException + */ + boolean deleteVpcPrivateGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException; } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 00392c3b3a3..137a4a0099a 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -351,14 +351,11 @@ updateVPCOffering=com.cloud.api.commands.UpdateVPCOfferingCmd;1 deleteVPCOffering=com.cloud.api.commands.DeleteVPCOfferingCmd;1 listVPCOfferings=com.cloud.api.commands.ListVPCOfferingsCmd;15 -#### Private gateway commands -#createPrivateGateway=com.cloud.api.commands.CreatePrivateGatewayCmd;15 -#listPrivateGateways=com.cloud.api.commands.ListPrivateGatewaysCmd;15 -#deletePrivateGateway=com.cloud.api.commands.DeletePrivateGatewayCmd;15 +#### Private gateway commands +createPrivateGateway=com.cloud.api.commands.CreatePrivateGatewayCmd;1 +#listPrivateGateways=com.cloud.api.commands.ListPrivateGatewaysCmd;1 +deletePrivateGateway=com.cloud.api.commands.DeletePrivateGatewayCmd;1 -#### Private network command -createPrivateNetwork=com.cloud.api.commands.CreatePrivateNetworkCmd;1 - #### createNetworkACL=com.cloud.api.commands.CreateNetworkACLCmd;15 deleteNetworkACL=com.cloud.api.commands.DeleteNetworkACLCmd;15 diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index f39a8b2fe7b..52712e6cdb1 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -32,7 +32,6 @@ import com.cloud.acl.ControlledEntity.ACLType; import com.cloud.api.ApiConstants.HostDetails; import com.cloud.api.ApiConstants.VMDetails; import com.cloud.api.commands.QueryAsyncJobResultCmd; -import com.cloud.api.response.NetworkACLResponse; import com.cloud.api.response.AccountResponse; import com.cloud.api.response.ApiResponseSerializer; import com.cloud.api.response.AsyncJobResponse; @@ -59,11 +58,13 @@ import com.cloud.api.response.LBStickinessResponse; import com.cloud.api.response.LDAPConfigResponse; import com.cloud.api.response.ListResponse; import com.cloud.api.response.LoadBalancerResponse; +import com.cloud.api.response.NetworkACLResponse; import com.cloud.api.response.NetworkOfferingResponse; import com.cloud.api.response.NetworkResponse; import com.cloud.api.response.NicResponse; import com.cloud.api.response.PhysicalNetworkResponse; import com.cloud.api.response.PodResponse; +import com.cloud.api.response.PrivateGatewayResponse; import com.cloud.api.response.ProjectAccountResponse; import com.cloud.api.response.ProjectInvitationResponse; import com.cloud.api.response.ProjectResponse; @@ -149,6 +150,7 @@ import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcOffering; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -3527,4 +3529,22 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + @Override + public PrivateGatewayResponse createPrivateGatewayResponseResponse(PrivateGateway result) { + PrivateGatewayResponse response = new PrivateGatewayResponse(); + response.setId(result.getId()); + response.setVlan(result.getVlanTag()); + response.setGateway(result.getGateway()); + response.setNetmask(result.getNetmask()); + response.setVpcId(result.getVpcId()); + response.setZoneId(result.getZoneId()); + DataCenter zone = ApiDBUtils.findZoneById(result.getZoneId()); + response.setZoneName(zone.getName()); + response.setAddress(result.getIp4Address()); + response.setPhysicalNetworkId(result.getPhysicalNetworkId()); + response.setObjectName("privategateway"); + + return response; + } + } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index cf0e61a25a8..f566dd8e977 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -127,6 +127,7 @@ import com.cloud.network.security.dao.VmRulesetLogDaoImpl; import com.cloud.network.vpc.VpcManagerImpl; import com.cloud.network.vpc.Dao.PrivateIpDaoImpl; import com.cloud.network.vpc.Dao.VpcDaoImpl; +import com.cloud.network.vpc.Dao.VpcGatewayDaoImpl; import com.cloud.network.vpc.Dao.VpcOfferingDaoImpl; import com.cloud.network.vpc.Dao.VpcOfferingServiceMapDaoImpl; import com.cloud.network.vpn.RemoteAccessVpnManagerImpl; @@ -340,6 +341,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com addDao("VpcOfferingDao", VpcOfferingDaoImpl.class); addDao("VpcOfferingServiceMapDao", VpcOfferingServiceMapDaoImpl.class); addDao("PrivateIpDao", PrivateIpDaoImpl.class); + addDao("VpcGatewayDao", VpcGatewayDaoImpl.class); } @Override diff --git a/server/src/com/cloud/dc/DataCenterVO.java b/server/src/com/cloud/dc/DataCenterVO.java index 28cc484b491..12418b1be17 100644 --- a/server/src/com/cloud/dc/DataCenterVO.java +++ b/server/src/com/cloud/dc/DataCenterVO.java @@ -97,7 +97,7 @@ public class DataCenterVO implements DataCenter, Identity { @Column(name="firewall_provider") private String firewallProvider; - @Column(name="mac_address", updatable = false, nullable=false) + @Column(name="mac_address", nullable=false) @TableGenerator(name="mac_address_sq", table="data_center", pkColumnName="id", valueColumnName="mac_address", allocationSize=1) private long macAddress = 1; @@ -406,4 +406,12 @@ public class DataCenterVO implements DataCenter, Identity { public void setUuid(String uuid) { this.uuid = uuid; } -} + + public long getMacAddress() { + return macAddress; + } + + public void setMacAddress(long macAddress) { + this.macAddress = macAddress; + } +} diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index e66c01d90a4..97e9086c4d7 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -444,6 +444,21 @@ public interface NetworkManager extends NetworkService { */ NicProfile releaseNic(VirtualMachineProfile vmProfile, NetworkVO network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException; + + + /** + * @param zoneId + * @param trafficType + * @return + */ + List getPhysicalNtwksSupportingTrafficType(long zoneId, TrafficType trafficType); + + + /** + * @param guestNic + * @return + */ + boolean isPrivateGateway(Nic guestNic); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index e89d9e816e0..f0d873c9b65 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -23,6 +23,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; @@ -312,6 +313,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag NetworkACLService _networkACLMgr; private final HashMap _systemNetworks = new HashMap(5); + private static Long _privateOfferingId = null; ScheduledExecutorService _executor; @@ -1344,6 +1346,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag GuestType.Isolated); privateGatewayNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOffering); _systemNetworks.put(NetworkOfferingVO.SystemPrivateGatewayNetworkOffering, privateGatewayNetworkOffering); + _privateOfferingId = privateGatewayNetworkOffering.getId(); // populate providers @@ -3372,8 +3375,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) { boolean result = false; - Transaction txn = Transaction.currentTxn(); - txn.start(); NetworkVO network = _networksDao.lockRow(networkId, true); if (network == null) { s_logger.debug("Unable to find network with id: " + networkId); @@ -3386,10 +3387,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag network.setState(Network.State.Shutdown); _networksDao.update(network.getId(), network); - txn.commit(); boolean success = shutdownNetworkElementsAndResources(context, cleanupElements, network); + Transaction txn = Transaction.currentTxn(); txn.start(); if (success) { if (s_logger.isDebugEnabled()) { @@ -6104,7 +6105,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new CloudRuntimeException("This physical network already supports the traffic type: " + trafficType); } // For Storage, Control, Management, Public check if the zone has any other physical network with this -// traffictype already present + // traffictype already present // If yes, we cant add these traffics to one more physical network in the zone. if (TrafficType.isSystemNetwork(trafficType) || TrafficType.Public.equals(trafficType) || TrafficType.Storage.equals(trafficType)) { @@ -7096,7 +7097,6 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag // Get system network offeirng NetworkOfferingVO ntwkOff = _systemNetworks.get(NetworkOffering.SystemPrivateGatewayNetworkOffering); - // Validate physical network PhysicalNetwork pNtwk = _physicalNetworkDao.findById(physicalNetworkId); if (pNtwk == null) { @@ -7130,14 +7130,38 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag Transaction txn = Transaction.currentTxn(); txn.start(); - //create Guest network - Network privateNetwork = createGuestNetwork(ntwkOff.getId(), networkName, displayText, gateway, cidr, vlan, - null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, null); + + //lock datacenter as we need to get mac address seq from there + DataCenterVO dc = _dcDao.lockRow(pNtwk.getDataCenterId(), true); + + //check if we need to create guest network + Network privateNetwork = _networksDao.getPrivateNetwork(BroadcastDomainType.Vlan.toUri(vlan).toString(), cidr, + networkOwnerId, pNtwk.getDataCenterId()); + if (privateNetwork == null) { + //create Guest network + privateNetwork = createGuestNetwork(ntwkOff.getId(), networkName, displayText, gateway, cidr, vlan, + null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null, null); + s_logger.debug("Created private network " + privateNetwork); + } else { + s_logger.debug("Private network already exists: " + privateNetwork); + } //add entry to private_ip_address table - PrivateIpVO privateIp = new PrivateIpVO(startIp, privateNetwork.getId()); + PrivateIpVO privateIp = _privateIpDao.findByIpAndSourceNetworkId(privateNetwork.getId(), startIp); + if (privateIp != null) { + throw new InvalidParameterValueException("Private ip address " + startIp + " already used for private gateway" + + " in zone " + _configMgr.getZone(pNtwk.getDataCenterId()).getName()); + } + + Long mac = dc.getMacAddress(); + Long nextMac = mac + 1; + dc.setMacAddress(nextMac); + + privateIp = new PrivateIpVO(startIp, privateNetwork.getId(), nextMac); _privateIpDao.persist(privateIp); + _dcDao.update(dc.getId(), dc); + txn.commit(); s_logger.debug("Private network " + privateNetwork + " is created"); @@ -7154,4 +7178,28 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return setupDns; } + + @Override + public List getPhysicalNtwksSupportingTrafficType(long zoneId, TrafficType trafficType) { + + List pNtwks = _physicalNetworkDao.listByZone(zoneId); + + Iterator it = pNtwks.iterator(); + while (it.hasNext()) { + PhysicalNetwork pNtwk = it.next(); + if (!_pNTrafficTypeDao.isTrafficTypeSupported(pNtwk.getId(), trafficType)) { + it.remove(); + } + } + return pNtwks; + } + + @Override + public boolean isPrivateGateway(Nic guestNic) { + Network network = getNetwork(guestNic.getNetworkId()); + if (network.getTrafficType() != TrafficType.Guest || network.getNetworkOfferingId() != _privateOfferingId.longValue()) { + return false; + } + return true; + } } diff --git a/server/src/com/cloud/network/NetworkVO.java b/server/src/com/cloud/network/NetworkVO.java index 03cec169510..b1f1c0a8b41 100644 --- a/server/src/com/cloud/network/NetworkVO.java +++ b/server/src/com/cloud/network/NetworkVO.java @@ -458,7 +458,6 @@ public class NetworkVO implements Network, Identity { return buf.toString(); } - public String getUuid() { return this.uuid; } diff --git a/server/src/com/cloud/network/dao/NetworkDao.java b/server/src/com/cloud/network/dao/NetworkDao.java index 299f5ee8a26..61893e5679c 100644 --- a/server/src/com/cloud/network/dao/NetworkDao.java +++ b/server/src/com/cloud/network/dao/NetworkDao.java @@ -97,5 +97,7 @@ public interface NetworkDao extends GenericDao { int getNetworkCountByVpcId(long vpcId); List listByVpc(long vpcId); + + NetworkVO getPrivateNetwork(String broadcastUri, String cidr, long accountId, long zoneId); } diff --git a/server/src/com/cloud/network/dao/NetworkDaoImpl.java b/server/src/com/cloud/network/dao/NetworkDaoImpl.java index 8fa107c8710..1d74fc10b36 100644 --- a/server/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/server/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -31,6 +31,7 @@ import com.cloud.network.NetworkVO; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; +import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDaoImpl; import com.cloud.utils.component.ComponentLocator; @@ -88,6 +89,7 @@ public class NetworkDaoImpl extends GenericDaoBase implements N AllFieldsSearch.and("related", AllFieldsSearch.entity().getRelated(), Op.EQ); AllFieldsSearch.and("guestType", AllFieldsSearch.entity().getGuestType(), Op.EQ); AllFieldsSearch.and("physicalNetwork", AllFieldsSearch.entity().getPhysicalNetworkId(), Op.EQ); + AllFieldsSearch.and("broadcastUri", AllFieldsSearch.entity().getBroadcastUri(), Op.EQ); AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), Op.EQ); AllFieldsSearch.done(); @@ -471,4 +473,16 @@ public class NetworkDaoImpl extends GenericDaoBase implements N return listBy(sc, null); } + + @Override + public NetworkVO getPrivateNetwork(String broadcastUri, String cidr, long accountId, long zoneId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("datacenter", zoneId); + sc.setParameters("broadcastUri", broadcastUri); + sc.setParameters("cidr", cidr); + sc.setParameters("account", accountId); + sc.setParameters("offering", _ntwkOffDao.findByUniqueName(NetworkOffering.SystemPrivateGatewayNetworkOffering).getId()); + return findOneBy(sc); + } + } diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index f9acc1289ed..563f5eface1 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -1,3 +1,4 @@ + // Copyright 2012 Citrix Systems, Inc. Licensed under the // Apache License, Version 2.0 (the "License"); you may not use this // file except in compliance with the License. Citrix Systems, Inc. @@ -39,7 +40,9 @@ import com.cloud.network.router.VpcVirtualNetworkApplianceManager; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.NetworkACL; import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcGateway; import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.offering.NetworkOffering; import com.cloud.utils.component.Inject; import com.cloud.utils.exception.CloudRuntimeException; @@ -99,7 +102,6 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return true; } - @Override public boolean implementVpc(Vpc vpc, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, @@ -152,14 +154,17 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc DataCenter.class, network.getDataCenterId()); } - for (VirtualRouter router : routers) { - //Add router to guest network - if (!_networkMgr.isVmPartOfNetwork(router.getId(), network.getId())) { - if (!_vpcRouterMgr.addVpcRouterToGuestNetwork(router, network, false)) { - throw new CloudRuntimeException("Failed to add VPC router " + router + " to guest network " + network); - } else { - s_logger.debug("Successfully added VPC router " + router + " to guest network " + network); - } + if (routers.size() > 1) { + throw new CloudRuntimeException("Found more than one router in vpc " + vpc); + } + + DomainRouterVO router = routers.get(0); + //Add router to guest network if needed + if (!_networkMgr.isVmPartOfNetwork(router.getId(), network.getId())) { + if (!_vpcRouterMgr.addVpcRouterToGuestNetwork(router, network, false)) { + throw new CloudRuntimeException("Failed to add VPC router " + router + " to guest network " + network); + } else { + s_logger.debug("Successfully added VPC router " + router + " to guest network " + network); } } @@ -192,14 +197,18 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc throw new ResourceUnavailableException("Can't find at least one running router!", DataCenter.class, network.getDataCenterId()); } - for (VirtualRouter router : routers) { - //Add router to guest network if needed - if (!_networkMgr.isVmPartOfNetwork(router.getId(), network.getId())) { - if (!_vpcRouterMgr.addVpcRouterToGuestNetwork(router, network, false)) { - throw new CloudRuntimeException("Failed to add VPC router " + router + " to guest network " + network); - } else { - s_logger.debug("Successfully added VPC router " + router + " to guest network " + network); - } + + if (routers.size() > 1) { + throw new CloudRuntimeException("Found more than one router in vpc " + vpc); + } + + DomainRouterVO router = routers.get(0); + //Add router to guest network if needed + if (!_networkMgr.isVmPartOfNetwork(router.getId(), network.getId())) { + if (!_vpcRouterMgr.addVpcRouterToGuestNetwork(router, network, false)) { + throw new CloudRuntimeException("Failed to add VPC router " + router + " to guest network " + network); + } else { + s_logger.debug("Successfully added VPC router " + router + " to guest network " + network); } } } @@ -293,27 +302,49 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc } @Override - public boolean createPrivateGateway() { - //TODO - add implementation here - return true; + public boolean createPrivateGateway(PrivateGateway gateway) throws ConcurrentOperationException, ResourceUnavailableException { + if (gateway.getType() != VpcGateway.Type.Private) { + s_logger.warn("Type of vpc gateway is not " + VpcGateway.Type.Private); + return false; + } + + List routers = _vpcMgr.getVpcRouters(gateway.getVpcId()); + if (routers == null || routers.isEmpty()) { + s_logger.debug(this.getName() + " element doesn't need to create Private gateway on the backend; VPC virtual " + + "router doesn't exist in the vpc id=" + gateway.getVpcId()); + return true; + } + + if (routers.size() > 1) { + throw new CloudRuntimeException("Found more than one router in vpc " + gateway.getVpcId()); + } + + VirtualRouter router = routers.get(0); + + return _vpcRouterMgr.setupPrivateGateway(gateway, router); } @Override - public boolean createVpnGateway() { - //TODO - add implementation here - return true; - } - - @Override - public boolean deletePrivateGateway() { - //TODO - add implementation here - return true; - } - - @Override - public boolean deleteVpnGateway() { - //TODO - add implementation here - return true; + public boolean deletePrivateGateway(PrivateGateway gateway) throws ConcurrentOperationException, ResourceUnavailableException { + if (gateway.getType() != VpcGateway.Type.Private) { + s_logger.warn("Type of vpc gateway is not " + VpcGateway.Type.Private); + return false; + } + + List routers = _vpcMgr.getVpcRouters(gateway.getVpcId()); + if (routers == null || routers.isEmpty()) { + s_logger.debug(this.getName() + " element doesn't need to delete Private gateway on the backend; VPC virtual " + + "router doesn't exist in the vpc id=" + gateway.getVpcId()); + return true; + } + + if (routers.size() > 1) { + throw new CloudRuntimeException("Found more than one router in vpc " + gateway.getVpcId()); + } + + VirtualRouter router = routers.get(0); + + return _vpcRouterMgr.destroyPrivateGateway(gateway, router); } @Override diff --git a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java index 27c05981a6d..ab078743498 100644 --- a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java @@ -21,17 +21,22 @@ import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientVirtualNetworkCapcityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.State; +import com.cloud.network.NetworkManager; import com.cloud.network.NetworkProfile; import com.cloud.network.NetworkVO; +import com.cloud.network.Networks.AddressFormat; import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.vpc.PrivateIpAddress; import com.cloud.network.vpc.PrivateIpVO; import com.cloud.network.vpc.Dao.PrivateIpDao; import com.cloud.offering.NetworkOffering; @@ -53,6 +58,8 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { protected ConfigurationManager _configMgr; @Inject protected PrivateIpDao _privateIpDao; + @Inject + protected NetworkManager _networkMgr; private static final TrafficType[] _trafficTypes = {TrafficType.Guest}; @@ -106,14 +113,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { network.setCidr(userSpecified.getCidr()); network.setGateway(userSpecified.getGateway()); } else { - String guestNetworkCidr = dc.getGuestNetworkCidr(); - if (guestNetworkCidr != null) { - String[] cidrTuple = guestNetworkCidr.split("\\/"); - network.setGateway(NetUtils.getIpRangeStartIpFromCidr(cidrTuple[0], Long.parseLong(cidrTuple[1]))); - network.setCidr(guestNetworkCidr); - } else if (dc.getNetworkType() == NetworkType.Advanced) { - throw new CloudRuntimeException("Can't design network " + network + "; guest CIDR is not configured per zone " + dc); - } + throw new InvalidParameterValueException("Can't design network " + network + "; netmask/gateway must be passed in"); } if (offering.getSpecifyVlan()) { @@ -157,20 +157,47 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { if (!canHandle(offering, dc)) { return null; } - + if (nic == null) { nic = new NicProfile(ReservationStrategy.Create, null, null, null, null); - } else if (nic.getIp4Address() == null) { + } + + getIp(nic, dc, network); + + if (nic.getIp4Address() == null) { nic.setStrategy(ReservationStrategy.Start); } else { nic.setStrategy(ReservationStrategy.Create); } - _privateIpDao.allocateIpAddress(network.getDataCenterId(), network.getId()); - nic.setStrategy(ReservationStrategy.Create); - return nic; } + + + protected void getIp(NicProfile nic, DataCenter dc, Network network) + throws InsufficientVirtualNetworkCapcityException, + InsufficientAddressCapacityException { + if (nic.getIp4Address() == null) { + PrivateIpVO ipVO = _privateIpDao.allocateIpAddress(network.getDataCenterId(), network.getId()); + String vlanTag = network.getBroadcastUri().getHost(); + String netmask = NetUtils.getCidrNetmask(network.getCidr()); + PrivateIpAddress ip = new PrivateIpAddress(ipVO, vlanTag, network.getGateway(), netmask, ipVO.getMacAddress()); + + nic.setIp4Address(ip.getIpAddress()); + nic.setGateway(ip.getGateway()); + nic.setNetmask(ip.getNetmask()); + nic.setIsolationUri(IsolationType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastUri(IsolationType.Vlan.toUri(ip.getVlanTag())); + nic.setBroadcastType(BroadcastDomainType.Vlan); + nic.setFormat(AddressFormat.Ip4); + nic.setReservationId(String.valueOf(ip.getVlanTag())); + nic.setMacAddress(ip.getMacAddress()); + } + + nic.setDns1(dc.getDns1()); + nic.setDns2(dc.getDns2()); + } + @Override public void updateNicProfile(NicProfile profile, Network network) { @@ -186,7 +213,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { if (nic.getIp4Address() == null) { - _privateIpDao.allocateIpAddress(network.getDataCenterId(), network.getId()); + getIp(nic, _configMgr.getZone(network.getDataCenterId()), network); nic.setStrategy(ReservationStrategy.Create); } } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java index 3d756bfde8c..0d738ee20b4 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java @@ -23,6 +23,7 @@ import com.cloud.network.Network; import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.rules.NetworkACL; import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.user.Account; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.VirtualMachineProfile.Param; @@ -56,4 +57,22 @@ public interface VpcVirtualNetworkApplianceManager extends VirtualNetworkApplian boolean applyNetworkACLs(Network network, List rules, List routers) throws ResourceUnavailableException; + /** + * @param gateway + * @param router TODO + * @return + * @throws ResourceUnavailableException + * @throws ConcurrentOperationException + */ + boolean setupPrivateGateway(PrivateGateway gateway, VirtualRouter router) throws ConcurrentOperationException, ResourceUnavailableException; + + /** + * @param gateway + * @param router + * @return + * @throws ResourceUnavailableException + * @throws ConcurrentOperationException + */ + boolean destroyPrivateGateway(PrivateGateway gateway, VirtualRouter router) throws ConcurrentOperationException, ResourceUnavailableException; + } diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 425f18259e6..0f62037595d 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -26,6 +26,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager.OnError; import com.cloud.agent.api.PlugNicAnswer; import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.SetSourceNatAnswer; import com.cloud.agent.api.SetupGuestNetworkAnswer; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.UnPlugNicAnswer; @@ -70,6 +71,7 @@ import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.NetworkACL; +import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.Dao.VpcDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; @@ -552,7 +554,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian //set source nat ip if (sourceNatIpAdd != null) { IpAddressTO sourceNatIp = sourceNatIpAdd.first(); - SetSourceNatCommand cmd = new SetSourceNatCommand(sourceNatIp, addSourceNat, null); + SetSourceNatCommand cmd = new SetSourceNatCommand(sourceNatIp, addSourceNat); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn()); @@ -754,7 +756,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian cmds.addCommand(plugNicCmd); } - //if ip is source nat, create source nat command + // create vpc assoc commands if (!publicIps.isEmpty()) { createVpcAssociateIPCommands(router, publicIps, cmds); } @@ -764,12 +766,21 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian PlugNicCommand plugNicCmd = new PlugNicCommand(_itMgr.toVmTO(profile), getNicTO(router, guestNic.getNetworkId())); cmds.addCommand(plugNicCmd); - //and set guest network - VirtualMachine vm = _vmDao.findById(router.getId()); - NicProfile nicProfile = _networkMgr.getNicProfile(vm, guestNic.getNetworkId()); - SetupGuestNetworkCommand setupCmd = createSetupGuestNetworkCommand(router, true, nicProfile); - cmds.addCommand(setupCmd); - + if (!_networkMgr.isPrivateGateway(guestNic)) { + //set guest network + VirtualMachine vm = _vmDao.findById(router.getId()); + NicProfile nicProfile = _networkMgr.getNicProfile(vm, guestNic.getNetworkId()); + SetupGuestNetworkCommand setupCmd = createSetupGuestNetworkCommand(router, true, nicProfile); + cmds.addCommand(setupCmd); + } else { + //set source nat + Integer networkRate = _networkMgr.getNetworkRate(guestNic.getNetworkId(), router.getId()); + IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, guestNic.getIp4Address(), true, false, + true, guestNic.getBroadcastUri().getHost(), guestNic.getGateway(), guestNic.getNetmask(), guestNic.getMacAddress(), + null, networkRate, false); + SetSourceNatCommand cmd = new SetSourceNatCommand(ip, true); + cmds.addCommand(cmd); + } } } catch (Exception ex) { s_logger.warn("Failed to add router " + router + " to network due to exception ", ex); @@ -819,4 +830,96 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian } } } + + @Override + public boolean setupPrivateGateway(PrivateGateway gateway, VirtualRouter router) throws ConcurrentOperationException, ResourceUnavailableException { + boolean result = true; + try { + Network network = _networkMgr.getNetwork(gateway.getNetworkId()); + NicProfile guestNic = _itMgr.addVmToNetwork(router, network, null); + + //setup source nat + if (guestNic != null) { + result = setupVpcPrivateNetwork(router, true, guestNic); + } else { + s_logger.warn("Failed to setup gateway " + gateway + " on router " + router + " with the source nat"); + result = false; + } + } catch (Exception ex) { + s_logger.warn("Failed to create private gateway " + gateway + " on router " + router + " due to ", ex); + result = false; + } finally { + if (!result) { + s_logger.debug("Removing gateway " + gateway + " from router " + router + " as a part of cleanup"); + if (destroyPrivateGateway(gateway, router)) { + s_logger.debug("Removed the gateway " + gateway + " from router " + router + " as a part of cleanup"); + } else { + s_logger.warn("Failed to remove the gateway " + gateway + " from router " + router + " as a part of cleanup"); + } + } + } + return result; + } + + /** + * @param router + * @param add + * @param privateNic + * @return + * @throws AgentUnavailableException + */ + protected boolean setupVpcPrivateNetwork(VirtualRouter router, boolean add, NicProfile privateNic) + throws AgentUnavailableException { + boolean result = true; + Commands cmds = new Commands(OnError.Stop); + + Integer networkRate = _networkMgr.getNetworkRate(privateNic.getNetworkId(), router.getId()); + IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, privateNic.getIp4Address(), add, false, + true, privateNic.getBroadCastUri().getHost(), privateNic.getGateway(), privateNic.getNetmask(), privateNic.getMacAddress(), + null, networkRate, false); + Network network = _networkMgr.getNetwork(privateNic.getNetworkId()); + ip.setTrafficType(network.getTrafficType()); + + SetSourceNatCommand cmd = new SetSourceNatCommand(ip, add); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn()); + cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); + cmds.addCommand("SetSourceNatCommand", cmd); + sendCommandsToRouter(router, cmds); + + SetSourceNatAnswer setupAnswer = cmds.getAnswer(SetSourceNatAnswer.class); + String setup = add ? "set" : "destroy"; + if (!(setupAnswer != null && setupAnswer.getResult())) { + s_logger.warn("Unable to " + setup + " source nat for private gateway " + privateNic + " on router " + router); + result = false; + } + + return result; + } + + @Override + public boolean destroyPrivateGateway(PrivateGateway gateway, VirtualRouter router) + throws ConcurrentOperationException, ResourceUnavailableException { + + if (!_networkMgr.isVmPartOfNetwork(router.getId(), gateway.getNetworkId())) { + s_logger.debug("Router doesn't have nic for gateway " + gateway + " so no need to removed it"); + return true; + } + + Network privateNetwork = _networkMgr.getNetwork(gateway.getNetworkId()); + + s_logger.debug("Unsetting source nat for " + router + "'s private gateway " + gateway + " as a part of delete private gateway"); + boolean result = setupVpcPrivateNetwork(router, false, _networkMgr.getNicProfile(router, privateNetwork.getId())); + if (!result) { + s_logger.warn("Failed to delete private gateway " + gateway + " on router " + router); + return false; + } + + s_logger.debug("Removing router " + router + " from private network " + privateNetwork + " as a part of delete private gateway"); + result = result && _itMgr.removeVmFromNetwork(router, privateNetwork, null); + s_logger.debug("Private gateawy " + gateway + " is removed from router " + router); + + return result; + } } diff --git a/server/src/com/cloud/network/vpc/Dao/PrivateIpDao.java b/server/src/com/cloud/network/vpc/Dao/PrivateIpDao.java index 226b8b1269d..9f8d8114d83 100644 --- a/server/src/com/cloud/network/vpc/Dao/PrivateIpDao.java +++ b/server/src/com/cloud/network/vpc/Dao/PrivateIpDao.java @@ -58,5 +58,8 @@ public interface PrivateIpDao extends GenericDao{ * @param networkId */ void deleteByNetworkId(long networkId); + + int countByNetworkId(long ntwkId); + } diff --git a/server/src/com/cloud/network/vpc/Dao/PrivateIpDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/PrivateIpDaoImpl.java index a9d945663e4..7fc626c5b8b 100644 --- a/server/src/com/cloud/network/vpc/Dao/PrivateIpDaoImpl.java +++ b/server/src/com/cloud/network/vpc/Dao/PrivateIpDaoImpl.java @@ -40,6 +40,7 @@ public class PrivateIpDaoImpl extends GenericDaoBase implemen private final SearchBuilder AllFieldsSearch; private final GenericSearchBuilder CountAllocatedByNetworkId; + private final GenericSearchBuilder CountByNetworkId; protected PrivateIpDaoImpl() { @@ -57,6 +58,11 @@ public class PrivateIpDaoImpl extends GenericDaoBase implemen CountAllocatedByNetworkId.and("networkId", CountAllocatedByNetworkId.entity().getNetworkId(), Op.EQ); CountAllocatedByNetworkId.and("taken", CountAllocatedByNetworkId.entity().getTakenAt(), Op.NNULL); CountAllocatedByNetworkId.done(); + + CountByNetworkId = createSearchBuilder(Integer.class); + CountByNetworkId.select(null, Func.COUNT, CountByNetworkId.entity().getId()); + CountByNetworkId.and("networkId", CountByNetworkId.entity().getNetworkId(), Op.EQ); + CountByNetworkId.done(); } @Override @@ -126,4 +132,12 @@ public class PrivateIpDaoImpl extends GenericDaoBase implemen sc.setParameters("networkId", networkId); remove(sc); } + + @Override + public int countByNetworkId(long ntwkId) { + SearchCriteria sc = CountByNetworkId.create(); + sc.setParameters("networkId", ntwkId); + List results = customSearch(sc, null); + return results.get(0); + } } diff --git a/server/src/com/cloud/network/vpc/Dao/VpcGatewayDao.java b/server/src/com/cloud/network/vpc/Dao/VpcGatewayDao.java index 8e9a72b214a..add2f4228ad 100644 --- a/server/src/com/cloud/network/vpc/Dao/VpcGatewayDao.java +++ b/server/src/com/cloud/network/vpc/Dao/VpcGatewayDao.java @@ -19,5 +19,5 @@ import com.cloud.utils.db.GenericDao; * @author Alena Prokharchyk */ public interface VpcGatewayDao extends GenericDao{ - + VpcGatewayVO getPrivateGateway(long vpcId); } diff --git a/server/src/com/cloud/network/vpc/Dao/VpcGatewayDaoImpl.java b/server/src/com/cloud/network/vpc/Dao/VpcGatewayDaoImpl.java new file mode 100644 index 00000000000..f19ff569f22 --- /dev/null +++ b/server/src/com/cloud/network/vpc/Dao/VpcGatewayDaoImpl.java @@ -0,0 +1,50 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc.Dao; + +import javax.ejb.Local; + +import com.cloud.network.vpc.VpcGateway; +import com.cloud.network.vpc.VpcGatewayVO; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +/** + * @author Alena Prokharchyk + */ + +@Local(value = VpcGatewayDao.class) +@DB(txn = false) +public class VpcGatewayDaoImpl extends GenericDaoBase implements VpcGatewayDao{ + protected final SearchBuilder AllFieldsSearch; + + protected VpcGatewayDaoImpl() { + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), SearchCriteria.Op.EQ); + AllFieldsSearch.and("type", AllFieldsSearch.entity().getType(), SearchCriteria.Op.EQ); + AllFieldsSearch.done(); + } + + + @Override + public VpcGatewayVO getPrivateGateway(long vpcId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("vpcId", vpcId); + sc.setParameters("type", VpcGateway.Type.Private); + + return findOneBy(sc); + } + +} diff --git a/server/src/com/cloud/network/vpc/PrivateGatewayProfile.java b/server/src/com/cloud/network/vpc/PrivateGatewayProfile.java new file mode 100644 index 00000000000..912a14325d5 --- /dev/null +++ b/server/src/com/cloud/network/vpc/PrivateGatewayProfile.java @@ -0,0 +1,95 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +/** + * @author Alena Prokharchyk + */ +public class PrivateGatewayProfile implements PrivateGateway{ + VpcGateway vpcGateway; + String vlanTag; + String gateway; + String netmask; + long physicalNetworkId; + + /** + * @param vpcGateway + * @param vlanTag + * @param gateway + * @param netmask + * @param physicalNetworkId TODO + */ + public PrivateGatewayProfile(VpcGateway vpcGateway, String vlanTag, String gateway, String netmask, long physicalNetworkId) { + super(); + this.vpcGateway = vpcGateway; + this.vlanTag = vlanTag; + this.gateway = gateway; + this.netmask = netmask; + this.physicalNetworkId = physicalNetworkId; + } + + @Override + public long getId() { + return vpcGateway.getId(); + } + + @Override + public String getIp4Address() { + return vpcGateway.getIp4Address(); + } + + @Override + public Type getType() { + return vpcGateway.getType(); + } + + @Override + public Long getVpcId() { + return vpcGateway.getVpcId(); + } + + @Override + public long getZoneId() { + return vpcGateway.getZoneId(); + } + + @Override + public Long getNetworkId() { + return vpcGateway.getNetworkId(); + } + + @Override + public String getUuid() { + return vpcGateway.getUuid(); + } + + @Override + public String getVlanTag() { + return vlanTag; + } + + @Override + public String getGateway() { + return gateway; + } + + @Override + public String getNetmask() { + return netmask; + } + + @Override + public long getPhysicalNetworkId() { + return physicalNetworkId; + } +} diff --git a/server/src/com/cloud/network/vpc/PrivateIpAddress.java b/server/src/com/cloud/network/vpc/PrivateIpAddress.java new file mode 100644 index 00000000000..7a568c17157 --- /dev/null +++ b/server/src/com/cloud/network/vpc/PrivateIpAddress.java @@ -0,0 +1,68 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by 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. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.network.vpc; + +import com.cloud.utils.net.NetUtils; + +/** + * @author Alena Prokharchyk + */ +public class PrivateIpAddress implements PrivateIp{ + String vlanTag; + String gateway; + String netmask; + String ipAddress; + String macAddress; + + /** + * @param privateIp + * @param vlanTag + * @param gateway + * @param netmask + * @param macAddress TODO + * @param physicalNetworkId TODO + */ + public PrivateIpAddress(PrivateIpVO privateIp, String vlanTag, String gateway, String netmask, long macAddress) { + super(); + this.ipAddress = privateIp.getIpAddress(); + this.vlanTag = vlanTag; + this.gateway = gateway; + this.netmask = netmask; + this.macAddress = NetUtils.long2Mac(macAddress); + } + + @Override + public String getVlanTag() { + return vlanTag; + } + + @Override + public String getGateway() { + return gateway; + } + + @Override + public String getNetmask() { + return netmask; + } + + @Override + public String getIpAddress() { + return ipAddress; + } + + @Override + public String getMacAddress() { + return macAddress; + } +} diff --git a/server/src/com/cloud/network/vpc/PrivateIpVO.java b/server/src/com/cloud/network/vpc/PrivateIpVO.java index 42df20ce923..48397559cfd 100644 --- a/server/src/com/cloud/network/vpc/PrivateIpVO.java +++ b/server/src/com/cloud/network/vpc/PrivateIpVO.java @@ -39,6 +39,9 @@ public class PrivateIpVO { @Column(name="ip_address", updatable=false, nullable=false) String ipAddress; + @Column(name="mac_address") + private long macAddress; + @Column(name="taken") @Temporal(value=TemporalType.TIMESTAMP) private Date takenAt; @@ -49,9 +52,10 @@ public class PrivateIpVO { public PrivateIpVO() { } - public PrivateIpVO(String ipAddress, long networkId) { + public PrivateIpVO(String ipAddress, long networkId, long macAddress) { this.ipAddress = ipAddress; this.networkId = networkId; + this.macAddress = macAddress; } public void setTakenAt(Date takenDate) { @@ -73,4 +77,8 @@ public class PrivateIpVO { public long getId() { return id; } + + public long getMacAddress() { + return macAddress; + } } diff --git a/server/src/com/cloud/network/vpc/VpcGatewayVO.java b/server/src/com/cloud/network/vpc/VpcGatewayVO.java index 277c440da53..35a17384fd3 100644 --- a/server/src/com/cloud/network/vpc/VpcGatewayVO.java +++ b/server/src/com/cloud/network/vpc/VpcGatewayVO.java @@ -12,11 +12,119 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.network.vpc; +import java.util.Date; +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.utils.db.GenericDao; + /** * @author Alena Prokharchyk */ -public class VpcGatewayVO { + +@Entity +@Table(name="vpc_gateways") +public class VpcGatewayVO implements VpcGateway{ - public VpcGatewayVO() { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name = "ip4_address") + String ip4Address; + + @Column(name = "type") + @Enumerated(value = EnumType.STRING) + VpcGateway.Type type; + + @Column(name="vpc_id") + Long vpcId; + + @Column(name="zone_id") + long zoneId; + + @Column(name="network_id") + Long networkId; + + @Column(name=GenericDao.CREATED_COLUMN) + Date created; + + @Column(name=GenericDao.REMOVED_COLUMN) + Date removed; + + @Column(name="uuid") + private String uuid; + + protected VpcGatewayVO(){ + this.uuid = UUID.randomUUID().toString(); + } + + /** + * @param ip4Address + * @param type + * @param vpcId + * @param zoneId + * @param networkId + * @param account_id + */ + public VpcGatewayVO(String ip4Address, Type type, Long vpcId, long zoneId, Long networkId) { + super(); + this.ip4Address = ip4Address; + this.type = type; + this.vpcId = vpcId; + this.zoneId = zoneId; + this.networkId = networkId; + this.uuid = UUID.randomUUID().toString(); + } + + @Override + public String getUuid() { + return this.uuid; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getIp4Address() { + return ip4Address; + } + + @Override + public VpcGateway.Type getType() { + return type; + } + + @Override + public Long getVpcId() { + return vpcId; + } + + @Override + public long getZoneId() { + return zoneId; + } + + @Override + public Long getNetworkId() { + return networkId; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder("VpcGateway["); + buf.append(id).append("|").append(ip4Address.toString()).append("|").append(vpcId).append("]"); + return buf.toString(); } } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 55e95be2480..02fdce93d43 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -34,6 +34,7 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.UnsupportedServiceException; import com.cloud.network.IPAddressVO; @@ -42,11 +43,15 @@ import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.PhysicalNetwork; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; +import com.cloud.network.vpc.Dao.PrivateIpDao; import com.cloud.network.vpc.Dao.VpcDao; +import com.cloud.network.vpc.Dao.VpcGatewayDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; import com.cloud.network.vpc.Dao.VpcOfferingServiceMapDao; import com.cloud.offering.NetworkOffering; @@ -97,6 +102,10 @@ public class VpcManagerImpl implements VpcManager, Manager{ IPAddressDao _ipAddressDao; @Inject DomainRouterDao _routerDao; + @Inject + VpcGatewayDao _vpcGatewayDao; + @Inject + PrivateIpDao _privateIpDao; private VpcProvider vpcElement = null; @@ -223,9 +232,6 @@ public class VpcManagerImpl implements VpcManager, Manager{ } } } - - - txn.commit(); UserContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name); @@ -875,7 +881,7 @@ public class VpcManagerImpl implements VpcManager, Manager{ @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") - public boolean restartVpc(Long vpcId) throws ConcurrentOperationException, ResourceUnavailableException, + public boolean restartVpc(long vpcId) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { Account caller = UserContext.current().getCaller(); @@ -916,4 +922,132 @@ public class VpcManagerImpl implements VpcManager, Manager{ public List getVpcRouters(long vpcId) { return _routerDao.listRoutersByVpcId(vpcId); } + + @Override + public PrivateGateway getVpcPrivateGateway(long id) { + VpcGateway gateway = _vpcGatewayDao.findById(id); + + if (gateway == null || gateway.getType() != VpcGateway.Type.Private) { + return null; + } + Network network = _ntwkMgr.getNetwork(gateway.getNetworkId()); + String vlanTag = network.getBroadcastUri().getHost(); + String netmask = NetUtils.getCidrNetmask(network.getCidr()); + return new PrivateGatewayProfile(gateway, vlanTag, network.getGateway(),netmask, network.getPhysicalNetworkId()); + } + + @Override + @DB + public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, + String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException, + ConcurrentOperationException, InsufficientCapacityException { + + //Validate parameters + Vpc vpc = getVpc(vpcId); + if (vpc == null) { + throw new InvalidParameterValueException("Unable to find VPC by id given"); + } + + //allow only one private gateway per vpc + VpcGatewayVO gatewayVO = _vpcGatewayDao.getPrivateGateway(vpcId); + if (gatewayVO != null) { + throw new InvalidParameterValueException("Private ip address already exists for vpc " + vpc); + } + + //Validate physical network + if (physicalNetworkId == null) { + List pNtwks = _ntwkMgr.getPhysicalNtwksSupportingTrafficType(vpc.getZoneId(), TrafficType.Guest); + if (pNtwks.isEmpty() || pNtwks.size() != 1) { + throw new InvalidParameterValueException("Physical network can't be determined; pass physical network id"); + } + physicalNetworkId = pNtwks.get(0).getId(); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + s_logger.debug("Creating Private gateway for VPC " + vpc); + //1) create private network + String networkName = "vpc-" + vpc.getName() + "-privateNetwork"; + Network privateNtwk = _ntwkMgr.createPrivateNetwork(networkName, networkName, physicalNetworkId, + vlan, ipAddress, null, gateway, netmask, gatewayOwnerId); + + //2) create gateway entry + gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(), + privateNtwk.getId()); + _vpcGatewayDao.persist(gatewayVO); + + s_logger.debug("Created vpc gateway entry " + gatewayVO); + + txn.commit(); + + return getVpcPrivateGateway(gatewayVO.getId()); + } + + + @Override + public PrivateGateway applyVpcGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException { + PrivateGateway gateway = getVpcPrivateGateway(gatewayId); + if (getVpcElement().createPrivateGateway(gateway)) { + s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend"); + return gateway; + } else { + s_logger.warn("Private gateway " + gateway + " failed to apply on the backend"); + return null; + } + } + + @Override + public boolean deleteVpcPrivateGateway(Long gatewayId) throws ConcurrentOperationException, ResourceUnavailableException { + VpcGatewayVO gatewayVO = _vpcGatewayDao.findById(gatewayId); + if (gatewayVO == null || gatewayVO.getType() != VpcGateway.Type.Private) { + throw new InvalidParameterValueException("Can't find private gateway by id specified"); + } + + //1) delete the gateaway on the backend + PrivateGateway gateway = getVpcPrivateGateway(gatewayId); + if (getVpcElement().deletePrivateGateway(gateway)) { + s_logger.debug("Private gateway " + gateway + " was applied succesfully on the backend"); + } else { + s_logger.warn("Private gateway " + gateway + " failed to apply on the backend"); + return false; + } + + //2) Delete private gateway + return deletePrivateGateway(gateway); + } + + @DB + public boolean deletePrivateGateway(PrivateGateway gateway) { + //check if there are ips allocted in the network + long networkId = gateway.getNetworkId(); + boolean deleteNetwork = true; + List privateIps = _privateIpDao.listByNetworkId(networkId); + if (privateIps.size() > 1 || !privateIps.get(0).getIpAddress().equalsIgnoreCase(gateway.getIp4Address())) { + s_logger.debug("Not removing network id=" + gateway.getNetworkId() + " as it has private ip addresses for other gateways"); + deleteNetwork = false; + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + PrivateIpVO ip = _privateIpDao.findByIpAndSourceNetworkId(gateway.getNetworkId(), gateway.getIp4Address()); + if (ip != null) { + _privateIpDao.remove(ip.getId()); + s_logger.debug("Deleted private ip " + ip); + } + + if (deleteNetwork) { + User callerUser = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); + Account owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM); + ReservationContext context = new ReservationContextImpl(null, null, callerUser, owner); + _ntwkMgr.destroyNetwork(networkId, context); + s_logger.debug("Deleted private network id=" + networkId); + } + + _vpcGatewayDao.remove(gateway.getId()); + s_logger.debug("Deleted private gateway " + gateway); + + txn.commit(); + return true; + } } diff --git a/server/src/com/cloud/projects/ProjectVO.java b/server/src/com/cloud/projects/ProjectVO.java index 631d4c923e4..ad61dac1bec 100644 --- a/server/src/com/cloud/projects/ProjectVO.java +++ b/server/src/com/cloud/projects/ProjectVO.java @@ -92,7 +92,6 @@ public class ProjectVO implements Project, Identity { return domainId; } - @Override public long getId() { return id; diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 594986c226c..0c7e62219c0 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -43,7 +43,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicVO; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Event; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 83c76c8ef63..88c2e38681c 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2213,7 +2213,7 @@ CREATE TABLE `cloud`.`vpc_gateways` ( `network_id` bigint unsigned NOT NULL COMMENT 'network id vpc gateway belongs to', `vpc_id` bigint unsigned NOT NULL COMMENT 'id of the vpc the gateway belongs to', `zone_id` bigint unsigned NOT NULL COMMENT 'id of the zone the gateway belongs to', - `created` datetime NOT NULL COMMENT 'date created', + `created` datetime COMMENT 'date created', `removed` datetime COMMENT 'date removed if not null', PRIMARY KEY (`id`), CONSTRAINT `fk_vpc_gateways__network_id` FOREIGN KEY `fk_vpc_gateways__network_id`(`network_id`) REFERENCES `networks`(`id`), @@ -2228,6 +2228,7 @@ CREATE TABLE `cloud`.`private_ip_address` ( `ip_address` char(40) NOT NULL COMMENT 'ip address', `network_id` bigint unsigned NOT NULL COMMENT 'id of the network ip belongs to', `reservation_id` char(40) COMMENT 'reservation id', + `mac_address` varchar(17) COMMENT 'mac address', `taken` datetime COMMENT 'Date taken', PRIMARY KEY (`id`), CONSTRAINT `fk_private_ip_address__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks` (`id`) ON DELETE CASCADE