diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterAnswer.java b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterAnswer.java new file mode 100644 index 00000000000..3337e92cf79 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterAnswer.java @@ -0,0 +1,40 @@ +// 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.agent.api; + +/** + * + */ +public class CreateLogicalRouterAnswer extends Answer { + + private String _logicalRouterUuid; + + public CreateLogicalRouterAnswer(Command command, boolean success, + String details, String logicalRouterUuid) { + super(command, success, details); + this._logicalRouterUuid = logicalRouterUuid; + } + + public CreateLogicalRouterAnswer(Command command, Exception e) { + super(command, e); + } + + public String getLogicalSwitchUuid() { + return _logicalRouterUuid; + } + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterCommand.java b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterCommand.java new file mode 100644 index 00000000000..57440dfc4b0 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterCommand.java @@ -0,0 +1,115 @@ +// 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.agent.api; + +/** + * + */ +public class CreateLogicalRouterCommand extends Command { + private String _gatewayServiceUuid; + private String _logicalSwitchUuid; + private long _vlanId; + private String _name; + private String _ownerName; + private String _publicIpCidr; + private String _publicNextHop; + private String _internalIpCidr; + + public CreateLogicalRouterCommand(String gatewayServiceUuid, long vlanId, + String logicalSwitchUuid, String name, + String publicIpCidr, String publicNextHop, + String internalIpCidr, String ownerName) { + super(); + this._gatewayServiceUuid = gatewayServiceUuid; + this._logicalSwitchUuid = logicalSwitchUuid; + this._vlanId = vlanId; + this._name = name; + this._ownerName = ownerName; + this._publicIpCidr = publicIpCidr; + this._publicNextHop = publicNextHop; + this._internalIpCidr = internalIpCidr; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getGatewayServiceUuid() { + return _gatewayServiceUuid; + } + + public void setGatewayServiceUuid(String gatewayServiceUuid) { + this._gatewayServiceUuid = gatewayServiceUuid; + } + + public String getLogicalSwitchUuid() { + return _logicalSwitchUuid; + } + + public void setLogicalSwitchUuid(String logicalSwitchUuid) { + _logicalSwitchUuid = logicalSwitchUuid; + } + + public long getVlanId() { + return _vlanId; + } + + public void setVlanId(long vlanId) { + this._vlanId = vlanId; + } + + public String getName() { + return _name; + } + + public void setName(String name) { + this._name = name; + } + + public String getOwnerName() { + return _ownerName; + } + + public void setOwnerName(String ownerName) { + this._ownerName = ownerName; + } + + public String getPublicIpCidr() { + return _publicIpCidr; + } + + public void setPublicIpCidr(String publicIpCidr) { + this._publicIpCidr = publicIpCidr; + } + + public String getInternalIpCidr() { + return _internalIpCidr; + } + + public void setInternalIpCidr(String internalIpCidr) { + this._internalIpCidr = internalIpCidr; + } + + public String getPublicNextHop() { + return _publicNextHop; + } + + public void setPublicNextHop(String publicNextHop) { + this._publicNextHop = publicNextHop; + } +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/api/commands/AddNiciraNvpDeviceCmd.java b/plugins/network-elements/nicira-nvp/src/com/cloud/api/commands/AddNiciraNvpDeviceCmd.java index 6eac21f7255..28bc1fc9ad4 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/api/commands/AddNiciraNvpDeviceCmd.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/api/commands/AddNiciraNvpDeviceCmd.java @@ -67,6 +67,8 @@ public class AddNiciraNvpDeviceCmd extends BaseCmd { @Parameter(name=ApiConstants.NICIRA_NVP_TRANSPORT_ZONE_UUID, type=CommandType.STRING, required = true, description="The Transportzone UUID configured on the Nicira Controller") private String transportzoneuuid; + //FIXME add optional gateway service uuid + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index 1fcccdb1ee3..638ed8ab117 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -47,6 +47,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.CreateLogicalRouterAnswer; +import com.cloud.agent.api.CreateLogicalRouterCommand; import com.cloud.agent.api.CreateLogicalSwitchPortAnswer; import com.cloud.agent.api.CreateLogicalSwitchPortCommand; import com.cloud.agent.api.DeleteLogicalSwitchPortAnswer; @@ -62,6 +64,9 @@ import com.cloud.api.commands.DeleteNiciraNvpDeviceCmd; import com.cloud.api.commands.ListNiciraNvpDeviceNetworksCmd; import com.cloud.api.commands.ListNiciraNvpDevicesCmd; import com.cloud.api.response.NiciraNvpDeviceResponse; +import com.cloud.configuration.ConfigurationManager; +import com.cloud.dc.Vlan; +import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -80,11 +85,15 @@ import com.cloud.network.Network.Service; import com.cloud.network.NetworkVO; import com.cloud.network.Networks; import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.NetworkManager; import com.cloud.network.NiciraNvpDeviceVO; import com.cloud.network.NiciraNvpNicMappingVO; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.PublicIpAddress; +import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NiciraNvpDao; import com.cloud.network.dao.NiciraNvpNicMappingDao; import com.cloud.network.dao.PhysicalNetworkDao; @@ -98,11 +107,13 @@ import com.cloud.resource.ResourceState; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; +import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.ReservationContext; @@ -111,7 +122,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.NicDao; @Local(value = NetworkElement.class) -public class NiciraNvpElement extends AdapterBase implements ConnectivityProvider, NiciraNvpElementService, ResourceStateAdapter { +public class NiciraNvpElement extends AdapterBase implements ConnectivityProvider, SourceNatServiceProvider, NiciraNvpElementService, ResourceStateAdapter, IpDeployer { private static final Logger s_logger = Logger.getLogger(NiciraNvpElement.class); private static final Map> capabilities = setCapabilities(); @@ -137,6 +148,14 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide NiciraNvpNicMappingDao _niciraNvpNicMappingDao; @Inject NetworkDao _networkDao; + @Inject + NetworkManager _networkManager; + @Inject + ConfigurationManager _configMgr; + @Inject + NetworkServiceMapDao _ntwkSrvcDao; + @Inject + VlanDao _vlanDao; @Override public Map> getCapabilities() { @@ -148,12 +167,23 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide return Provider.NiciraNvp; } - private boolean canHandle(Network network) { + private boolean canHandle(Network network, Service service) { + s_logger.debug("Checking if NiciraNvpElement can handle service " + service.getName() + " on network " + network.getDisplayText()); if (network.getBroadcastDomainType() != BroadcastDomainType.Lswitch) { return false; } - return true; + if (!_networkManager.isProviderForNetwork(getProvider(), network.getId())) { + s_logger.debug("NiciraNvpElement is not a provider for network " + network.getDisplayText()); + return false; + } + + if (!_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), service, Network.Provider.NiciraNvp)) { + s_logger.debug("NiciraNvpElement can't provide the " + service.getName() + " service on network " + network.getDisplayText()); + return false; + } + + return true; } @Override @@ -169,12 +199,79 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + s_logger.debug("entering NiciraNvpElement implement function for network " + + network.getDisplayText() + " (state " + network.getState() + ")"); - if (!canHandle(network)) { + if (!canHandle(network, Service.Connectivity)) { return false; } - return true; + if (network.getBroadcastUri() == null) { + s_logger.error("Nic has no broadcast Uri with the LSwitch Uuid"); + return false; + } + + List devices = _niciraNvpDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (devices.isEmpty()) { + s_logger.error("No NiciraNvp Controller on physical network " + network.getPhysicalNetworkId()); + return false; + } + NiciraNvpDeviceVO niciraNvpDevice = devices.get(0); + HostVO niciraNvpHost = _hostDao.findById(niciraNvpDevice.getHostId()); + _hostDao.loadDetails(niciraNvpHost); + + Account owner = context.getAccount(); + + /** + * Lock the network as we might need to do multiple operations that + * should be done only once. + */ + Network lock = _networkDao.acquireInLockTable(network.getId(), + _networkManager.getNetworkLockTimeout()); + if (lock == null) { + throw new ConcurrentOperationException("Unable to lock network " + + network.getId()); + } + try { + if (_networkManager.isProviderSupportServiceInNetwork( + network.getId(), Service.SourceNat, Provider.NiciraNvp)) { + s_logger.debug("Apparently we are supposed to provide SourceNat on this network"); + + PublicIp sourceNatIp = _networkManager.assignSourceNatIpAddressToGuestNetwork(owner, network); + String publicCidr = sourceNatIp.getAddress().addr() + "/" + NetUtils.getCidrSize(sourceNatIp.getVlanNetmask()); + String internalCidr = network.getGateway() + "/" + network.getCidr().split("/")[1]; + long vlanid = (Vlan.UNTAGGED.equals(sourceNatIp.getVlanTag())) ? 0 : Long.parseLong(sourceNatIp.getVlanTag()); + + CreateLogicalRouterCommand cmd = new CreateLogicalRouterCommand( + niciraNvpHost.getDetail("gatewayserviceuuid"), + vlanid, + network.getBroadcastUri().getSchemeSpecificPart(), + "router-" + network.getDisplayText(), + publicCidr, + sourceNatIp.getGateway(), + internalCidr, + context.getDomain().getName() + "-" + context.getAccount().getAccountName()); + CreateLogicalRouterAnswer answer = + (CreateLogicalRouterAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd); + if (answer.getResult() == false) { + s_logger.error("Failed to create Logical Router for network " + network.getDisplayText()); + return false; + } + + } + + + } finally { + if (lock != null) { + _networkDao.releaseFromLockTable(lock.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Lock is released for network id " + + lock.getId() + " as a part of router startup in " + + dest); + } + } + } + return true; } @Override @@ -184,7 +281,7 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - if (!canHandle(network)) { + if (!canHandle(network, Service.Connectivity)) { return false; } @@ -244,7 +341,7 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException { - if (!canHandle(network)) { + if (!canHandle(network, Service.Connectivity)) { return false; } @@ -286,7 +383,7 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException { - if (!canHandle(network)) { + if (!canHandle(network, Service.Connectivity)) { return false; } @@ -296,7 +393,7 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide @Override public boolean destroy(Network network) throws ConcurrentOperationException, ResourceUnavailableException { - if (!canHandle(network)) { + if (!canHandle(network, Service.Connectivity)) { return false; } @@ -318,18 +415,34 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide @Override public boolean canEnableIndividualServices() { - return false; + return true; } @Override public boolean verifyServicesCombination(Set services) { - return true; + // This element can only function in a Nicra Nvp based + // SDN network, so Connectivity needs to be present here + if (services.contains(Service.Connectivity)) { + return true; + } + s_logger.debug("Unable to provide services without Connectivity service enabled for this element"); + return false; } private static Map> setCapabilities() { Map> capabilities = new HashMap>(); + // Basic L2 SDN provisioning capabilities.put(Service.Connectivity, null); + + // L3 Support : SourceNat + capabilities.put(Service.Gateway, null); + Map sourceNatCapabilities = new HashMap(); + sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount"); + sourceNatCapabilities.put(Capability.RedundantRouter, "true"); + capabilities.put(Service.SourceNat, sourceNatCapabilities); + + return capabilities; } @@ -540,4 +653,28 @@ public class NiciraNvpElement extends AdapterBase implements ConnectivityProvide return new DeleteHostAnswer(true); } + /** + * From interface SourceNatServiceProvider + */ + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } + + /** + * From interface IpDeployer + * @param network + * @param ipAddress + * @param services + * @return + * @throws ResourceUnavailableException + */ + @Override + public boolean applyIps(Network network, + List ipAddress, Set services) + throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/L3GatewayAttachment.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/L3GatewayAttachment.java index 65a0a8ed5c4..8b807fd9e72 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/L3GatewayAttachment.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/L3GatewayAttachment.java @@ -22,15 +22,13 @@ package com.cloud.network.nicira; public class L3GatewayAttachment extends Attachment { private String l3_gateway_service_uuid; private String type = "L3GatewayAttachment"; - private int vlan_id; + private Long vlan_id; public L3GatewayAttachment(String l3_gateway_service_uuid) { this.l3_gateway_service_uuid = l3_gateway_service_uuid; - // VLAN 0 is untagged, set explicitly of no vlan is given in the constructor - this.vlan_id = 0; } - public L3GatewayAttachment(String l3_gateway_service_uuid, int vlan_id) { + public L3GatewayAttachment(String l3_gateway_service_uuid, long vlan_id) { this.l3_gateway_service_uuid = l3_gateway_service_uuid; this.vlan_id = vlan_id; } @@ -43,11 +41,11 @@ public class L3GatewayAttachment extends Attachment { this.l3_gateway_service_uuid = l3_gateway_service_uuid; } - public int getVlanId() { + public long getVlanId() { return vlan_id; } - public void setVlanId(int vlan_id) { + public void setVlanId(long vlan_id) { this.vlan_id = vlan_id; } diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/PatchAttachment.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/PatchAttachment.java new file mode 100644 index 00000000000..e57c2493f1c --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/PatchAttachment.java @@ -0,0 +1,39 @@ +// 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.network.nicira; + +/** + * + */ +public class PatchAttachment extends Attachment { + private final String type = "PatchAttachment"; + private String peer_port_uuid; + + public PatchAttachment(String peerPortUuid) { + this.peer_port_uuid = peerPortUuid; + } + + public String getPeerPortUuid() { + return peer_port_uuid; + } + + public void setPeerPortUuid(String peerPortUuid) { + this.peer_port_uuid = peerPortUuid; + } + + +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/RouterNextHop.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/RouterNextHop.java index be302fab79a..c018af37467 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/RouterNextHop.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/RouterNextHop.java @@ -22,6 +22,10 @@ package com.cloud.network.nicira; public class RouterNextHop { private String gateway_ip_address; private String type = "RouterNextHop"; + + public RouterNextHop(String gatewayIpAddress) { + this.gateway_ip_address = gatewayIpAddress; + } public String getGatewayIpAddress() { return gateway_ip_address; diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java index 31cac6f000c..4aa6ff18798 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java @@ -27,6 +27,8 @@ import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.CreateLogicalRouterAnswer; +import com.cloud.agent.api.CreateLogicalRouterCommand; import com.cloud.agent.api.CreateLogicalSwitchAnswer; import com.cloud.agent.api.CreateLogicalSwitchCommand; import com.cloud.agent.api.CreateLogicalSwitchPortAnswer; @@ -48,17 +50,28 @@ import com.cloud.agent.api.UpdateLogicalSwitchPortAnswer; import com.cloud.agent.api.UpdateLogicalSwitchPortCommand; import com.cloud.host.Host; import com.cloud.host.Host.Type; +import com.cloud.network.nicira.Attachment; import com.cloud.network.nicira.ControlClusterStatus; +import com.cloud.network.nicira.L3GatewayAttachment; +import com.cloud.network.nicira.LogicalRouterConfig; +import com.cloud.network.nicira.LogicalRouterPort; import com.cloud.network.nicira.LogicalSwitch; import com.cloud.network.nicira.LogicalSwitchPort; +import com.cloud.network.nicira.Match; import com.cloud.network.nicira.NiciraNvpApi; import com.cloud.network.nicira.NiciraNvpApiException; import com.cloud.network.nicira.NiciraNvpList; import com.cloud.network.nicira.NiciraNvpTag; +import com.cloud.network.nicira.PatchAttachment; +import com.cloud.network.nicira.RouterNextHop; +import com.cloud.network.nicira.SingleDefaultRouteImplictRoutingConfig; +import com.cloud.network.nicira.SourceNatRule; import com.cloud.network.nicira.TransportZoneBinding; import com.cloud.network.nicira.VifAttachment; import com.cloud.resource.ServerResource; +import edu.emory.mathcs.backport.java.util.Arrays; + public class NiciraNvpResource implements ServerResource { private static final Logger s_logger = Logger.getLogger(NiciraNvpResource.class); @@ -197,6 +210,9 @@ public class NiciraNvpResource implements ServerResource { else if (cmd instanceof FindLogicalSwitchPortCommand) { return executeRequest((FindLogicalSwitchPortCommand) cmd, numRetries); } + else if (cmd instanceof CreateLogicalRouterCommand) { + return executeRequest((CreateLogicalRouterCommand) cmd, 0); //TODO set to numRetries when done + } s_logger.debug("Received unsupported command " + cmd.toString()); return Answer.createUnsupportedCommandAnswer(cmd); } @@ -340,6 +356,99 @@ public class NiciraNvpResource implements ServerResource { } } + private Answer executeRequest(CreateLogicalRouterCommand cmd, int numRetries) { + String routerName = cmd.getName(); + String gatewayServiceUuid = cmd.getGatewayServiceUuid(); + String logicalSwitchUuid = cmd.getLogicalSwitchUuid(); + + List tags = new ArrayList(); + tags.add(new NiciraNvpTag("cs_account",cmd.getOwnerName())); + + String publicNetworkNextHopIp = cmd.getPublicNextHop(); + String publicNetworkIpAddress = cmd.getPublicIpCidr(); + String internalNetworkAddress = cmd.getInternalIpCidr(); + + s_logger.debug("Creating a logical router with external ip " + + publicNetworkIpAddress + " and internal ip " + internalNetworkAddress + + "on gateway service " + gatewayServiceUuid); + + try { + // Create the Router + LogicalRouterConfig lrc = new LogicalRouterConfig(); + lrc.setDisplayName(routerName); + lrc.setTags(tags); + lrc.setRoutingConfig(new SingleDefaultRouteImplictRoutingConfig( + new RouterNextHop(publicNetworkNextHopIp))); + lrc = _niciraNvpApi.createLogicalRouter(lrc); + + try { + // Create the outside port for the router + LogicalRouterPort lrpo = new LogicalRouterPort(); + lrpo.setAdminStatusEnabled(true); + lrpo.setDisplayName(routerName + "-port"); + lrpo.setTags(tags); + List outsideIpAddresses = new ArrayList(); + outsideIpAddresses.add(publicNetworkIpAddress); + lrpo.setIpAddresses(outsideIpAddresses); + lrpo = _niciraNvpApi.createLogicalRouterPort(lrc.getUuid(),lrpo); + + // Attach the outside port to the gateway service on the correct VLAN + L3GatewayAttachment attachment = new L3GatewayAttachment(gatewayServiceUuid); + if (cmd.getVlanId() != 0) { + attachment.setVlanId(cmd.getVlanId()); + } + _niciraNvpApi.modifyLogicalRouterPortAttachment(lrc.getUuid(), lrpo.getUuid(), attachment); + + // Create the inside port for the router + LogicalRouterPort lrpi = new LogicalRouterPort(); + lrpi.setAdminStatusEnabled(true); + lrpi.setDisplayName(routerName + "-port"); + lrpi.setTags(tags); + List insideIpAddresses = new ArrayList(); + insideIpAddresses.add(internalNetworkAddress); + lrpi.setIpAddresses(insideIpAddresses); + lrpi = _niciraNvpApi.createLogicalRouterPort(lrc.getUuid(),lrpi); + + // Create the inside port on the lswitch + LogicalSwitchPort lsp = new LogicalSwitchPort(routerName + "-port", tags, true); + lsp = _niciraNvpApi.createLogicalSwitchPort(logicalSwitchUuid, lsp); + + // Attach the inside router port to the lswitch port with a PatchAttachment + _niciraNvpApi.modifyLogicalRouterPortAttachment(lrc.getUuid(), lrpi.getUuid(), + new PatchAttachment(lsp.getUuid())); + + // Attach the inside lswitch port to the router with a PatchAttachment + _niciraNvpApi.modifyLogicalSwitchPortAttachment(logicalSwitchUuid, lsp.getUuid(), + new PatchAttachment(lrpi.getUuid())); + + // Setup the source nat rule + SourceNatRule snr = new SourceNatRule(); + snr.setToSourceIpAddressMin(publicNetworkIpAddress.split("/")[0]); + snr.setToSourceIpAddressMax(publicNetworkIpAddress.split("/")[0]); + Match match = new Match(); + match.setSourceIpAddresses(internalNetworkAddress); + snr.setMatch(match); + _niciraNvpApi.createLogicalRouterNatRule(lrc.getUuid(), snr); + } finally { + // We need to destroy the router if we already created it + // this will also take care of any router ports + // TODO Clean up the switchport + try { + _niciraNvpApi.deleteLogicalRouter(lrc.getUuid()); + } catch (NiciraNvpApiException e) {} + } + + return new CreateLogicalRouterAnswer(cmd, true, "Logical Router created (uuid " + lrc.getUuid() + ")", lrc.getUuid()); + } catch (NiciraNvpApiException e) { + if (numRetries > 0) { + return retry(cmd, --numRetries); + } + else { + return new CreateLogicalRouterAnswer(cmd, e); + } + } + } + private Answer executeRequest(ReadyCommand cmd) { return new ReadyAnswer(cmd); }