diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java index 19a39c0de9..84e178749a 100644 --- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java +++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java @@ -15,8 +15,11 @@ */ package org.onosproject.openstacknetworking.api; +import com.google.common.collect.Maps; import org.onlab.packet.MacAddress; +import java.util.Map; + /** * Provides constants used in OpenStackSwitching. */ @@ -35,6 +38,20 @@ public final class Constants { public static final MacAddress DEFAULT_GATEWAY_MAC = MacAddress.valueOf(DEFAULT_GATEWAY_MAC_STR); public static final MacAddress DEFAULT_EXTERNAL_ROUTER_MAC = MacAddress.valueOf("fe:00:00:00:00:01"); + private static final String CAVIUM_PCI_VENDOR_INFO = "177d:9712"; + private static final String PORT_NAME_PREFIX_CAVIUM = "enp"; + public static final String PCI_VENDOR_INFO = "pci_vendor_info"; + public static final String DIRECT = "direct"; + public static final String PCISLOT = "pci_slot"; + + public static final Map PORT_NAME_PREFIX_MAP = createPortNamePrefixMap(); + private static Map createPortNamePrefixMap() { + Map portNamePrefixMap = Maps.newHashMap(); + //Additional pci vendor information will be added + portNamePrefixMap.put(CAVIUM_PCI_VENDOR_INFO, PORT_NAME_PREFIX_CAVIUM); + return portNamePrefixMap; + } + public static final int PRIORITY_TUNNEL_TAG_RULE = 30000; public static final int PRIORITY_FLOATING_INTERNAL = 42000; public static final int PRIORITY_FLOATING_EXTERNAL = 41000; diff --git a/apps/openstacknetworking/app/BUCK b/apps/openstacknetworking/app/BUCK index 34933f4f33..6136f8f783 100644 --- a/apps/openstacknetworking/app/BUCK +++ b/apps/openstacknetworking/app/BUCK @@ -11,6 +11,8 @@ COMPILE_DEPS = [ '//cli:onos-cli', '//apps/openstacknode/api:onos-apps-openstacknode-api', '//apps/openstacknetworking/api:onos-apps-openstacknetworking-api', + '//protocols/ovsdb/api:onos-protocols-ovsdb-api', + '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc', '//lib:openstack4j-core', '//lib:openstack4j-http-connector', '//lib:openstack4j-httpclient', diff --git a/apps/openstacknetworking/app/pom.xml b/apps/openstacknetworking/app/pom.xml index 13ac53c7dd..fbc27fb0ab 100644 --- a/apps/openstacknetworking/app/pom.xml +++ b/apps/openstacknetworking/app/pom.xml @@ -113,6 +113,11 @@ tests test + + org.onosproject + onos-protocols-ovsdb-api + ${project.version} + org.onosproject onos-core-common diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDirectPortListCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDirectPortListCommand.java new file mode 100644 index 0000000000..319a7fa25c --- /dev/null +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDirectPortListCommand.java @@ -0,0 +1,67 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * 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.openstacknetworking.cli; + +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.openstacknetworking.api.OpenstackNetworkService; +import org.openstack4j.model.network.IP; +import org.openstack4j.model.network.Network; +import org.openstack4j.model.network.Port; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.onosproject.openstacknetworking.api.Constants.DIRECT; +import static org.onosproject.openstacknetworking.api.Constants.PCISLOT; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress; + +/** + * Lists OpenStack direct ports. + */ +@Command(scope = "onos", name = "openstack-direct-ports", + description = "Lists all OpenStack direct ports") +public class OpenstackDirectPortListCommand extends AbstractShellCommand { + private static final String UNBOUND = "unbound"; + private static final String FORMAT = "%-40s%-20s%-20s%-20s%-20s%-20s"; + + @Override + protected void execute() { + OpenstackNetworkService service = AbstractShellCommand.get(OpenstackNetworkService.class); + + List ports = service.ports().stream() + + .filter(port -> port.getvNicType().equals(DIRECT)) + .filter(port -> port.isAdminStateUp() && !port.getVifType().equals(UNBOUND)) + .collect(Collectors.toList()); + + + print(FORMAT, "ID", "Network", "MAC", "FIXED IPs", "PCI Slot", "Interface"); + for (Port port: ports) { + List fixedIps = port.getFixedIps().stream() + .map(IP::getIpAddress) + .collect(Collectors.toList()); + + Network osNet = service.network(port.getNetworkId()); + print(FORMAT, port.getId(), + osNet.getName(), + port.getMacAddress(), + fixedIps.isEmpty() ? "" : fixedIps, + port.getProfile() == null ? "" : port.getProfile().get(PCISLOT).toString(), + getIntfNameFromPciAddress(port)); + } + } +} diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenStackSwitchingDirectPortProvider.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenStackSwitchingDirectPortProvider.java new file mode 100644 index 0000000000..bd8473cf35 --- /dev/null +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenStackSwitchingDirectPortProvider.java @@ -0,0 +1,246 @@ +/* + * Copyright 2018-present Open Networking Foundation + * + * 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.openstacknetworking.impl; + +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.Modified; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.util.Tools; +import org.onosproject.cfg.ComponentConfigService; +import org.onosproject.cluster.ClusterService; +import org.onosproject.cluster.LeadershipService; +import org.onosproject.cluster.NodeId; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.mastership.MastershipService; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceService; +import org.onosproject.openstacknetworking.api.InstancePort; +import org.onosproject.openstacknetworking.api.InstancePortService; +import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent; +import org.onosproject.openstacknetworking.api.OpenstackNetworkListener; +import org.onosproject.openstacknetworking.api.OpenstackNetworkService; +import org.onosproject.openstacknode.api.OpenstackNode; +import org.onosproject.openstacknode.api.OpenstackNodeService; +import org.onosproject.ovsdb.controller.OvsdbController; +import org.openstack4j.model.network.Port; +import org.openstack4j.model.network.State; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Dictionary; +import java.util.Objects; +import java.util.Optional; + +import static org.onosproject.openstacknetworking.api.Constants.DIRECT; +import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress; +import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE; + +@Component(immediate = true) +public final class OpenStackSwitchingDirectPortProvider { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private static final String OVSDB_PORT = "ovsdbPortNum"; + private static final int DEFAULT_OVSDB_PORT = 6640; + private static final String UNBOUND = "unbound"; + private static final String PORT_NAME = "portName"; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected OpenstackNetworkService osNetworkService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected OpenstackNodeService osNodeService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected LeadershipService leadershipService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ClusterService clusterService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected OvsdbController ovsdbController; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected InstancePortService instancePortService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ComponentConfigService componentConfigService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected MastershipService mastershipService; + + @Property(name = OVSDB_PORT, intValue = DEFAULT_OVSDB_PORT, + label = "OVSDB server listen port") + private int ovsdbPort = DEFAULT_OVSDB_PORT; + + private final OpenstackNetworkListener openstackNetworkListener = new InternalOpenstackNetworkListener(); + + private NodeId localNodeId; + private ApplicationId appId; + + @Activate + void activate() { + appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID); + localNodeId = clusterService.getLocalNode().id(); + leadershipService.runForLeadership(appId.name()); + osNetworkService.addListener(openstackNetworkListener); + componentConfigService.registerProperties(getClass()); + + log.info("Started"); + } + + @Deactivate + void deactivate() { + leadershipService.withdraw(appId.name()); + osNetworkService.removeListener(openstackNetworkListener); + componentConfigService.unregisterProperties(getClass(), false); + + log.info("Stopped"); + } + + + @Modified + protected void modified(ComponentContext context) { + Dictionary properties = context.getProperties(); + int updatedOvsdbPort = Tools.getIntegerProperty(properties, OVSDB_PORT); + if (!Objects.equals(updatedOvsdbPort, ovsdbPort)) { + ovsdbPort = updatedOvsdbPort; + } + + log.info("Modified"); + } + private void processPortAdded(Port port) { + if (!port.getvNicType().equals(DIRECT)) { + log.trace("processPortAdded skipped because of unsupported vNicType: {}", port.getvNicType()); + return; + } else if (!port.isAdminStateUp() || port.getVifType().equals(UNBOUND)) { + log.trace("processPortAdded skipped because of status: {}, adminStateUp: {}, vifType: {}", + port.getState(), port.isAdminStateUp(), port.getVifType()); + return; + } else { + InstancePort instancePort = instancePortService.instancePort(port.getId()); + //Skip this if the instance port for the port id is already created. + if (instancePort != null) { + return; + } + + Optional osNode = osNodeService.completeNodes(COMPUTE).stream() + .filter(node -> node.hostname().equals(port.getHostId())) + .findAny(); + if (!osNode.isPresent()) { + log.error("processPortAdded failed because openstackNode doesn't exist that matches hostname {}", + port.getHostId()); + return; + } + log.trace("Retrieved openstackNode: {}", osNode.get().toString()); + + String intfName = getIntfNameFromPciAddress(port); + if (intfName == null) { + log.error("Failed to execute processPortAdded because of null interface name"); + return; + } + + log.trace("Retrieved interface name: {}", intfName); + + osNodeService.addVfPort(osNode.get(), intfName); + } + } + + private void processPortRemoved(Port port) { + if (!port.getvNicType().equals(DIRECT)) { + log.trace("processPortRemoved skipped because of unsupported vNicType: {}", port.getvNicType()); + return; + } else if (instancePortService.instancePort(port.getId()) == null) { + log.trace("processPortRemoved skipped because no instance port exist for portId: {}", port.getId()); + return; + } else { + InstancePort instancePort = instancePortService.instancePort(port.getId()); + if (instancePort == null) { + return; + } + DeviceId deviceId = instancePort.deviceId(); + if (deviceId == null) { + return; + } + OpenstackNode osNode = osNodeService.node(deviceId); + if (osNode == null) { + return; + } + + Optional removedPort = deviceService.getPorts(deviceId).stream() + .filter(p -> Objects.equals(p.number(), instancePort.portNumber())) + .findAny(); + + if (!removedPort.isPresent()) { + log.error("Failed to execute processPortAdded because port number doesn't exist"); + return; + } + + String intfName = removedPort.get().annotations().value(PORT_NAME); + + if (intfName == null) { + log.error("Failed to execute processPortAdded because of null interface name"); + return; + } + log.trace("Retrieved interface name: {}", intfName); + + osNodeService.removeVfPort(osNode, intfName); + } + } + + private class InternalOpenstackNetworkListener implements OpenstackNetworkListener { + @Override + public boolean isRelevant(OpenstackNetworkEvent event) { + // do not allow to proceed without leadership + NodeId leader = leadershipService.getLeader(appId.name()); + if (!Objects.equals(localNodeId, leader)) { + return false; + } + return true; + } + + @Override + public void event(OpenstackNetworkEvent event) { + switch (event.type()) { + case OPENSTACK_PORT_UPDATED: + if (event.port().getState() == State.DOWN) { + processPortRemoved(event.port()); + } else { + processPortAdded(event.port()); + } + break; + case OPENSTACK_PORT_REMOVED: + processPortRemoved(event.port()); + break; + default: + break; + + } + } + } +} diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java index 94669ed1e8..359d34efe4 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java @@ -69,6 +69,10 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.net.AnnotationKeys.PORT_NAME; +import static org.onosproject.openstacknetworking.api.Constants.DIRECT; +import static org.onosproject.openstacknetworking.api.Constants.PCISLOT; +import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_PREFIX_MAP; +import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getIntfNameFromPciAddress; import static org.slf4j.LoggerFactory.getLogger; /** @@ -105,6 +109,8 @@ public class OpenstackNetworkManager private static final String ERR_NOT_FOUND = " does not exist"; private static final String ERR_IN_USE = " still in use"; private static final String ERR_DUPLICATE = " already exists"; + private static final String PORT_NAME_PREFIX_VM = "tap"; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected CoreService coreService; @@ -312,11 +318,28 @@ public class OpenstackNetworkManager if (Strings.isNullOrEmpty(portName)) { return null; } - Optional osPort = osNetworkStore.ports() - .stream() - .filter(p -> p.getId().contains(portName.substring(3))) - .findFirst(); - return osPort.orElse(null); + + if (port.annotations().value(PORT_NAME).startsWith(PORT_NAME_PREFIX_VM)) { + Optional osPort = osNetworkStore.ports() + .stream() + .filter(p -> p.getId().contains(portName.substring(3))) + .findFirst(); + return osPort.orElse(null); + } else if (isDirectPort(portName)) { + //Additional prefixes will be added + Optional osPort = osNetworkStore.ports() + .stream() + .filter(p -> p.getvNicType().equals(DIRECT) && p.getProfile().get(PCISLOT) != null) + .filter(p -> getIntfNameFromPciAddress(p).equals(portName)) + .findFirst(); + return osPort.orElse(null); + } else { + return null; + } + } + + private boolean isDirectPort(String portName) { + return PORT_NAME_PREFIX_MAP.values().stream().filter(p -> portName.startsWith(p)).findAny().isPresent(); } @Override diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java index 1c7b2ecfae..164b25b217 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java @@ -213,7 +213,6 @@ public class OpenstackRoutingHandler { setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), !osRouter.isAdminStateUp()); }); - ExternalPeerRouter externalPeerRouter = osNetworkAdminService.externalPeerRouter(exGateway); VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.externalPeerRouterVlanId(); diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java index 14ee117123..538a5fd8a2 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java @@ -64,6 +64,7 @@ import java.util.stream.Collectors; import static org.onlab.util.Tools.groupedThreads; import static org.onosproject.net.AnnotationKeys.PORT_NAME; import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID; +import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_PREFIX_MAP; import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_CREATE_TIME; import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID; import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID; @@ -75,6 +76,7 @@ public final class OpenstackSwitchingHostProvider extends AbstractProvider imple private final Logger log = LoggerFactory.getLogger(getClass()); private static final String PORT_NAME_PREFIX_VM = "tap"; + private static final String PORT_NAME_PREFIX_CAVIUM = "enp"; private static final String ERR_ADD_HOST = "Failed to add host: "; private static final String ANNOTATION_SEGMENT_ID = "segId"; private static final String SONA_HOST_SCHEME = "sona"; @@ -229,11 +231,16 @@ public final class OpenstackSwitchingHostProvider extends AbstractProvider imple String portName = port.annotations().value(PORT_NAME); return !Strings.isNullOrEmpty(portName) && - portName.startsWith(PORT_NAME_PREFIX_VM); + (portName.startsWith(PORT_NAME_PREFIX_VM) || isDirectPort(portName)); + } + + private boolean isDirectPort(String portName) { + return PORT_NAME_PREFIX_MAP.values().stream().filter(p -> portName.startsWith(p)).findAny().isPresent(); } @Override public void event(DeviceEvent event) { + log.info("Device event occurred with type {}", event.type()); switch (event.type()) { case PORT_UPDATED: if (!event.port().isEnabled()) { @@ -335,6 +342,19 @@ public final class OpenstackSwitchingHostProvider extends AbstractProvider imple processPortAdded(port); }); + PORT_NAME_PREFIX_MAP.values().forEach(portNamePrefix -> { + deviceService.getPorts(osNode.intgBridge()).stream() + .filter(port -> port.annotations().value(PORT_NAME) + .startsWith(portNamePrefix) && + port.isEnabled()) + .forEach(port -> { + log.debug("Instance port {} is detected from {}", + port.annotations().value(portNamePrefix), + osNode.hostname()); + processPortAdded(port); + }); + }); + Tools.stream(hostService.getHosts()) .filter(host -> deviceService.getPort( host.location().deviceId(), diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java index 98fc0a97a1..7111820728 100644 --- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java +++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java @@ -22,6 +22,7 @@ import org.onosproject.net.DeviceId; import org.onosproject.openstacknode.api.OpenstackNode; import org.openstack4j.core.transport.ObjectMapperSingleton; import org.openstack4j.model.ModelEntity; +import org.openstack4j.model.network.Port; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,6 +34,9 @@ import java.util.Set; import java.util.TreeMap; import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT; +import static org.onosproject.openstacknetworking.api.Constants.PCISLOT; +import static org.onosproject.openstacknetworking.api.Constants.PCI_VENDOR_INFO; +import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_PREFIX_MAP; /** * An utility that used in openstack networking app. @@ -41,6 +45,11 @@ public final class OpenstackNetworkingUtil { protected static final Logger log = LoggerFactory.getLogger(OpenstackNetworkingUtil.class); + private static final int HEX_RADIX = 16; + private static final int ZERO_FUNCTION_NUMBER = 0; + private static final String PREFIX_DEVICE_NUMBER = "s"; + private static final String PREFIX_FUNCTION_NUMBER = "f"; + /** * Prevents object instantiation from external. */ @@ -125,4 +134,51 @@ public final class OpenstackNetworkingUtil { } return gw; } + + /** + * Extract the interface name with the supplied port. + * + * @param port port + * @return interface name + */ + public static String getIntfNameFromPciAddress(Port port) { + if (port.getProfile() != null && port.getProfile().get(PCISLOT) == null) { + log.error("Failed to retrieve the interface name because of no pci_slot information from the port"); + return null; + } + String busNumHex = port.getProfile().get(PCISLOT).toString().split(":")[1]; + String busNumDecimal = String.valueOf(Integer.parseInt(busNumHex, HEX_RADIX)); + + String deviceNumHex = port.getProfile().get(PCISLOT).toString() + .split(":")[2] + .split("\\.")[0]; + String deviceNumDecimal = String.valueOf(Integer.parseInt(deviceNumHex, HEX_RADIX)); + + String functionNumHex = port.getProfile().get(PCISLOT).toString() + .split(":")[2] + .split("\\.")[1]; + String functionNumDecimal = String.valueOf(Integer.parseInt(functionNumHex, HEX_RADIX)); + + String intfName; + + String vendorInfoForPort = String.valueOf(port.getProfile().get(PCI_VENDOR_INFO)); + + if (vendorInfoForPort == null) { + log.error("Failed to retrieve the interface name because of no pci vendor information from the port"); + return null; + } + String portNamePrefix = PORT_NAME_PREFIX_MAP.get(vendorInfoForPort); + if (vendorInfoForPort == null) { + log.error("Failed to retrieve the interface name because of no prefix information from the port"); + return null; + } + if (functionNumDecimal.equals(ZERO_FUNCTION_NUMBER)) { + intfName = portNamePrefix + busNumDecimal + PREFIX_DEVICE_NUMBER + deviceNumDecimal; + } else { + intfName = portNamePrefix + busNumDecimal + PREFIX_DEVICE_NUMBER + deviceNumDecimal + + PREFIX_FUNCTION_NUMBER + functionNumDecimal; + } + + return intfName; + } } diff --git a/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml index d3884df98f..3d6edff357 100644 --- a/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml +++ b/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -21,6 +21,9 @@ + + + diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManagerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManagerTest.java index 866aa55db2..8104c650fc 100644 --- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManagerTest.java +++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManagerTest.java @@ -631,6 +631,14 @@ public class OpenstackNetworkManagerTest { .findFirst().orElse(null); } + @Override + public void addVfPort(OpenstackNode osNode, String portName) { + } + + @Override + public void removeVfPort(OpenstackNode osNode, String portName) { + } + @Override public void addListener(OpenstackNodeListener listener) { listeners.add(listener); diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNodeServiceAdapter.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNodeServiceAdapter.java index a738c09f42..cbd480291c 100644 --- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNodeServiceAdapter.java +++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackNodeServiceAdapter.java @@ -57,6 +57,15 @@ public class OpenstackNodeServiceAdapter implements OpenstackNodeService { return null; } + @Override + public void addVfPort(OpenstackNode osNode, String portName) { + } + + @Override + public void removeVfPort(OpenstackNode osNode, String portName) { + } + + @Override public void addListener(OpenstackNodeListener listener) { diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNodeService.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNodeService.java index 8ebb007a1a..a692109966 100644 --- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNodeService.java +++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNodeService.java @@ -75,4 +75,20 @@ public interface OpenstackNodeService extends ListenerService { if (!isIntfEnabled(osNode, i.intf())) { - addSystemInterface(osNode, INTEGRATION_BRIDGE, i.intf()); + addOrRemoveSystemInterface(osNode, INTEGRATION_BRIDGE, i.intf(), true); } }); @@ -224,11 +223,7 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler { @Override public void processCompleteState(OpenstackNode osNode) { - OvsdbClientService ovsdbClient = ovsdbController.getOvsdbClient( - new OvsdbNodeId(osNode.managementIp(), DEFAULT_OVSDB_PORT)); - if (ovsdbClient != null && ovsdbClient.isConnected()) { - ovsdbClient.disconnect(); - } + //Do something if needed } @Override @@ -236,21 +231,6 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler { //TODO } - /** - * Checks whether the controller has a connection with an OVSDB that resides - * inside the given openstack node. - * - * @param osNode openstack node - * @return true if the controller is connected to the OVSDB, false otherwise - */ - private boolean isOvsdbConnected(OpenstackNode osNode) { - OvsdbNodeId ovsdb = new OvsdbNodeId(osNode.managementIp(), ovsdbPort); - OvsdbClientService client = ovsdbController.getOvsdbClient(ovsdb); - return deviceService.isAvailable(osNode.ovsdb()) && - client != null && - client.isConnected(); - } - /** * Creates a bridge with a given name on a given openstack node. * @@ -288,19 +268,27 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler { } /** - * Adds a network interface (aka port) into a given bridge of openstack node. + * Adds or removes a network interface (aka port) into a given bridge of openstack node. * * @param osNode openstack node * @param bridgeName bridge name * @param intfName interface name + * @param addOrRemove add port is true, remove it otherwise */ - private void addSystemInterface(OpenstackNode osNode, String bridgeName, String intfName) { + private void addOrRemoveSystemInterface(OpenstackNode osNode, String bridgeName, String intfName, + boolean addOrRemove) { Device device = deviceService.getDevice(osNode.ovsdb()); if (device == null || !device.is(BridgeConfig.class)) { + log.info("device is null or this device if not ovsdb device"); return; } BridgeConfig bridgeConfig = device.as(BridgeConfig.class); - bridgeConfig.addPort(BridgeName.bridgeName(bridgeName), intfName); + + if (addOrRemove) { + bridgeConfig.addPort(BridgeName.bridgeName(bridgeName), intfName); + } else { + bridgeConfig.deletePort(BridgeName.bridgeName(bridgeName), intfName); + } } /** @@ -377,6 +365,10 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler { private boolean isCurrentStateDone(OpenstackNode osNode) { switch (osNode.state()) { case INIT: + if (!isOvsdbConnected(osNode, ovsdbPort, ovsdbController, deviceService)) { + return false; + } + return deviceService.isAvailable(osNode.intgBridge()); case DEVICE_CREATED: if (osNode.dataIp() != null && @@ -465,9 +457,6 @@ public class DefaultOpenstackNodeHandler implements OpenstackNodeHandler { if (deviceService.isAvailable(device.id())) { log.debug("OVSDB {} detected", device.id()); bootstrapNode(osNode); - } else if (osNode.state() == COMPLETE) { - log.debug("Removing OVSDB {}", device.id()); - deviceAdminService.removeDevice(device.id()); } }); break; diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/OpenstackNodeManager.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/OpenstackNodeManager.java index fb8a871ade..f30787cb22 100644 --- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/OpenstackNodeManager.java +++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/OpenstackNodeManager.java @@ -20,15 +20,22 @@ import com.google.common.collect.ImmutableSet; 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.Modified; +import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; +import org.onlab.util.Tools; import org.onosproject.cluster.ClusterService; import org.onosproject.cluster.LeadershipService; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.event.ListenerRegistry; +import org.onosproject.net.Device; import org.onosproject.net.DeviceId; +import org.onosproject.net.behaviour.BridgeConfig; +import org.onosproject.net.behaviour.BridgeName; +import org.onosproject.net.device.DeviceService; import org.onosproject.openstacknode.api.OpenstackNode; import org.onosproject.openstacknode.api.OpenstackNodeAdminService; import org.onosproject.openstacknode.api.OpenstackNodeEvent; @@ -36,8 +43,12 @@ import org.onosproject.openstacknode.api.OpenstackNodeListener; import org.onosproject.openstacknode.api.OpenstackNodeService; import org.onosproject.openstacknode.api.OpenstackNodeStore; import org.onosproject.openstacknode.api.OpenstackNodeStoreDelegate; +import org.onosproject.ovsdb.controller.OvsdbController; +import org.onosproject.store.service.StorageService; +import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; +import java.util.Dictionary; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -46,8 +57,11 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static java.util.concurrent.Executors.newSingleThreadExecutor; +import static org.onlab.packet.TpPort.tpPort; import static org.onlab.util.Tools.groupedThreads; +import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE; import static org.onosproject.openstacknode.api.NodeState.COMPLETE; +import static org.onosproject.openstacknode.util.OpenstackNodeUtil.isOvsdbConnected; import static org.slf4j.LoggerFactory.getLogger; /** @@ -64,6 +78,8 @@ public class OpenstackNodeManager extends ListenerRegistry properties = context.getProperties(); + int updatedOvsdbPort = Tools.getIntegerProperty(properties, OVSDB_PORT); + if (!Objects.equals(updatedOvsdbPort, ovsdbPort)) { + ovsdbPort = updatedOvsdbPort; + } + + log.info("Modified"); + } + @Override public void createNode(OpenstackNode osNode) { checkNotNull(osNode, ERR_NULL_NODE); @@ -172,6 +212,57 @@ public class OpenstackNodeManager extends ListenerRegistry Objects.equals(osNode.intgBridge(), deviceId) || Objects.equals(osNode.ovsdb(), deviceId)) .findFirst().orElse(null); + } + + @Override + public void addVfPort(OpenstackNode osNode, String portName) { + } + + @Override + public void removeVfPort(OpenstackNode osNode, String portName) { + } @Override