Committed by
Gerrit Code Review
CORD-380 Added host provider for cordvtn service
- Renamed CordVtnConfigManager to CordVtnNodeManager - Moved all node bootstrap logic to CordVtnNodeManager - CordVtnService now provides VM add/remove and service dependency create/remove - Made CordVtn implement HostProvider so that it can inject/eject VM to the system Change-Id: I0011ac692ecea240d2d7fe48b3e7a1db4973b76e
Showing
10 changed files
with
1041 additions
and
957 deletions
| ... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.cordvtn; | 16 | package org.onosproject.cordvtn; |
| 17 | 17 | ||
| 18 | -import com.google.common.collect.Maps; | ||
| 19 | import com.google.common.collect.Sets; | 18 | import com.google.common.collect.Sets; |
| 20 | import org.apache.felix.scr.annotations.Activate; | 19 | import org.apache.felix.scr.annotations.Activate; |
| 21 | import org.apache.felix.scr.annotations.Component; | 20 | import org.apache.felix.scr.annotations.Component; |
| ... | @@ -24,59 +23,43 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -24,59 +23,43 @@ import org.apache.felix.scr.annotations.Reference; |
| 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 23 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 25 | import org.apache.felix.scr.annotations.Service; | 24 | import org.apache.felix.scr.annotations.Service; |
| 26 | import org.onlab.packet.Ethernet; | 25 | import org.onlab.packet.Ethernet; |
| 27 | -import org.onlab.packet.Ip4Address; | ||
| 28 | -import org.onlab.util.ItemNotFoundException; | ||
| 29 | import org.onlab.packet.IpAddress; | 26 | import org.onlab.packet.IpAddress; |
| 30 | -import org.onlab.util.KryoNamespace; | 27 | +import org.onlab.packet.MacAddress; |
| 31 | -import org.onosproject.cluster.ClusterService; | 28 | +import org.onlab.packet.VlanId; |
| 32 | import org.onosproject.core.ApplicationId; | 29 | import org.onosproject.core.ApplicationId; |
| 33 | import org.onosproject.core.CoreService; | 30 | import org.onosproject.core.CoreService; |
| 34 | import org.onosproject.mastership.MastershipService; | 31 | import org.onosproject.mastership.MastershipService; |
| 32 | +import org.onosproject.net.ConnectPoint; | ||
| 35 | import org.onosproject.net.DefaultAnnotations; | 33 | import org.onosproject.net.DefaultAnnotations; |
| 36 | -import org.onosproject.net.Device; | ||
| 37 | -import org.onosproject.net.DeviceId; | ||
| 38 | import org.onosproject.net.Host; | 34 | import org.onosproject.net.Host; |
| 39 | import org.onosproject.net.HostId; | 35 | import org.onosproject.net.HostId; |
| 36 | +import org.onosproject.net.HostLocation; | ||
| 40 | import org.onosproject.net.Port; | 37 | import org.onosproject.net.Port; |
| 41 | -import org.onosproject.net.behaviour.BridgeConfig; | 38 | +import org.onosproject.net.SparseAnnotations; |
| 42 | -import org.onosproject.net.behaviour.BridgeName; | ||
| 43 | -import org.onosproject.net.behaviour.ControllerInfo; | ||
| 44 | -import org.onosproject.net.behaviour.DefaultTunnelDescription; | ||
| 45 | -import org.onosproject.net.behaviour.TunnelConfig; | ||
| 46 | -import org.onosproject.net.behaviour.TunnelDescription; | ||
| 47 | -import org.onosproject.net.behaviour.TunnelName; | ||
| 48 | -import org.onosproject.net.device.DeviceAdminService; | ||
| 49 | -import org.onosproject.net.device.DeviceEvent; | ||
| 50 | -import org.onosproject.net.device.DeviceListener; | ||
| 51 | import org.onosproject.net.device.DeviceService; | 39 | import org.onosproject.net.device.DeviceService; |
| 52 | -import org.onosproject.net.driver.DriverHandler; | ||
| 53 | import org.onosproject.net.driver.DriverService; | 40 | import org.onosproject.net.driver.DriverService; |
| 54 | import org.onosproject.net.flow.FlowRuleService; | 41 | import org.onosproject.net.flow.FlowRuleService; |
| 55 | import org.onosproject.net.group.GroupService; | 42 | import org.onosproject.net.group.GroupService; |
| 43 | +import org.onosproject.net.host.DefaultHostDescription; | ||
| 44 | +import org.onosproject.net.host.HostDescription; | ||
| 56 | import org.onosproject.net.host.HostEvent; | 45 | import org.onosproject.net.host.HostEvent; |
| 57 | import org.onosproject.net.host.HostListener; | 46 | import org.onosproject.net.host.HostListener; |
| 47 | +import org.onosproject.net.host.HostProvider; | ||
| 48 | +import org.onosproject.net.host.HostProviderRegistry; | ||
| 49 | +import org.onosproject.net.host.HostProviderService; | ||
| 58 | import org.onosproject.net.host.HostService; | 50 | import org.onosproject.net.host.HostService; |
| 59 | import org.onosproject.net.packet.PacketContext; | 51 | import org.onosproject.net.packet.PacketContext; |
| 60 | import org.onosproject.net.packet.PacketProcessor; | 52 | import org.onosproject.net.packet.PacketProcessor; |
| 61 | import org.onosproject.net.packet.PacketService; | 53 | import org.onosproject.net.packet.PacketService; |
| 54 | +import org.onosproject.net.provider.AbstractProvider; | ||
| 55 | +import org.onosproject.net.provider.ProviderId; | ||
| 62 | import org.onosproject.openstackswitching.OpenstackNetwork; | 56 | import org.onosproject.openstackswitching.OpenstackNetwork; |
| 63 | import org.onosproject.openstackswitching.OpenstackPort; | 57 | import org.onosproject.openstackswitching.OpenstackPort; |
| 64 | import org.onosproject.openstackswitching.OpenstackSubnet; | 58 | import org.onosproject.openstackswitching.OpenstackSubnet; |
| 65 | import org.onosproject.openstackswitching.OpenstackSwitchingService; | 59 | import org.onosproject.openstackswitching.OpenstackSwitchingService; |
| 66 | -import org.onosproject.ovsdb.controller.OvsdbClientService; | ||
| 67 | -import org.onosproject.ovsdb.controller.OvsdbController; | ||
| 68 | -import org.onosproject.ovsdb.controller.OvsdbNodeId; | ||
| 69 | -import org.onosproject.store.serializers.KryoNamespaces; | ||
| 70 | -import org.onosproject.store.service.ConsistentMap; | ||
| 71 | -import org.onosproject.store.service.Serializer; | ||
| 72 | -import org.onosproject.store.service.StorageService; | ||
| 73 | import org.slf4j.Logger; | 60 | import org.slf4j.Logger; |
| 74 | 61 | ||
| 75 | -import java.util.ArrayList; | ||
| 76 | -import java.util.HashMap; | ||
| 77 | -import java.util.List; | ||
| 78 | import java.util.Map; | 62 | import java.util.Map; |
| 79 | -import java.util.Objects; | ||
| 80 | import java.util.Set; | 63 | import java.util.Set; |
| 81 | import java.util.concurrent.ExecutorService; | 64 | import java.util.concurrent.ExecutorService; |
| 82 | import java.util.concurrent.Executors; | 65 | import java.util.concurrent.Executors; |
| ... | @@ -84,8 +67,6 @@ import java.util.stream.Collectors; | ... | @@ -84,8 +67,6 @@ import java.util.stream.Collectors; |
| 84 | 67 | ||
| 85 | import static com.google.common.base.Preconditions.checkNotNull; | 68 | import static com.google.common.base.Preconditions.checkNotNull; |
| 86 | import static org.onlab.util.Tools.groupedThreads; | 69 | import static org.onlab.util.Tools.groupedThreads; |
| 87 | -import static org.onosproject.net.Device.Type.SWITCH; | ||
| 88 | -import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN; | ||
| 89 | import static org.slf4j.LoggerFactory.getLogger; | 70 | import static org.slf4j.LoggerFactory.getLogger; |
| 90 | 71 | ||
| 91 | /** | 72 | /** |
| ... | @@ -94,36 +75,15 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -94,36 +75,15 @@ import static org.slf4j.LoggerFactory.getLogger; |
| 94 | */ | 75 | */ |
| 95 | @Component(immediate = true) | 76 | @Component(immediate = true) |
| 96 | @Service | 77 | @Service |
| 97 | -public class CordVtn implements CordVtnService { | 78 | +public class CordVtn extends AbstractProvider implements CordVtnService, HostProvider { |
| 98 | 79 | ||
| 99 | protected final Logger log = getLogger(getClass()); | 80 | protected final Logger log = getLogger(getClass()); |
| 100 | 81 | ||
| 101 | - private static final int NUM_THREADS = 1; | ||
| 102 | - private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder() | ||
| 103 | - .register(KryoNamespaces.API) | ||
| 104 | - .register(CordVtnNode.class) | ||
| 105 | - .register(NodeState.class); | ||
| 106 | - | ||
| 107 | - private static final String DEFAULT_BRIDGE = "br-int"; | ||
| 108 | - private static final String VPORT_PREFIX = "tap"; | ||
| 109 | - private static final String DEFAULT_TUNNEL = "vxlan"; | ||
| 110 | - private static final String OK = "OK"; | ||
| 111 | - private static final String NO = "NO"; | ||
| 112 | - | ||
| 113 | - private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() { | ||
| 114 | - { | ||
| 115 | - put("key", "flow"); | ||
| 116 | - put("remote_ip", "flow"); | ||
| 117 | - } | ||
| 118 | - }; | ||
| 119 | - private static final int DPID_BEGIN = 3; | ||
| 120 | - private static final int OFPORT = 6653; | ||
| 121 | - | ||
| 122 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 82 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 123 | protected CoreService coreService; | 83 | protected CoreService coreService; |
| 124 | 84 | ||
| 125 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 85 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 126 | - protected StorageService storageService; | 86 | + protected HostProviderRegistry hostProviderRegistry; |
| 127 | 87 | ||
| 128 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 88 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 129 | protected DeviceService deviceService; | 89 | protected DeviceService deviceService; |
| ... | @@ -135,21 +95,12 @@ public class CordVtn implements CordVtnService { | ... | @@ -135,21 +95,12 @@ public class CordVtn implements CordVtnService { |
| 135 | protected DriverService driverService; | 95 | protected DriverService driverService; |
| 136 | 96 | ||
| 137 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 97 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 138 | - protected DeviceAdminService adminService; | ||
| 139 | - | ||
| 140 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 141 | protected FlowRuleService flowRuleService; | 98 | protected FlowRuleService flowRuleService; |
| 142 | 99 | ||
| 143 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 100 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 144 | protected PacketService packetService; | 101 | protected PacketService packetService; |
| 145 | 102 | ||
| 146 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 103 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 147 | - protected OvsdbController controller; | ||
| 148 | - | ||
| 149 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 150 | - protected ClusterService clusterService; | ||
| 151 | - | ||
| 152 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 153 | protected MastershipService mastershipService; | 104 | protected MastershipService mastershipService; |
| 154 | 105 | ||
| 155 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 106 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| ... | @@ -158,76 +109,32 @@ public class CordVtn implements CordVtnService { | ... | @@ -158,76 +109,32 @@ public class CordVtn implements CordVtnService { |
| 158 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 109 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 159 | protected OpenstackSwitchingService openstackService; | 110 | protected OpenstackSwitchingService openstackService; |
| 160 | 111 | ||
| 112 | + private static final int NUM_THREADS = 1; | ||
| 113 | + private static final String DEFAULT_TUNNEL = "vxlan"; | ||
| 114 | + private static final String SERVICE_ID = "serviceId"; | ||
| 115 | + private static final String LOCATION_IP = "locationIp"; | ||
| 116 | + private static final String OPENSTACK_VM_ID = "openstackVmId"; | ||
| 117 | + | ||
| 161 | private final ExecutorService eventExecutor = Executors | 118 | private final ExecutorService eventExecutor = Executors |
| 162 | .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler")); | 119 | .newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler")); |
| 163 | 120 | ||
| 164 | - private final DeviceListener deviceListener = new InternalDeviceListener(); | ||
| 165 | - private final HostListener hostListener = new InternalHostListener(); | ||
| 166 | private final PacketProcessor packetProcessor = new InternalPacketProcessor(); | 121 | private final PacketProcessor packetProcessor = new InternalPacketProcessor(); |
| 122 | + private final HostListener hostListener = new InternalHostListener(); | ||
| 167 | 123 | ||
| 168 | - private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); | 124 | + private HostProviderService hostProvider; |
| 169 | - private final BridgeHandler bridgeHandler = new BridgeHandler(); | ||
| 170 | - private final VmHandler vmHandler = new VmHandler(); | ||
| 171 | - | ||
| 172 | - private ApplicationId appId; | ||
| 173 | - private ConsistentMap<CordVtnNode, NodeState> nodeStore; | ||
| 174 | - private Map<HostId, OpenstackNetwork> hostNetMap = Maps.newHashMap(); | ||
| 175 | private CordVtnRuleInstaller ruleInstaller; | 125 | private CordVtnRuleInstaller ruleInstaller; |
| 176 | private CordVtnArpProxy arpProxy; | 126 | private CordVtnArpProxy arpProxy; |
| 177 | 127 | ||
| 178 | - private enum NodeState { | 128 | + /** |
| 179 | - | 129 | + * Creates an cordvtn host location provider. |
| 180 | - INIT { | 130 | + */ |
| 181 | - @Override | 131 | + public CordVtn() { |
| 182 | - public void process(CordVtn cordVtn, CordVtnNode node) { | 132 | + super(new ProviderId("host", CORDVTN_APP_ID)); |
| 183 | - cordVtn.connect(node); | ||
| 184 | - } | ||
| 185 | - }, | ||
| 186 | - OVSDB_CONNECTED { | ||
| 187 | - @Override | ||
| 188 | - public void process(CordVtn cordVtn, CordVtnNode node) { | ||
| 189 | - if (!cordVtn.getOvsdbConnectionState(node)) { | ||
| 190 | - cordVtn.connect(node); | ||
| 191 | - } else { | ||
| 192 | - cordVtn.createIntegrationBridge(node); | ||
| 193 | - } | ||
| 194 | - } | ||
| 195 | - }, | ||
| 196 | - BRIDGE_CREATED { | ||
| 197 | - @Override | ||
| 198 | - public void process(CordVtn cordVtn, CordVtnNode node) { | ||
| 199 | - if (!cordVtn.getOvsdbConnectionState(node)) { | ||
| 200 | - cordVtn.connect(node); | ||
| 201 | - } else { | ||
| 202 | - cordVtn.createTunnelInterface(node); | ||
| 203 | - } | ||
| 204 | - } | ||
| 205 | - }, | ||
| 206 | - COMPLETE { | ||
| 207 | - @Override | ||
| 208 | - public void process(CordVtn cordVtn, CordVtnNode node) { | ||
| 209 | - cordVtn.postInit(node); | ||
| 210 | - } | ||
| 211 | - }, | ||
| 212 | - INCOMPLETE { | ||
| 213 | - @Override | ||
| 214 | - public void process(CordVtn cordVtn, CordVtnNode node) { | ||
| 215 | - } | ||
| 216 | - }; | ||
| 217 | - | ||
| 218 | - // TODO Add physical port add state | ||
| 219 | - | ||
| 220 | - public abstract void process(CordVtn cordVtn, CordVtnNode node); | ||
| 221 | } | 133 | } |
| 222 | 134 | ||
| 223 | @Activate | 135 | @Activate |
| 224 | protected void activate() { | 136 | protected void activate() { |
| 225 | - appId = coreService.registerApplication("org.onosproject.cordvtn"); | 137 | + ApplicationId appId = coreService.registerApplication("org.onosproject.cordvtn"); |
| 226 | - nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder() | ||
| 227 | - .withSerializer(Serializer.using(NODE_SERIALIZER.build())) | ||
| 228 | - .withName("cordvtn-nodestore") | ||
| 229 | - .withApplicationId(appId) | ||
| 230 | - .build(); | ||
| 231 | 138 | ||
| 232 | ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService, | 139 | ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService, |
| 233 | deviceService, | 140 | deviceService, |
| ... | @@ -240,95 +147,29 @@ public class CordVtn implements CordVtnService { | ... | @@ -240,95 +147,29 @@ public class CordVtn implements CordVtnService { |
| 240 | packetService.addProcessor(packetProcessor, PacketProcessor.director(0)); | 147 | packetService.addProcessor(packetProcessor, PacketProcessor.director(0)); |
| 241 | arpProxy.requestPacket(); | 148 | arpProxy.requestPacket(); |
| 242 | 149 | ||
| 243 | - deviceService.addListener(deviceListener); | ||
| 244 | hostService.addListener(hostListener); | 150 | hostService.addListener(hostListener); |
| 151 | + hostProvider = hostProviderRegistry.register(this); | ||
| 245 | 152 | ||
| 246 | log.info("Started"); | 153 | log.info("Started"); |
| 247 | } | 154 | } |
| 248 | 155 | ||
| 249 | @Deactivate | 156 | @Deactivate |
| 250 | protected void deactivate() { | 157 | protected void deactivate() { |
| 251 | - deviceService.removeListener(deviceListener); | ||
| 252 | hostService.removeListener(hostListener); | 158 | hostService.removeListener(hostListener); |
| 253 | packetService.removeProcessor(packetProcessor); | 159 | packetService.removeProcessor(packetProcessor); |
| 254 | 160 | ||
| 255 | eventExecutor.shutdown(); | 161 | eventExecutor.shutdown(); |
| 256 | - nodeStore.clear(); | 162 | + hostProviderRegistry.unregister(this); |
| 257 | 163 | ||
| 258 | log.info("Stopped"); | 164 | log.info("Stopped"); |
| 259 | } | 165 | } |
| 260 | 166 | ||
| 261 | @Override | 167 | @Override |
| 262 | - public void addNode(CordVtnNode node) { | 168 | + public void triggerProbe(Host host) { |
| 263 | - checkNotNull(node); | 169 | + /* |
| 264 | - | 170 | + * Note: In CORD deployment, we assume that all hosts are configured. |
| 265 | - nodeStore.putIfAbsent(node, checkNodeState(node)); | 171 | + * Therefore no probe is required. |
| 266 | - initNode(node); | 172 | + */ |
| 267 | - } | ||
| 268 | - | ||
| 269 | - @Override | ||
| 270 | - public void deleteNode(CordVtnNode node) { | ||
| 271 | - checkNotNull(node); | ||
| 272 | - | ||
| 273 | - if (getOvsdbConnectionState(node)) { | ||
| 274 | - disconnect(node); | ||
| 275 | - } | ||
| 276 | - | ||
| 277 | - nodeStore.remove(node); | ||
| 278 | - } | ||
| 279 | - | ||
| 280 | - @Override | ||
| 281 | - public int getNodeCount() { | ||
| 282 | - return nodeStore.size(); | ||
| 283 | - } | ||
| 284 | - | ||
| 285 | - @Override | ||
| 286 | - public List<CordVtnNode> getNodes() { | ||
| 287 | - List<CordVtnNode> nodes = new ArrayList<>(); | ||
| 288 | - nodes.addAll(nodeStore.keySet()); | ||
| 289 | - return nodes; | ||
| 290 | - } | ||
| 291 | - | ||
| 292 | - @Override | ||
| 293 | - public void initNode(CordVtnNode node) { | ||
| 294 | - checkNotNull(node); | ||
| 295 | - | ||
| 296 | - if (!nodeStore.containsKey(node)) { | ||
| 297 | - log.warn("Node {} does not exist, add node first", node.hostname()); | ||
| 298 | - return; | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | - NodeState state = checkNodeState(node); | ||
| 302 | - state.process(this, node); | ||
| 303 | - } | ||
| 304 | - | ||
| 305 | - @Override | ||
| 306 | - public boolean getNodeInitState(CordVtnNode node) { | ||
| 307 | - checkNotNull(node); | ||
| 308 | - | ||
| 309 | - NodeState state = getNodeState(node); | ||
| 310 | - return state != null && state.equals(NodeState.COMPLETE); | ||
| 311 | - } | ||
| 312 | - | ||
| 313 | - @Override | ||
| 314 | - public String checkNodeInitState(CordVtnNode node) { | ||
| 315 | - checkNotNull(node); | ||
| 316 | - | ||
| 317 | - NodeState state = getNodeState(node); | ||
| 318 | - if (state == null) { | ||
| 319 | - log.warn("Failed to get init state of {}", node.hostname()); | ||
| 320 | - return null; | ||
| 321 | - } | ||
| 322 | - | ||
| 323 | - String result = String.format( | ||
| 324 | - "Integration bridge created/connected : %s (%s)%n" + | ||
| 325 | - "VXLAN interface created : %s%n" + | ||
| 326 | - "Physical interface added : %s (%s)", | ||
| 327 | - checkIntegrationBridge(node) ? OK : NO, DEFAULT_BRIDGE, | ||
| 328 | - checkTunnelInterface(node) ? OK : NO, | ||
| 329 | - checkPhyInterface(node) ? OK : NO, node.phyPortName()); | ||
| 330 | - | ||
| 331 | - return result; | ||
| 332 | } | 173 | } |
| 333 | 174 | ||
| 334 | @Override | 175 | @Override |
| ... | @@ -341,6 +182,7 @@ public class CordVtn implements CordVtnService { | ... | @@ -341,6 +182,7 @@ public class CordVtn implements CordVtnService { |
| 341 | return; | 182 | return; |
| 342 | } | 183 | } |
| 343 | 184 | ||
| 185 | + log.info("Service dependency from {} to {} created.", tService.id().id(), pService.id().id()); | ||
| 344 | ruleInstaller.populateServiceDependencyRules(tService, pService); | 186 | ruleInstaller.populateServiceDependencyRules(tService, pService); |
| 345 | } | 187 | } |
| 346 | 188 | ||
| ... | @@ -354,326 +196,140 @@ public class CordVtn implements CordVtnService { | ... | @@ -354,326 +196,140 @@ public class CordVtn implements CordVtnService { |
| 354 | return; | 196 | return; |
| 355 | } | 197 | } |
| 356 | 198 | ||
| 199 | + log.info("Service dependency from {} to {} removed.", tService.id().id(), pService.id().id()); | ||
| 357 | ruleInstaller.removeServiceDependencyRules(tService, pService); | 200 | ruleInstaller.removeServiceDependencyRules(tService, pService); |
| 358 | } | 201 | } |
| 359 | 202 | ||
| 360 | - /** | 203 | + @Override |
| 361 | - * Returns state of a given cordvtn node. | 204 | + public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) { |
| 362 | - * | 205 | + Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port()); |
| 363 | - * @param node cordvtn node | 206 | + OpenstackPort vPort = openstackService.port(port); |
| 364 | - * @return node state, or null if no such node exists | 207 | + if (vPort == null) { |
| 365 | - */ | 208 | + log.warn("Failed to get OpenstackPort for {}", getPortName(port)); |
| 366 | - private NodeState getNodeState(CordVtnNode node) { | 209 | + return; |
| 367 | - checkNotNull(node); | ||
| 368 | - | ||
| 369 | - try { | ||
| 370 | - return nodeStore.get(node).value(); | ||
| 371 | - } catch (NullPointerException e) { | ||
| 372 | - log.error("Failed to get state of {}", node.hostname()); | ||
| 373 | - return null; | ||
| 374 | } | 210 | } |
| 375 | - } | ||
| 376 | 211 | ||
| 377 | - /** | 212 | + MacAddress mac = vPort.macAddress(); |
| 378 | - * Sets a new state for a given cordvtn node. | 213 | + HostId hostId = HostId.hostId(mac); |
| 379 | - * | ||
| 380 | - * @param node cordvtn node | ||
| 381 | - * @param newState new node state | ||
| 382 | - */ | ||
| 383 | - private void setNodeState(CordVtnNode node, NodeState newState) { | ||
| 384 | - checkNotNull(node); | ||
| 385 | 214 | ||
| 386 | - log.info("Changed {} state: {}", node.hostname(), newState.toString()); | 215 | + Host host = hostService.getHost(hostId); |
| 387 | - | 216 | + if (host != null) { |
| 388 | - nodeStore.put(node, newState); | 217 | + // Host is already known to the system, no HOST_ADDED event is triggered in this case. |
| 389 | - newState.process(this, node); | 218 | + // It happens when the application is restarted. |
| 390 | - } | 219 | + // TODO check host description if it has all the information |
| 391 | - | 220 | + serviceVmAdded(host); |
| 392 | - /** | 221 | + return; |
| 393 | - * Checks current state of a given cordvtn node and returns it. | ||
| 394 | - * | ||
| 395 | - * @param node cordvtn node | ||
| 396 | - * @return node state | ||
| 397 | - */ | ||
| 398 | - private NodeState checkNodeState(CordVtnNode node) { | ||
| 399 | - checkNotNull(node); | ||
| 400 | - | ||
| 401 | - if (checkIntegrationBridge(node) && checkTunnelInterface(node)) { | ||
| 402 | - // TODO add physical port add state | ||
| 403 | - if (checkPhyInterface(node)) { | ||
| 404 | - return NodeState.COMPLETE; | ||
| 405 | - } else { | ||
| 406 | - return NodeState.INCOMPLETE; | ||
| 407 | - } | ||
| 408 | - } else if (checkIntegrationBridge(node)) { | ||
| 409 | - return NodeState.BRIDGE_CREATED; | ||
| 410 | - } else if (getOvsdbConnectionState(node)) { | ||
| 411 | - return NodeState.OVSDB_CONNECTED; | ||
| 412 | - } else { | ||
| 413 | - return NodeState.INIT; | ||
| 414 | } | 222 | } |
| 415 | - } | ||
| 416 | 223 | ||
| 417 | - /** | 224 | + Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values()); |
| 418 | - * Performs tasks after node initialization. | 225 | + SparseAnnotations annotations = DefaultAnnotations.builder() |
| 419 | - * First disconnect unnecessary OVSDB connection and then installs flow rules | 226 | + .set(OPENSTACK_VM_ID, vPort.deviceId()) |
| 420 | - * for existing VMs if there are any. | 227 | + .set(SERVICE_ID, vPort.networkId()) |
| 421 | - * | 228 | + .set(LOCATION_IP, node.localIp().toString()) |
| 422 | - * @param node cordvtn node | 229 | + .build(); |
| 423 | - */ | ||
| 424 | - private void postInit(CordVtnNode node) { | ||
| 425 | - disconnect(node); | ||
| 426 | - | ||
| 427 | - ruleInstaller.init(node.intBrId(), node.phyPortName(), node.localIp()); | ||
| 428 | - hostService.getConnectedHosts(node.intBrId()) | ||
| 429 | - .stream() | ||
| 430 | - .forEach(vmHandler::connected); | ||
| 431 | - | ||
| 432 | - log.info("Finished initializing {}", node.hostname()); | ||
| 433 | - } | ||
| 434 | 230 | ||
| 435 | - /** | 231 | + HostDescription hostDesc = new DefaultHostDescription( |
| 436 | - * Returns connection state of OVSDB server for a given node. | 232 | + mac, |
| 437 | - * | 233 | + VlanId.NONE, |
| 438 | - * @param node cordvtn node | 234 | + new HostLocation(connectPoint, System.currentTimeMillis()), |
| 439 | - * @return true if it is connected, false otherwise | 235 | + ip, |
| 440 | - */ | 236 | + annotations); |
| 441 | - private boolean getOvsdbConnectionState(CordVtnNode node) { | ||
| 442 | - checkNotNull(node); | ||
| 443 | 237 | ||
| 444 | - OvsdbClientService ovsdbClient = getOvsdbClient(node); | 238 | + hostProvider.hostDetected(hostId, hostDesc, false); |
| 445 | - return deviceService.isAvailable(node.ovsdbId()) && | ||
| 446 | - ovsdbClient != null && ovsdbClient.isConnected(); | ||
| 447 | } | 239 | } |
| 448 | 240 | ||
| 449 | - /** | 241 | + @Override |
| 450 | - * Connects to OVSDB server for a given node. | 242 | + public void removeServiceVm(ConnectPoint connectPoint) { |
| 451 | - * | 243 | + Host host = hostService.getConnectedHosts(connectPoint) |
| 452 | - * @param node cordvtn node | 244 | + .stream() |
| 453 | - */ | 245 | + .findFirst() |
| 454 | - private void connect(CordVtnNode node) { | 246 | + .orElse(null); |
| 455 | - checkNotNull(node); | ||
| 456 | 247 | ||
| 457 | - if (!nodeStore.containsKey(node)) { | 248 | + if (host == null) { |
| 458 | - log.warn("Node {} does not exist", node.hostname()); | 249 | + log.debug("No host is connected on {}", connectPoint.toString()); |
| 459 | return; | 250 | return; |
| 460 | } | 251 | } |
| 461 | 252 | ||
| 462 | - if (!getOvsdbConnectionState(node)) { | 253 | + hostProvider.hostVanished(host.id()); |
| 463 | - controller.connect(node.ovsdbIp(), node.ovsdbPort()); | ||
| 464 | - } | ||
| 465 | } | 254 | } |
| 466 | 255 | ||
| 467 | /** | 256 | /** |
| 468 | - * Disconnects OVSDB server for a given node. | 257 | + * Returns CordService by service ID. |
| 469 | * | 258 | * |
| 470 | - * @param node cordvtn node | 259 | + * @param serviceId service id |
| 260 | + * @return cord service, or null if it fails to get network from OpenStack | ||
| 471 | */ | 261 | */ |
| 472 | - private void disconnect(CordVtnNode node) { | 262 | + private CordService getCordService(CordServiceId serviceId) { |
| 473 | - checkNotNull(node); | 263 | + OpenstackNetwork vNet = openstackService.network(serviceId.id()); |
| 474 | - | 264 | + if (vNet == null) { |
| 475 | - if (!nodeStore.containsKey(node)) { | 265 | + log.warn("Couldn't find OpenStack network for service {}", serviceId.id()); |
| 476 | - log.warn("Node {} does not exist", node.hostname()); | 266 | + return null; |
| 477 | - return; | ||
| 478 | } | 267 | } |
| 479 | 268 | ||
| 480 | - if (getOvsdbConnectionState(node)) { | 269 | + OpenstackSubnet subnet = vNet.subnets().stream() |
| 481 | - OvsdbClientService ovsdbClient = getOvsdbClient(node); | 270 | + .findFirst() |
| 482 | - ovsdbClient.disconnect(); | 271 | + .orElse(null); |
| 272 | + if (subnet == null) { | ||
| 273 | + log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id()); | ||
| 274 | + return null; | ||
| 483 | } | 275 | } |
| 484 | - } | ||
| 485 | - | ||
| 486 | - /** | ||
| 487 | - * Returns cordvtn node associated with a given OVSDB device. | ||
| 488 | - * | ||
| 489 | - * @param ovsdbId OVSDB device id | ||
| 490 | - * @return cordvtn node, null if it fails to find the node | ||
| 491 | - */ | ||
| 492 | - private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) { | ||
| 493 | - return getNodes().stream() | ||
| 494 | - .filter(node -> node.ovsdbId().equals(ovsdbId)) | ||
| 495 | - .findFirst().orElse(null); | ||
| 496 | - } | ||
| 497 | - | ||
| 498 | - /** | ||
| 499 | - * Returns cordvtn node associated with a given integration bridge. | ||
| 500 | - * | ||
| 501 | - * @param bridgeId device id of integration bridge | ||
| 502 | - * @return cordvtn node, null if it fails to find the node | ||
| 503 | - */ | ||
| 504 | - private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) { | ||
| 505 | - return getNodes().stream() | ||
| 506 | - .filter(node -> node.intBrId().equals(bridgeId)) | ||
| 507 | - .findFirst().orElse(null); | ||
| 508 | - } | ||
| 509 | - | ||
| 510 | - /** | ||
| 511 | - * Returns port name. | ||
| 512 | - * | ||
| 513 | - * @param port port | ||
| 514 | - * @return port name | ||
| 515 | - */ | ||
| 516 | - private String getPortName(Port port) { | ||
| 517 | - return port.annotations().value("portName"); | ||
| 518 | - } | ||
| 519 | 276 | ||
| 520 | - /** | 277 | + Set<CordServiceId> tServices = Sets.newHashSet(); |
| 521 | - * Returns OVSDB client for a given node. | 278 | + // TODO get tenant services from XOS |
| 522 | - * | ||
| 523 | - * @param node cordvtn node | ||
| 524 | - * @return OVSDB client, or null if it fails to get OVSDB client | ||
| 525 | - */ | ||
| 526 | - private OvsdbClientService getOvsdbClient(CordVtnNode node) { | ||
| 527 | - checkNotNull(node); | ||
| 528 | - | ||
| 529 | - OvsdbClientService ovsdbClient = controller.getOvsdbClient( | ||
| 530 | - new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt())); | ||
| 531 | - if (ovsdbClient == null) { | ||
| 532 | - log.debug("Couldn't find OVSDB client for {}", node.hostname()); | ||
| 533 | - } | ||
| 534 | - return ovsdbClient; | ||
| 535 | - } | ||
| 536 | 279 | ||
| 537 | - /** | 280 | + Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) |
| 538 | - * Creates an integration bridge for a given node. | 281 | + .stream() |
| 539 | - * | 282 | + .collect(Collectors.toMap(host -> host, this::getTunnelIp)); |
| 540 | - * @param node cordvtn node | ||
| 541 | - */ | ||
| 542 | - private void createIntegrationBridge(CordVtnNode node) { | ||
| 543 | - if (checkIntegrationBridge(node)) { | ||
| 544 | - return; | ||
| 545 | - } | ||
| 546 | 283 | ||
| 547 | - List<ControllerInfo> controllers = new ArrayList<>(); | 284 | + return new CordService(vNet, subnet, hosts, tServices); |
| 548 | - Sets.newHashSet(clusterService.getNodes()).stream() | ||
| 549 | - .forEach(controller -> { | ||
| 550 | - ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp"); | ||
| 551 | - controllers.add(ctrlInfo); | ||
| 552 | - }); | ||
| 553 | - | ||
| 554 | - String dpid = node.intBrId().toString().substring(DPID_BEGIN); | ||
| 555 | - | ||
| 556 | - try { | ||
| 557 | - DriverHandler handler = driverService.createHandler(node.ovsdbId()); | ||
| 558 | - BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class); | ||
| 559 | - bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers); | ||
| 560 | - } catch (ItemNotFoundException e) { | ||
| 561 | - log.warn("Failed to create integration bridge on {}", node.ovsdbId()); | ||
| 562 | - } | ||
| 563 | } | 285 | } |
| 564 | 286 | ||
| 565 | /** | 287 | /** |
| 566 | - * Creates tunnel interface to the integration bridge for a given node. | 288 | + * Returns CordService by OpenStack network. |
| 567 | * | 289 | * |
| 568 | - * @param node cordvtn node | 290 | + * @param vNet OpenStack network |
| 291 | + * @return cord service | ||
| 569 | */ | 292 | */ |
| 570 | - private void createTunnelInterface(CordVtnNode node) { | 293 | + private CordService getCordService(OpenstackNetwork vNet) { |
| 571 | - if (checkTunnelInterface(node)) { | 294 | + checkNotNull(vNet); |
| 572 | - return; | ||
| 573 | - } | ||
| 574 | - | ||
| 575 | - DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder(); | ||
| 576 | - for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) { | ||
| 577 | - optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key)); | ||
| 578 | - } | ||
| 579 | - | ||
| 580 | - TunnelDescription description = new DefaultTunnelDescription( | ||
| 581 | - null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL), | ||
| 582 | - optionBuilder.build()); | ||
| 583 | 295 | ||
| 584 | - try { | 296 | + CordServiceId serviceId = CordServiceId.of(vNet.id()); |
| 585 | - DriverHandler handler = driverService.createHandler(node.ovsdbId()); | 297 | + OpenstackSubnet subnet = vNet.subnets().stream() |
| 586 | - TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class); | 298 | + .findFirst() |
| 587 | - tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description); | 299 | + .orElse(null); |
| 588 | - } catch (ItemNotFoundException e) { | 300 | + if (subnet == null) { |
| 589 | - log.warn("Failed to create tunnel interface on {}", node.ovsdbId()); | 301 | + log.warn("Couldn't find OpenStack subnet for service {}", serviceId); |
| 302 | + return null; | ||
| 590 | } | 303 | } |
| 591 | - } | ||
| 592 | - | ||
| 593 | - /** | ||
| 594 | - * Checks if integration bridge exists and available. | ||
| 595 | - * | ||
| 596 | - * @param node cordvtn node | ||
| 597 | - * @return true if the bridge is available, false otherwise | ||
| 598 | - */ | ||
| 599 | - private boolean checkIntegrationBridge(CordVtnNode node) { | ||
| 600 | - return (deviceService.getDevice(node.intBrId()) != null | ||
| 601 | - && deviceService.isAvailable(node.intBrId())); | ||
| 602 | - } | ||
| 603 | 304 | ||
| 604 | - /** | 305 | + Set<CordServiceId> tServices = Sets.newHashSet(); |
| 605 | - * Checks if tunnel interface exists. | 306 | + // TODO get tenant services from XOS |
| 606 | - * | ||
| 607 | - * @param node cordvtn node | ||
| 608 | - * @return true if the interface exists, false otherwise | ||
| 609 | - */ | ||
| 610 | - private boolean checkTunnelInterface(CordVtnNode node) { | ||
| 611 | - return deviceService.getPorts(node.intBrId()) | ||
| 612 | - .stream() | ||
| 613 | - .filter(p -> getPortName(p).contains(DEFAULT_TUNNEL) | ||
| 614 | - && p.isEnabled()) | ||
| 615 | - .findAny().isPresent(); | ||
| 616 | - } | ||
| 617 | 307 | ||
| 618 | - /** | 308 | + Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) |
| 619 | - * Checks if physical interface exists. | ||
| 620 | - * | ||
| 621 | - * @param node cordvtn node | ||
| 622 | - * @return true if the interface exists, false otherwise | ||
| 623 | - */ | ||
| 624 | - private boolean checkPhyInterface(CordVtnNode node) { | ||
| 625 | - return deviceService.getPorts(node.intBrId()) | ||
| 626 | .stream() | 309 | .stream() |
| 627 | - .filter(p -> getPortName(p).contains(node.phyPortName()) | 310 | + .collect(Collectors.toMap(host -> host, this::getTunnelIp)); |
| 628 | - && p.isEnabled()) | ||
| 629 | - .findAny().isPresent(); | ||
| 630 | - } | ||
| 631 | 311 | ||
| 632 | - /** | 312 | + return new CordService(vNet, subnet, hosts, tServices); |
| 633 | - * Returns remote ip address for tunneling. | ||
| 634 | - * | ||
| 635 | - * @param bridgeId device id | ||
| 636 | - * @return ip address, null if no such device exists | ||
| 637 | - */ | ||
| 638 | - private Ip4Address getRemoteIp(DeviceId bridgeId) { | ||
| 639 | - CordVtnNode node = getNodeByBridgeId(bridgeId); | ||
| 640 | - if (node != null) { | ||
| 641 | - return node.localIp().getIp4Address(); | ||
| 642 | - } else { | ||
| 643 | - log.debug("Couldn't find node information for {}", bridgeId); | ||
| 644 | - return null; | ||
| 645 | - } | ||
| 646 | } | 313 | } |
| 647 | 314 | ||
| 648 | /** | 315 | /** |
| 649 | - * Returns OpenStack port associated with a given host. | 316 | + * Returns IP address for tunneling for a given host. |
| 650 | * | 317 | * |
| 651 | * @param host host | 318 | * @param host host |
| 652 | - * @return OpenStack port, or null if no port has been found | 319 | + * @return ip address |
| 653 | */ | 320 | */ |
| 654 | - private OpenstackPort getOpenstackPortByHost(Host host) { | 321 | + private IpAddress getTunnelIp(Host host) { |
| 655 | - Port port = deviceService.getPort(host.location().deviceId(), | 322 | + return IpAddress.valueOf(host.annotations().value(LOCATION_IP)); |
| 656 | - host.location().port()); | ||
| 657 | - if (port == null) { | ||
| 658 | - log.debug("Failed to get port for {}", host.id()); | ||
| 659 | - return null; | ||
| 660 | - } | ||
| 661 | - return openstackService.port(port); | ||
| 662 | } | 323 | } |
| 663 | 324 | ||
| 664 | /** | 325 | /** |
| 665 | - * Returns OpenStack network associated with a given host. | 326 | + * Returns port name. |
| 666 | * | 327 | * |
| 667 | - * @param host host | 328 | + * @param port port |
| 668 | - * @return OpenStack network, or null if no network has been found | 329 | + * @return port name |
| 669 | */ | 330 | */ |
| 670 | - private OpenstackNetwork getOpenstackNetworkByHost(Host host) { | 331 | + private String getPortName(Port port) { |
| 671 | - OpenstackPort vPort = getOpenstackPortByHost(host); | 332 | + return port.annotations().value("portName"); |
| 672 | - if (vPort != null) { | ||
| 673 | - return openstackService.network(vPort.networkId()); | ||
| 674 | - } else { | ||
| 675 | - return null; | ||
| 676 | - } | ||
| 677 | } | 333 | } |
| 678 | 334 | ||
| 679 | /** | 335 | /** |
| ... | @@ -698,137 +354,66 @@ public class CordVtn implements CordVtnService { | ... | @@ -698,137 +354,66 @@ public class CordVtn implements CordVtnService { |
| 698 | } | 354 | } |
| 699 | 355 | ||
| 700 | /** | 356 | /** |
| 701 | - * Returns host IP assigned by OpenStack. | 357 | + * Handles VM detected situation. |
| 702 | * | 358 | * |
| 703 | * @param host host | 359 | * @param host host |
| 704 | - * @return IPv4 prefix, or null if it fails to get IP from OpenStack | ||
| 705 | - */ | ||
| 706 | - private IpAddress getHostIpFromOpenstack(Host host) { | ||
| 707 | - OpenstackPort vPort = getOpenstackPortByHost(host); | ||
| 708 | - | ||
| 709 | - if (vPort == null || vPort.fixedIps().isEmpty()) { | ||
| 710 | - log.error("Failed to get VM IP for {}", host.id()); | ||
| 711 | - return null; | ||
| 712 | - } | ||
| 713 | - // Assumes there's only one fixed IP is assigned to a port | ||
| 714 | - return (Ip4Address) vPort.fixedIps().values() | ||
| 715 | - .stream() | ||
| 716 | - .findFirst() | ||
| 717 | - .orElse(null); | ||
| 718 | - } | ||
| 719 | - | ||
| 720 | - /** | ||
| 721 | - * Returns port name with OpenStack port information. | ||
| 722 | - * | ||
| 723 | - * @param vPort OpenStack port | ||
| 724 | - * @return port name | ||
| 725 | */ | 360 | */ |
| 726 | - private String getPortName(OpenstackPort vPort) { | 361 | + private void serviceVmAdded(Host host) { |
| 727 | - checkNotNull(vPort); | 362 | + String vNetId = host.annotations().value(SERVICE_ID); |
| 728 | - return VPORT_PREFIX + vPort.id().substring(0, 10); | 363 | + OpenstackNetwork vNet = openstackService.network(vNetId); |
| 729 | - } | ||
| 730 | - | ||
| 731 | - /** | ||
| 732 | - * Returns if the host is VM or not. | ||
| 733 | - * | ||
| 734 | - * @param host host | ||
| 735 | - * @return true if the host is a VM. | ||
| 736 | - */ | ||
| 737 | - private boolean isVm(Host host) { | ||
| 738 | - Port port = deviceService.getPort(host.location().deviceId(), | ||
| 739 | - host.location().port()); | ||
| 740 | - return getPortName(port).contains(VPORT_PREFIX); | ||
| 741 | - } | ||
| 742 | - | ||
| 743 | - /** | ||
| 744 | - * Returns CordService by service ID. | ||
| 745 | - * | ||
| 746 | - * @param serviceId service id | ||
| 747 | - * @return cord service, or null if it fails to get network from OpenStack | ||
| 748 | - */ | ||
| 749 | - private CordService getCordService(CordServiceId serviceId) { | ||
| 750 | - OpenstackNetwork vNet = openstackService.network(serviceId.id()); | ||
| 751 | if (vNet == null) { | 364 | if (vNet == null) { |
| 752 | - log.warn("Couldn't find OpenStack network for service {}", serviceId.id()); | 365 | + log.warn("Failed to get OpenStack network {} for VM {}({}).", |
| 753 | - return null; | 366 | + vNetId, |
| 754 | - } | 367 | + host.id(), |
| 755 | - | 368 | + host.annotations().value(OPENSTACK_VM_ID)); |
| 756 | - OpenstackSubnet subnet = vNet.subnets().stream() | 369 | + return; |
| 757 | - .findFirst() | ||
| 758 | - .orElse(null); | ||
| 759 | - if (subnet == null) { | ||
| 760 | - log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id()); | ||
| 761 | - return null; | ||
| 762 | } | 370 | } |
| 763 | 371 | ||
| 764 | - Set<CordServiceId> tServices = Sets.newHashSet(); | 372 | + log.info("VM {} is detected, MAC: {} IP: {}", |
| 765 | - // TODO get tenant services from XOS | 373 | + host.annotations().value(OPENSTACK_VM_ID), |
| 374 | + host.mac(), | ||
| 375 | + host.ipAddresses().stream().findFirst().get()); | ||
| 766 | 376 | ||
| 767 | - Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) | 377 | + CordService service = getCordService(vNet); |
| 768 | - .stream() | 378 | + if (service != null) { |
| 769 | - .collect(Collectors.toMap(host -> host, | 379 | + // TODO check if the service needs an update on its group buckets after done CORD-433 |
| 770 | - host -> getRemoteIp(host.location().deviceId()))); | 380 | + ruleInstaller.updateServiceGroup(service); |
| 381 | + arpProxy.addServiceIp(service.serviceIp()); | ||
| 382 | + } | ||
| 771 | 383 | ||
| 772 | - return new CordService(vNet, subnet, hosts, tServices); | 384 | + ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet); |
| 773 | } | 385 | } |
| 774 | 386 | ||
| 775 | /** | 387 | /** |
| 776 | - * Returns CordService by OpenStack network. | 388 | + * Handles VM removed situation. |
| 777 | * | 389 | * |
| 778 | - * @param vNet OpenStack network | 390 | + * @param host host |
| 779 | - * @return cord service | ||
| 780 | */ | 391 | */ |
| 781 | - private CordService getCordService(OpenstackNetwork vNet) { | 392 | + private void serviceVmRemoved(Host host) { |
| 782 | - checkNotNull(vNet); | 393 | + String vNetId = host.annotations().value(SERVICE_ID); |
| 783 | - | 394 | + OpenstackNetwork vNet = openstackService.network(host.annotations().value(SERVICE_ID)); |
| 784 | - CordServiceId serviceId = CordServiceId.of(vNet.id()); | 395 | + if (vNet == null) { |
| 785 | - OpenstackSubnet subnet = vNet.subnets().stream() | 396 | + log.warn("Failed to get OpenStack network {} for VM {}({}).", |
| 786 | - .findFirst() | 397 | + vNetId, |
| 787 | - .orElse(null); | 398 | + host.id(), |
| 788 | - if (subnet == null) { | 399 | + host.annotations().value(OPENSTACK_VM_ID)); |
| 789 | - log.warn("Couldn't find OpenStack subnet for service {}", serviceId); | 400 | + return; |
| 790 | - return null; | ||
| 791 | } | 401 | } |
| 792 | 402 | ||
| 793 | - Set<CordServiceId> tServices = Sets.newHashSet(); | 403 | + log.info("VM {} is vanished, MAC: {} IP: {}", |
| 794 | - // TODO get tenant services from XOS | 404 | + host.annotations().value(OPENSTACK_VM_ID), |
| 795 | - | 405 | + host.mac(), |
| 796 | - Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet) | 406 | + host.ipAddresses().stream().findFirst().get()); |
| 797 | - .stream() | ||
| 798 | - .collect(Collectors.toMap(host -> host, | ||
| 799 | - host -> getRemoteIp(host.location().deviceId()))); | ||
| 800 | 407 | ||
| 801 | - return new CordService(vNet, subnet, hosts, tServices); | 408 | + ruleInstaller.removeBasicConnectionRules(host); |
| 802 | - } | ||
| 803 | - | ||
| 804 | - private class InternalDeviceListener implements DeviceListener { | ||
| 805 | - | ||
| 806 | - @Override | ||
| 807 | - public void event(DeviceEvent event) { | ||
| 808 | 409 | ||
| 809 | - Device device = event.subject(); | 410 | + CordService service = getCordService(vNet); |
| 810 | - ConnectionHandler<Device> handler = | 411 | + if (service != null) { |
| 811 | - (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler); | 412 | + // TODO check if the service needs an update on its group buckets after done CORD-433 |
| 413 | + ruleInstaller.updateServiceGroup(service); | ||
| 812 | 414 | ||
| 813 | - switch (event.type()) { | 415 | + if (getHostsWithOpenstackNetwork(vNet).isEmpty()) { |
| 814 | - case PORT_ADDED: | 416 | + arpProxy.removeServiceIp(service.serviceIp()); |
| 815 | - eventExecutor.submit(() -> bridgeHandler.portAdded(event.port())); | ||
| 816 | - break; | ||
| 817 | - case PORT_UPDATED: | ||
| 818 | - if (!event.port().isEnabled()) { | ||
| 819 | - eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port())); | ||
| 820 | - } | ||
| 821 | - break; | ||
| 822 | - case DEVICE_ADDED: | ||
| 823 | - case DEVICE_AVAILABILITY_CHANGED: | ||
| 824 | - if (deviceService.isAvailable(device.id())) { | ||
| 825 | - eventExecutor.submit(() -> handler.connected(device)); | ||
| 826 | - } else { | ||
| 827 | - eventExecutor.submit(() -> handler.disconnected(device)); | ||
| 828 | - } | ||
| 829 | - break; | ||
| 830 | - default: | ||
| 831 | - break; | ||
| 832 | } | 417 | } |
| 833 | } | 418 | } |
| 834 | } | 419 | } |
| ... | @@ -837,14 +422,14 @@ public class CordVtn implements CordVtnService { | ... | @@ -837,14 +422,14 @@ public class CordVtn implements CordVtnService { |
| 837 | 422 | ||
| 838 | @Override | 423 | @Override |
| 839 | public void event(HostEvent event) { | 424 | public void event(HostEvent event) { |
| 840 | - Host vm = event.subject(); | 425 | + Host host = event.subject(); |
| 841 | 426 | ||
| 842 | switch (event.type()) { | 427 | switch (event.type()) { |
| 843 | case HOST_ADDED: | 428 | case HOST_ADDED: |
| 844 | - eventExecutor.submit(() -> vmHandler.connected(vm)); | 429 | + eventExecutor.submit(() -> serviceVmAdded(host)); |
| 845 | break; | 430 | break; |
| 846 | case HOST_REMOVED: | 431 | case HOST_REMOVED: |
| 847 | - eventExecutor.submit(() -> vmHandler.disconnected(vm)); | 432 | + eventExecutor.submit(() -> serviceVmRemoved(host)); |
| 848 | break; | 433 | break; |
| 849 | default: | 434 | default: |
| 850 | break; | 435 | break; |
| ... | @@ -852,172 +437,6 @@ public class CordVtn implements CordVtnService { | ... | @@ -852,172 +437,6 @@ public class CordVtn implements CordVtnService { |
| 852 | } | 437 | } |
| 853 | } | 438 | } |
| 854 | 439 | ||
| 855 | - private class OvsdbHandler implements ConnectionHandler<Device> { | ||
| 856 | - | ||
| 857 | - @Override | ||
| 858 | - public void connected(Device device) { | ||
| 859 | - CordVtnNode node = getNodeByOvsdbId(device.id()); | ||
| 860 | - if (node != null) { | ||
| 861 | - setNodeState(node, checkNodeState(node)); | ||
| 862 | - } else { | ||
| 863 | - log.debug("Unregistered device {} connected, ignore it.", device.id()); | ||
| 864 | - } | ||
| 865 | - } | ||
| 866 | - | ||
| 867 | - @Override | ||
| 868 | - public void disconnected(Device device) { | ||
| 869 | - if (!deviceService.isAvailable(device.id())) { | ||
| 870 | - adminService.removeDevice(device.id()); | ||
| 871 | - } | ||
| 872 | - } | ||
| 873 | - } | ||
| 874 | - | ||
| 875 | - private class BridgeHandler implements ConnectionHandler<Device> { | ||
| 876 | - | ||
| 877 | - @Override | ||
| 878 | - public void connected(Device device) { | ||
| 879 | - CordVtnNode node = getNodeByBridgeId(device.id()); | ||
| 880 | - if (node != null) { | ||
| 881 | - setNodeState(node, checkNodeState(node)); | ||
| 882 | - } else { | ||
| 883 | - log.debug("Unregistered device {} connected, ignore it.", device.id()); | ||
| 884 | - } | ||
| 885 | - } | ||
| 886 | - | ||
| 887 | - @Override | ||
| 888 | - public void disconnected(Device device) { | ||
| 889 | - CordVtnNode node = getNodeByBridgeId(device.id()); | ||
| 890 | - if (node != null) { | ||
| 891 | - log.info("Integration Bridge is disconnected from {}", node.hostname()); | ||
| 892 | - setNodeState(node, NodeState.INCOMPLETE); | ||
| 893 | - } | ||
| 894 | - } | ||
| 895 | - | ||
| 896 | - /** | ||
| 897 | - * Handles port added situation. | ||
| 898 | - * If the added port is tunnel or physical port, proceed remaining node | ||
| 899 | - * initialization. Otherwise, do nothing. | ||
| 900 | - * | ||
| 901 | - * @param port port | ||
| 902 | - */ | ||
| 903 | - public void portAdded(Port port) { | ||
| 904 | - CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); | ||
| 905 | - if (node == null) { | ||
| 906 | - return; | ||
| 907 | - } else { | ||
| 908 | - log.debug("Port {} added to unregistered device, ignore it.", getPortName(port)); | ||
| 909 | - } | ||
| 910 | - | ||
| 911 | - // TODO add host by updating network config | ||
| 912 | - String portName = getPortName(port); | ||
| 913 | - if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) { | ||
| 914 | - return; | ||
| 915 | - } | ||
| 916 | - | ||
| 917 | - log.info("Port {} is added to {}", portName, node.hostname()); | ||
| 918 | - setNodeState(node, checkNodeState(node)); | ||
| 919 | - } | ||
| 920 | - | ||
| 921 | - /** | ||
| 922 | - * Handles port removed situation. | ||
| 923 | - * If the removed port is tunnel or physical port, proceed remaining node | ||
| 924 | - * initialization.Others, do nothing. | ||
| 925 | - * | ||
| 926 | - * @param port port | ||
| 927 | - */ | ||
| 928 | - public void portRemoved(Port port) { | ||
| 929 | - CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); | ||
| 930 | - if (node == null) { | ||
| 931 | - return; | ||
| 932 | - } | ||
| 933 | - | ||
| 934 | - // TODO remove host by updating network config | ||
| 935 | - String portName = getPortName(port); | ||
| 936 | - if (!portName.contains(DEFAULT_TUNNEL) && !portName.equals(node.phyPortName())) { | ||
| 937 | - return; | ||
| 938 | - } | ||
| 939 | - | ||
| 940 | - log.info("Port {} is removed from {}", portName, node.hostname()); | ||
| 941 | - setNodeState(node, NodeState.INCOMPLETE); | ||
| 942 | - } | ||
| 943 | - } | ||
| 944 | - | ||
| 945 | - private class VmHandler implements ConnectionHandler<Host> { | ||
| 946 | - | ||
| 947 | - @Override | ||
| 948 | - public void connected(Host host) { | ||
| 949 | - // TODO remove check VM here after applying network config host provider | ||
| 950 | - if (!isVm(host)) { | ||
| 951 | - log.debug("Host {} is not a VM, ignore it.", host.id()); | ||
| 952 | - return; | ||
| 953 | - } | ||
| 954 | - | ||
| 955 | - CordVtnNode node = getNodeByBridgeId(host.location().deviceId()); | ||
| 956 | - if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) { | ||
| 957 | - log.debug("VM {} is detected unknown or incomplete device, ignore it.", host.id()); | ||
| 958 | - return; | ||
| 959 | - } | ||
| 960 | - | ||
| 961 | - OpenstackNetwork vNet = getOpenstackNetworkByHost(host); | ||
| 962 | - if (vNet == null) { | ||
| 963 | - log.debug("Failed to get OpenStack network for VM {}, ignore it.", host.id()); | ||
| 964 | - return; | ||
| 965 | - } | ||
| 966 | - | ||
| 967 | - // TODO host ip should be set in host information after applying network config host provider | ||
| 968 | - IpAddress hostIp = getHostIpFromOpenstack(host); | ||
| 969 | - if (hostIp == null) { | ||
| 970 | - log.debug("Failed to get host IP of {}, ignore it.", host.id()); | ||
| 971 | - return; | ||
| 972 | - } | ||
| 973 | - | ||
| 974 | - log.info("VM {} is detected", host.id()); | ||
| 975 | - hostNetMap.put(host.id(), vNet); | ||
| 976 | - | ||
| 977 | - CordService service = getCordService(vNet); | ||
| 978 | - if (service != null) { | ||
| 979 | - // TODO check if the service needs an update on its group buckets after done CORD-433 | ||
| 980 | - ruleInstaller.updateServiceGroup(service); | ||
| 981 | - arpProxy.addServiceIp(service.serviceIp()); | ||
| 982 | - } | ||
| 983 | - | ||
| 984 | - ruleInstaller.populateBasicConnectionRules( | ||
| 985 | - host, | ||
| 986 | - hostIp, | ||
| 987 | - checkNotNull(getRemoteIp(host.location().deviceId())).getIp4Address(), | ||
| 988 | - vNet); | ||
| 989 | - } | ||
| 990 | - | ||
| 991 | - @Override | ||
| 992 | - public void disconnected(Host host) { | ||
| 993 | - CordVtnNode node = getNodeByBridgeId(host.location().deviceId()); | ||
| 994 | - if (node == null || !Objects.equals(getNodeState(node), NodeState.COMPLETE)) { | ||
| 995 | - // do nothing for the host on unregistered or unprepared device | ||
| 996 | - return; | ||
| 997 | - } | ||
| 998 | - | ||
| 999 | - OpenstackNetwork vNet = hostNetMap.get(host.id()); | ||
| 1000 | - if (vNet == null) { | ||
| 1001 | - return; | ||
| 1002 | - } | ||
| 1003 | - | ||
| 1004 | - log.info("VM {} is vanished", host.id()); | ||
| 1005 | - ruleInstaller.removeBasicConnectionRules(host); | ||
| 1006 | - | ||
| 1007 | - CordService service = getCordService(vNet); | ||
| 1008 | - if (service != null) { | ||
| 1009 | - // TODO check if the service needs an update on its group buckets after done CORD-433 | ||
| 1010 | - ruleInstaller.updateServiceGroup(service); | ||
| 1011 | - | ||
| 1012 | - if (getHostsWithOpenstackNetwork(vNet).isEmpty()) { | ||
| 1013 | - arpProxy.removeServiceIp(service.serviceIp()); | ||
| 1014 | - } | ||
| 1015 | - } | ||
| 1016 | - | ||
| 1017 | - hostNetMap.remove(host.id()); | ||
| 1018 | - } | ||
| 1019 | - } | ||
| 1020 | - | ||
| 1021 | private class InternalPacketProcessor implements PacketProcessor { | 440 | private class InternalPacketProcessor implements PacketProcessor { |
| 1022 | 441 | ||
| 1023 | @Override | 442 | @Override | ... | ... |
| 1 | -/* | ||
| 2 | - * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | - * | ||
| 4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | - * you may not use this file except in compliance with the License. | ||
| 6 | - * You may obtain a copy of the License at | ||
| 7 | - * | ||
| 8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | - * | ||
| 10 | - * Unless required by applicable law or agreed to in writing, software | ||
| 11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | - * See the License for the specific language governing permissions and | ||
| 14 | - * limitations under the License. | ||
| 15 | - */ | ||
| 16 | -package org.onosproject.cordvtn; | ||
| 17 | - | ||
| 18 | -import org.apache.felix.scr.annotations.Activate; | ||
| 19 | -import org.apache.felix.scr.annotations.Component; | ||
| 20 | -import org.apache.felix.scr.annotations.Deactivate; | ||
| 21 | -import org.apache.felix.scr.annotations.Reference; | ||
| 22 | -import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 23 | -import org.onosproject.core.ApplicationId; | ||
| 24 | -import org.onosproject.core.CoreService; | ||
| 25 | -import org.onosproject.net.config.ConfigFactory; | ||
| 26 | -import org.onosproject.net.config.NetworkConfigEvent; | ||
| 27 | -import org.onosproject.net.config.NetworkConfigListener; | ||
| 28 | -import org.onosproject.net.config.NetworkConfigRegistry; | ||
| 29 | -import org.onosproject.net.config.NetworkConfigService; | ||
| 30 | -import org.onosproject.net.config.basics.SubjectFactories; | ||
| 31 | -import org.slf4j.Logger; | ||
| 32 | - | ||
| 33 | -import java.util.concurrent.ExecutorService; | ||
| 34 | - | ||
| 35 | -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | ||
| 36 | -import static org.onlab.util.Tools.groupedThreads; | ||
| 37 | -import static org.slf4j.LoggerFactory.getLogger; | ||
| 38 | - | ||
| 39 | -/** | ||
| 40 | - * Reads node information from the network config file and handles the config | ||
| 41 | - * update events. | ||
| 42 | - * Only a leader controller performs the node addition or deletion. | ||
| 43 | - */ | ||
| 44 | -@Component(immediate = true) | ||
| 45 | -public class CordVtnConfigManager { | ||
| 46 | - | ||
| 47 | - protected final Logger log = getLogger(getClass()); | ||
| 48 | - | ||
| 49 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 50 | - protected CoreService coreService; | ||
| 51 | - | ||
| 52 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 53 | - protected NetworkConfigRegistry configRegistry; | ||
| 54 | - | ||
| 55 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 56 | - protected NetworkConfigService configService; | ||
| 57 | - | ||
| 58 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 59 | - protected CordVtnService cordVtnService; | ||
| 60 | - | ||
| 61 | - private final ConfigFactory configFactory = | ||
| 62 | - new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") { | ||
| 63 | - @Override | ||
| 64 | - public CordVtnConfig createConfig() { | ||
| 65 | - return new CordVtnConfig(); | ||
| 66 | - } | ||
| 67 | - }; | ||
| 68 | - | ||
| 69 | - private final NetworkConfigListener configListener = new InternalConfigListener(); | ||
| 70 | - private ApplicationId appId; | ||
| 71 | - protected ExecutorService eventExecutor; | ||
| 72 | - | ||
| 73 | - | ||
| 74 | - @Activate | ||
| 75 | - protected void active() { | ||
| 76 | - appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID); | ||
| 77 | - | ||
| 78 | - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtncfg", "event-handler")); | ||
| 79 | - configService.addListener(configListener); | ||
| 80 | - configRegistry.registerConfigFactory(configFactory); | ||
| 81 | - } | ||
| 82 | - | ||
| 83 | - @Deactivate | ||
| 84 | - protected void deactivate() { | ||
| 85 | - configRegistry.unregisterConfigFactory(configFactory); | ||
| 86 | - configService.removeListener(configListener); | ||
| 87 | - eventExecutor.shutdown(); | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - private void readConfiguration() { | ||
| 91 | - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class); | ||
| 92 | - | ||
| 93 | - if (config == null) { | ||
| 94 | - log.warn("No configuration found"); | ||
| 95 | - return; | ||
| 96 | - } | ||
| 97 | - | ||
| 98 | - config.cordVtnNodes().forEach(node -> { | ||
| 99 | - CordVtnNode cordVtnNode = new CordVtnNode( | ||
| 100 | - node.hostname(), | ||
| 101 | - node.ovsdbIp(), | ||
| 102 | - node.ovsdbPort(), | ||
| 103 | - node.bridgeId(), | ||
| 104 | - node.phyPortName(), | ||
| 105 | - node.localIp()); | ||
| 106 | - | ||
| 107 | - cordVtnService.addNode(cordVtnNode); | ||
| 108 | - }); | ||
| 109 | - } | ||
| 110 | - | ||
| 111 | - private class InternalConfigListener implements NetworkConfigListener { | ||
| 112 | - | ||
| 113 | - @Override | ||
| 114 | - public void event(NetworkConfigEvent event) { | ||
| 115 | - if (!event.configClass().equals(CordVtnConfig.class)) { | ||
| 116 | - return; | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - switch (event.type()) { | ||
| 120 | - case CONFIG_ADDED: | ||
| 121 | - log.info("Network configuration added"); | ||
| 122 | - eventExecutor.execute(CordVtnConfigManager.this::readConfiguration); | ||
| 123 | - break; | ||
| 124 | - case CONFIG_UPDATED: | ||
| 125 | - log.info("Network configuration updated"); | ||
| 126 | - eventExecutor.execute(CordVtnConfigManager.this::readConfiguration); | ||
| 127 | - break; | ||
| 128 | - default: | ||
| 129 | - break; | ||
| 130 | - } | ||
| 131 | - } | ||
| 132 | - } | ||
| 133 | -} |
| 1 | +/* | ||
| 2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.cordvtn; | ||
| 17 | + | ||
| 18 | +import com.google.common.collect.Sets; | ||
| 19 | +import org.apache.felix.scr.annotations.Activate; | ||
| 20 | +import org.apache.felix.scr.annotations.Component; | ||
| 21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
| 22 | +import org.apache.felix.scr.annotations.Reference; | ||
| 23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 24 | +import org.apache.felix.scr.annotations.Service; | ||
| 25 | +import org.onlab.util.ItemNotFoundException; | ||
| 26 | +import org.onlab.util.KryoNamespace; | ||
| 27 | +import org.onosproject.cluster.ClusterService; | ||
| 28 | +import org.onosproject.core.ApplicationId; | ||
| 29 | +import org.onosproject.core.CoreService; | ||
| 30 | +import org.onosproject.mastership.MastershipService; | ||
| 31 | +import org.onosproject.net.ConnectPoint; | ||
| 32 | +import org.onosproject.net.DefaultAnnotations; | ||
| 33 | +import org.onosproject.net.Device; | ||
| 34 | +import org.onosproject.net.DeviceId; | ||
| 35 | +import org.onosproject.net.Host; | ||
| 36 | +import org.onosproject.net.Port; | ||
| 37 | +import org.onosproject.net.behaviour.BridgeConfig; | ||
| 38 | +import org.onosproject.net.behaviour.BridgeName; | ||
| 39 | +import org.onosproject.net.behaviour.ControllerInfo; | ||
| 40 | +import org.onosproject.net.behaviour.DefaultTunnelDescription; | ||
| 41 | +import org.onosproject.net.behaviour.TunnelConfig; | ||
| 42 | +import org.onosproject.net.behaviour.TunnelDescription; | ||
| 43 | +import org.onosproject.net.behaviour.TunnelName; | ||
| 44 | +import org.onosproject.net.config.ConfigFactory; | ||
| 45 | +import org.onosproject.net.config.NetworkConfigEvent; | ||
| 46 | +import org.onosproject.net.config.NetworkConfigListener; | ||
| 47 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
| 48 | +import org.onosproject.net.config.NetworkConfigService; | ||
| 49 | +import org.onosproject.net.config.basics.SubjectFactories; | ||
| 50 | +import org.onosproject.net.device.DeviceAdminService; | ||
| 51 | +import org.onosproject.net.device.DeviceEvent; | ||
| 52 | +import org.onosproject.net.device.DeviceListener; | ||
| 53 | +import org.onosproject.net.device.DeviceService; | ||
| 54 | +import org.onosproject.net.driver.DriverHandler; | ||
| 55 | +import org.onosproject.net.driver.DriverService; | ||
| 56 | +import org.onosproject.net.flow.FlowRuleService; | ||
| 57 | +import org.onosproject.net.group.GroupService; | ||
| 58 | +import org.onosproject.net.host.HostService; | ||
| 59 | +import org.onosproject.ovsdb.controller.OvsdbClientService; | ||
| 60 | +import org.onosproject.ovsdb.controller.OvsdbController; | ||
| 61 | +import org.onosproject.ovsdb.controller.OvsdbNodeId; | ||
| 62 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
| 63 | +import org.onosproject.store.service.ConsistentMap; | ||
| 64 | +import org.onosproject.store.service.Serializer; | ||
| 65 | +import org.onosproject.store.service.StorageService; | ||
| 66 | +import org.slf4j.Logger; | ||
| 67 | + | ||
| 68 | +import java.util.ArrayList; | ||
| 69 | +import java.util.HashMap; | ||
| 70 | +import java.util.List; | ||
| 71 | +import java.util.Map; | ||
| 72 | +import java.util.concurrent.ExecutorService; | ||
| 73 | + | ||
| 74 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 75 | +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | ||
| 76 | +import static org.onlab.util.Tools.groupedThreads; | ||
| 77 | +import static org.onosproject.net.Device.Type.SWITCH; | ||
| 78 | +import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN; | ||
| 79 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 80 | + | ||
| 81 | +/** | ||
| 82 | + * Reads node information from the network config file and handles the config | ||
| 83 | + * update events. | ||
| 84 | + * Only a leader controller performs the node addition or deletion. | ||
| 85 | + */ | ||
| 86 | +@Component(immediate = true) | ||
| 87 | +@Service(value = CordVtnNodeManager.class) | ||
| 88 | +public class CordVtnNodeManager { | ||
| 89 | + | ||
| 90 | + protected final Logger log = getLogger(getClass()); | ||
| 91 | + | ||
| 92 | + private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder() | ||
| 93 | + .register(KryoNamespaces.API) | ||
| 94 | + .register(CordVtnNode.class) | ||
| 95 | + .register(NodeState.class); | ||
| 96 | + | ||
| 97 | + private static final String DEFAULT_BRIDGE = "br-int"; | ||
| 98 | + private static final String DEFAULT_TUNNEL = "vxlan"; | ||
| 99 | + private static final String VPORT_PREFIX = "tap"; | ||
| 100 | + private static final String OK = "OK"; | ||
| 101 | + private static final String NO = "NO"; | ||
| 102 | + | ||
| 103 | + private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() { | ||
| 104 | + { | ||
| 105 | + put("key", "flow"); | ||
| 106 | + put("remote_ip", "flow"); | ||
| 107 | + } | ||
| 108 | + }; | ||
| 109 | + private static final int DPID_BEGIN = 3; | ||
| 110 | + private static final int OFPORT = 6653; | ||
| 111 | + | ||
| 112 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 113 | + protected CoreService coreService; | ||
| 114 | + | ||
| 115 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 116 | + protected NetworkConfigRegistry configRegistry; | ||
| 117 | + | ||
| 118 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 119 | + protected NetworkConfigService configService; | ||
| 120 | + | ||
| 121 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 122 | + protected StorageService storageService; | ||
| 123 | + | ||
| 124 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 125 | + protected DeviceAdminService adminService; | ||
| 126 | + | ||
| 127 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 128 | + protected OvsdbController controller; | ||
| 129 | + | ||
| 130 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 131 | + protected ClusterService clusterService; | ||
| 132 | + | ||
| 133 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 134 | + protected DriverService driverService; | ||
| 135 | + | ||
| 136 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 137 | + protected DeviceService deviceService; | ||
| 138 | + | ||
| 139 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 140 | + protected HostService hostService; | ||
| 141 | + | ||
| 142 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 143 | + protected FlowRuleService flowRuleService; | ||
| 144 | + | ||
| 145 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 146 | + protected MastershipService mastershipService; | ||
| 147 | + | ||
| 148 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 149 | + protected GroupService groupService; | ||
| 150 | + | ||
| 151 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 152 | + protected CordVtnService cordVtnService; | ||
| 153 | + | ||
| 154 | + private final ConfigFactory configFactory = | ||
| 155 | + new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") { | ||
| 156 | + @Override | ||
| 157 | + public CordVtnConfig createConfig() { | ||
| 158 | + return new CordVtnConfig(); | ||
| 159 | + } | ||
| 160 | + }; | ||
| 161 | + | ||
| 162 | + private final ExecutorService eventExecutor = | ||
| 163 | + newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtncfg", "event-handler")); | ||
| 164 | + | ||
| 165 | + private final NetworkConfigListener configListener = new InternalConfigListener(); | ||
| 166 | + private final DeviceListener deviceListener = new InternalDeviceListener(); | ||
| 167 | + | ||
| 168 | + private final OvsdbHandler ovsdbHandler = new OvsdbHandler(); | ||
| 169 | + private final BridgeHandler bridgeHandler = new BridgeHandler(); | ||
| 170 | + | ||
| 171 | + private ConsistentMap<CordVtnNode, NodeState> nodeStore; | ||
| 172 | + private CordVtnRuleInstaller ruleInstaller; | ||
| 173 | + private ApplicationId appId; | ||
| 174 | + | ||
| 175 | + private enum NodeState { | ||
| 176 | + | ||
| 177 | + INIT { | ||
| 178 | + @Override | ||
| 179 | + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | ||
| 180 | + nodeManager.connectOvsdb(node); | ||
| 181 | + } | ||
| 182 | + }, | ||
| 183 | + OVSDB_CONNECTED { | ||
| 184 | + @Override | ||
| 185 | + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | ||
| 186 | + if (!nodeManager.getOvsdbConnectionState(node)) { | ||
| 187 | + nodeManager.connectOvsdb(node); | ||
| 188 | + } else { | ||
| 189 | + nodeManager.createIntegrationBridge(node); | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + }, | ||
| 193 | + BRIDGE_CREATED { | ||
| 194 | + @Override | ||
| 195 | + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | ||
| 196 | + if (!nodeManager.getOvsdbConnectionState(node)) { | ||
| 197 | + nodeManager.connectOvsdb(node); | ||
| 198 | + } else { | ||
| 199 | + nodeManager.createTunnelInterface(node); | ||
| 200 | + } | ||
| 201 | + } | ||
| 202 | + }, | ||
| 203 | + COMPLETE { | ||
| 204 | + @Override | ||
| 205 | + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | ||
| 206 | + nodeManager.postInit(node); | ||
| 207 | + } | ||
| 208 | + }, | ||
| 209 | + INCOMPLETE { | ||
| 210 | + @Override | ||
| 211 | + public void process(CordVtnNodeManager nodeManager, CordVtnNode node) { | ||
| 212 | + } | ||
| 213 | + }; | ||
| 214 | + | ||
| 215 | + // TODO Add physical port add state | ||
| 216 | + | ||
| 217 | + public abstract void process(CordVtnNodeManager nodeManager, CordVtnNode node); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + @Activate | ||
| 221 | + protected void active() { | ||
| 222 | + appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID); | ||
| 223 | + | ||
| 224 | + nodeStore = storageService.<CordVtnNode, NodeState>consistentMapBuilder() | ||
| 225 | + .withSerializer(Serializer.using(NODE_SERIALIZER.build())) | ||
| 226 | + .withName("cordvtn-nodestore") | ||
| 227 | + .withApplicationId(appId) | ||
| 228 | + .build(); | ||
| 229 | + | ||
| 230 | + ruleInstaller = new CordVtnRuleInstaller(appId, flowRuleService, | ||
| 231 | + deviceService, | ||
| 232 | + driverService, | ||
| 233 | + groupService, | ||
| 234 | + mastershipService, | ||
| 235 | + DEFAULT_TUNNEL); | ||
| 236 | + | ||
| 237 | + deviceService.addListener(deviceListener); | ||
| 238 | + configService.addListener(configListener); | ||
| 239 | + configRegistry.registerConfigFactory(configFactory); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + @Deactivate | ||
| 243 | + protected void deactivate() { | ||
| 244 | + configRegistry.unregisterConfigFactory(configFactory); | ||
| 245 | + configService.removeListener(configListener); | ||
| 246 | + deviceService.removeListener(deviceListener); | ||
| 247 | + | ||
| 248 | + eventExecutor.shutdown(); | ||
| 249 | + nodeStore.clear(); | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + /** | ||
| 253 | + * Adds a new node to the service. | ||
| 254 | + * | ||
| 255 | + * @param node cordvtn node | ||
| 256 | + */ | ||
| 257 | + public void addNode(CordVtnNode node) { | ||
| 258 | + checkNotNull(node); | ||
| 259 | + | ||
| 260 | + nodeStore.putIfAbsent(node, checkNodeState(node)); | ||
| 261 | + initNode(node); | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + /** | ||
| 265 | + * Deletes a node from the service. | ||
| 266 | + * | ||
| 267 | + * @param node cordvtn node | ||
| 268 | + */ | ||
| 269 | + public void deleteNode(CordVtnNode node) { | ||
| 270 | + checkNotNull(node); | ||
| 271 | + | ||
| 272 | + if (getOvsdbConnectionState(node)) { | ||
| 273 | + disconnectOvsdb(node); | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + nodeStore.remove(node); | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + /** | ||
| 280 | + * Initiates node to serve virtual tenant network. | ||
| 281 | + * | ||
| 282 | + * @param node cordvtn node | ||
| 283 | + */ | ||
| 284 | + public void initNode(CordVtnNode node) { | ||
| 285 | + checkNotNull(node); | ||
| 286 | + | ||
| 287 | + if (!nodeStore.containsKey(node)) { | ||
| 288 | + log.warn("Node {} does not exist, add node first", node.hostname()); | ||
| 289 | + return; | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | + NodeState state = checkNodeState(node); | ||
| 293 | + state.process(this, node); | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + /** | ||
| 297 | + * Returns node initialization state. | ||
| 298 | + * | ||
| 299 | + * @param node cordvtn node | ||
| 300 | + * @return true if initial node setup is completed, otherwise false | ||
| 301 | + */ | ||
| 302 | + public boolean getNodeInitState(CordVtnNode node) { | ||
| 303 | + checkNotNull(node); | ||
| 304 | + | ||
| 305 | + NodeState state = getNodeState(node); | ||
| 306 | + return state != null && state.equals(NodeState.COMPLETE); | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + /** | ||
| 310 | + * Returns detailed node initialization state. | ||
| 311 | + * Return string includes the following information. | ||
| 312 | + * | ||
| 313 | + * Integration bridge created/connected: OK or NO | ||
| 314 | + * VXLAN interface created: OK or NO | ||
| 315 | + * Physical interface added: OK or NO | ||
| 316 | + * | ||
| 317 | + * @param node cordvtn node | ||
| 318 | + * @return string including detailed node init state | ||
| 319 | + */ | ||
| 320 | + public String checkNodeInitState(CordVtnNode node) { | ||
| 321 | + checkNotNull(node); | ||
| 322 | + | ||
| 323 | + NodeState state = getNodeState(node); | ||
| 324 | + if (state == null) { | ||
| 325 | + log.warn("Failed to get init state of {}", node.hostname()); | ||
| 326 | + return null; | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | + String result = String.format( | ||
| 330 | + "Integration bridge created/connected : %s (%s)%n" + | ||
| 331 | + "VXLAN interface created : %s%n" + | ||
| 332 | + "Physical interface added : %s (%s)", | ||
| 333 | + checkIntegrationBridge(node) ? OK : NO, DEFAULT_BRIDGE, | ||
| 334 | + checkTunnelInterface(node) ? OK : NO, | ||
| 335 | + checkPhyInterface(node) ? OK : NO, node.phyPortName()); | ||
| 336 | + | ||
| 337 | + return result; | ||
| 338 | + } | ||
| 339 | + | ||
| 340 | + /** | ||
| 341 | + * Returns the number of the nodes known to the service. | ||
| 342 | + * | ||
| 343 | + * @return number of nodes | ||
| 344 | + */ | ||
| 345 | + public int getNodeCount() { | ||
| 346 | + return nodeStore.size(); | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + /** | ||
| 350 | + * Returns all nodes known to the service. | ||
| 351 | + * | ||
| 352 | + * @return list of nodes | ||
| 353 | + */ | ||
| 354 | + public List<CordVtnNode> getNodes() { | ||
| 355 | + List<CordVtnNode> nodes = new ArrayList<>(); | ||
| 356 | + nodes.addAll(nodeStore.keySet()); | ||
| 357 | + return nodes; | ||
| 358 | + } | ||
| 359 | + | ||
| 360 | + /** | ||
| 361 | + * Returns cordvtn node associated with a given OVSDB device. | ||
| 362 | + * | ||
| 363 | + * @param ovsdbId OVSDB device id | ||
| 364 | + * @return cordvtn node, null if it fails to find the node | ||
| 365 | + */ | ||
| 366 | + private CordVtnNode getNodeByOvsdbId(DeviceId ovsdbId) { | ||
| 367 | + return getNodes().stream() | ||
| 368 | + .filter(node -> node.ovsdbId().equals(ovsdbId)) | ||
| 369 | + .findFirst().orElse(null); | ||
| 370 | + } | ||
| 371 | + | ||
| 372 | + /** | ||
| 373 | + * Returns cordvtn node associated with a given integration bridge. | ||
| 374 | + * | ||
| 375 | + * @param bridgeId device id of integration bridge | ||
| 376 | + * @return cordvtn node, null if it fails to find the node | ||
| 377 | + */ | ||
| 378 | + private CordVtnNode getNodeByBridgeId(DeviceId bridgeId) { | ||
| 379 | + return getNodes().stream() | ||
| 380 | + .filter(node -> node.intBrId().equals(bridgeId)) | ||
| 381 | + .findFirst().orElse(null); | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + /** | ||
| 385 | + * Returns state of a given cordvtn node. | ||
| 386 | + * | ||
| 387 | + * @param node cordvtn node | ||
| 388 | + * @return node state, or null if no such node exists | ||
| 389 | + */ | ||
| 390 | + private NodeState getNodeState(CordVtnNode node) { | ||
| 391 | + checkNotNull(node); | ||
| 392 | + | ||
| 393 | + try { | ||
| 394 | + return nodeStore.get(node).value(); | ||
| 395 | + } catch (NullPointerException e) { | ||
| 396 | + log.error("Failed to get state of {}", node.hostname()); | ||
| 397 | + return null; | ||
| 398 | + } | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + /** | ||
| 402 | + * Sets a new state for a given cordvtn node. | ||
| 403 | + * | ||
| 404 | + * @param node cordvtn node | ||
| 405 | + * @param newState new node state | ||
| 406 | + */ | ||
| 407 | + private void setNodeState(CordVtnNode node, NodeState newState) { | ||
| 408 | + checkNotNull(node); | ||
| 409 | + | ||
| 410 | + log.debug("Changed {} state: {}", node.hostname(), newState.toString()); | ||
| 411 | + | ||
| 412 | + nodeStore.put(node, newState); | ||
| 413 | + newState.process(this, node); | ||
| 414 | + } | ||
| 415 | + | ||
| 416 | + /** | ||
| 417 | + * Checks current state of a given cordvtn node and returns it. | ||
| 418 | + * | ||
| 419 | + * @param node cordvtn node | ||
| 420 | + * @return node state | ||
| 421 | + */ | ||
| 422 | + private NodeState checkNodeState(CordVtnNode node) { | ||
| 423 | + checkNotNull(node); | ||
| 424 | + | ||
| 425 | + if (checkIntegrationBridge(node) && checkTunnelInterface(node)) { | ||
| 426 | + // TODO add physical port add state | ||
| 427 | + if (checkPhyInterface(node)) { | ||
| 428 | + return NodeState.COMPLETE; | ||
| 429 | + } else { | ||
| 430 | + return NodeState.INCOMPLETE; | ||
| 431 | + } | ||
| 432 | + } else if (checkIntegrationBridge(node)) { | ||
| 433 | + return NodeState.BRIDGE_CREATED; | ||
| 434 | + } else if (getOvsdbConnectionState(node)) { | ||
| 435 | + return NodeState.OVSDB_CONNECTED; | ||
| 436 | + } else { | ||
| 437 | + return NodeState.INIT; | ||
| 438 | + } | ||
| 439 | + } | ||
| 440 | + | ||
| 441 | + /** | ||
| 442 | + * Performs tasks after node initialization. | ||
| 443 | + * It disconnects unnecessary OVSDB connection and installs initial flow | ||
| 444 | + * rules on the device. | ||
| 445 | + * | ||
| 446 | + * @param node cordvtn node | ||
| 447 | + */ | ||
| 448 | + private void postInit(CordVtnNode node) { | ||
| 449 | + disconnectOvsdb(node); | ||
| 450 | + | ||
| 451 | + ruleInstaller.init(node.intBrId(), node.phyPortName(), node.localIp()); | ||
| 452 | + | ||
| 453 | + // add existing hosts to the service | ||
| 454 | + deviceService.getPorts(node.intBrId()).stream() | ||
| 455 | + .filter(port -> getPortName(port).startsWith(VPORT_PREFIX) && | ||
| 456 | + port.isEnabled()) | ||
| 457 | + .forEach(port -> cordVtnService.addServiceVm(node, getConnectPoint(port))); | ||
| 458 | + | ||
| 459 | + // remove stale hosts from the service | ||
| 460 | + hostService.getHosts().forEach(host -> { | ||
| 461 | + Port port = deviceService.getPort(host.location().deviceId(), host.location().port()); | ||
| 462 | + if (port == null) { | ||
| 463 | + cordVtnService.removeServiceVm(getConnectPoint(host)); | ||
| 464 | + } | ||
| 465 | + }); | ||
| 466 | + | ||
| 467 | + log.info("Finished init {}", node.hostname()); | ||
| 468 | + } | ||
| 469 | + | ||
| 470 | + /** | ||
| 471 | + * Returns port name. | ||
| 472 | + * | ||
| 473 | + * @param port port | ||
| 474 | + * @return port name | ||
| 475 | + */ | ||
| 476 | + private String getPortName(Port port) { | ||
| 477 | + return port.annotations().value("portName"); | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + /** | ||
| 481 | + * Returns connection state of OVSDB server for a given node. | ||
| 482 | + * | ||
| 483 | + * @param node cordvtn node | ||
| 484 | + * @return true if it is connected, false otherwise | ||
| 485 | + */ | ||
| 486 | + private boolean getOvsdbConnectionState(CordVtnNode node) { | ||
| 487 | + checkNotNull(node); | ||
| 488 | + | ||
| 489 | + OvsdbClientService ovsdbClient = getOvsdbClient(node); | ||
| 490 | + return deviceService.isAvailable(node.ovsdbId()) && | ||
| 491 | + ovsdbClient != null && ovsdbClient.isConnected(); | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + /** | ||
| 495 | + * Connects to OVSDB server for a given node. | ||
| 496 | + * | ||
| 497 | + * @param node cordvtn node | ||
| 498 | + */ | ||
| 499 | + private void connectOvsdb(CordVtnNode node) { | ||
| 500 | + checkNotNull(node); | ||
| 501 | + | ||
| 502 | + if (!nodeStore.containsKey(node)) { | ||
| 503 | + log.warn("Node {} does not exist", node.hostname()); | ||
| 504 | + return; | ||
| 505 | + } | ||
| 506 | + | ||
| 507 | + if (!getOvsdbConnectionState(node)) { | ||
| 508 | + controller.connect(node.ovsdbIp(), node.ovsdbPort()); | ||
| 509 | + } | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + /** | ||
| 513 | + * Disconnects OVSDB server for a given node. | ||
| 514 | + * | ||
| 515 | + * @param node cordvtn node | ||
| 516 | + */ | ||
| 517 | + private void disconnectOvsdb(CordVtnNode node) { | ||
| 518 | + checkNotNull(node); | ||
| 519 | + | ||
| 520 | + if (!nodeStore.containsKey(node)) { | ||
| 521 | + log.warn("Node {} does not exist", node.hostname()); | ||
| 522 | + return; | ||
| 523 | + } | ||
| 524 | + | ||
| 525 | + if (getOvsdbConnectionState(node)) { | ||
| 526 | + OvsdbClientService ovsdbClient = getOvsdbClient(node); | ||
| 527 | + ovsdbClient.disconnect(); | ||
| 528 | + } | ||
| 529 | + } | ||
| 530 | + | ||
| 531 | + /** | ||
| 532 | + * Returns OVSDB client for a given node. | ||
| 533 | + * | ||
| 534 | + * @param node cordvtn node | ||
| 535 | + * @return OVSDB client, or null if it fails to get OVSDB client | ||
| 536 | + */ | ||
| 537 | + private OvsdbClientService getOvsdbClient(CordVtnNode node) { | ||
| 538 | + checkNotNull(node); | ||
| 539 | + | ||
| 540 | + OvsdbClientService ovsdbClient = controller.getOvsdbClient( | ||
| 541 | + new OvsdbNodeId(node.ovsdbIp(), node.ovsdbPort().toInt())); | ||
| 542 | + if (ovsdbClient == null) { | ||
| 543 | + log.trace("Couldn't find OVSDB client for {}", node.hostname()); | ||
| 544 | + } | ||
| 545 | + return ovsdbClient; | ||
| 546 | + } | ||
| 547 | + | ||
| 548 | + /** | ||
| 549 | + * Creates an integration bridge for a given node. | ||
| 550 | + * | ||
| 551 | + * @param node cordvtn node | ||
| 552 | + */ | ||
| 553 | + private void createIntegrationBridge(CordVtnNode node) { | ||
| 554 | + if (checkIntegrationBridge(node)) { | ||
| 555 | + return; | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + List<ControllerInfo> controllers = new ArrayList<>(); | ||
| 559 | + Sets.newHashSet(clusterService.getNodes()).stream() | ||
| 560 | + .forEach(controller -> { | ||
| 561 | + ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp"); | ||
| 562 | + controllers.add(ctrlInfo); | ||
| 563 | + }); | ||
| 564 | + | ||
| 565 | + String dpid = node.intBrId().toString().substring(DPID_BEGIN); | ||
| 566 | + | ||
| 567 | + try { | ||
| 568 | + DriverHandler handler = driverService.createHandler(node.ovsdbId()); | ||
| 569 | + BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class); | ||
| 570 | + bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers); | ||
| 571 | + } catch (ItemNotFoundException e) { | ||
| 572 | + log.warn("Failed to create integration bridge on {}", node.ovsdbId()); | ||
| 573 | + } | ||
| 574 | + } | ||
| 575 | + | ||
| 576 | + /** | ||
| 577 | + * Creates tunnel interface to the integration bridge for a given node. | ||
| 578 | + * | ||
| 579 | + * @param node cordvtn node | ||
| 580 | + */ | ||
| 581 | + private void createTunnelInterface(CordVtnNode node) { | ||
| 582 | + if (checkTunnelInterface(node)) { | ||
| 583 | + return; | ||
| 584 | + } | ||
| 585 | + | ||
| 586 | + DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder(); | ||
| 587 | + for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) { | ||
| 588 | + optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key)); | ||
| 589 | + } | ||
| 590 | + | ||
| 591 | + TunnelDescription description = new DefaultTunnelDescription( | ||
| 592 | + null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL), | ||
| 593 | + optionBuilder.build()); | ||
| 594 | + | ||
| 595 | + try { | ||
| 596 | + DriverHandler handler = driverService.createHandler(node.ovsdbId()); | ||
| 597 | + TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class); | ||
| 598 | + tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description); | ||
| 599 | + } catch (ItemNotFoundException e) { | ||
| 600 | + log.warn("Failed to create tunnel interface on {}", node.ovsdbId()); | ||
| 601 | + } | ||
| 602 | + } | ||
| 603 | + | ||
| 604 | + /** | ||
| 605 | + * Checks if integration bridge exists and available. | ||
| 606 | + * | ||
| 607 | + * @param node cordvtn node | ||
| 608 | + * @return true if the bridge is available, false otherwise | ||
| 609 | + */ | ||
| 610 | + private boolean checkIntegrationBridge(CordVtnNode node) { | ||
| 611 | + return (deviceService.getDevice(node.intBrId()) != null | ||
| 612 | + && deviceService.isAvailable(node.intBrId())); | ||
| 613 | + } | ||
| 614 | + | ||
| 615 | + /** | ||
| 616 | + * Checks if tunnel interface exists. | ||
| 617 | + * | ||
| 618 | + * @param node cordvtn node | ||
| 619 | + * @return true if the interface exists, false otherwise | ||
| 620 | + */ | ||
| 621 | + private boolean checkTunnelInterface(CordVtnNode node) { | ||
| 622 | + return deviceService.getPorts(node.intBrId()) | ||
| 623 | + .stream() | ||
| 624 | + .filter(p -> getPortName(p).contains(DEFAULT_TUNNEL) && | ||
| 625 | + p.isEnabled()) | ||
| 626 | + .findAny().isPresent(); | ||
| 627 | + } | ||
| 628 | + | ||
| 629 | + /** | ||
| 630 | + * Checks if physical interface exists. | ||
| 631 | + * | ||
| 632 | + * @param node cordvtn node | ||
| 633 | + * @return true if the interface exists, false otherwise | ||
| 634 | + */ | ||
| 635 | + private boolean checkPhyInterface(CordVtnNode node) { | ||
| 636 | + return deviceService.getPorts(node.intBrId()) | ||
| 637 | + .stream() | ||
| 638 | + .filter(p -> getPortName(p).contains(node.phyPortName()) && | ||
| 639 | + p.isEnabled()) | ||
| 640 | + .findAny().isPresent(); | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + /** | ||
| 644 | + * Returns connect point of a given port. | ||
| 645 | + * | ||
| 646 | + * @param port port | ||
| 647 | + * @return connect point | ||
| 648 | + */ | ||
| 649 | + private ConnectPoint getConnectPoint(Port port) { | ||
| 650 | + return new ConnectPoint(port.element().id(), port.number()); | ||
| 651 | + } | ||
| 652 | + | ||
| 653 | + /** | ||
| 654 | + * Returns connect point of a given host. | ||
| 655 | + * | ||
| 656 | + * @param host host | ||
| 657 | + * @return connect point | ||
| 658 | + */ | ||
| 659 | + private ConnectPoint getConnectPoint(Host host) { | ||
| 660 | + return new ConnectPoint(host.location().deviceId(), host.location().port()); | ||
| 661 | + } | ||
| 662 | + | ||
| 663 | + private class OvsdbHandler implements ConnectionHandler<Device> { | ||
| 664 | + | ||
| 665 | + @Override | ||
| 666 | + public void connected(Device device) { | ||
| 667 | + CordVtnNode node = getNodeByOvsdbId(device.id()); | ||
| 668 | + if (node != null) { | ||
| 669 | + setNodeState(node, checkNodeState(node)); | ||
| 670 | + } else { | ||
| 671 | + log.debug("{} is detected on unregistered node, ignore it.", device.id()); | ||
| 672 | + } | ||
| 673 | + } | ||
| 674 | + | ||
| 675 | + @Override | ||
| 676 | + public void disconnected(Device device) { | ||
| 677 | + if (!deviceService.isAvailable(device.id())) { | ||
| 678 | + adminService.removeDevice(device.id()); | ||
| 679 | + } | ||
| 680 | + } | ||
| 681 | + } | ||
| 682 | + | ||
| 683 | + private class BridgeHandler implements ConnectionHandler<Device> { | ||
| 684 | + | ||
| 685 | + @Override | ||
| 686 | + public void connected(Device device) { | ||
| 687 | + CordVtnNode node = getNodeByBridgeId(device.id()); | ||
| 688 | + if (node != null) { | ||
| 689 | + setNodeState(node, checkNodeState(node)); | ||
| 690 | + } else { | ||
| 691 | + log.debug("{} is detected on unregistered node, ignore it.", device.id()); | ||
| 692 | + } | ||
| 693 | + } | ||
| 694 | + | ||
| 695 | + @Override | ||
| 696 | + public void disconnected(Device device) { | ||
| 697 | + CordVtnNode node = getNodeByBridgeId(device.id()); | ||
| 698 | + if (node != null) { | ||
| 699 | + log.debug("Integration Bridge is disconnected from {}", node.hostname()); | ||
| 700 | + setNodeState(node, NodeState.INCOMPLETE); | ||
| 701 | + } | ||
| 702 | + } | ||
| 703 | + | ||
| 704 | + /** | ||
| 705 | + * Handles port added situation. | ||
| 706 | + * If the added port is tunnel or physical port, proceed remaining node | ||
| 707 | + * initialization. Otherwise, do nothing. | ||
| 708 | + * | ||
| 709 | + * @param port port | ||
| 710 | + */ | ||
| 711 | + public void portAdded(Port port) { | ||
| 712 | + CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); | ||
| 713 | + String portName = getPortName(port); | ||
| 714 | + | ||
| 715 | + if (node == null) { | ||
| 716 | + log.debug("{} is added to unregistered node, ignore it.", portName); | ||
| 717 | + return; | ||
| 718 | + } | ||
| 719 | + | ||
| 720 | + log.debug("Port {} is added to {}", portName, node.hostname()); | ||
| 721 | + | ||
| 722 | + if (portName.startsWith(VPORT_PREFIX)) { | ||
| 723 | + if (getNodeInitState(node)) { | ||
| 724 | + cordVtnService.addServiceVm(node, getConnectPoint(port)); | ||
| 725 | + } else { | ||
| 726 | + log.debug("VM is detected on incomplete node, ignore it.", portName); | ||
| 727 | + } | ||
| 728 | + } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.phyPortName())) { | ||
| 729 | + setNodeState(node, checkNodeState(node)); | ||
| 730 | + } | ||
| 731 | + } | ||
| 732 | + | ||
| 733 | + /** | ||
| 734 | + * Handles port removed situation. | ||
| 735 | + * If the removed port is tunnel or physical port, proceed remaining node | ||
| 736 | + * initialization.Others, do nothing. | ||
| 737 | + * | ||
| 738 | + * @param port port | ||
| 739 | + */ | ||
| 740 | + public void portRemoved(Port port) { | ||
| 741 | + CordVtnNode node = getNodeByBridgeId((DeviceId) port.element().id()); | ||
| 742 | + String portName = getPortName(port); | ||
| 743 | + | ||
| 744 | + if (node == null) { | ||
| 745 | + return; | ||
| 746 | + } | ||
| 747 | + | ||
| 748 | + log.debug("Port {} is removed from {}", portName, node.hostname()); | ||
| 749 | + | ||
| 750 | + if (portName.startsWith(VPORT_PREFIX)) { | ||
| 751 | + if (getNodeInitState(node)) { | ||
| 752 | + cordVtnService.removeServiceVm(getConnectPoint(port)); | ||
| 753 | + } else { | ||
| 754 | + log.debug("VM is vanished from incomplete node, ignore it.", portName); | ||
| 755 | + } | ||
| 756 | + } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.phyPortName())) { | ||
| 757 | + setNodeState(node, NodeState.INCOMPLETE); | ||
| 758 | + } | ||
| 759 | + } | ||
| 760 | + } | ||
| 761 | + | ||
| 762 | + private class InternalDeviceListener implements DeviceListener { | ||
| 763 | + | ||
| 764 | + @Override | ||
| 765 | + public void event(DeviceEvent event) { | ||
| 766 | + | ||
| 767 | + Device device = event.subject(); | ||
| 768 | + ConnectionHandler<Device> handler = | ||
| 769 | + (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler); | ||
| 770 | + | ||
| 771 | + switch (event.type()) { | ||
| 772 | + case PORT_ADDED: | ||
| 773 | + eventExecutor.submit(() -> bridgeHandler.portAdded(event.port())); | ||
| 774 | + break; | ||
| 775 | + case PORT_UPDATED: | ||
| 776 | + if (!event.port().isEnabled()) { | ||
| 777 | + eventExecutor.submit(() -> bridgeHandler.portRemoved(event.port())); | ||
| 778 | + } | ||
| 779 | + break; | ||
| 780 | + case DEVICE_ADDED: | ||
| 781 | + case DEVICE_AVAILABILITY_CHANGED: | ||
| 782 | + if (deviceService.isAvailable(device.id())) { | ||
| 783 | + eventExecutor.submit(() -> handler.connected(device)); | ||
| 784 | + } else { | ||
| 785 | + eventExecutor.submit(() -> handler.disconnected(device)); | ||
| 786 | + } | ||
| 787 | + break; | ||
| 788 | + default: | ||
| 789 | + break; | ||
| 790 | + } | ||
| 791 | + } | ||
| 792 | + } | ||
| 793 | + | ||
| 794 | + /** | ||
| 795 | + * Reads node configuration from config file. | ||
| 796 | + */ | ||
| 797 | + private void readConfiguration() { | ||
| 798 | + CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class); | ||
| 799 | + | ||
| 800 | + if (config == null) { | ||
| 801 | + log.warn("No configuration found"); | ||
| 802 | + return; | ||
| 803 | + } | ||
| 804 | + | ||
| 805 | + config.cordVtnNodes().forEach(node -> { | ||
| 806 | + CordVtnNode cordVtnNode = new CordVtnNode( | ||
| 807 | + node.hostname(), | ||
| 808 | + node.ovsdbIp(), | ||
| 809 | + node.ovsdbPort(), | ||
| 810 | + node.bridgeId(), | ||
| 811 | + node.phyPortName(), | ||
| 812 | + node.localIp()); | ||
| 813 | + | ||
| 814 | + addNode(cordVtnNode); | ||
| 815 | + }); | ||
| 816 | + } | ||
| 817 | + | ||
| 818 | + private class InternalConfigListener implements NetworkConfigListener { | ||
| 819 | + | ||
| 820 | + @Override | ||
| 821 | + public void event(NetworkConfigEvent event) { | ||
| 822 | + if (!event.configClass().equals(CordVtnConfig.class)) { | ||
| 823 | + return; | ||
| 824 | + } | ||
| 825 | + | ||
| 826 | + switch (event.type()) { | ||
| 827 | + case CONFIG_ADDED: | ||
| 828 | + log.info("Network configuration added"); | ||
| 829 | + eventExecutor.execute(CordVtnNodeManager.this::readConfiguration); | ||
| 830 | + break; | ||
| 831 | + case CONFIG_UPDATED: | ||
| 832 | + log.info("Network configuration updated"); | ||
| 833 | + eventExecutor.execute(CordVtnNodeManager.this::readConfiguration); | ||
| 834 | + break; | ||
| 835 | + default: | ||
| 836 | + break; | ||
| 837 | + } | ||
| 838 | + } | ||
| 839 | + } | ||
| 840 | +} |
| ... | @@ -165,13 +165,10 @@ public class CordVtnRuleInstaller { | ... | @@ -165,13 +165,10 @@ public class CordVtnRuleInstaller { |
| 165 | * Populates basic rules that connect a VM to the other VMs in the system. | 165 | * Populates basic rules that connect a VM to the other VMs in the system. |
| 166 | * | 166 | * |
| 167 | * @param host host | 167 | * @param host host |
| 168 | - * @param hostIp host ip | ||
| 169 | * @param tunnelIp tunnel ip | 168 | * @param tunnelIp tunnel ip |
| 170 | * @param vNet openstack network | 169 | * @param vNet openstack network |
| 171 | */ | 170 | */ |
| 172 | - public void populateBasicConnectionRules(Host host, IpAddress hostIp, IpAddress tunnelIp, | 171 | + public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) { |
| 173 | - OpenstackNetwork vNet) { | ||
| 174 | - // TODO we can get host ip from host.ip() after applying NetworkConfig host provider | ||
| 175 | checkNotNull(host); | 172 | checkNotNull(host); |
| 176 | checkNotNull(vNet); | 173 | checkNotNull(vNet); |
| 177 | 174 | ||
| ... | @@ -182,6 +179,7 @@ public class CordVtnRuleInstaller { | ... | @@ -182,6 +179,7 @@ public class CordVtnRuleInstaller { |
| 182 | 179 | ||
| 183 | PortNumber inPort = host.location().port(); | 180 | PortNumber inPort = host.location().port(); |
| 184 | MacAddress dstMac = host.mac(); | 181 | MacAddress dstMac = host.mac(); |
| 182 | + IpAddress hostIp = host.ipAddresses().stream().findFirst().get(); | ||
| 185 | long tunnelId = Long.parseLong(vNet.segmentId()); | 183 | long tunnelId = Long.parseLong(vNet.segmentId()); |
| 186 | 184 | ||
| 187 | OpenstackSubnet subnet = vNet.subnets().stream() | 185 | OpenstackSubnet subnet = vNet.subnets().stream() |
| ... | @@ -352,7 +350,7 @@ public class CordVtnRuleInstaller { | ... | @@ -352,7 +350,7 @@ public class CordVtnRuleInstaller { |
| 352 | 350 | ||
| 353 | Group group = groupService.getGroup(deviceId, groupKey); | 351 | Group group = groupService.getGroup(deviceId, groupKey); |
| 354 | if (group == null) { | 352 | if (group == null) { |
| 355 | - log.debug("No group exists for service {} in {}", service.id(), deviceId); | 353 | + log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId); |
| 356 | continue; | 354 | continue; |
| 357 | } | 355 | } |
| 358 | 356 | ... | ... |
| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.cordvtn; | 16 | package org.onosproject.cordvtn; |
| 17 | 17 | ||
| 18 | -import java.util.List; | 18 | +import org.onosproject.net.ConnectPoint; |
| 19 | 19 | ||
| 20 | /** | 20 | /** |
| 21 | * Service for provisioning overlay virtual networks on compute nodes. | 21 | * Service for provisioning overlay virtual networks on compute nodes. |
| ... | @@ -23,61 +23,21 @@ import java.util.List; | ... | @@ -23,61 +23,21 @@ import java.util.List; |
| 23 | public interface CordVtnService { | 23 | public interface CordVtnService { |
| 24 | 24 | ||
| 25 | String CORDVTN_APP_ID = "org.onosproject.cordvtn"; | 25 | String CORDVTN_APP_ID = "org.onosproject.cordvtn"; |
| 26 | - /** | ||
| 27 | - * Adds a new node to the service. | ||
| 28 | - * | ||
| 29 | - * @param node cordvtn node | ||
| 30 | - */ | ||
| 31 | - void addNode(CordVtnNode node); | ||
| 32 | - | ||
| 33 | - /** | ||
| 34 | - * Deletes a node from the service. | ||
| 35 | - * | ||
| 36 | - * @param node cordvtn node | ||
| 37 | - */ | ||
| 38 | - void deleteNode(CordVtnNode node); | ||
| 39 | - | ||
| 40 | - /** | ||
| 41 | - * Initiates node to serve virtual tenant network. | ||
| 42 | - * | ||
| 43 | - * @param node cordvtn node | ||
| 44 | - */ | ||
| 45 | - void initNode(CordVtnNode node); | ||
| 46 | - | ||
| 47 | - /** | ||
| 48 | - * Returns the number of the nodes known to the service. | ||
| 49 | - * | ||
| 50 | - * @return number of nodes | ||
| 51 | - */ | ||
| 52 | - int getNodeCount(); | ||
| 53 | 26 | ||
| 54 | /** | 27 | /** |
| 55 | - * Returns node initialization state. | 28 | + * Adds a new VM on a given node and connect point. |
| 56 | - * | ||
| 57 | - * @param node cordvtn node | ||
| 58 | - * @return true if initial node setup is completed, otherwise false | ||
| 59 | - */ | ||
| 60 | - boolean getNodeInitState(CordVtnNode node); | ||
| 61 | - | ||
| 62 | - /** | ||
| 63 | - * Returns detailed node initialization state. | ||
| 64 | - * Return string includes the following information. | ||
| 65 | - * | ||
| 66 | - * Integration bridge created/connected: OK or NO | ||
| 67 | - * VXLAN interface created: OK or NO | ||
| 68 | - * Physical interface added: OK or NO | ||
| 69 | * | 29 | * |
| 70 | * @param node cordvtn node | 30 | * @param node cordvtn node |
| 71 | - * @return string including detailed node init state | 31 | + * @param connectPoint connect point |
| 72 | */ | 32 | */ |
| 73 | - String checkNodeInitState(CordVtnNode node); | 33 | + void addServiceVm(CordVtnNode node, ConnectPoint connectPoint); |
| 74 | 34 | ||
| 75 | /** | 35 | /** |
| 76 | - * Returns all nodes known to the service. | 36 | + * Removes a VM from a given node and connect point. |
| 77 | * | 37 | * |
| 78 | - * @return list of nodes | 38 | + * @param connectPoint connect point |
| 79 | */ | 39 | */ |
| 80 | - List<CordVtnNode> getNodes(); | 40 | + void removeServiceVm(ConnectPoint connectPoint); |
| 81 | 41 | ||
| 82 | /** | 42 | /** |
| 83 | * Creates dependencies for a given tenant service. | 43 | * Creates dependencies for a given tenant service. | ... | ... |
| ... | @@ -21,7 +21,7 @@ import org.apache.karaf.shell.commands.Command; | ... | @@ -21,7 +21,7 @@ import org.apache.karaf.shell.commands.Command; |
| 21 | import org.onlab.packet.IpAddress; | 21 | import org.onlab.packet.IpAddress; |
| 22 | import org.onlab.packet.TpPort; | 22 | import org.onlab.packet.TpPort; |
| 23 | import org.onosproject.cli.AbstractShellCommand; | 23 | import org.onosproject.cli.AbstractShellCommand; |
| 24 | -import org.onosproject.cordvtn.CordVtnService; | 24 | +import org.onosproject.cordvtn.CordVtnNodeManager; |
| 25 | import org.onosproject.cordvtn.CordVtnNode; | 25 | import org.onosproject.cordvtn.CordVtnNode; |
| 26 | import org.onosproject.net.DeviceId; | 26 | import org.onosproject.net.DeviceId; |
| 27 | 27 | ||
| ... | @@ -63,7 +63,7 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { | ... | @@ -63,7 +63,7 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { |
| 63 | checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format"); | 63 | checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format"); |
| 64 | checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format"); | 64 | checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format"); |
| 65 | 65 | ||
| 66 | - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); | 66 | + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class); |
| 67 | String[] ipPort = ovsdb.split(":"); | 67 | String[] ipPort = ovsdb.split(":"); |
| 68 | CordVtnNode node = new CordVtnNode(hostname, | 68 | CordVtnNode node = new CordVtnNode(hostname, |
| 69 | IpAddress.valueOf(ipPort[0]), | 69 | IpAddress.valueOf(ipPort[0]), |
| ... | @@ -71,6 +71,6 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { | ... | @@ -71,6 +71,6 @@ public class CordVtnNodeAddCommand extends AbstractShellCommand { |
| 71 | DeviceId.deviceId(bridgeId), | 71 | DeviceId.deviceId(bridgeId), |
| 72 | phyPortName, | 72 | phyPortName, |
| 73 | IpAddress.valueOf(localIp)); | 73 | IpAddress.valueOf(localIp)); |
| 74 | - service.addNode(node); | 74 | + nodeManager.addNode(node); |
| 75 | } | 75 | } |
| 76 | } | 76 | } | ... | ... |
| ... | @@ -20,7 +20,7 @@ import org.apache.karaf.shell.commands.Argument; | ... | @@ -20,7 +20,7 @@ import org.apache.karaf.shell.commands.Argument; |
| 20 | import org.apache.karaf.shell.commands.Command; | 20 | import org.apache.karaf.shell.commands.Command; |
| 21 | import org.onosproject.cli.AbstractShellCommand; | 21 | import org.onosproject.cli.AbstractShellCommand; |
| 22 | import org.onosproject.cordvtn.CordVtnNode; | 22 | import org.onosproject.cordvtn.CordVtnNode; |
| 23 | -import org.onosproject.cordvtn.CordVtnService; | 23 | +import org.onosproject.cordvtn.CordVtnNodeManager; |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * Checks detailed node init state. | 26 | * Checks detailed node init state. |
| ... | @@ -35,8 +35,8 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { | ... | @@ -35,8 +35,8 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
| 37 | protected void execute() { | 37 | protected void execute() { |
| 38 | - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); | 38 | + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class); |
| 39 | - CordVtnNode node = service.getNodes() | 39 | + CordVtnNode node = nodeManager.getNodes() |
| 40 | .stream() | 40 | .stream() |
| 41 | .filter(n -> n.hostname().equals(hostname)) | 41 | .filter(n -> n.hostname().equals(hostname)) |
| 42 | .findFirst() | 42 | .findFirst() |
| ... | @@ -47,6 +47,6 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { | ... | @@ -47,6 +47,6 @@ public class CordVtnNodeCheckCommand extends AbstractShellCommand { |
| 47 | return; | 47 | return; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | - print(service.checkNodeInitState(node)); | 50 | + print(nodeManager.checkNodeInitState(node)); |
| 51 | } | 51 | } |
| 52 | } | 52 | } | ... | ... |
| ... | @@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; | ... | @@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; |
| 19 | import org.apache.karaf.shell.commands.Argument; | 19 | import org.apache.karaf.shell.commands.Argument; |
| 20 | import org.apache.karaf.shell.commands.Command; | 20 | import org.apache.karaf.shell.commands.Command; |
| 21 | import org.onosproject.cli.AbstractShellCommand; | 21 | import org.onosproject.cli.AbstractShellCommand; |
| 22 | -import org.onosproject.cordvtn.CordVtnService; | 22 | +import org.onosproject.cordvtn.CordVtnNodeManager; |
| 23 | import org.onosproject.cordvtn.CordVtnNode; | 23 | import org.onosproject.cordvtn.CordVtnNode; |
| 24 | 24 | ||
| 25 | import java.util.NoSuchElementException; | 25 | import java.util.NoSuchElementException; |
| ... | @@ -37,12 +37,12 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { | ... | @@ -37,12 +37,12 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { |
| 37 | 37 | ||
| 38 | @Override | 38 | @Override |
| 39 | protected void execute() { | 39 | protected void execute() { |
| 40 | - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); | 40 | + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class); |
| 41 | 41 | ||
| 42 | for (String hostname : hostnames) { | 42 | for (String hostname : hostnames) { |
| 43 | CordVtnNode node; | 43 | CordVtnNode node; |
| 44 | try { | 44 | try { |
| 45 | - node = service.getNodes() | 45 | + node = nodeManager.getNodes() |
| 46 | .stream() | 46 | .stream() |
| 47 | .filter(n -> n.hostname().equals(hostname)) | 47 | .filter(n -> n.hostname().equals(hostname)) |
| 48 | .findFirst().get(); | 48 | .findFirst().get(); |
| ... | @@ -51,7 +51,7 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { | ... | @@ -51,7 +51,7 @@ public class CordVtnNodeDeleteCommand extends AbstractShellCommand { |
| 51 | continue; | 51 | continue; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | - service.deleteNode(node); | 54 | + nodeManager.deleteNode(node); |
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | } | 57 | } | ... | ... |
| ... | @@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; | ... | @@ -19,7 +19,7 @@ package org.onosproject.cordvtn.cli; |
| 19 | import org.apache.karaf.shell.commands.Argument; | 19 | import org.apache.karaf.shell.commands.Argument; |
| 20 | import org.apache.karaf.shell.commands.Command; | 20 | import org.apache.karaf.shell.commands.Command; |
| 21 | import org.onosproject.cli.AbstractShellCommand; | 21 | import org.onosproject.cli.AbstractShellCommand; |
| 22 | -import org.onosproject.cordvtn.CordVtnService; | 22 | +import org.onosproject.cordvtn.CordVtnNodeManager; |
| 23 | import org.onosproject.cordvtn.CordVtnNode; | 23 | import org.onosproject.cordvtn.CordVtnNode; |
| 24 | 24 | ||
| 25 | import java.util.NoSuchElementException; | 25 | import java.util.NoSuchElementException; |
| ... | @@ -37,12 +37,12 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { | ... | @@ -37,12 +37,12 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { |
| 37 | 37 | ||
| 38 | @Override | 38 | @Override |
| 39 | protected void execute() { | 39 | protected void execute() { |
| 40 | - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); | 40 | + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class); |
| 41 | 41 | ||
| 42 | for (String hostname : hostnames) { | 42 | for (String hostname : hostnames) { |
| 43 | CordVtnNode node; | 43 | CordVtnNode node; |
| 44 | try { | 44 | try { |
| 45 | - node = service.getNodes() | 45 | + node = nodeManager.getNodes() |
| 46 | .stream() | 46 | .stream() |
| 47 | .filter(n -> n.hostname().equals(hostname)) | 47 | .filter(n -> n.hostname().equals(hostname)) |
| 48 | .findFirst().get(); | 48 | .findFirst().get(); |
| ... | @@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { | ... | @@ -51,7 +51,7 @@ public class CordVtnNodeInitCommand extends AbstractShellCommand { |
| 51 | continue; | 51 | continue; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | - service.initNode(node); | 54 | + nodeManager.initNode(node); |
| 55 | } | 55 | } |
| 56 | } | 56 | } |
| 57 | } | 57 | } | ... | ... |
| ... | @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
| 21 | import com.fasterxml.jackson.databind.node.ArrayNode; | 21 | import com.fasterxml.jackson.databind.node.ArrayNode; |
| 22 | import org.apache.karaf.shell.commands.Command; | 22 | import org.apache.karaf.shell.commands.Command; |
| 23 | import org.onosproject.cli.AbstractShellCommand; | 23 | import org.onosproject.cli.AbstractShellCommand; |
| 24 | -import org.onosproject.cordvtn.CordVtnService; | 24 | +import org.onosproject.cordvtn.CordVtnNodeManager; |
| 25 | import org.onosproject.cordvtn.CordVtnNode; | 25 | import org.onosproject.cordvtn.CordVtnNode; |
| 26 | 26 | ||
| 27 | import java.util.Collections; | 27 | import java.util.Collections; |
| ... | @@ -36,12 +36,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { | ... | @@ -36,12 +36,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { |
| 36 | 36 | ||
| 37 | @Override | 37 | @Override |
| 38 | protected void execute() { | 38 | protected void execute() { |
| 39 | - CordVtnService service = AbstractShellCommand.get(CordVtnService.class); | 39 | + CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class); |
| 40 | - List<CordVtnNode> nodes = service.getNodes(); | 40 | + List<CordVtnNode> nodes = nodeManager.getNodes(); |
| 41 | Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR); | 41 | Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR); |
| 42 | 42 | ||
| 43 | if (outputJson()) { | 43 | if (outputJson()) { |
| 44 | - print("%s", json(service, nodes)); | 44 | + print("%s", json(nodeManager, nodes)); |
| 45 | } else { | 45 | } else { |
| 46 | for (CordVtnNode node : nodes) { | 46 | for (CordVtnNode node : nodes) { |
| 47 | print("hostname=%s, ovsdb=%s, br-int=%s, phyPort=%s, localIp=%s, init=%s", | 47 | print("hostname=%s, ovsdb=%s, br-int=%s, phyPort=%s, localIp=%s, init=%s", |
| ... | @@ -50,13 +50,13 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { | ... | @@ -50,13 +50,13 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { |
| 50 | node.intBrId().toString(), | 50 | node.intBrId().toString(), |
| 51 | node.phyPortName(), | 51 | node.phyPortName(), |
| 52 | node.localIp().toString(), | 52 | node.localIp().toString(), |
| 53 | - getState(service, node)); | 53 | + getState(nodeManager, node)); |
| 54 | } | 54 | } |
| 55 | - print("Total %s nodes", service.getNodeCount()); | 55 | + print("Total %s nodes", nodeManager.getNodeCount()); |
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | - private JsonNode json(CordVtnService service, List<CordVtnNode> nodes) { | 59 | + private JsonNode json(CordVtnNodeManager nodeManager, List<CordVtnNode> nodes) { |
| 60 | ObjectMapper mapper = new ObjectMapper(); | 60 | ObjectMapper mapper = new ObjectMapper(); |
| 61 | ArrayNode result = mapper.createArrayNode(); | 61 | ArrayNode result = mapper.createArrayNode(); |
| 62 | for (CordVtnNode node : nodes) { | 62 | for (CordVtnNode node : nodes) { |
| ... | @@ -67,12 +67,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { | ... | @@ -67,12 +67,12 @@ public class CordVtnNodeListCommand extends AbstractShellCommand { |
| 67 | .put("brInt", node.intBrId().toString()) | 67 | .put("brInt", node.intBrId().toString()) |
| 68 | .put("phyPort", node.phyPortName()) | 68 | .put("phyPort", node.phyPortName()) |
| 69 | .put("localIp", node.localIp().toString()) | 69 | .put("localIp", node.localIp().toString()) |
| 70 | - .put("init", getState(service, node))); | 70 | + .put("init", getState(nodeManager, node))); |
| 71 | } | 71 | } |
| 72 | return result; | 72 | return result; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | - private String getState(CordVtnService service, CordVtnNode node) { | 75 | + private String getState(CordVtnNodeManager nodeManager, CordVtnNode node) { |
| 76 | - return service.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE"; | 76 | + return nodeManager.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE"; |
| 77 | } | 77 | } |
| 78 | } | 78 | } | ... | ... |
-
Please register or login to post a comment