Add a network plugin for OpenDaylight

This plugin is a technology preview and designed to work with the OVSDB module
This commit is contained in:
Hugo Trippaers 2013-12-19 10:50:44 +01:00
parent cbe2560a78
commit 1f9528bad3
24 changed files with 1863 additions and 0 deletions

16
LICENSE.header Normal file
View File

@ -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.

View File

@ -0,0 +1,132 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-plugin-network-opendaylight</artifactId>
<name>Apache CloudStack Plugin - Network Opendaylight</name>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.4.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<!-- not parenting to the maven-default pom, as we want this in services -->
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<testOutputDirectory>${basedir}/target/test-classes</testOutputDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${basedir}/src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>checkstyle</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<failsOnError>true</failsOnError>
<configLocation>tooling/checkstyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<sourceDirectory>${project.basedir}</sourceDirectory>
<includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat</includes>
<excludes>**\/target\/,**\/bin\/</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.mycila.maven-license-plugin</groupId>
<artifactId>maven-license-plugin</artifactId>
<version>1.9.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
<configuration>
<strictCheck>true</strictCheck>
<aggregate>true</aggregate>
<header>../../../LICENSE.header</header>
<mapping>
<xml>XML_STYLE</xml>
    <java>DOUBLESLASH_STYLE</java>
    <clj>SEMICOLON_STYLE</clj>
</mapping>
<useDefaultExcludes>false</useDefaultExcludes>
<excludes>
<exclude>target/**</exclude>
<exclude>.settings/**</exclude>
<exclude>.checkstyle</exclude>
<exclude>.project</exclude>
<exclude>.classpath</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -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<Service, Map<Capability, String>> s_capabilities = setCapabilities();
@Inject
ResourceManager resourceManager;
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return s_capabilities;
}
@Override
public Provider getProvider() {
return Provider.Opendaylight;
}
@Override
public boolean configure(String name, Map<String, Object> 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<Service> 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<String, String> details, List<String> 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<Service, Map<Capability, String>> setCapabilities() {
Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
// L2 Support : SDN provisioning
capabilities.put(Service.Connectivity, null);
return capabilities;
}
}

View File

@ -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<OpenDaylightControllerVO> 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<OpenDaylightControllerVO> 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<OpenDaylightControllerVO> 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<OpenDaylightControllerVO> 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<OpenDaylightControllerVO> 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);
}
}

View File

@ -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<String, Object> configuration = new HashMap<String, Object>();
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<String, Object> params) {
for (Entry<String, Object> entry : params.entrySet()) {
configuration.put(entry.getKey(), entry.getValue());
}
updateConfiguration();
}
@Override
public Map<String, Object> 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<String, Object> params) throws ConfigurationException {
for (Entry<String, Object> 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.<String> 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<NeutronNodeWrapper> 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");
}
}

View File

@ -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;
}

View File

@ -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<Class<?>> getCommands() {
List<Class<?>> commands = new ArrayList<Class<?>>();
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<String, String> hostParams = new HashMap<String, String>();
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<String, Object> hostdetails = new HashMap<String, Object>();
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<OpenDaylightControllerVO>() {
@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<NetworkVO> 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());
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<OpenDaylightControllerVO, Long> {
List<OpenDaylightControllerVO> listByPhysicalNetwork(long physicalNetworkId);
}

View File

@ -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<OpenDaylightControllerVO, Long> implements OpenDaylightControllerMappingDao {
private SearchBuilder<OpenDaylightControllerVO> physicalNetworkIdSearch;
public OpenDaylightControllerMappingDaoImpl() {
physicalNetworkIdSearch = createSearchBuilder();
physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ);
physicalNetworkIdSearch.done();
}
@Override
public List<OpenDaylightControllerVO> listByPhysicalNetwork(long physicalNetworkId) {
SearchCriteria<OpenDaylightControllerVO> sc = physicalNetworkIdSearch.create();
sc.setParameters("physicalNetworkId", physicalNetworkId);
return search(sc, null);
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,42 @@
<!--
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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
<bean id="OpendaylightGuestNetworkGuru" class="org.apache.cloudstack.network.opendaylight.OpendaylightGuestNetworkGuru">
<property name="name" value="OpendaylightGuestNetworkGuru" />
</bean>
<bean id="OpendaylightElement" class="org.apache.cloudstack.network.opendaylight.OpendaylightElement">
<property name="name" value="OpendaylightElement" />
</bean>
<bean id="OpenDaylightControllerResourceManager" class="org.apache.cloudstack.network.opendaylight.agent.OpenDaylightControllerResourceManagerImpl"/>
<bean id="OpenDaylightControllerMappingDao" class="org.apache.cloudstack.network.opendaylight.dao.OpenDaylightControllerMappingDaoImpl" />
</beans>

View File

@ -51,6 +51,7 @@
<module>network-elements/bigswitch-vns</module>
<module>network-elements/midonet</module>
<module>network-elements/stratosphere-ssp</module>
<module>network-elements/opendaylight</module>
<module>storage-allocators/random</module>
<module>user-authenticators/ldap</module>
<module>user-authenticators/md5</module>