Start implementing IpDeployer Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/de41cb7c Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/de41cb7c Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/de41cb7c
Branch: refs/heads/nicira-l3support Commit: de41cb7cb5ee0fb128c81fb5b00f3eb537e4eec2 Parents: dd68a00 Author: Hugo Trippaers <[email protected]> Authored: Fri Sep 28 11:32:53 2012 -0700 Committer: Hugo Trippaers <[email protected]> Committed: Fri Sep 28 11:32:53 2012 -0700 ---------------------------------------------------------------------- .../agent/api/AssignIpToLogicalRouterAnswer.java | 35 +++++ .../agent/api/AssignIpToLogicalRouterCommand.java | 98 +++++++++++++++ .../cloud/network/element/NiciraNvpElement.java | 46 +++++-- .../src/com/cloud/network/nicira/NiciraNvpApi.java | 24 ++++- .../com/cloud/network/nicira/NiciraNvpList.java | 10 +- .../cloud/network/resource/NiciraNvpResource.java | 76 +++++++++++- 6 files changed, 271 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterAnswer.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterAnswer.java b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterAnswer.java new file mode 100644 index 0000000..1eda213 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterAnswer.java @@ -0,0 +1,35 @@ +// 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; + +import com.cloud.agent.api.Command; + +/** + * + */ +public class AssignIpToLogicalRouterAnswer extends Answer { + + public AssignIpToLogicalRouterAnswer(Command command, boolean success, + String details) { + super(command, success, details); + } + + public AssignIpToLogicalRouterAnswer(Command command, Exception e) { + super(command, e); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterCommand.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterCommand.java b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterCommand.java new file mode 100644 index 0000000..98c36a8 --- /dev/null +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/AssignIpToLogicalRouterCommand.java @@ -0,0 +1,98 @@ +// 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; + +import com.cloud.network.IpAddress; + +/** + * + */ +public class AssignIpToLogicalRouterCommand extends Command { + private String logicalRouterUuid; + private String gatewayServiceUuid; + private String publicIpCidr; + private long publicIpVlan; + private boolean sourceNat; + private String internalNetworkCidr; + + public AssignIpToLogicalRouterCommand(String logicalRouterUuid, String gatewayServiceUuid, String publicIpCidr, long publicIpVlan, boolean sourceNat, String internetNetworkCidr) { + this.logicalRouterUuid = logicalRouterUuid; + this.gatewayServiceUuid = gatewayServiceUuid; + this.publicIpCidr = publicIpCidr; + this.sourceNat = sourceNat; + this.internalNetworkCidr = internetNetworkCidr; + this.publicIpVlan = publicIpVlan; + } + + public String getLogicalRouterUuid() { + return logicalRouterUuid; + } + + public void setLogicalRouterUuid(String logicalRouterUuid) { + this.logicalRouterUuid = logicalRouterUuid; + } + + public String getGatewayServiceUuid() { + return gatewayServiceUuid; + } + + public void setGatewayServiceUuid(String gatewayServiceUuid) { + this.gatewayServiceUuid = gatewayServiceUuid; + } + + public String getPublicIpCidr() { + return publicIpCidr; + } + + public void setPublicIpCidr(String publicIpCidr) { + this.publicIpCidr = publicIpCidr; + } + + public long getPublicIpVlan() { + return publicIpVlan; + } + + public void setPublicIpVlan(long publicIpVlan) { + this.publicIpVlan = publicIpVlan; + } + + public boolean isSourceNat() { + return sourceNat; + } + + public void setSourceNat(boolean sourceNat) { + this.sourceNat = sourceNat; + } + + public String getInternalNetworkCidr() { + return internalNetworkCidr; + } + + public void setInternalNetworkCidr(String internalNetworkCidr) { + this.internalNetworkCidr = internalNetworkCidr; + } + + /* (non-Javadoc) + * @see com.cloud.agent.api.Command#executeInSequence() + */ + @Override + public boolean executeInSequence() { + // TODO Auto-generated method stub + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java ---------------------------------------------------------------------- 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 9a220dc..7a0b268 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 @@ -256,6 +256,10 @@ public class NiciraNvpElement extends AdapterBase implements + network.getId()); } try { + // FIXME Check if any services other than connectiviy are required + // If that is the case start the logical router with only the + // internal interface, leave the external interfaces to the + // IpDeployer if (_networkManager.isProviderSupportServiceInNetwork( network.getId(), Service.SourceNat, Provider.NiciraNvp)) { s_logger.debug("Apparently we are supposed to provide SourceNat on this network"); @@ -457,9 +461,10 @@ public class NiciraNvpElement extends AdapterBase implements NiciraNvpRouterMappingVO routermapping = _niciraNvpRouterMappingDao .findByNetworkIdI(network.getId()); if (routermapping == null) { - s_logger.error("No logical router uuid found for network " + s_logger.warn("No logical router uuid found for network " + network.getDisplayText()); - return false; + // This might be cause by a failed deployment, so don't make shutdown fail as well. + return true; } DeleteLogicalRouterCommand cmd = new DeleteLogicalRouterCommand(routermapping.getLogicalRouterUuid()); @@ -470,6 +475,8 @@ public class NiciraNvpElement extends AdapterBase implements + network.getDisplayText()); return false; } + + _niciraNvpRouterMappingDao.remove(routermapping.getId()); } return true; @@ -507,11 +514,15 @@ public class NiciraNvpElement extends AdapterBase implements public boolean verifyServicesCombination(Set<Service> services) { // 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; + if (!services.contains(Service.Connectivity)) { + s_logger.warn("Unable to provide services without Connectivity service enabled for this element"); + return false; } - s_logger.debug("Unable to provide services without Connectivity service enabled for this element"); - return false; + if ((services.contains(Service.PortForwarding) || services.contains(Service.StaticNat)) && !services.contains(Service.PortForwarding)) { + s_logger.warn("Unable to provider StaticNat and/or PortForwarding without the SourceNat service"); + return false; + } + return true; } private static Map<Service, Map<Capability, String>> setCapabilities() { @@ -808,8 +819,14 @@ public class NiciraNvpElement extends AdapterBase implements List<? extends PublicIpAddress> ipAddress, Set<Service> services) throws ResourceUnavailableException { s_logger.debug("Entering applyIps"); // TODO Remove this line - // TODO Auto-generated method stub - return false; + + // The Nicira Nvp L3 Gateway doesn't need the addresses configured on + // the router interface. Only configure the CIDR and individual ip + // addresses become available when DNAT rules are created for them. + // The cidr setup is done during implementation of the logical router + // in the function implement + + return true; } /** @@ -819,9 +836,12 @@ public class NiciraNvpElement extends AdapterBase implements public boolean applyStaticNats(Network config, List<? extends StaticNat> rules) throws ResourceUnavailableException { + // FIXME Implement this s_logger.debug("Entering applyStaticNats"); // TODO Remove this line - // TODO Auto-generated method stub - return false; + for (StaticNat rule : rules) { + s_logger.debug ("StaticNat rule : from " + rule.getSourceIpAddressId() + " to " + rule.getDestIpAddress() + (rule.isForRevoke() ? " for revoke" : "")); + } + return true; } /** @@ -830,8 +850,12 @@ public class NiciraNvpElement extends AdapterBase implements @Override public boolean applyPFRules(Network network, List<PortForwardingRule> rules) throws ResourceUnavailableException { + // FIXME Implement this s_logger.debug("Entering applyPFRules"); // TODO Remove this line - // TODO Auto-generated method stub + for (PortForwardingRule rule : rules) { + s_logger.debug ("PortForwardingRule rule : from " + rule.getSourceIpAddressId() + + " to " + rule.getDestinationIpAddress().addr() + " port " + rule.getDestinationPortStart() + "-" + rule.getDestinationPortEnd()); + } return false; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java index 1c7b741..a04dd1e 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java @@ -181,7 +181,7 @@ public class NiciraNvpApi { NiciraNvpList<LogicalSwitchPort> lspl = executeRetrieveObject(new TypeToken<NiciraNvpList<LogicalSwitchPort>>(){}.getType(), uri, params); - if (lspl == null || lspl.getResult_count() != 1) { + if (lspl == null || lspl.getResultCount() != 1) { throw new NiciraNvpApiException("Unexpected response from API"); } @@ -262,6 +262,28 @@ public class NiciraNvpApi { executeDeleteObject(uri); } + public NiciraNvpList<LogicalRouterPort> findLogicalRouterPortByGatewayServiceAndVlanId(String logicalRouterUuid, String gatewayServiceUuid, long vlanId) throws NiciraNvpApiException { + String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/lport"; + Map<String,String> params = new HashMap<String,String>(); + params.put("attachment_gwsvc_uuid", gatewayServiceUuid); + params.put("attachment_vlan", "0"); + params.put("fields","*"); + + return executeRetrieveObject(new TypeToken<NiciraNvpList<LogicalRouterPort>>(){}.getType(), uri, params); + } + + public LogicalRouterConfig findOneLogicalRouterByUuid(String logicalRouterUuid) throws NiciraNvpApiException { + String uri = "/ws.v1/lrouter/" + logicalRouterUuid; + + return executeRetrieveObject(new TypeToken<LogicalRouterConfig>(){}.getType(), uri, Collections.<String,String>emptyMap()); + } + + public void updateLogicalRouterPortConfig(String logicalRouterUuid, LogicalRouterPort logicalRouterPort) throws NiciraNvpApiException { + String uri = "/ws.v1/lrouter/" + logicalRouterUuid + "/lport" + logicalRouterPort.getUuid(); + + executeUpdateObject(logicalRouterPort, uri, Collections.<String,String>emptyMap()); + } + private <T> void executeUpdateObject(T newObject, String uri, Map<String,String> parameters) throws NiciraNvpApiException { String url; try { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java index 13d352d..c97e40e 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java @@ -30,12 +30,16 @@ public class NiciraNvpList<T> { this.results = results; } - public int getResult_count() { + public int getResultCount() { return result_count; } - public void setResult_count(int result_count) { + public void setResultCount(int result_count) { this.result_count = result_count; - } + } + + public boolean isEmpty() { + return result_count == 0; + } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/de41cb7c/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java ---------------------------------------------------------------------- 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 817c630..96ed856 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 @@ -26,6 +26,8 @@ import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AssignIpToLogicalRouterAnswer; +import com.cloud.agent.api.AssignIpToLogicalRouterCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateLogicalRouterAnswer; import com.cloud.agent.api.CreateLogicalRouterCommand; @@ -218,6 +220,9 @@ public class NiciraNvpResource implements ServerResource { else if (cmd instanceof DeleteLogicalRouterCommand) { return executeRequest((DeleteLogicalRouterCommand) cmd, numRetries); } + else if (cmd instanceof AssignIpToLogicalRouterCommand) { + return executeRequest((AssignIpToLogicalRouterCommand) cmd, numRetries); + } s_logger.debug("Received unsupported command " + cmd.toString()); return Answer.createUnsupportedCommandAnswer(cmd); } @@ -345,7 +350,7 @@ public class NiciraNvpResource implements ServerResource { try { NiciraNvpList<LogicalSwitchPort> ports = _niciraNvpApi.findLogicalSwitchPortsByUuid(logicalSwitchUuid, logicalSwitchPortUuid); - if (ports.getResult_count() == 0) { + if (ports.getResultCount() == 0) { return new FindLogicalSwitchPortAnswer(cmd, false, "Logical switchport " + logicalSwitchPortUuid + " not found", null); } else { @@ -434,13 +439,15 @@ public class NiciraNvpResource implements ServerResource { match.setSourceIpAddresses(internalNetworkAddress); snr.setMatch(match); _niciraNvpApi.createLogicalRouterNatRule(lrc.getUuid(), snr); - } finally { + } catch (NiciraNvpApiException e) { // 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) {} + } catch (NiciraNvpApiException ex) {} + + throw e; } return new CreateLogicalRouterAnswer(cmd, true, "Logical Router created (uuid " + lrc.getUuid() + ")", lrc.getUuid()); @@ -468,6 +475,69 @@ public class NiciraNvpResource implements ServerResource { } } + private Answer executeRequest(AssignIpToLogicalRouterCommand cmd, int numRetries) { + try { + LogicalRouterConfig lrc = _niciraNvpApi.findOneLogicalRouterByUuid(cmd.getLogicalRouterUuid()); + + NiciraNvpList<LogicalRouterPort> ports = + _niciraNvpApi.findLogicalRouterPortByGatewayServiceAndVlanId(cmd.getLogicalRouterUuid(), + cmd.getGatewayServiceUuid(), cmd.getPublicIpVlan()); + + String publicNetworkIpAddress = cmd.getPublicIpCidr(); + + if (ports.isEmpty()) { + // No attachment on this network, we need to create one + // Create the outside port for the router + LogicalRouterPort lrpo = new LogicalRouterPort(); + lrpo.setAdminStatusEnabled(true); + lrpo.setDisplayName(lrc.getDisplayName() + "-outside-port"); + lrpo.setTags(lrc.getTags()); + List<String> outsideIpAddresses = new ArrayList<String>(); + 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(cmd.getGatewayServiceUuid()); + if (cmd.getPublicIpVlan() != 0) { + attachment.setVlanId(cmd.getPublicIpVlan()); + } + _niciraNvpApi.modifyLogicalRouterPortAttachment(lrc.getUuid(), lrpo.getUuid(), attachment); + return new AssignIpToLogicalRouterAnswer(cmd, true, "Ip address configured on new logical router port"); + } + else { + // There is already and attachment to this public network, see if we need to add this IP + boolean found = false; + LogicalRouterPort publicPort = null; + for (LogicalRouterPort port : ports.getResults()) { + for (String cidr : port.getIpAddresses()) { + if (publicNetworkIpAddress.equals(cidr)) { + found = true; + publicPort = port; + break; + } + } + } + if (found) { + s_logger.warn("Ip " + publicNetworkIpAddress + " is already configured on logical router " + cmd.getLogicalRouterUuid()); + return new AssignIpToLogicalRouterAnswer(cmd, true, "Ip address already alocated on logical Router"); + } + + publicPort.getIpAddresses().add(publicNetworkIpAddress); + _niciraNvpApi.updateLogicalRouterPortConfig(cmd.getLogicalRouterUuid(), publicPort); + return new AssignIpToLogicalRouterAnswer(cmd, true, "Ip address configured on existing logical router port"); + } + } catch (NiciraNvpApiException e) { + if (numRetries > 0) { + return retry(cmd, --numRetries); + } + else { + return new DeleteLogicalRouterAnswer(cmd, e); + } + } + + } + private Answer executeRequest(ReadyCommand cmd) { return new ReadyAnswer(cmd); }
