You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/07/13 22:52:12 UTC

[7/11] Phase 1 of Nicira integration

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/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
new file mode 100644
index 0000000..ba4b961
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java
@@ -0,0 +1,502 @@
+/** 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.element;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.CreateLogicalSwitchPortAnswer;
+import com.cloud.agent.api.CreateLogicalSwitchPortCommand;
+import com.cloud.agent.api.DeleteLogicalSwitchPortAnswer;
+import com.cloud.agent.api.DeleteLogicalSwitchPortCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupNiciraNvpCommand;
+import com.cloud.api.commands.AddNiciraNvpDeviceCmd;
+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.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.DetailVO;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.Network;
+import com.cloud.network.ExternalNetworkDeviceManager.NetworkDevice;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+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.NiciraNvpDeviceVO;
+import com.cloud.network.NiciraNvpNicMappingVO;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NiciraNvpDao;
+import com.cloud.network.dao.NiciraNvpNicMappingDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.network.guru.NiciraNvpGuestNetworkGuru;
+import com.cloud.network.resource.NiciraNvpResource;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+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.vm.NicProfile;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.NicDao;
+
+@Local(value = NetworkElement.class)
+public class NiciraNvpElement extends AdapterBase implements NetworkElement, NiciraNvpElementService, ResourceStateAdapter {
+    private static final Logger s_logger = Logger.getLogger(NiciraNvpElement.class);
+    
+    private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
+    
+
+    @Inject 
+    NicDao _nicDao;
+    @Inject 
+    ResourceManager _resourceMgr;    
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
+    @Inject
+    NiciraNvpDao _niciraNvpDao;
+    @Inject 
+    HostDetailsDao _hostDetailsDao;
+    @Inject
+    HostDao _hostDao;  
+    @Inject
+    AgentManager _agentMgr;
+    @Inject
+    NiciraNvpNicMappingDao _niciraNvpNicMappingDao;
+    @Inject
+    NetworkDao _networkDao;
+    
+    @Override
+    public Map<Service, Map<Capability, String>> getCapabilities() {
+        return capabilities;
+    }
+
+    @Override
+    public Provider getProvider() {
+        return Provider.NiciraNvp;
+    }
+    
+    private boolean canHandle(Network network) {
+        if (network.getBroadcastDomainType() != BroadcastDomainType.Lswitch) {
+            return false;
+        }
+        
+        return true;        
+    }
+    
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        super.configure(name, params);
+        _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+        return true;
+    }
+
+    @Override
+    public boolean implement(Network network, NetworkOffering offering,
+            DeployDestination dest, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException,
+            InsufficientCapacityException {
+        
+        if (!canHandle(network)) {
+            return false;
+        }
+        
+        return true;
+    }
+
+    @Override
+    public boolean prepare(Network network, NicProfile nic,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            DeployDestination dest, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException,
+            InsufficientCapacityException {
+        
+        if (!canHandle(network)) {
+            return false;
+        }
+
+        if (network.getBroadcastUri() == null) {
+            s_logger.error("Nic has no broadcast Uri with the LSwitch Uuid");
+            return false;
+        }
+
+        NicVO nicVO = _nicDao.findById(nic.getId());
+
+        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());
+        
+        CreateLogicalSwitchPortCommand cmd = new CreateLogicalSwitchPortCommand(network.getBroadcastUri().getSchemeSpecificPart(), nicVO.getUuid(), 
+                context.getDomain().getName() + "-" + context.getAccount().getAccountName(), nic.getName());
+        CreateLogicalSwitchPortAnswer answer = (CreateLogicalSwitchPortAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd);
+        
+        if (answer == null || !answer.getResult()) {
+            s_logger.error ("CreateLogicalSwitchPortCommand failed");
+            return false;
+        }
+        
+        NiciraNvpNicMappingVO nicMap = new NiciraNvpNicMappingVO(network.getBroadcastUri().getSchemeSpecificPart(), answer.getLogicalSwitchPortUuid(), nicVO.getUuid());
+        _niciraNvpNicMappingDao.persist(nicMap);
+
+        return true;
+    }
+
+    @Override
+    public boolean release(Network network, NicProfile nic,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            ReservationContext context) throws ConcurrentOperationException,
+            ResourceUnavailableException {
+
+        if (!canHandle(network)) {
+            return false;
+        }
+
+        if (network.getBroadcastUri() == null) {
+            s_logger.error("Nic has no broadcast Uri with the LSwitch Uuid");
+            return false;
+        }
+        
+        NicVO nicVO = _nicDao.findById(nic.getId());
+
+        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());
+        
+        NiciraNvpNicMappingVO nicMap = _niciraNvpNicMappingDao.findByNicUuid(nicVO.getUuid());
+        if (nicMap == null) {
+            s_logger.error("No mapping for nic " + nic.getName());
+            return false;
+        }
+        
+        DeleteLogicalSwitchPortCommand cmd = new DeleteLogicalSwitchPortCommand(nicMap.getLogicalSwitchUuid(), nicMap.getLogicalSwitchPortUuid());
+        DeleteLogicalSwitchPortAnswer answer = (DeleteLogicalSwitchPortAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd);
+        
+        if (answer == null || !answer.getResult()) {
+            s_logger.error ("DeleteLogicalSwitchPortCommand failed");
+            return false;
+        }
+        
+        _niciraNvpNicMappingDao.remove(nicMap.getId());
+        
+        return true;
+    }
+
+    @Override
+    public boolean shutdown(Network network, ReservationContext context,
+            boolean cleanup) throws ConcurrentOperationException,
+            ResourceUnavailableException {
+        if (!canHandle(network)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean destroy(Network network)
+            throws ConcurrentOperationException, ResourceUnavailableException {
+        if (!canHandle(network)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean isReady(PhysicalNetworkServiceProvider provider) {
+        return true;
+    }
+
+    @Override
+    public boolean shutdownProviderInstances(
+            PhysicalNetworkServiceProvider provider, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException {
+        // Nothing to do here.
+        return true;
+    }
+
+    @Override
+    public boolean canEnableIndividualServices() {
+        return false;
+    }
+
+    @Override
+    public boolean verifyServicesCombination(List<String> services) {
+        return true;
+    }
+
+    private static Map<Service, Map<Capability, String>> setCapabilities() {
+        Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
+
+        capabilities.put(Service.Connectivity, null);
+        return capabilities;
+    }
+
+    @Override
+    public String getPropertiesFile() {
+        return "nicira-nvp_commands.properties";
+    }
+
+    @Override
+    @DB
+    public NiciraNvpDeviceVO addNiciraNvpDevice(AddNiciraNvpDeviceCmd cmd) {
+        ServerResource resource = new NiciraNvpResource();
+        String deviceName = Network.Provider.NiciraNvp.getName();
+        NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        NiciraNvpDeviceVO niciraNvpDevice = null;
+        
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork == null) {
+            throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
+        }
+        long zoneId = physicalNetwork.getDataCenterId();
+
+        PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(), networkDevice.getNetworkServiceProvder());
+        if (ntwkSvcProvider == null) {
+            throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() +
+                    " is not enabled in the physical network: " + physicalNetworkId + "to add this device");
+        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
+                    " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device");
+        }
+        
+        if (_niciraNvpDao.listByPhysicalNetwork(physicalNetworkId).size() != 0) {
+            throw new CloudRuntimeException("A NiciraNvp device is already configured on this physical network");
+        }
+        
+        Map<String, String> params = new HashMap<String,String>();
+        params.put("guid", UUID.randomUUID().toString());
+        params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
+        params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
+        params.put("name", "Nicira Controller - " + cmd.getHost());
+        params.put("ip", cmd.getHost());
+        params.put("adminuser", cmd.getUsername());
+        params.put("adminpass", cmd.getPassword());
+        params.put("transportzoneuuid", cmd.getTransportzoneUuid());
+        params.put("transportzoneisotype", physicalNetwork.getIsolationMethods().get(0).toLowerCase()); // FIXME What to do with multiple isolation types
+
+        Map<String, Object> hostdetails = new HashMap<String,Object>();
+        hostdetails.putAll(params);
+        
+        
+        Transaction txn = Transaction.currentTxn();
+        try {
+            resource.configure(cmd.getHost(), hostdetails);
+            
+            Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.L2Networking, params);
+            if (host != null) {
+                txn.start();
+                
+                niciraNvpDevice = new NiciraNvpDeviceVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName);
+                _niciraNvpDao.persist(niciraNvpDevice);
+                
+                DetailVO detail = new DetailVO(host.getId(), "niciranvpdeviceid", String.valueOf(niciraNvpDevice.getId()));
+                _hostDetailsDao.persist(detail);
+
+                txn.commit();
+                return niciraNvpDevice;
+            } else {
+                throw new CloudRuntimeException("Failed to add Nicira Nvp Device due to internal error.");
+            }            
+        } catch (ConfigurationException e) {
+            txn.rollback();
+            throw new CloudRuntimeException(e.getMessage());
+        }
+    }
+
+    @Override
+    public NiciraNvpDeviceResponse createNiciraNvpDeviceResponse(
+            NiciraNvpDeviceVO niciraNvpDeviceVO) {
+        NiciraNvpDeviceResponse response = new NiciraNvpDeviceResponse();
+        response.setDeviceName(niciraNvpDeviceVO.getDeviceName());
+        response.setPhysicalNetworkId(niciraNvpDeviceVO.getPhysicalNetworkId());
+        response.setId(niciraNvpDeviceVO.getId());
+        response.setProviderName(niciraNvpDeviceVO.getProviderName());
+        return response;
+    }
+    
+    @Override
+    public boolean deleteNiciraNvpDevice(DeleteNiciraNvpDeviceCmd cmd) {
+        Long niciraDeviceId = cmd.getNiciraNvpDeviceId();
+        NiciraNvpDeviceVO niciraNvpDevice = _niciraNvpDao.findById(niciraDeviceId);
+        if (niciraNvpDevice == null) {
+            throw new InvalidParameterValueException("Could not find a nicira device with id " + niciraDeviceId);
+        }        
+        
+        // Find the physical network we work for
+        Long physicalNetworkId = niciraNvpDevice.getPhysicalNetworkId();
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork != null) {
+            // Lets see if there are networks that use us
+            // Find the nicira networks on this physical network
+            List<NetworkVO> networkList = _networkDao.listByPhysicalNetwork(physicalNetworkId);
+            
+            // Networks with broadcast type lswitch are ours
+            for (NetworkVO network : networkList) {
+                if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Lswitch) {
+                    if ((network.getState() != Network.State.Shutdown) && (network.getState() != Network.State.Destroy)) {
+                        throw new CloudRuntimeException("This Nicira Nvp device can not be deleted as there are one or more logical networks provisioned by cloudstack.");
+                    }
+                }
+            }
+        }
+        
+        HostVO niciraHost = _hostDao.findById(niciraNvpDevice.getHostId());
+        Long hostId = niciraHost.getId();
+        
+        niciraHost.setResourceState(ResourceState.Maintenance);
+        _hostDao.update(hostId, niciraHost);
+        _resourceMgr.deleteHost(hostId, false, false);
+    
+        _niciraNvpDao.remove(niciraDeviceId);
+        
+        return true;
+    }
+    
+    @Override
+    public List<NiciraNvpDeviceVO> listNiciraNvpDevices(ListNiciraNvpDevicesCmd cmd) {
+        Long physicalNetworkId = cmd.getPhysicalNetworkId();
+        Long niciraNvpDeviceId = cmd.getNiciraNvpDeviceId();
+        List<NiciraNvpDeviceVO> responseList = new ArrayList<NiciraNvpDeviceVO>();
+        
+        if (physicalNetworkId == null && niciraNvpDeviceId == null) {
+            throw new InvalidParameterValueException("Either physical network Id or nicira device Id must be specified");
+        }
+        
+        if (niciraNvpDeviceId != null) {
+            NiciraNvpDeviceVO niciraNvpDevice = _niciraNvpDao.findById(niciraNvpDeviceId);
+            if (niciraNvpDevice == null) {
+                throw new InvalidParameterValueException("Could not find Nicira Nvp device with id: " + niciraNvpDevice);
+            }
+            responseList.add(niciraNvpDevice);
+        }
+        else {
+            PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+            if (physicalNetwork == null) {
+                throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId);
+            }
+            responseList = _niciraNvpDao.listByPhysicalNetwork(physicalNetworkId);
+        }
+        
+        return responseList;
+    }
+    
+    @Override    
+    public List<? extends Network> listNiciraNvpDeviceNetworks(ListNiciraNvpDeviceNetworksCmd cmd) {
+        Long niciraDeviceId = cmd.getNiciraNvpDeviceId();
+        NiciraNvpDeviceVO niciraNvpDevice = _niciraNvpDao.findById(niciraDeviceId);
+        if (niciraNvpDevice == null) {
+            throw new InvalidParameterValueException("Could not find a nicira device with id " + niciraDeviceId);
+        }        
+        
+        // Find the physical network we work for
+        Long physicalNetworkId = niciraNvpDevice.getPhysicalNetworkId();
+        PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
+        if (physicalNetwork == null) {
+            // No such physical network, so no provisioned networks
+            return Collections.emptyList();
+        }
+        
+        // Find the nicira networks on this physical network
+        List<NetworkVO> networkList = _networkDao.listByPhysicalNetwork(physicalNetworkId);
+        
+        // Networks with broadcast type lswitch are ours
+        List<NetworkVO> responseList  = new ArrayList<NetworkVO>();
+        for (NetworkVO network : networkList) {
+            if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Lswitch) {
+                responseList.add(network);
+            }
+        }
+        
+        return responseList;
+    }
+    
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host,
+            StartupCommand[] cmd) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host,
+            StartupCommand[] startup, ServerResource resource,
+            Map<String, String> details, List<String> hostTags) {
+        if (!(startup[0] instanceof StartupNiciraNvpCommand)) {
+            return null;
+        }
+        host.setType(Host.Type.L2Networking);
+        return host;
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced,
+            boolean isForceDeleteStorage) throws UnableDeleteHostException {
+        if (!(host.getType() == Host.Type.L2Networking)) {
+            return null;
+        }
+        return new DeleteHostAnswer(true);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElementService.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElementService.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElementService.java
new file mode 100644
index 0000000..0f503e7
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElementService.java
@@ -0,0 +1,28 @@
+package com.cloud.network.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddNiciraNvpDeviceCmd;
+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.network.Network;
+import com.cloud.network.NiciraNvpDeviceVO;
+import com.cloud.utils.component.PluggableService;
+
+public interface NiciraNvpElementService extends PluggableService {
+
+    public NiciraNvpDeviceVO addNiciraNvpDevice(AddNiciraNvpDeviceCmd cmd);
+
+    public NiciraNvpDeviceResponse createNiciraNvpDeviceResponse(
+            NiciraNvpDeviceVO niciraDeviceVO);
+
+    boolean deleteNiciraNvpDevice(DeleteNiciraNvpDeviceCmd cmd);
+
+    List<? extends Network> listNiciraNvpDeviceNetworks(
+            ListNiciraNvpDeviceNetworksCmd cmd);
+
+    List<NiciraNvpDeviceVO> listNiciraNvpDevices(ListNiciraNvpDevicesCmd cmd);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
new file mode 100644
index 0000000..3bac88b
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java
@@ -0,0 +1,257 @@
+/** 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.guru;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.CreateLogicalSwitchAnswer;
+import com.cloud.agent.api.CreateLogicalSwitchCommand;
+import com.cloud.agent.api.DeleteLogicalSwitchAnswer;
+import com.cloud.agent.api.DeleteLogicalSwitchCommand;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.NetworkProfile;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.State;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.NiciraNvpDeviceVO;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NiciraNvpDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.user.Account;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.component.Inject;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value=NetworkGuru.class)
+public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru {
+    private static final Logger s_logger = Logger.getLogger(NiciraNvpGuestNetworkGuru.class);
+    
+    @Inject 
+    NetworkManager _externalNetworkManager;
+    @Inject
+    NetworkManager _networkMgr;
+    @Inject
+    NetworkDao _networkDao;
+    @Inject
+    DataCenterDao _zoneDao;
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    AccountDao _accountDao;
+    @Inject
+    NiciraNvpDao _niciraNvpDao;
+    @Inject
+    HostDao _hostDao;
+    @Inject
+    ResourceManager _resourceMgr;    
+    @Inject
+    AgentManager _agentMgr;
+    @Inject
+    HostDetailsDao _hostDetailsDao;
+    
+    public NiciraNvpGuestNetworkGuru() {
+        super();
+        _isolationMethods = new IsolationMethod[] { IsolationMethod.STT };
+    }
+
+    @Override
+    protected boolean canHandle(NetworkOffering offering, final NetworkType networkType, final PhysicalNetwork physicalNetwork) {
+        // This guru handles only Guest Isolated network that supports Source nat service
+        if (networkType == NetworkType.Advanced 
+                && isMyTrafficType(offering.getTrafficType()) 
+                && offering.getGuestType() == Network.GuestType.Isolated
+                && isMyIsolationMethod(physicalNetwork)) {
+            return true;
+        } else {
+            s_logger.trace("We only take care of Guest networks of type   " + GuestType.Isolated + " in zone of type " + NetworkType.Advanced);
+            return false;
+        }
+    }
+    
+    @Override
+    public Network design(NetworkOffering offering, DeploymentPlan plan,
+            Network userSpecified, Account owner) {
+        // Check of the isolation type of the related physical network is STT
+        PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
+        if (physnet == null || physnet.getIsolationMethods() == null || !physnet.getIsolationMethods().contains("STT")) {
+            s_logger.debug("Refusing to design this network, the physical isolation type is not STT");
+            return null;
+        }
+
+        List<NiciraNvpDeviceVO> devices = _niciraNvpDao.listByPhysicalNetwork(physnet.getId());
+        if (devices.isEmpty()) {
+            s_logger.error("No NiciraNvp Controller on physical network " + physnet.getName());
+            return null;
+        }
+        s_logger.debug("Nicira Nvp " + devices.get(0).getUuid() + " found on physical network " + physnet.getId());
+
+        s_logger.debug("Physical isolation type is STT, asking GuestNetworkGuru to design this network");        
+        NetworkVO networkObject = (NetworkVO) super.design(offering, plan, userSpecified, owner);
+        if (networkObject == null) {
+            return null;
+        }
+        // Override the broadcast domain type
+        networkObject.setBroadcastDomainType(BroadcastDomainType.Lswitch);
+        
+        return networkObject;
+    }
+
+    @Override
+    public Network implement(Network network, NetworkOffering offering,
+            DeployDestination dest, ReservationContext context)
+            throws InsufficientVirtualNetworkCapcityException {
+        assert (network.getState() == State.Implementing) : "Why are we implementing " + network;
+
+        long dcId = dest.getDataCenter().getId();
+
+        //get physical network id
+        long physicalNetworkId = _networkMgr.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType());
+
+        NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated,
+                network.getDataCenterId(), physicalNetworkId);
+
+        if (network.getGateway() != null) {
+            implemented.setGateway(network.getGateway());
+        }
+
+        if (network.getCidr() != null) {
+            implemented.setCidr(network.getCidr());
+        }
+        
+        // Name is either the given name or the uuid
+        String name = implemented.getName();
+        if (name == null || name.isEmpty()) {
+            name = implemented.getUuid();
+        }
+        if (name.length() > 40 ) {
+            name = name.substring(0, 39); // max length 40
+        }
+        
+        List<NiciraNvpDeviceVO> devices = _niciraNvpDao.listByPhysicalNetwork(physicalNetworkId);
+        if (devices.isEmpty()) {
+            s_logger.error("No NiciraNvp Controller on physical network " + physicalNetworkId);
+            return null;
+        }
+        NiciraNvpDeviceVO niciraNvpDevice = devices.get(0);
+        HostVO niciraNvpHost = _hostDao.findById(niciraNvpDevice.getHostId());
+        _hostDao.loadDetails(niciraNvpHost);
+        String transportzoneuuid = niciraNvpHost.getDetail("transportzoneuuid");
+        String transportzoneisotype = niciraNvpHost.getDetail("transportzoneisotype");
+        
+        CreateLogicalSwitchCommand cmd = new CreateLogicalSwitchCommand(transportzoneuuid, transportzoneisotype, network.getName(), 
+                context.getDomain().getName() + "-" + context.getAccount().getAccountName());
+        CreateLogicalSwitchAnswer answer = (CreateLogicalSwitchAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd);
+        
+        if (answer == null || !answer.getResult()) {
+            s_logger.error ("CreateLogicalSwitchCommand failed");
+            return null;
+        }
+        
+        try {
+            implemented.setBroadcastUri(new URI("lswitch", answer.getLogicalSwitchUuid(), null));
+            implemented.setBroadcastDomainType(BroadcastDomainType.Lswitch);
+            s_logger.info("Implemented OK, network linked to  = " + implemented.getBroadcastUri().toString());
+        } catch (URISyntaxException e) {
+            s_logger.error("Unable to store logical switch id in broadcast uri, uuid = " + implemented.getUuid(), e);
+        }
+        
+        return implemented;
+    }
+
+    @Override
+    public void reserve(NicProfile nic, Network network,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            DeployDestination dest, ReservationContext context)
+            throws InsufficientVirtualNetworkCapcityException,
+            InsufficientAddressCapacityException {
+        // TODO Auto-generated method stub
+        super.reserve(nic, network, vm, dest, context);
+    }
+
+    @Override
+    public boolean release(NicProfile nic,
+            VirtualMachineProfile<? extends VirtualMachine> vm,
+            String reservationId) {
+        // TODO Auto-generated method stub
+        return super.release(nic, vm, reservationId);
+    }
+
+    @Override
+    public void shutdown(NetworkProfile profile, NetworkOffering offering) {    
+        NetworkVO networkObject = _networkDao.findById(profile.getId());
+        if (networkObject.getBroadcastDomainType() != BroadcastDomainType.Lswitch ||
+                networkObject.getBroadcastUri() == null) {
+            s_logger.warn("BroadcastUri is empty or incorrect for guestnetwork " + networkObject.getDisplayText());
+            return;
+        }
+        
+        List<NiciraNvpDeviceVO> devices = _niciraNvpDao.listByPhysicalNetwork(networkObject.getPhysicalNetworkId());
+        if (devices.isEmpty()) {
+            s_logger.error("No NiciraNvp Controller on physical network " + networkObject.getPhysicalNetworkId());
+            return;
+        }
+        NiciraNvpDeviceVO niciraNvpDevice = devices.get(0);
+        HostVO niciraNvpHost = _hostDao.findById(niciraNvpDevice.getHostId());
+        
+        DeleteLogicalSwitchCommand cmd = new DeleteLogicalSwitchCommand(networkObject.getBroadcastUri().getSchemeSpecificPart());
+        DeleteLogicalSwitchAnswer answer = (DeleteLogicalSwitchAnswer) _agentMgr.easySend(niciraNvpHost.getId(), cmd);
+        
+        if (answer == null || !answer.getResult()) {
+            s_logger.error ("DeleteLogicalSwitchCommand failed");
+        }
+
+        super.shutdown(profile, offering);
+    }
+
+    @Override
+    public boolean trash(Network network, NetworkOffering offering,
+            Account owner) {
+        return super.trash(network, offering, owner);
+    }
+    
+    
+    
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Attachment.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Attachment.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Attachment.java
new file mode 100644
index 0000000..f70d0a1
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/Attachment.java
@@ -0,0 +1,22 @@
+/** 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 abstract class Attachment {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitch.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitch.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitch.java
new file mode 100644
index 0000000..5502442
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitch.java
@@ -0,0 +1,99 @@
+/** 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;
+
+import java.util.List;
+
+public class LogicalSwitch {
+    private String display_name;
+    private boolean port_isolation_enabled;
+    private List<NiciraNvpTag> tags;
+    private List<TransportZoneBinding> transport_zones;
+    private String type;
+    private String uuid;
+    private String _href;
+    //private RequestQueryParameters _query;
+    //private LogicalSwitchRelations _relations;
+    private String _schema;
+    
+    public String getDisplay_name() {
+        return display_name;
+    }
+    
+    public void setDisplay_name(String display_name) {
+        this.display_name = display_name;
+    }
+    
+    public boolean isPort_isolation_enabled() {
+        return port_isolation_enabled;
+    }
+    
+    public void setPort_isolation_enabled(boolean port_isolation_enabled) {
+        this.port_isolation_enabled = port_isolation_enabled;
+    }
+    
+    public String getType() {
+        return type;
+    }
+    
+    public void setType(String type) {
+        this.type = type;
+    }
+    
+    public String getUuid() {
+        return uuid;
+    }
+    
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+    
+    public String get_href() {
+        return _href;
+    }
+    
+    public void set_href(String _href) {
+        this._href = _href;
+    }
+    
+    public String get_schema() {
+        return _schema;
+    }
+    
+    public void set_schema(String _schema) {
+        this._schema = _schema;
+    }
+
+    public List<NiciraNvpTag> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<NiciraNvpTag> tags) {
+        this.tags = tags;
+    }
+
+    public List<TransportZoneBinding> getTransport_zones() {
+        return transport_zones;
+    }
+
+    public void setTransport_zones(List<TransportZoneBinding> transport_zones) {
+        this.transport_zones = transport_zones;
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitchPort.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitchPort.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitchPort.java
new file mode 100644
index 0000000..e74fda2
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/LogicalSwitchPort.java
@@ -0,0 +1,118 @@
+/** 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;
+
+import java.util.List;
+
+public class LogicalSwitchPort {
+    private String display_name;
+    private List<NiciraNvpTag> tags;
+    private Integer portno;
+    private boolean admin_status_enabled;
+    //private List<AddressPairs> allowed_address_pairs;
+    private String queue_uuid;
+    private List<String> security_profiles;
+    private List<String> mirror_targets;
+    private String type;
+    private String uuid;
+    
+    public LogicalSwitchPort() {
+        super();
+    }
+
+    public LogicalSwitchPort(String display_name, List<NiciraNvpTag> tags,
+            boolean admin_status_enabled) {
+        super();
+        this.display_name = display_name;
+        this.tags = tags;
+        this.admin_status_enabled = admin_status_enabled;
+    }
+
+    public String getDisplay_name() {
+        return display_name;
+    }
+
+    public void setDisplay_name(String display_name) {
+        this.display_name = display_name;
+    }
+
+    public List<NiciraNvpTag> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<NiciraNvpTag> tags) {
+        this.tags = tags;
+    }
+
+    public Integer getPortno() {
+        return portno;
+    }
+
+    public void setPortno(Integer portno) {
+        this.portno = portno;
+    }
+
+    public boolean isAdmin_status_enabled() {
+        return admin_status_enabled;
+    }
+
+    public void setAdmin_status_enabled(boolean admin_status_enabled) {
+        this.admin_status_enabled = admin_status_enabled;
+    }
+
+    public String getQueue_uuid() {
+        return queue_uuid;
+    }
+
+    public void setQueue_uuid(String queue_uuid) {
+        this.queue_uuid = queue_uuid;
+    }
+
+    public List<String> getSecurity_profiles() {
+        return security_profiles;
+    }
+
+    public void setSecurity_profiles(List<String> security_profiles) {
+        this.security_profiles = security_profiles;
+    }
+
+    public List<String> getMirror_targets() {
+        return mirror_targets;
+    }
+
+    public void setMirror_targets(List<String> mirror_targets) {
+        this.mirror_targets = mirror_targets;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/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
new file mode 100644
index 0000000..c2cf9c5
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApi.java
@@ -0,0 +1,413 @@
+/** 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;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+import org.apache.log4j.Logger;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+public class NiciraNvpApi {
+    private static final Logger s_logger = Logger.getLogger(NiciraNvpApi.class);
+    
+    private String _name;
+    private String _host;
+    private String _adminuser;
+    private String _adminpass;
+    
+    private HttpClient _client;
+
+    public NiciraNvpApi(String host, String adminuser, String adminpass) throws NiciraNvpApiException {
+        this._host = host;
+        this._adminpass = adminpass;
+        this._adminuser = adminuser;
+        
+        if (_host == null || _adminpass == null || _adminuser == null) {
+            throw new NiciraNvpApiException("host, adminuser and adminpass may not be null");
+        }
+
+        _client = new HttpClient( );
+        _client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
+        
+        try {             
+            // Cast to ProtocolSocketFactory to avoid the deprecated constructor with the SecureProtocolSocketFactory parameter
+            Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new TrustingProtocolSocketFactory(), 443));
+        } catch (IOException e) {
+            s_logger.warn("Failed to register the TrustingProtocolSocketFactory, falling back to default SSLSocketFactory", e);
+        }
+        
+    }
+    
+    /**
+     * Logs into the Nicira API. The cookie is stored in the <code>_authcookie<code> variable.
+     * <p>
+     * The method returns false if the login failed or the connection could not be made.
+     * 
+     */
+    private void login() throws NiciraNvpApiException {
+        String url;
+        
+        try {
+            url = new URL("https", _host, "/ws.v1/login").toString();
+        } catch (MalformedURLException e) {
+            s_logger.error("Unable to build Nicira API URL", e);
+            throw new NiciraNvpApiException("Unable to build Nicira API URL", e);
+        }
+        
+        PostMethod pm = new PostMethod(url);
+        pm.addParameter("username", _adminuser);
+        pm.addParameter("password", _adminpass);
+        
+        try {
+            _client.executeMethod(pm);
+        } catch (HttpException e) {
+            throw new NiciraNvpApiException("Nicira NVP API login failed ", e);
+        } catch (IOException e) {
+            throw new NiciraNvpApiException("Nicira NVP API login failed ", e);
+        }
+        
+        if (pm.getStatusCode() != HttpStatus.SC_OK) {
+            s_logger.error("Nicira NVP API login failed : " + pm.getStatusText());
+            throw new NiciraNvpApiException("Nicira NVP API login failed " + pm.getStatusText());
+        }
+        
+        // Success; the cookie required for login is kept in _client
+    }
+    
+    public LogicalSwitch createLogicalSwitch(LogicalSwitch logicalSwitch) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch";
+        LogicalSwitch createdLogicalSwitch = executeCreateObject(logicalSwitch, new TypeToken<LogicalSwitch>(){}.getType(), uri, Collections.<String,String>emptyMap());
+        
+        return createdLogicalSwitch;
+    }
+
+    public void deleteLogicalSwitch(String uuid) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch/" + uuid;
+        executeDeleteObject(uri);
+    }
+    
+    public LogicalSwitchPort createLogicalSwitchPort(String logicalSwitchUuid, LogicalSwitchPort logicalSwitchPort) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch/" + logicalSwitchUuid + "/lport";
+        LogicalSwitchPort createdLogicalSwitchPort = executeCreateObject(logicalSwitchPort, new TypeToken<LogicalSwitchPort>(){}.getType(), uri, Collections.<String,String>emptyMap());;
+        
+        return createdLogicalSwitchPort;
+    }
+
+    public void modifyLogicalSwitchPortAttachment(String logicalSwitchUuid, String logicalSwitchPortUuid, Attachment attachment) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch/" + logicalSwitchUuid + "/lport/" + logicalSwitchPortUuid + "/attachment";
+        executeUpdateObject(attachment, uri, Collections.<String,String>emptyMap());
+    }
+    
+    public void deleteLogicalSwitchPort(String logicalSwitchUuid, String logicalSwitchPortUuid) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch/" + logicalSwitchUuid + "/lport/" + logicalSwitchPortUuid;
+        executeDeleteObject(uri);
+    }
+    
+    public String findLogicalSwitchPortUuidByVifAttachmentUuid(String logicalSwitchUuid, String vifAttachmentUuid) throws NiciraNvpApiException {
+        String uri = "/ws.v1/lswitch/" + logicalSwitchUuid + "/lport";
+        Map<String,String> params = new HashMap<String,String>();
+        params.put("attachment_vif_uuid", vifAttachmentUuid);
+        params.put("fields", "uuid");
+            
+        NiciraNvpList<LogicalSwitchPort> lspl = executeRetrieveObject(new TypeToken<NiciraNvpList<LogicalSwitchPort>>(){}.getType(), uri, params);
+                
+        if (lspl == null || lspl.getResult_count() != 1) {
+            throw new NiciraNvpApiException("Unexpected response from API");
+        }
+        
+        LogicalSwitchPort lsp = lspl.getResults().get(0);
+        return lsp.getUuid();
+    }
+    
+    private <T> void executeUpdateObject(T newObject, String uri, Map<String,String> parameters) throws NiciraNvpApiException {
+        String url;
+        try {
+            url = new URL("https", _host, uri).toString();
+        } catch (MalformedURLException e) {
+            s_logger.error("Unable to build Nicira API URL", e);
+            throw new NiciraNvpApiException("Connection to NVP Failed");
+        }
+        
+        Gson gson = new Gson();
+        
+        PutMethod pm = new PutMethod(url);
+        pm.setRequestHeader("Content-Type", "application/json");
+        try {
+            pm.setRequestEntity(new StringRequestEntity(
+                    gson.toJson(newObject),"application/json", null));
+        } catch (UnsupportedEncodingException e) {
+            throw new NiciraNvpApiException("Failed to encode json request body", e);
+        }
+                
+        executeMethod(pm);
+        
+        if (pm.getStatusCode() != HttpStatus.SC_OK) {
+            String errorMessage = responseToErrorMessage(pm);
+            s_logger.error("Failed to update object : " + errorMessage);
+            throw new NiciraNvpApiException("Failed to update object : " + errorMessage);
+        }
+        
+    }
+    
+    private <T> T executeCreateObject(T newObject, Type returnObjectType, String uri, Map<String,String> parameters) throws NiciraNvpApiException {
+        String url;
+        try {
+            url = new URL("https", _host, uri).toString();
+        } catch (MalformedURLException e) {
+            s_logger.error("Unable to build Nicira API URL", e);
+            throw new NiciraNvpApiException("Unable to build Nicira API URL", e);
+        }
+        
+        Gson gson = new Gson();
+        
+        PostMethod pm = new PostMethod(url);
+        pm.setRequestHeader("Content-Type", "application/json");
+        try {
+            pm.setRequestEntity(new StringRequestEntity(
+                    gson.toJson(newObject),"application/json", null));
+        } catch (UnsupportedEncodingException e) {
+            throw new NiciraNvpApiException("Failed to encode json request body", e);
+        }
+                
+        executeMethod(pm);
+        
+        if (pm.getStatusCode() != HttpStatus.SC_CREATED) {
+            String errorMessage = responseToErrorMessage(pm);
+            s_logger.error("Failed to create object : " + errorMessage);
+            throw new NiciraNvpApiException("Failed to create object : " + errorMessage);
+        }
+        
+        T result;
+        try {
+            result = gson.fromJson(pm.getResponseBodyAsString(), TypeToken.get(newObject.getClass()).getType());
+        } catch (IOException e) {
+            throw new NiciraNvpApiException("Failed to decode json response body", e);
+        }
+        
+        return result;        
+    }
+    
+    private void executeDeleteObject(String uri) throws NiciraNvpApiException {
+        String url;
+        try {
+            url = new URL("https", _host, uri).toString();
+        } catch (MalformedURLException e) {
+            s_logger.error("Unable to build Nicira API URL", e);
+            throw new NiciraNvpApiException("Unable to build Nicira API URL", e);
+        }
+            
+        DeleteMethod dm = new DeleteMethod(url);
+        dm.setRequestHeader("Content-Type", "application/json");
+                
+        executeMethod(dm);
+        
+        if (dm.getStatusCode() != HttpStatus.SC_NO_CONTENT) {
+            String errorMessage = responseToErrorMessage(dm);
+            s_logger.error("Failed to delete object : " + errorMessage);
+            throw new NiciraNvpApiException("Failed to delete object : " + errorMessage);
+        }
+    }
+    
+    private <T> T executeRetrieveObject(Type returnObjectType, String uri, Map<String,String> parameters) throws NiciraNvpApiException {
+        String url;
+        try {
+            url = new URL("https", _host, uri).toString();
+        } catch (MalformedURLException e) {
+            s_logger.error("Unable to build Nicira API URL", e);
+            throw new NiciraNvpApiException("Unable to build Nicira API URL", e);
+        }
+            
+        GetMethod gm = new GetMethod(url);
+        gm.setRequestHeader("Content-Type", "application/json");
+        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(parameters.size());
+        for (Entry<String,String> e : parameters.entrySet()) {
+            nameValuePairs.add(new NameValuePair(e.getKey(), e.getValue()));
+        }
+        gm.setQueryString(nameValuePairs.toArray(new NameValuePair[0]));
+                
+        executeMethod(gm);
+        
+        if (gm.getStatusCode() != HttpStatus.SC_OK) {
+            String errorMessage = responseToErrorMessage(gm);
+            s_logger.error("Failed to retrieve object : " + errorMessage);
+            throw new NiciraNvpApiException("Failed to retrieve object : " + errorMessage);
+        }
+            
+        Gson gson = new Gson();
+        T returnValue;
+        try {
+            returnValue = gson.fromJson(gm.getResponseBodyAsString(), returnObjectType);
+        } catch (IOException e) {
+            s_logger.error("IOException while retrieving response body",e);
+            throw new NiciraNvpApiException(e);
+        }
+        
+        return returnValue;
+    }
+    
+    private void executeMethod(HttpMethodBase method) throws NiciraNvpApiException {
+        try {
+            _client.executeMethod(method);
+            if (method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
+                // login and try again
+                login();
+                _client.executeMethod(method);
+            }
+        } catch (HttpException e) {
+            s_logger.error("HttpException caught while trying to connect to the Nicira NVP Controller", e);
+            throw new NiciraNvpApiException("API call to Nicira NVP Controller Failed", e);
+        } catch (IOException e) {
+            s_logger.error("IOException caught while trying to connect to the Nicira NVP Controller", e);
+            throw new NiciraNvpApiException("API call to Nicira NVP Controller Failed", e);            
+        }
+    }
+    
+    private String responseToErrorMessage(HttpMethodBase method) {
+        assert method.isRequestSent() : "no use getting an error message unless the request is sent";
+        
+        if ("text/html".equals(method.getResponseHeader("Content-Type").getValue())) {
+            // The error message is the response content
+            // Safety margin of 1024 characters, anything longer is probably useless
+            // and will clutter the logs
+            try {
+                return  method.getResponseBodyAsString(1024);
+            } catch (IOException e) {
+                s_logger.debug("Error while loading response body", e);
+            }
+        }
+        
+        // The default
+        return method.getStatusText();
+    }
+    
+    /* The Nicira controller uses a self-signed certificate. The 
+     * TrustingProtocolSocketFactory will accept any provided
+     * certificate when making an SSL connection to the SDN 
+     * Manager
+     */
+    private class TrustingProtocolSocketFactory implements SecureProtocolSocketFactory {
+
+        private SSLSocketFactory ssf;
+        
+        public TrustingProtocolSocketFactory() throws IOException {
+            // Create a trust manager that does not validate certificate chains
+            TrustManager[] trustAllCerts = new TrustManager[] {
+                new X509TrustManager() {
+                    public X509Certificate[] getAcceptedIssuers() {
+                        return null;
+                    }
+         
+                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                        // Trust always
+                    }
+         
+                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                        // Trust always
+                    }
+                }
+            };
+         
+            try {
+                // Install the all-trusting trust manager
+                SSLContext sc = SSLContext.getInstance("SSL");
+                sc.init(null, trustAllCerts, new java.security.SecureRandom());
+                ssf =  sc.getSocketFactory();
+            } catch (KeyManagementException e) {
+                throw new IOException(e);
+            } catch (NoSuchAlgorithmException e) {
+                throw new IOException(e);
+            }
+        }
+        
+        @Override
+        public Socket createSocket(String host, int port) throws IOException,
+                UnknownHostException {
+            return ssf.createSocket(host, port);
+        }
+
+        @Override
+        public Socket createSocket(String address, int port, InetAddress localAddress,
+                int localPort) throws IOException, UnknownHostException {
+            return ssf.createSocket(address, port, localAddress, localPort);
+        }
+
+        @Override
+        public Socket createSocket(Socket socket, String host, int port,
+                boolean autoClose) throws IOException, UnknownHostException {
+            return ssf.createSocket(socket, host, port, autoClose);
+        }
+
+        @Override
+        public Socket createSocket(String host, int port, InetAddress localAddress,
+                int localPort, HttpConnectionParams params) throws IOException,
+                UnknownHostException, ConnectTimeoutException {
+            int timeout = params.getConnectionTimeout();
+            if (timeout == 0) {
+                return createSocket(host, port, localAddress, localPort);
+            }
+            else {
+                Socket s = ssf.createSocket();
+                s.bind(new InetSocketAddress(localAddress, localPort));
+                s.connect(new InetSocketAddress(host, port), timeout);
+                return s;
+            }
+        }
+
+        
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApiException.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApiException.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApiException.java
new file mode 100644
index 0000000..2a09cc0
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpApiException.java
@@ -0,0 +1,20 @@
+package com.cloud.network.nicira;
+
+public class NiciraNvpApiException extends Exception {
+
+    public NiciraNvpApiException() {
+    }
+
+    public NiciraNvpApiException(String message) {
+        super(message);
+    }
+
+    public NiciraNvpApiException(Throwable cause) {
+        super(cause);
+    }
+
+    public NiciraNvpApiException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/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
new file mode 100644
index 0000000..79f582a
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpList.java
@@ -0,0 +1,25 @@
+package com.cloud.network.nicira;
+
+import java.util.List;
+
+public class NiciraNvpList<T> {
+    private List<T> results;
+    private int result_count;
+
+    public List<T> getResults() {
+        return results;
+    }
+
+    public void setResults(List<T> results) {
+        this.results = results;
+    }
+
+    public int getResult_count() {
+        return result_count;
+    }
+
+    public void setResult_count(int result_count) {
+        this.result_count = result_count;
+    }        
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpTag.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpTag.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpTag.java
new file mode 100644
index 0000000..de0b40f
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/NiciraNvpTag.java
@@ -0,0 +1,47 @@
+/** 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 NiciraNvpTag {
+    private String scope;
+    private String tag;
+    
+    public NiciraNvpTag() {}
+    
+    public NiciraNvpTag(String scope, String tag) {
+        this.scope = scope;
+        this.tag = tag;
+    }
+    
+    public String getScope() {
+        return scope;
+    }
+    
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+    
+    public String getTag() {
+        return tag;
+    }
+    
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/TransportZoneBinding.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/TransportZoneBinding.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/TransportZoneBinding.java
new file mode 100644
index 0000000..530352e
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/TransportZoneBinding.java
@@ -0,0 +1,47 @@
+/** 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 TransportZoneBinding {
+    private String zone_uuid;
+    private String transport_type;
+    
+    public TransportZoneBinding() {}
+    
+    public TransportZoneBinding(String zone_uuid, String transport_type) {
+        this.zone_uuid = zone_uuid;
+        this.transport_type = transport_type;
+    }
+
+    public String getZone_uuid() {
+        return zone_uuid;
+    }
+
+    public void setZone_uuid(String zone_uuid) {
+        this.zone_uuid = zone_uuid;
+    }
+
+    public String getTransport_type() {
+        return transport_type;
+    }
+
+    public void setTransport_type(String transport_type) {
+        this.transport_type = transport_type;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/VifAttachment.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/VifAttachment.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/VifAttachment.java
new file mode 100644
index 0000000..a5f0de7
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/nicira/VifAttachment.java
@@ -0,0 +1,43 @@
+/** 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 VifAttachment extends Attachment {
+    private final String type = "VifAttachment";
+    private String vif_uuid;
+    
+    public VifAttachment() {
+    }
+    
+    public VifAttachment(String vifUuid) {
+        this.vif_uuid = vifUuid;
+    }
+
+    public String getVif_uuid() {
+        return vif_uuid;
+    }
+
+    public void setVif_uuid(String vif_uuid) {
+        this.vif_uuid = vif_uuid;
+    }
+
+    public String getType() {
+        return type;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/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
new file mode 100644
index 0000000..ae7b37e
--- /dev/null
+++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/resource/NiciraNvpResource.java
@@ -0,0 +1,240 @@
+package com.cloud.network.resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+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.CreateLogicalSwitchAnswer;
+import com.cloud.agent.api.CreateLogicalSwitchCommand;
+import com.cloud.agent.api.CreateLogicalSwitchPortAnswer;
+import com.cloud.agent.api.CreateLogicalSwitchPortCommand;
+import com.cloud.agent.api.DeleteLogicalSwitchAnswer;
+import com.cloud.agent.api.DeleteLogicalSwitchCommand;
+import com.cloud.agent.api.DeleteLogicalSwitchPortAnswer;
+import com.cloud.agent.api.DeleteLogicalSwitchPortCommand;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupNiciraNvpCommand;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.network.nicira.LogicalSwitch;
+import com.cloud.network.nicira.LogicalSwitchPort;
+import com.cloud.network.nicira.NiciraNvpApi;
+import com.cloud.network.nicira.NiciraNvpApiException;
+import com.cloud.network.nicira.NiciraNvpTag;
+import com.cloud.network.nicira.TransportZoneBinding;
+import com.cloud.network.nicira.VifAttachment;
+import com.cloud.resource.ServerResource;
+
+public class NiciraNvpResource implements ServerResource {
+    private static final Logger s_logger = Logger.getLogger(NiciraNvpResource.class);
+    
+    private String _name;
+    private String _ip;
+    private String _adminuser;
+    private String _adminpass;
+    private String _guid;
+    private String _zoneId;
+    
+    private NiciraNvpApi _niciraNvpApi;
+    
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        
+        _name = (String) params.get("name");
+        if (_name == null) {
+            throw new ConfigurationException("Unable to find name");
+        }
+        
+        _ip = (String) params.get("ip");
+        if (_ip == null) {
+            throw new ConfigurationException("Unable to find IP");
+        }
+        
+        _adminuser = (String) params.get("adminuser");
+        if (_adminuser == null) {
+            throw new ConfigurationException("Unable to find admin username");
+        }
+        
+        _adminpass = (String) params.get("adminpass");
+        if (_adminpass == null) {
+            throw new ConfigurationException("Unable to find admin password");
+        }               
+        
+        _guid = (String)params.get("guid");
+        if (_guid == null) {
+            throw new ConfigurationException("Unable to find the guid");
+        }
+        
+        _zoneId = (String) params.get("zoneId");
+        if (_zoneId == null) {
+            throw new ConfigurationException("Unable to find zone");
+        }
+        
+        try {
+            _niciraNvpApi = new NiciraNvpApi(_ip, _adminuser, _adminpass);
+        } catch (NiciraNvpApiException e) {
+            throw new ConfigurationException(e.getMessage());
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    @Override
+    public Type getType() {
+        // Think up a better name for this Type?
+        return Host.Type.L2Networking;
+    }
+
+    @Override
+    public StartupCommand[] initialize() {
+        StartupNiciraNvpCommand sc = new StartupNiciraNvpCommand();
+        sc.setGuid(_guid);
+        sc.setName(_name);
+        sc.setDataCenter(_zoneId);
+        sc.setPod("");
+        sc.setPrivateIpAddress("");
+        sc.setStorageIpAddress("");
+        sc.setVersion("");
+        return new StartupCommand[] { sc };
+    }
+
+    @Override
+    public PingCommand getCurrentStatus(long id) {
+        return new PingCommand(Host.Type.L2Networking, id);
+    }
+
+    @Override
+    public Answer executeRequest(Command cmd) {
+        if (cmd instanceof ReadyCommand) {
+            return executeRequest((ReadyCommand) cmd);
+        }
+        else if (cmd instanceof MaintainCommand) {
+            return executeRequest((MaintainCommand)cmd);
+        }
+        else if (cmd instanceof CreateLogicalSwitchCommand) {
+            return executeRequest((CreateLogicalSwitchCommand)cmd);
+        }
+        else if (cmd instanceof DeleteLogicalSwitchCommand) {
+            return executeRequest((DeleteLogicalSwitchCommand) cmd);
+        }
+        else if (cmd instanceof CreateLogicalSwitchPortCommand) {
+            return executeRequest((CreateLogicalSwitchPortCommand) cmd);
+        }
+        else if (cmd instanceof DeleteLogicalSwitchPortCommand) {
+            return executeRequest((DeleteLogicalSwitchPortCommand) cmd);
+        }
+        s_logger.debug("Received unsupported command " + cmd.toString());
+        return Answer.createUnsupportedCommandAnswer(cmd);
+    }
+
+    @Override
+    public void disconnected() {
+    }
+
+    @Override
+    public IAgentControl getAgentControl() {
+        return null;
+    }
+
+    @Override
+    public void setAgentControl(IAgentControl agentControl) {
+    }
+    
+    private Answer executeRequest(CreateLogicalSwitchCommand cmd) {
+        LogicalSwitch logicalSwitch = new LogicalSwitch();
+        logicalSwitch.setDisplay_name("lswitch-" + cmd.getOwnerName());
+        logicalSwitch.setPort_isolation_enabled(false);
+
+        // Set transport binding
+        List<TransportZoneBinding> ltzb = new ArrayList<TransportZoneBinding>();
+        ltzb.add(new TransportZoneBinding(cmd.getTransportUuid(), cmd.getTransportType()));
+        logicalSwitch.setTransport_zones(ltzb);
+
+        // Tags set to scope cs_account and account name
+        List<NiciraNvpTag> tags = new ArrayList<NiciraNvpTag>();
+        tags.add(new NiciraNvpTag("cs_account",cmd.getOwnerName()));
+        logicalSwitch.setTags(tags);
+        
+        try {
+            logicalSwitch = _niciraNvpApi.createLogicalSwitch(logicalSwitch);
+            return new CreateLogicalSwitchAnswer(cmd, true, "Logicalswitch " + logicalSwitch.getUuid() + " created", logicalSwitch.getUuid());
+        } catch (NiciraNvpApiException e) {
+            return new CreateLogicalSwitchAnswer(cmd, e);
+        }
+        
+    }
+    
+    private Answer executeRequest(DeleteLogicalSwitchCommand cmd) {
+        try {
+            _niciraNvpApi.deleteLogicalSwitch(cmd.getLogicalSwitchUuid());
+            return new DeleteLogicalSwitchAnswer(cmd, true, "Logicalswitch " + cmd.getLogicalSwitchUuid() + " deleted");
+        } catch (NiciraNvpApiException e) {
+            return new DeleteLogicalSwitchAnswer(cmd, e);
+        }
+    }
+    
+    private Answer executeRequest(CreateLogicalSwitchPortCommand cmd) {
+        String logicalSwitchUuid = cmd.getLogicalSwitchUuid();
+        String attachmentUuid = cmd.getAttachmentUuid();
+        
+        try {
+            // Tags set to scope cs_account and account name
+            List<NiciraNvpTag> tags = new ArrayList<NiciraNvpTag>();
+            tags.add(new NiciraNvpTag("cs_account",cmd.getOwnerName()));
+
+            LogicalSwitchPort logicalSwitchPort = new LogicalSwitchPort(attachmentUuid, tags, true);
+            LogicalSwitchPort newPort = _niciraNvpApi.createLogicalSwitchPort(logicalSwitchUuid, logicalSwitchPort);
+            _niciraNvpApi.modifyLogicalSwitchPortAttachment(cmd.getLogicalSwitchUuid(), newPort.getUuid(), new VifAttachment(attachmentUuid));
+            return new CreateLogicalSwitchPortAnswer(cmd, true, "Logical switch port " + newPort.getUuid() + " created", newPort.getUuid());
+        } catch (NiciraNvpApiException e) {
+            return new CreateLogicalSwitchPortAnswer(cmd, e);
+        }
+        
+    }
+    
+    private Answer executeRequest(DeleteLogicalSwitchPortCommand cmd) {
+        try {
+            _niciraNvpApi.deleteLogicalSwitchPort(cmd.getLogicalSwitchUuid(), cmd.getLogicalSwitchPortUuid());
+            return new DeleteLogicalSwitchPortAnswer(cmd, true, "Logical switch port " + cmd.getLogicalSwitchPortUuid() + " deleted");
+        } catch (NiciraNvpApiException e) {
+            return new DeleteLogicalSwitchPortAnswer(cmd, e);
+        }
+    }
+
+    private Answer executeRequest(ReadyCommand cmd) {
+        return new ReadyAnswer(cmd);
+    }
+    
+    private Answer executeRequest(MaintainCommand cmd) {
+        return new MaintainAnswer(cmd);
+    }    
+ 
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
index d031fee..7bfa715 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
@@ -12,11 +12,14 @@
 // Automatically generated by addcopyright.py at 04/03/2012
 package com.cloud.network.guru;
 
+import java.util.List;
+
 import javax.ejb.Local;
 
 import org.apache.log4j.Logger;
 
 import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.deploy.DeploymentPlan;
 import com.cloud.event.EventTypes;
@@ -38,7 +41,10 @@ import com.cloud.vm.ReservationContext;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.Network.GuestType;
 import com.cloud.network.Network.State;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
 
 @Local(value=NetworkGuru.class)
 public class OvsGuestNetworkGuru extends GuestNetworkGuru {
@@ -46,6 +52,28 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
 	
 	@Inject NetworkManager _externalNetworkManager;
 	@Inject OvsTunnelManager _ovsTunnelMgr;
+
+    OvsGuestNetworkGuru() {
+        super();
+        _isolationMethods = new IsolationMethod[] { IsolationMethod.GRE, IsolationMethod.L3, IsolationMethod.VLAN };
+    }
+    
+    protected boolean canHandle(NetworkOffering offering,
+            final NetworkType networkType, final PhysicalNetwork physicalNetwork) {
+        // This guru handles only Guest Isolated network that supports Source
+        // nat service
+        if (networkType == NetworkType.Advanced
+                && isMyTrafficType(offering.getTrafficType())
+                && offering.getGuestType() == Network.GuestType.Isolated
+                && isMyIsolationMethod(physicalNetwork)) {
+            return true;
+        } else {
+            s_logger.trace("We only take care of Guest networks of type   "
+                    + GuestType.Isolated + " in zone of type "
+                    + NetworkType.Advanced);
+            return false;
+        }
+    }    
 	
 	@Override
     public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/server/src/com/cloud/host/dao/HostDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java
index a6d794d..ab1e77e 100755
--- a/server/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/server/src/com/cloud/host/dao/HostDaoImpl.java
@@ -354,7 +354,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
     	txn.start();
     	SearchCriteria<HostVO> sc = UnmanagedApplianceSearch.create();
     	sc.setParameters("lastPinged", lastPingSecondsAfter);
-    	sc.setParameters("types", Type.ExternalDhcp, Type.ExternalFirewall, Type.ExternalLoadBalancer, Type.PxeServer, Type.TrafficMonitor);
+        sc.setParameters("types", Type.ExternalDhcp, Type.ExternalFirewall, Type.ExternalLoadBalancer, Type.PxeServer, Type.TrafficMonitor, Type.L2Networking);
     	List<HostVO> hosts = lockRows(sc, null, true);
     	
     	for (HostVO host : hosts) {
@@ -493,7 +493,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
         List<HostVO> result = new ArrayList<HostVO>();
         ResultSet rs = null;
         try {
-            String sql = "select h.id from host h left join  cluster c on h.cluster_id=c.id where h.mgmt_server_id is not null and h.last_ping < ? and h.status in ('Up', 'Updating', 'Disconnected', 'Connecting') and h.type not in ('ExternalFirewall', 'ExternalLoadBalancer', 'TrafficMonitor', 'SecondaryStorage', 'LocalSecondaryStorage') and (h.cluster_id is null or c.managed_state = 'Managed') ;" ;
+            String sql = "select h.id from host h left join  cluster c on h.cluster_id=c.id where h.mgmt_server_id is not null and h.last_ping < ? and h.status in ('Up', 'Updating', 'Disconnected', 'Connecting') and h.type not in ('ExternalFirewall', 'ExternalLoadBalancer', 'TrafficMonitor', 'SecondaryStorage', 'LocalSecondaryStorage', 'L2Networking') and (h.cluster_id is null or c.managed_state = 'Managed') ;" ;
             pstmt = txn.prepareStatement(sql);
             pstmt.setLong(1, timeout);
             rs = pstmt.executeQuery();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index a515194..bd547ab 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -28,12 +28,18 @@ import com.cloud.storage.dao.VMTemplateDetailsDao;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.utils.component.Inject;
 import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
 
 public abstract class HypervisorGuruBase extends AdapterBase implements HypervisorGuru {
 	
 	@Inject VMTemplateDetailsDao _templateDetailsDao;
+    @Inject NicDao _nicDao;
+    @Inject VMInstanceDao _virtualMachineDao;
 	
     protected HypervisorGuruBase() {
         super();
@@ -55,6 +61,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         to.setIsolationuri(profile.getIsolationUri());
         to.setNetworkRateMbps(profile.getNetworkRate());
         to.setName(profile.getName());
+        
+        // Workaround to make sure the TO has the UUID we need for Niciri integration
+        NicVO nicVO = _nicDao.findById(profile.getId());
+        to.setUuid(nicVO.getUuid());
         return to;
     }
 
@@ -92,6 +102,11 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         	details.putAll(detailsInVm);
         }
         to.setDetails(details);
+        
+        // Workaround to make sure the TO has the UUID we need for Niciri integration
+        VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
+        to.setUuid(vmInstance.getUuid());
+        
         return to;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/server/src/com/cloud/network/ExternalNetworkDeviceManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/ExternalNetworkDeviceManager.java b/server/src/com/cloud/network/ExternalNetworkDeviceManager.java
index 115de1b..dec0608 100644
--- a/server/src/com/cloud/network/ExternalNetworkDeviceManager.java
+++ b/server/src/com/cloud/network/ExternalNetworkDeviceManager.java
@@ -39,6 +39,8 @@ public interface ExternalNetworkDeviceManager extends Manager {
         public static final NetworkDevice NetscalerSDXLoadBalancer = new NetworkDevice("NetscalerSDXLoadBalancer", Network.Provider.Netscaler.getName());
         public static final NetworkDevice F5BigIpLoadBalancer = new NetworkDevice("F5BigIpLoadBalancer", Network.Provider.F5BigIp.getName());
         public static final NetworkDevice JuniperSRXFirewall = new NetworkDevice("JuniperSRXFirewall", Network.Provider.JuniperSRX.getName());
+        public static final NetworkDevice NiciraNvp = new NetworkDevice("NiciraNvp", Network.Provider.NiciraNvp.getName());
+        
         
         public NetworkDevice(String deviceName, String ntwkServiceprovider) {
             _name = deviceName;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/79c7da07/server/src/com/cloud/network/NetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java
index f26d40d..d04a140 100755
--- a/server/src/com/cloud/network/NetworkManagerImpl.java
+++ b/server/src/com/cloud/network/NetworkManagerImpl.java
@@ -1455,7 +1455,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
         try {
             if (predefined == null
-                    || (offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null && predefined.getBroadcastDomainType() != BroadcastDomainType.Vlan)) {
+                    || (offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null && 
+                    !(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch))) {
                 List<NetworkVO> configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId());
                 if (configs.size() > 0) {
                     if (s_logger.isDebugEnabled()) {
@@ -1721,6 +1722,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
 
         Integer networkRate = getNetworkRate(config.getId(), null);
         to.setNetworkRateMbps(networkRate);
+        
+        to.setUuid(config.getUuid());
 
         return to;
     }