Wired up the creation of the SourceNat router in the element

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

Branch: refs/heads/nicira-l3support
Commit: fe997651a6da0d3883cf54b0c32bf5f975b3fce0
Parents: bfc8da1
Author: Hugo Trippaers <[email protected]>
Authored: Thu Sep 27 15:34:53 2012 -0700
Committer: Hugo Trippaers <[email protected]>
Committed: Thu Sep 27 15:34:53 2012 -0700

----------------------------------------------------------------------
 .../cloud/agent/api/CreateLogicalRouterAnswer.java |   40 ++++
 .../agent/api/CreateLogicalRouterCommand.java      |  115 +++++++++++
 .../cloud/api/commands/AddNiciraNvpDeviceCmd.java  |    2 +
 .../cloud/network/element/NiciraNvpElement.java    |  159 ++++++++++++++-
 .../cloud/network/nicira/L3GatewayAttachment.java  |   10 +-
 .../com/cloud/network/nicira/PatchAttachment.java  |   39 ++++
 .../com/cloud/network/nicira/RouterNextHop.java    |    4 +
 .../cloud/network/resource/NiciraNvpResource.java  |  109 ++++++++++
 8 files changed, 461 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterAnswer.java
----------------------------------------------------------------------
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 0000000..3337e92
--- /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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/agent/api/CreateLogicalRouterCommand.java
----------------------------------------------------------------------
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 0000000..57440df
--- /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;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/api/commands/AddNiciraNvpDeviceCmd.java
----------------------------------------------------------------------
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 6eac21f..28bc1fc 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 ///////////////////////
     /////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/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 1fcccdb..638ed8a 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<Service, Map<Capability, String>> 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<Service, Map<Capability, String>> 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<NiciraNvpDeviceVO> 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<Service> 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<Service, Map<Capability, String>> setCapabilities() {
         Map<Service, Map<Capability, String>> capabilities = new 
HashMap<Service, Map<Capability, String>>();
 
+        // Basic L2 SDN provisioning
         capabilities.put(Service.Connectivity, null);
+        
+        // L3 Support : SourceNat
+        capabilities.put(Service.Gateway, null);
+        Map<Capability, String> sourceNatCapabilities = new 
HashMap<Capability, String>();
+        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<? extends PublicIpAddress> ipAddress, Set<Service> 
services)
+                       throws ResourceUnavailableException {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/L3GatewayAttachment.java
----------------------------------------------------------------------
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 65a0a8e..8b807fd 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;
        }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/PatchAttachment.java
----------------------------------------------------------------------
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 0000000..e57c249
--- /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;
+       }
+       
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/RouterNextHop.java
----------------------------------------------------------------------
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 be302fa..c018af3 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;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/fe997651/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 31cac6f..4aa6ff1 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<NiciraNvpTag> tags = new ArrayList<NiciraNvpTag>();
+        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<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(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<String> insideIpAddresses = new 
ArrayList<String>();
+                       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);
     }

Reply via email to