YuanyouZhang
Committed by Gerrit Code Review

[ONOS-2262] - OVSDB -- Create the implementation of HostProvider using

OVSDB prototol.
1.Notify the Host System when the ovsdb vm port is added.
2.Notify the Host System when the ovsdb vm port is removed.

Change-Id: I46355cec84db897360a6eb37190a5bd7a8f3047d
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.controller;
import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Objects;
import java.util.Set;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
/**
* This class is default event subject that implements OvsdbEventSubject.
*/
public class DefaultEventSubject implements OvsdbEventSubject {
private final MacAddress mac;
private final Set<IpAddress> ips;
private final OvsdbPortName portname;
private final OvsdbPortNumber portnumber;
private final OvsdbDatapathId dpid;
private final OvsdbPortType portType;
private final OvsdbIfaceId ifaceid;
/**
* Creates an end-station event subject using the supplied information.
*
* @param mac host MAC address
* @param ips host MAC ips
* @param portname port name
* @param portnumber port number
* @param dpid ovs dpid
* @param portType port type
* @param ifaceid vm ifaceid
*/
public DefaultEventSubject(MacAddress mac, Set<IpAddress> ips,
OvsdbPortName portname, OvsdbPortNumber portnumber, OvsdbDatapathId dpid,
OvsdbPortType portType, OvsdbIfaceId ifaceid) {
super();
this.mac = mac;
this.ips = ips;
this.portname = portname;
this.portnumber = portnumber;
this.dpid = dpid;
this.portType = portType;
this.ifaceid = ifaceid;
}
@Override
public MacAddress hwAddress() {
return mac;
}
@Override
public Set<IpAddress> ipAddress() {
return ips;
}
@Override
public OvsdbPortName portName() {
return portname;
}
@Override
public OvsdbPortNumber portNumber() {
return portnumber;
}
@Override
public OvsdbPortType portType() {
return portType;
}
@Override
public OvsdbDatapathId dpid() {
return dpid;
}
@Override
public OvsdbIfaceId ifaceid() {
return ifaceid;
}
@Override
public int hashCode() {
return Objects.hash(mac, portname, portnumber, dpid, portType, ifaceid);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultEventSubject) {
final DefaultEventSubject other = (DefaultEventSubject) obj;
return Objects.equals(this.mac, other.mac)
&& Objects.equals(this.portname, other.portname)
&& Objects.equals(this.portnumber, other.portnumber)
&& Objects.equals(this.dpid, other.dpid)
&& Objects.equals(this.portType, other.portType)
&& Objects.equals(this.ifaceid, other.ifaceid);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("mac", mac).add("portname", portname)
.add("portnumber", portnumber).add("portType", portType)
.add("ipAddresses", ips).add("dpid", dpid).add("ifaceid", ifaceid)
.toString();
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.controller;
import java.util.Set;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
/**
* Represents for a entity that carry important information for listener.
*/
public interface OvsdbEventSubject extends EventSubject {
/**
* Returns the MAC address associated with this host (NIC).
*
* @return the MAC address of this host
*/
MacAddress hwAddress();
/**
* Returns the IP address associated with this host's MAC.
*
* @return host IP address
*/
Set<IpAddress> ipAddress();
/**
* Returns the Port name associated with the host.
*
* @return port name
*/
OvsdbPortName portName();
/**
* Returns the Port number associated with the host.
*
* @return port number
*/
OvsdbPortNumber portNumber();
/**
* Returns the Port type associated with the host.
*
* @return port type
*/
OvsdbPortType portType();
/**
* Returns the Ovs dpid associated with the host.
*
* @return Ovs dpid
*/
OvsdbDatapathId dpid();
/**
* Returns the vm ifaceid associated with the host.
*
* @return vm ifaceid
*/
OvsdbIfaceId ifaceid();
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.controller;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
* The class representing a ifaceid. This class is immutable.
*/
public class OvsdbIfaceId {
private final String value;
/**
* Constructor from a String ifaceid.
*
* @param value the ifaceid to use
*/
public OvsdbIfaceId(String value) {
checkNotNull(value, "value is not null");
this.value = value;
}
/**
* Gets the value of the ifaceid.
*
* @return the value of the ifaceid
*/
public String value() {
return value;
}
@Override
public int hashCode() {
return Objects.hash(value);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof OvsdbIfaceId) {
final OvsdbIfaceId otherIfaceId = (OvsdbIfaceId) obj;
return Objects.equals(this.value, otherIfaceId.value);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("value", value).toString();
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.controller;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
* The class representing a port type. This class is immutable.
*/
public class OvsdbPortType {
private final String value;
/**
* Constructor from a String port type.
*
* @param value the port type to use
*/
public OvsdbPortType(String value) {
checkNotNull(value, "value is not null");
this.value = value;
}
/**
* Gets the value of the port type.
*
* @return the value of the port type
*/
public String value() {
return value;
}
@Override
public int hashCode() {
return Objects.hash(value);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof OvsdbPortType) {
final OvsdbPortType otherOvsdbPortType = (OvsdbPortType) obj;
return Objects.equals(this.value, otherOvsdbPortType.value);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("value", value).toString();
}
}
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-ovsdb-providers</artifactId>
<version>1.3.0-SNAPSHOT</version>
</parent>
<artifactId>onos-ovsdb-provider-host</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-ovsdb-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.provider.host;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.toHex;
import static org.slf4j.LoggerFactory.getLogger;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.VlanId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.ovsdb.controller.EventSubject;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbEvent;
import org.onosproject.ovsdb.controller.OvsdbEventListener;
import org.onosproject.ovsdb.controller.OvsdbEventSubject;
import org.slf4j.Logger;
/**
* Provider which uses an ovsdb controller to detect host.
*/
@Component(immediate = true)
@Service
public class OvsdbHostProvider extends AbstractProvider implements HostProvider {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostProviderRegistry providerRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OvsdbController controller;
private HostProviderService providerService;
private OvsdbEventListener innerEventListener = new InnerOvsdbEventListener();
@Activate
public void activate() {
providerService = providerRegistry.register(this);
controller.addOvsdbEventListener(innerEventListener);
log.info("Started");
}
@Deactivate
public void deactivate() {
providerRegistry.unregister(this);
providerService = null;
log.info("Stopped");
}
public OvsdbHostProvider() {
super(new ProviderId("ovsdb", "org.onosproject.ovsdb.provider.host"));
}
@Override
public void triggerProbe(Host host) {
log.info("Triggering probe on host {}", host);
}
private class InnerOvsdbEventListener implements OvsdbEventListener {
@Override
public void handle(OvsdbEvent<EventSubject> event) {
OvsdbEventSubject subject = null;
if (event.subject() instanceof OvsdbEventSubject) {
subject = (OvsdbEventSubject) event.subject();
}
checkNotNull(subject, "EventSubject is not null");
// If ifaceid is null,it indicates this is not a vm port.
if (subject.ifaceid() == null) {
return;
}
switch (event.type()) {
case PORT_ADDED:
HostId hostId = HostId.hostId(subject.hwAddress(), null);
DeviceId deviceId = DeviceId.deviceId(uri(subject.dpid().value()));
PortNumber portNumber = PortNumber.portNumber(subject
.portNumber().value(), subject.portName().value());
HostLocation loaction = new HostLocation(deviceId, portNumber,
0L);
DefaultAnnotations annotations = DefaultAnnotations.builder()
.set("ifaceid", subject.ifaceid().value()).build();
HostDescription hostDescription = new DefaultHostDescription(
subject.hwAddress(),
VlanId.vlanId(),
loaction,
annotations);
providerService.hostDetected(hostId, hostDescription);
break;
case PORT_REMOVED:
HostId host = HostId.hostId(subject.hwAddress(), null);
providerService.hostVanished(host);
break;
default:
break;
}
}
}
public URI uri(String value) {
try {
return new URI("of", toHex(Long.valueOf(value)), null);
} catch (URISyntaxException e) {
return null;
}
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.
*/
/**
*Provider that uses ovsdb controller as a means of infrastructure host discovery.
*
*/
package org.onosproject.ovsdb.provider.host;
\ No newline at end of file
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed 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.onosproject.ovsdb.provider.host;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.ovsdb.controller.DefaultEventSubject;
import org.onosproject.ovsdb.controller.EventSubject;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbDatapathId;
import org.onosproject.ovsdb.controller.OvsdbEvent;
import org.onosproject.ovsdb.controller.OvsdbEventListener;
import org.onosproject.ovsdb.controller.OvsdbIfaceId;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbNodeListener;
import org.onosproject.ovsdb.controller.OvsdbPortName;
import org.onosproject.ovsdb.controller.OvsdbPortNumber;
import org.onosproject.ovsdb.controller.OvsdbPortType;
/**
* Test for ovsdb host provider.
*/
public class OvsdbHostProviderTest {
private static final MacAddress MAC = MacAddress
.valueOf("00:00:11:00:00:01");
private final OvsdbHostProvider provider = new OvsdbHostProvider();
private final TestHostRegistry hostRegistry = new TestHostRegistry();
protected OvsdbControllerTest controller = new OvsdbControllerTest();
private TestHostProviderService providerService;
@Before
public void setUp() {
provider.providerRegistry = hostRegistry;
provider.controller = controller;
provider.activate();
}
@Test
public void basics() {
assertNotNull("registration expected", providerService);
assertEquals("incorrect provider", provider, providerService.provider());
}
@Test
public void portAdded() {
DefaultEventSubject eventSubject = new DefaultEventSubject(MAC, null,
new OvsdbPortName("portName"),
new OvsdbPortNumber(0L),
new OvsdbDatapathId("10002"),
new OvsdbPortType("vxlan"),
new OvsdbIfaceId("102345"));
controller.ovsdbEventListener
.handle(new OvsdbEvent<EventSubject>(
OvsdbEvent.Type.PORT_ADDED,
eventSubject));
assertNotNull("never went throught the provider service",
providerService.added);
}
@Test
public void portRemoved() {
DefaultEventSubject eventSubject = new DefaultEventSubject(MAC, null,
new OvsdbPortName("portName"),
new OvsdbPortNumber(0L),
new OvsdbDatapathId("10002"),
new OvsdbPortType("vxlan"),
new OvsdbIfaceId("102345"));
controller.ovsdbEventListener
.handle(new OvsdbEvent<EventSubject>(
OvsdbEvent.Type.PORT_REMOVED,
eventSubject));
assertEquals("port status unhandled", 1, providerService.removeCount);
}
@After
public void tearDown() {
provider.deactivate();
provider.coreService = null;
provider.providerRegistry = null;
}
private class TestHostRegistry implements HostProviderRegistry {
@Override
public HostProviderService register(HostProvider provider) {
providerService = new TestHostProviderService(provider);
return providerService;
}
@Override
public void unregister(HostProvider provider) {
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
}
private class TestHostProviderService
extends AbstractProviderService<HostProvider>
implements HostProviderService {
DeviceId added = null;
DeviceId moved = null;
DeviceId spine = null;
public int removeCount;
protected TestHostProviderService(HostProvider provider) {
super(provider);
}
@Override
public void hostDetected(HostId hostId, HostDescription hostDescription) {
DeviceId descr = hostDescription.location().deviceId();
if (added == null) {
added = descr;
} else if ((moved == null) && !descr.equals(added)) {
moved = descr;
} else {
spine = descr;
}
}
@Override
public void hostVanished(HostId hostId) {
removeCount++;
}
}
private class OvsdbControllerTest implements OvsdbController {
private OvsdbEventListener ovsdbEventListener = null;
@Override
public void addNodeListener(OvsdbNodeListener listener) {
}
@Override
public void removeNodeListener(OvsdbNodeListener listener) {
}
@Override
public void addOvsdbEventListener(OvsdbEventListener listener) {
ovsdbEventListener = listener;
}
@Override
public void removeOvsdbEventListener(OvsdbEventListener listener) {
ovsdbEventListener = null;
}
@Override
public List<OvsdbNodeId> getNodeIds() {
return null;
}
@Override
public OvsdbClientService getOvsdbClient(OvsdbNodeId nodeId) {
return null;
}
}
}
......@@ -15,6 +15,7 @@
<modules>
<module>device</module>
<module>host</module>
</modules>
<dependencies>
......