diff --git a/LICENSE.header b/LICENSE.header
new file mode 100644
index 00000000000..4eacb643179
--- /dev/null
+++ b/LICENSE.header
@@ -0,0 +1,16 @@
+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.
diff --git a/plugins/network-elements/opendaylight/pom.xml b/plugins/network-elements/opendaylight/pom.xml
new file mode 100644
index 00000000000..8c69b6ebe17
--- /dev/null
+++ b/plugins/network-elements/opendaylight/pom.xml
@@ -0,0 +1,132 @@
+
+
+ 4.0.0
+ cloud-plugin-network-opendaylight
+ Apache CloudStack Plugin - Network Opendaylight
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.4.0-SNAPSHOT
+ ../../pom.xml
+
+
+
+
+ ${basedir}/src/main/java
+ ${basedir}/src/main/scripts
+ ${basedir}/src/test/java
+ ${basedir}/target/classes
+ ${basedir}/target/test-classes
+
+
+ ${basedir}/src/main/resources
+
+
+
+
+ ${basedir}/src/test/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+
+
+ org.apache.cloudstack
+ checkstyle
+ ${project.version}
+
+
+
+
+ process-classes
+
+ check
+
+
+
+
+ true
+ tooling/checkstyle.xml
+ true
+ true
+ ${project.basedir}
+ **\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat
+ **\/target\/,**\/bin\/
+
+
+
+ com.mycila.maven-license-plugin
+ maven-license-plugin
+ 1.9.0
+
+
+ process-classes
+
+ format
+
+
+
+
+ true
+ true
+
+
+ XML_STYLE
+ DOUBLESLASH_STYLE
+ SEMICOLON_STYLE
+
+ false
+
+ target/**
+ .settings/**
+ .checkstyle
+ .project
+ .classpath
+
+
+
+
+
+
+
+ integration
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+
+
+
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java
new file mode 100644
index 00000000000..9761e744f6b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightElement.java
@@ -0,0 +1,174 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.StartupOpenDaylightControllerCommand;
+
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.element.ConnectivityProvider;
+import com.cloud.network.element.NetworkElement;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+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.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Component
+@Local(value = {NetworkElement.class, ConnectivityProvider.class})
+public class OpendaylightElement extends AdapterBase implements ConnectivityProvider, ResourceStateAdapter {
+
+ private static final Logger s_logger = Logger.getLogger(OpendaylightElement.class);
+ private static final Map> s_capabilities = setCapabilities();
+
+ @Inject
+ ResourceManager resourceManager;
+
+ @Override
+ public Map> getCapabilities() {
+ return s_capabilities;
+ }
+
+ @Override
+ public Provider getProvider() {
+ return Provider.Opendaylight;
+ }
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ boolean configured = super.configure(name, params);
+ if (configured)
+ resourceManager.registerResourceStateAdapter(name, this);
+ return configured;
+ }
+
+ @Override
+ public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException, InsufficientCapacityException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException, InsufficientCapacityException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean isReady(PhysicalNetworkServiceProvider provider) {
+ return true;
+ }
+
+ @Override
+ public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ return true;
+ }
+
+ @Override
+ public boolean canEnableIndividualServices() {
+ return false;
+ }
+
+ @Override
+ public boolean verifyServicesCombination(Set services) {
+ if (services.contains(Service.Connectivity) && services.size() == 1)
+ return true;
+ return false;
+ }
+
+ @Override
+ public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] startup) {
+ if (!(startup[0] instanceof StartupOpenDaylightControllerCommand)) {
+ return null;
+ }
+ throw new CloudRuntimeException("createHostVOForConnectedAgent is not implemented for OpendaylightElement");
+ }
+
+ @Override
+ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, List hostTags) {
+ if (!(startup[0] instanceof StartupOpenDaylightControllerCommand)) {
+ return null;
+ }
+ host.setType(Host.Type.L2Networking);
+ return host;
+ }
+
+ @Override
+ public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
+ return new DeleteHostAnswer(true);
+ }
+
+ private static Map> setCapabilities() {
+ Map> capabilities = new HashMap>();
+
+ // L2 Support : SDN provisioning
+ capabilities.put(Service.Connectivity, null);
+
+ return capabilities;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
new file mode 100644
index 00000000000..0b547e76f18
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java
@@ -0,0 +1,276 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
+import com.cloud.network.Network;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.Network.State;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.NetworkProfile;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.network.guru.GuestNetworkGuru;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
+import com.cloud.user.Account;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachineProfile;
+
+public class OpendaylightGuestNetworkGuru extends GuestNetworkGuru {
+ private static final Logger s_logger = Logger.getLogger(OpendaylightGuestNetworkGuru.class);
+
+ @Inject
+ protected NetworkOfferingServiceMapDao ntwkOfferingSrvcDao;
+ @Inject
+ PhysicalNetworkDao physicalNetworkDao;
+ @Inject
+ OpenDaylightControllerMappingDao openDaylightControllerMappingDao;
+ @Inject
+ NetworkModel networkModel;
+ @Inject
+ AgentManager agentManager;
+ @Inject
+ NetworkDao networkDao;
+
+ public OpendaylightGuestNetworkGuru() {
+ _isolationMethods = new IsolationMethod[] {IsolationMethod.ODL};
+ }
+
+ @Override
+ protected boolean canHandle(NetworkOffering offering, NetworkType networkType, PhysicalNetwork physicalNetwork) {
+ if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && offering.getGuestType() == Network.GuestType.Isolated &&
+ isMyIsolationMethod(physicalNetwork) && ntwkOfferingSrvcDao.areServicesSupportedByNetworkOffering(offering.getId(), Service.Connectivity)
+ && ntwkOfferingSrvcDao.isProviderForNetworkOffering(offering.getId(), Provider.Opendaylight)) {
+ 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) {
+ PhysicalNetworkVO physnet = physicalNetworkDao.findById(plan.getPhysicalNetworkId());
+ DataCenter dc = _dcDao.findById(plan.getDataCenterId());
+ if (!canHandle(offering, dc.getNetworkType(), physnet)) {
+ s_logger.debug("Refusing to design this network");
+ return null;
+ }
+
+ List devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physnet.getId());
+ if (devices.isEmpty()) {
+ s_logger.error("No Controller on physical network " + physnet.getName());
+ return null;
+ }
+ s_logger.debug("Controller " + devices.get(0).getUuid() + " found on physical network " + physnet.getId());
+ s_logger.debug("Physical isolation type is ODL, 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.OpenDaylight);
+
+ 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 = network.getPhysicalNetworkId();
+
+ // physical network id can be null in Guest Network in Basic zone, so locate the physical network
+ if (physicalNetworkId == null) {
+ physicalNetworkId = networkModel.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 = network.getName();
+ if (name == null || name.isEmpty()) {
+ name = ((NetworkVO)network).getUuid();
+ }
+
+ List devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+ if (devices.isEmpty()) {
+ s_logger.error("No Controller on physical network " + physicalNetworkId);
+ return null;
+ }
+ OpenDaylightControllerVO controller = devices.get(0);
+
+ ConfigureNetworkCommand cmd = new ConfigureNetworkCommand(name, context.getAccount().getAccountName());
+ ConfigureNetworkAnswer answer = (ConfigureNetworkAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("ConfigureNetworkCommand failed");
+ return null;
+ }
+
+ implemented.setBroadcastUri(BroadcastDomainType.OpenDaylight.toUri(answer.getNetworkUuid()));
+ implemented.setBroadcastDomainType(BroadcastDomainType.OpenDaylight);
+ s_logger.info("Implemented OK, network linked to = " + implemented.getBroadcastUri().toString());
+
+ return implemented;
+ }
+
+ @Override
+ public void reserve(NicProfile nic, Network network, VirtualMachineProfile vm, DeployDestination dest, ReservationContext context)
+ throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
+ super.reserve(nic, network, vm, dest, context);
+
+ //get physical network id
+ Long physicalNetworkId = network.getPhysicalNetworkId();
+
+ List devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+ if (devices.isEmpty()) {
+ s_logger.error("No Controller on physical network " + physicalNetworkId);
+ throw new InsufficientVirtualNetworkCapcityException("No OpenDaylight Controller configured for this network", dest.getPod().getId());
+ }
+ OpenDaylightControllerVO controller = devices.get(0);
+
+ AddHypervisorCommand addCmd = new AddHypervisorCommand(dest.getHost().getUuid(), dest.getHost().getPrivateIpAddress());
+ AddHypervisorAnswer addAnswer = (AddHypervisorAnswer)agentManager.easySend(controller.getHostId(), addCmd);
+ if (addAnswer == null || !addAnswer.getResult()) {
+ s_logger.error("Failed to add " + dest.getHost().getName() + " as a node to the controller");
+ throw new InsufficientVirtualNetworkCapcityException("Failed to add destination hypervisor to the OpenDaylight Controller", dest.getPod().getId());
+ }
+
+ ConfigurePortCommand cmd = new ConfigurePortCommand(UUID.fromString(nic.getUuid()), UUID.fromString(BroadcastDomainType.getValue(network.getBroadcastUri())), context
+ .getAccount().getAccountName(), nic.getMacAddress());
+ ConfigurePortAnswer answer = (ConfigurePortAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("ConfigureNetworkCommand failed");
+ throw new InsufficientVirtualNetworkCapcityException("Failed to configure the port on the OpenDaylight Controller", dest.getPod().getId());
+ }
+
+ }
+
+ @Override
+ public boolean release(NicProfile nic, VirtualMachineProfile vm, String reservationId) {
+ boolean success = super.release(nic, vm, reservationId);
+
+ if (success) {
+ //get physical network id
+ NetworkVO network = _networkDao.findById(nic.getNetworkId());
+ Long physicalNetworkId = network.getPhysicalNetworkId();
+
+ List devices = openDaylightControllerMappingDao.listByPhysicalNetwork(physicalNetworkId);
+ if (devices.isEmpty()) {
+ s_logger.error("No Controller on physical network " + physicalNetworkId);
+ throw new CloudRuntimeException("No OpenDaylight controller on this physical network");
+ }
+ OpenDaylightControllerVO controller = devices.get(0);
+
+ DestroyPortCommand cmd = new DestroyPortCommand(UUID.fromString(nic.getUuid()));
+ DestroyPortAnswer answer = (DestroyPortAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("DestroyPortCommand failed");
+ success = false;
+ }
+ }
+
+ return success;
+ }
+
+ @Override
+ public void shutdown(NetworkProfile profile, NetworkOffering offering) {
+ NetworkVO networkObject = networkDao.findById(profile.getId());
+ if (networkObject.getBroadcastDomainType() != BroadcastDomainType.OpenDaylight || networkObject.getBroadcastUri() == null) {
+ s_logger.warn("BroadcastUri is empty or incorrect for guestnetwork " + networkObject.getDisplayText());
+ return;
+ }
+
+ List devices = openDaylightControllerMappingDao.listByPhysicalNetwork(networkObject.getPhysicalNetworkId());
+ if (devices.isEmpty()) {
+ s_logger.error("No Controller on physical network " + networkObject.getPhysicalNetworkId());
+ return;
+ }
+ OpenDaylightControllerVO controller = devices.get(0);
+
+ DestroyNetworkCommand cmd = new DestroyNetworkCommand(BroadcastDomainType.getValue(networkObject.getBroadcastUri()));
+ DestroyNetworkAnswer answer = (DestroyNetworkAnswer)agentManager.easySend(controller.getHostId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("DestroyNetworkCommand failed");
+ }
+
+ super.shutdown(profile, offering);
+ }
+
+ @Override
+ public boolean trash(Network network, NetworkOffering offering) {
+ // TODO Auto-generated method stub
+ return super.trash(network, offering);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
new file mode 100644
index 00000000000..5c1e1e4ba2e
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResource.java
@@ -0,0 +1,321 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.InvalidParameterException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.opendaylight.agent.commands.AddHypervisorCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigureNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.ConfigurePortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyNetworkCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.DestroyPortCommand;
+import org.apache.cloudstack.network.opendaylight.agent.commands.StartupOpenDaylightControllerCommand;
+import org.apache.cloudstack.network.opendaylight.agent.responses.AddHypervisorAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigureNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.ConfigurePortAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyNetworkAnswer;
+import org.apache.cloudstack.network.opendaylight.agent.responses.DestroyPortAnswer;
+import org.apache.cloudstack.network.opendaylight.api.NeutronRestApiException;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetwork;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNetworkWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNode;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodeWrapper;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronNodesList;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPort;
+import org.apache.cloudstack.network.opendaylight.api.model.NeutronPortWrapper;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNetworksNorthboundAction;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronNodesNorthboundAction;
+import org.apache.cloudstack.network.opendaylight.api.resources.NeutronPortsNorthboundAction;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+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.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.resource.ServerResource;
+
+public class OpenDaylightControllerResource implements ServerResource {
+ private static final Logger s_logger = Logger.getLogger(OpenDaylightControllerResource.class);
+ private Map configuration = new HashMap();
+
+ private URL controllerUrl;
+ private String controllerUsername;
+ private String controllerPassword;
+
+ private int runLevel;
+
+ @Override
+ public String getName() {
+ if (configuration.containsKey("name"))
+ return (String)configuration.get("name");
+ else
+ return null;
+ }
+
+ @Override
+ public void setName(String name) {
+ configuration.put("name", name);
+ }
+
+ @Override
+ public void setConfigParams(Map params) {
+ for (Entry entry : params.entrySet()) {
+ configuration.put(entry.getKey(), entry.getValue());
+ }
+ updateConfiguration();
+ }
+
+ @Override
+ public Map getConfigParams() {
+ return Collections.unmodifiableMap(configuration);
+ }
+
+ @Override
+ public int getRunLevel() {
+ return runLevel;
+ }
+
+ @Override
+ public void setRunLevel(int level) {
+ runLevel = level;
+ }
+
+ @Override
+ public boolean configure(String name, Map params) throws ConfigurationException {
+ for (Entry entry : params.entrySet()) {
+ configuration.put(entry.getKey(), entry.getValue());
+ }
+ updateConfiguration();
+ return true;
+ }
+
+ @Override
+ public boolean start() {
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ return true;
+ }
+
+ @Override
+ public Type getType() {
+ return Type.L2Networking;
+ }
+
+ @Override
+ public StartupCommand[] initialize() {
+ StartupOpenDaylightControllerCommand sc = new StartupOpenDaylightControllerCommand();
+ sc.setGuid((String)configuration.get("guid"));
+ sc.setName(getName());
+ sc.setDataCenter((String)configuration.get("zoneId"));
+ sc.setPod("");
+ sc.setPrivateIpAddress("");
+ sc.setStorageIpAddress("");
+ sc.setVersion(OpenDaylightControllerResource.class.getPackage().getImplementationVersion());
+ 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 ConfigureNetworkCommand) {
+ return executeRequest((ConfigureNetworkCommand)cmd);
+ } else if (cmd instanceof DestroyNetworkCommand) {
+ return executeRequest((DestroyNetworkCommand)cmd);
+ } else if (cmd instanceof ConfigurePortCommand) {
+ return executeRequest((ConfigurePortCommand)cmd);
+ } else if (cmd instanceof DestroyPortCommand) {
+ return executeRequest((DestroyPortCommand)cmd);
+ } else if (cmd instanceof AddHypervisorCommand) {
+ return executeRequest((AddHypervisorCommand)cmd);
+ } else if (cmd instanceof ReadyCommand) {
+ return executeRequest((ReadyCommand)cmd);
+ } else if (cmd instanceof MaintainCommand) {
+ return executeRequest((MaintainCommand)cmd);
+ } else {
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+ }
+
+ @Override
+ public void disconnected() {
+ s_logger.warn("OpenDaylightControllerResource is disconnected from the controller at " + controllerUrl);
+
+ }
+
+ @Override
+ public IAgentControl getAgentControl() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setAgentControl(IAgentControl agentControl) {
+ // TODO Auto-generated method stub
+
+ }
+
+ private Answer executeRequest(final ReadyCommand cmd) {
+ return new ReadyAnswer(cmd);
+ }
+
+ private Answer executeRequest(final MaintainCommand cmd) {
+ return new MaintainAnswer(cmd);
+ }
+
+ private Answer executeRequest(ConfigureNetworkCommand cmd) {
+ NeutronNetworksNorthboundAction configureNetwork = new NeutronNetworksNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+ NeutronNetwork newNetwork = new NeutronNetwork();
+
+ // Configuration from the command
+ newNetwork.setName(cmd.getName());
+ newNetwork.setTenantId(cmd.getTenantId());
+
+ // Static configuation
+ newNetwork.setNetworkType("gre");
+ newNetwork.setShared(false);
+ newNetwork.setSegmentationId(100);
+ newNetwork.setId(UUID.randomUUID());
+
+ NeutronNetworkWrapper wrapper = new NeutronNetworkWrapper();
+ wrapper.setNetwork(newNetwork);
+ try {
+ wrapper = configureNetwork.createNeutronNetwork(wrapper);
+ } catch (NeutronRestApiException e) {
+ s_logger.error("createNeutronNetwork failed", e);
+ return new ConfigureNetworkAnswer(cmd, e);
+ }
+
+ return new ConfigureNetworkAnswer(cmd, true, null, wrapper.getNetwork().getId().toString());
+ }
+
+ private Answer executeRequest(DestroyNetworkCommand cmd) {
+ NeutronNetworksNorthboundAction configureNetwork = new NeutronNetworksNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+ try {
+ configureNetwork.deleteNeutronNetwork(cmd.getNetworkUuid());
+ } catch (NeutronRestApiException e) {
+ s_logger.error("deleteNeutronNetwork failed", e);
+ return new DestroyNetworkAnswer(cmd, e);
+ }
+
+ return new DestroyNetworkAnswer(cmd, true, "Network " + cmd.getNetworkUuid() + " deleted");
+ }
+
+ private Answer executeRequest(ConfigurePortCommand cmd) {
+ NeutronPortsNorthboundAction configurePort = new NeutronPortsNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+ NeutronPort newPort = new NeutronPort();
+
+ // Configuration from the command
+ newPort.setId(cmd.getPortId());
+ newPort.setTenantId(cmd.getTennantId());
+ newPort.setAdminStateUp(true);
+ newPort.setName(cmd.getPortId().toString());
+ newPort.setNetworkId(cmd.getNetworkId());
+ newPort.setMacAddress(cmd.getMacAddress());
+ newPort.setDeviceId(UUID.randomUUID());
+
+ // Static valus
+ newPort.setStatus("ACTIVE");
+ newPort.setFixedIps(Collections. emptyList());
+
+ NeutronPortWrapper portWrapper = new NeutronPortWrapper();
+ portWrapper.setPort(newPort);
+ try {
+ portWrapper = configurePort.createNeutronPort(portWrapper);
+ } catch (NeutronRestApiException e) {
+ s_logger.error("createPortCommand failed", e);
+ return new ConfigurePortAnswer(cmd, e);
+ }
+
+ return new ConfigurePortAnswer(cmd, true, "Port " + portWrapper.getPort().getId().toString() + " created");
+
+ }
+
+ private Answer executeRequest(DestroyPortCommand cmd) {
+ NeutronPortsNorthboundAction configurePort = new NeutronPortsNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+ try {
+ configurePort.deleteNeutronPort(cmd.getPortId().toString());
+ } catch (NeutronRestApiException e) {
+ s_logger.error("deleteNeutronPort failed", e);
+ return new DestroyPortAnswer(cmd, e);
+ }
+
+ return new DestroyPortAnswer(cmd, true, "Port " + cmd.getPortId().toString() + " deleted");
+ }
+
+ private Answer executeRequest(AddHypervisorCommand cmd) {
+ NeutronNodesNorthboundAction nodeActions = new NeutronNodesNorthboundAction(controllerUrl, controllerUsername, controllerPassword);
+ try {
+ NeutronNodesList nodes = nodeActions.listAllNodes();
+ if (nodes.getNodes() != null) {
+ for (NeutronNodeWrapper nodeWrapper : nodes.getNodes()) {
+ NeutronNode node = nodeWrapper.getNode();
+ if (node.getId().equals(cmd.getHostId())) {
+ return new AddHypervisorAnswer(cmd, true, "Hypervisor already connected");
+ }
+ }
+ }
+
+ // Not found in the existing node list, add it
+ nodeActions.updateNeutronNodeV2("OVS", cmd.getHostId(), cmd.getIpAddress(), 6640);
+ } catch (NeutronRestApiException e) {
+ s_logger.error("Call to OpenDaylight failed", e);
+ return new AddHypervisorAnswer(cmd, e);
+ }
+ return new AddHypervisorAnswer(cmd, true, "Hypervisor " + cmd.getHostId() + " added");
+ }
+
+ private void updateConfiguration() {
+ if (!configuration.containsKey("url") || !configuration.containsKey("username") || !configuration.containsKey("password"))
+ throw new InvalidParameterException("OpenDaylightControllerResource needs a url, username and password.");
+ try {
+ controllerUrl = new URL((String)configuration.get("url"));
+ } catch (MalformedURLException e) {
+ throw new InvalidParameterException("OpenDaylightControllerResource found an invalid controller url");
+ }
+ controllerUsername = (String)configuration.get("username");
+ controllerPassword = (String)configuration.get("password");
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
new file mode 100644
index 00000000000..1bc0e82a82a
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManager.java
@@ -0,0 +1,34 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent;
+
+import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.utils.component.PluggableService;
+
+public interface OpenDaylightControllerResourceManager extends PluggableService {
+
+ public OpenDaylightControllerVO addController(AddOpenDaylightControllerCmd cmd);
+
+ public void deleteController(DeleteOpenDaylightControllerCmd cmd) throws InvalidParameterValueException;
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
new file mode 100644
index 00000000000..ad4db158900
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/OpenDaylightControllerResourceManagerImpl.java
@@ -0,0 +1,173 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
+import org.apache.cloudstack.network.opendaylight.api.commands.AddOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.api.commands.DeleteOpenDaylightControllerCmd;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDao;
+import org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerVO;
+
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.network.Network;
+import com.cloud.network.Networks;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.network.dao.PhysicalNetworkVO;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallback;
+import com.cloud.utils.db.TransactionStatus;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class OpenDaylightControllerResourceManagerImpl implements OpenDaylightControllerResourceManager {
+ private final static Logger s_logger = Logger.getLogger(OpenDaylightControllerResourceManagerImpl.class);
+
+ @Inject
+ HostDao hostDao;
+ @Inject
+ ResourceManager resourceManager;
+ @Inject
+ PhysicalNetworkDao physicalNetworkDao;
+ @Inject
+ PhysicalNetworkServiceProviderDao physicalNetworkServiceProviderDao;
+ @Inject
+ OpenDaylightControllerMappingDao openDaylightControllerMappingDao;
+ @Inject
+ NetworkDao networkDao;
+
+ @Override
+ public List> getCommands() {
+ List> commands = new ArrayList>();
+ commands.add(AddOpenDaylightControllerCmd.class);
+ return commands;
+ }
+
+ @Override
+ public OpenDaylightControllerVO addController(AddOpenDaylightControllerCmd cmd) {
+ ServerResource odlController = new OpenDaylightControllerResource();
+
+ final String deviceName = NetworkDevice.OpenDaylightController.getName();
+ NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName);
+ final Long physicalNetworkId = cmd.getPhysicalNetworkId();
+ PhysicalNetworkVO physicalNetwork = physicalNetworkDao.findById(physicalNetworkId);
+ if (physicalNetwork == null) {
+ throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId);
+ }
+ long zoneId = physicalNetwork.getDataCenterId();
+
+ final 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");
+ }
+
+ final Map hostParams = new HashMap();
+ hostParams.put("guid", UUID.randomUUID().toString());
+ hostParams.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
+ hostParams.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
+ hostParams.put("name", "ODL Controller - " + hostParams.get("guid"));
+ hostParams.put("url", cmd.getUrl());
+ hostParams.put("username", cmd.getUsername());
+ hostParams.put("password", cmd.getPassword());
+
+ Map hostdetails = new HashMap();
+ hostdetails.putAll(hostParams);
+
+ try {
+ odlController.configure(hostParams.get("name"), hostdetails);
+ final Host host = resourceManager.addHost(zoneId, odlController, Host.Type.L2Networking, hostParams);
+ if (host != null) {
+ return Transaction.execute(new TransactionCallback() {
+ @Override
+ public OpenDaylightControllerVO doInTransaction(TransactionStatus status) {
+ OpenDaylightControllerVO controller = new OpenDaylightControllerVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), hostParams
+ .get("name"));
+ openDaylightControllerMappingDao.persist(controller);
+ return controller;
+ }
+ });
+ } else {
+ throw new CloudRuntimeException("Failed to create host object for ODL Controller");
+ }
+ } catch (ConfigurationException e) {
+ throw new CloudRuntimeException("Failed to add ODL Controller as a resource", e);
+ }
+ }
+
+ @Override
+ public void deleteController(DeleteOpenDaylightControllerCmd cmd) throws InvalidParameterValueException {
+ OpenDaylightControllerVO controller = openDaylightControllerMappingDao.findById(cmd.getId());
+ if (controller == null) {
+ throw new InvalidParameterValueException("No ODL Controller with id " + cmd.getId());
+ }
+
+ // Find the physical network we work for
+ Long physicalNetworkId = controller.getPhysicalNetworkId();
+ PhysicalNetworkVO physicalNetwork = physicalNetworkDao.findById(physicalNetworkId);
+ if (physicalNetwork != null) {
+ // Lets see if there are networks that use us
+ List networkList = networkDao.listByPhysicalNetwork(physicalNetworkId);
+
+ // Networks with broadcast type lswitch are ours
+ for (NetworkVO network : networkList) {
+ if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.OpenDaylight) {
+ if ((network.getState() != Network.State.Shutdown) && (network.getState() != Network.State.Destroy)) {
+ throw new CloudRuntimeException("This Controller can not be deleted as there are one or more logical networks provisioned by cloudstack.");
+ }
+ }
+ }
+ }
+
+ HostVO host = hostDao.findById(controller.getHostId());
+ Long hostId = host.getId();
+
+ host.setResourceState(ResourceState.Maintenance);
+ hostDao.update(hostId, host);
+ resourceManager.deleteHost(hostId, false, false);
+
+ openDaylightControllerMappingDao.remove(cmd.getId());
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java
new file mode 100644
index 00000000000..06e94b35390
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/AddHypervisorCommand.java
@@ -0,0 +1,58 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class AddHypervisorCommand extends Command {
+ private String hostId;
+ private String ipAddress;
+
+ public AddHypervisorCommand() {
+ }
+
+ public AddHypervisorCommand(String hostId, String ipAddress) {
+ this.hostId = hostId;
+ this.ipAddress = ipAddress;
+ }
+
+ public String getHostId() {
+ return hostId;
+ }
+
+ public void setHostId(String hostId) {
+ this.hostId = hostId;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java
new file mode 100644
index 00000000000..bfbcde4ca43
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigureNetworkCommand.java
@@ -0,0 +1,54 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class ConfigureNetworkCommand extends Command {
+ private String name;
+ private String tenantId;
+
+ public ConfigureNetworkCommand(String name, String tenantId) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(String tennantId) {
+ tenantId = tennantId;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java
new file mode 100644
index 00000000000..3d4d2a2a69a
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/ConfigurePortCommand.java
@@ -0,0 +1,80 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import java.util.UUID;
+
+import com.cloud.agent.api.Command;
+
+public class ConfigurePortCommand extends Command {
+ private UUID networkId;
+ private String tennantId;
+ private String macAddress;
+ private UUID portId;
+
+ public ConfigurePortCommand() {
+ }
+
+ public ConfigurePortCommand(UUID portId, UUID networkId, String tennantId, String macAddress) {
+ this.portId = portId;
+ this.networkId = networkId;
+ this.tennantId = tennantId;
+ this.macAddress = macAddress;
+ }
+
+ public UUID getNetworkId() {
+ return networkId;
+ }
+
+ public void setNetworkId(UUID networkId) {
+ this.networkId = networkId;
+ }
+
+ public String getTennantId() {
+ return tennantId;
+ }
+
+ public void setTennantId(String tennantId) {
+ this.tennantId = tennantId;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public UUID getPortId() {
+ return portId;
+ }
+
+ public void setPortId(UUID portId) {
+ this.portId = portId;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java
new file mode 100644
index 00000000000..6d1bc044315
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyNetworkCommand.java
@@ -0,0 +1,45 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import com.cloud.agent.api.Command;
+
+public class DestroyNetworkCommand extends Command {
+ private String networkUuid;
+
+ public DestroyNetworkCommand(String networkUuid) {
+ this.networkUuid = networkUuid;
+ }
+
+ public String getNetworkUuid() {
+ return networkUuid;
+ }
+
+ public void setNetworkUuid(String networkUuid) {
+ this.networkUuid = networkUuid;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java
new file mode 100644
index 00000000000..c0a89371c1a
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/DestroyPortCommand.java
@@ -0,0 +1,50 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import java.util.UUID;
+
+import com.cloud.agent.api.Command;
+
+public class DestroyPortCommand extends Command {
+ private UUID portId;
+
+ public DestroyPortCommand() {
+ }
+
+ public DestroyPortCommand(UUID portId) {
+ this.portId = portId;
+ }
+
+ public UUID getPortId() {
+ return portId;
+ }
+
+ public void setPortId(UUID portId) {
+ this.portId = portId;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java
new file mode 100644
index 00000000000..de3a7a3b54b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/commands/StartupOpenDaylightControllerCommand.java
@@ -0,0 +1,29 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.agent.commands;
+
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.host.Host;
+
+public class StartupOpenDaylightControllerCommand extends StartupCommand {
+ public StartupOpenDaylightControllerCommand() {
+ super(Host.Type.L2Networking);
+ }
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java
new file mode 100644
index 00000000000..79867051e13
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/AddHypervisorAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class AddHypervisorAnswer extends Answer {
+
+ public AddHypervisorAnswer(Command command, boolean success, String details) {
+ super(command, success, details);
+ }
+
+ public AddHypervisorAnswer(Command command, Exception e) {
+ super(command, e);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.java
new file mode 100644
index 00000000000..81c4a6fd45d
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigureNetworkAnswer.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 org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class ConfigureNetworkAnswer extends Answer {
+ private String networkUuid;
+
+ public ConfigureNetworkAnswer(Command command, boolean success, String details, String networkUuid) {
+ this.networkUuid = networkUuid;
+ }
+
+ public ConfigureNetworkAnswer(Command command, boolean success, String details) {
+ super(command, success, details);
+ }
+
+ public ConfigureNetworkAnswer(Command command, Exception e) {
+ super(command, e);
+ }
+
+ public String getNetworkUuid() {
+ return networkUuid;
+ }
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java
new file mode 100644
index 00000000000..cf9acc1d535
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/ConfigurePortAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class ConfigurePortAnswer extends Answer {
+
+ public ConfigurePortAnswer(Command command, boolean success, String details) {
+ super(command, success, details);
+ }
+
+ public ConfigurePortAnswer(Command command, Exception e) {
+ super(command, e);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java
new file mode 100644
index 00000000000..10284b4918b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyNetworkAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class DestroyNetworkAnswer extends Answer {
+
+ public DestroyNetworkAnswer(Command command, boolean success, String details) {
+ super(command, success, details);
+ }
+
+ public DestroyNetworkAnswer(Command command, Exception e) {
+ super(command, e);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java
new file mode 100644
index 00000000000..07bb0dbfff3
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/agent/responses/DestroyPortAnswer.java
@@ -0,0 +1,35 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network.opendaylight.agent.responses;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class DestroyPortAnswer extends Answer {
+
+ public DestroyPortAnswer(Command command, boolean success, String details) {
+ super(command, success, details);
+ }
+
+ public DestroyPortAnswer(Command command, Exception e) {
+ super(command, e);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java
new file mode 100644
index 00000000000..87999821ef8
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDao.java
@@ -0,0 +1,28 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.dao;
+
+import java.util.List;
+
+import com.cloud.utils.db.GenericDao;
+
+public interface OpenDaylightControllerMappingDao extends GenericDao {
+ List listByPhysicalNetwork(long physicalNetworkId);
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java
new file mode 100644
index 00000000000..1d0becaef56
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerMappingDaoImpl.java
@@ -0,0 +1,45 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.dao;
+
+import java.util.List;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+public class OpenDaylightControllerMappingDaoImpl extends GenericDaoBase implements OpenDaylightControllerMappingDao {
+ private SearchBuilder physicalNetworkIdSearch;
+
+ public OpenDaylightControllerMappingDaoImpl() {
+ physicalNetworkIdSearch = createSearchBuilder();
+ physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ);
+ physicalNetworkIdSearch.done();
+ }
+
+ @Override
+ public List listByPhysicalNetwork(long physicalNetworkId) {
+ SearchCriteria sc = physicalNetworkIdSearch.create();
+ sc.setParameters("physicalNetworkId", physicalNetworkId);
+ return search(sc, null);
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
new file mode 100644
index 00000000000..61d5682bde6
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/dao/OpenDaylightControllerVO.java
@@ -0,0 +1,101 @@
+//
+// 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 org.apache.cloudstack.network.opendaylight.dao;
+
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name = "external_opendaylight_controllers")
+public class OpenDaylightControllerVO implements InternalIdentity {
+ private static final long serialVersionUID = -575928081553194369L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "uuid")
+ private String uuid;
+
+ @Column(name = "host_id")
+ private long hostId;
+
+ @Column(name = "physical_network_id")
+ private long physicalNetworkId;
+
+ @Column(name = "provider_name")
+ private String providerName;
+
+ @Column(name = "device_name")
+ private String deviceName;
+
+ public OpenDaylightControllerVO() {
+ uuid = UUID.randomUUID().toString();
+ }
+
+ public OpenDaylightControllerVO(final long hostId, final long physicalNetworkId, final String providerName, final String deviceName) {
+ super();
+ this.hostId = hostId;
+ this.physicalNetworkId = physicalNetworkId;
+ this.providerName = providerName;
+ this.deviceName = deviceName;
+ uuid = UUID.randomUUID().toString();
+ }
+
+ @Override
+ public long getId() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public long getPhysicalNetworkId() {
+ return physicalNetworkId;
+ }
+
+ public long getHostId() {
+ return hostId;
+ }
+
+ public String getProviderName() {
+ return providerName;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+}
diff --git a/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties
new file mode 100644
index 00000000000..36d2331db5b
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/module.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+name=opendaylight
+parent=network
diff --git a/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml
new file mode 100644
index 00000000000..76b6a920c70
--- /dev/null
+++ b/plugins/network-elements/opendaylight/src/main/resources/META-INF/cloudstack/opendaylight/spring-opendaylight-context.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 8ec6a711376..85a7bbee3ee 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -51,6 +51,7 @@
network-elements/bigswitch-vns
network-elements/midonet
network-elements/stratosphere-ssp
+ network-elements/opendaylight
storage-allocators/random
user-authenticators/ldap
user-authenticators/md5