Committed by
Gerrit Code Review
Some improvements on cordvtn
- Removed unnecessary CordVtnNodeConfig class - Don't allow local and host management IP range overlapping - Check node init state saved in the store instead of really check when a VM is detected or vanished since it's too slow Change-Id: I076780bdc3946b2000176cb05805003ba7c8724d
Showing
7 changed files
with
130 additions
and
240 deletions
| ... | @@ -70,9 +70,11 @@ import org.slf4j.Logger; | ... | @@ -70,9 +70,11 @@ import org.slf4j.Logger; |
| 70 | 70 | ||
| 71 | import java.util.List; | 71 | import java.util.List; |
| 72 | import java.util.Map; | 72 | import java.util.Map; |
| 73 | +import java.util.Objects; | ||
| 73 | import java.util.Set; | 74 | import java.util.Set; |
| 74 | import java.util.concurrent.ExecutorService; | 75 | import java.util.concurrent.ExecutorService; |
| 75 | import java.util.stream.Collectors; | 76 | import java.util.stream.Collectors; |
| 77 | +import java.util.stream.StreamSupport; | ||
| 76 | 78 | ||
| 77 | import static com.google.common.base.Preconditions.checkNotNull; | 79 | import static com.google.common.base.Preconditions.checkNotNull; |
| 78 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | 80 | import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; |
| ... | @@ -266,7 +268,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -266,7 +268,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
| 266 | } | 268 | } |
| 267 | } | 269 | } |
| 268 | 270 | ||
| 269 | - Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values()); | 271 | + Set<IpAddress> fixedIp = Sets.newHashSet(vPort.fixedIps().values()); |
| 270 | DefaultAnnotations.Builder annotations = DefaultAnnotations.builder() | 272 | DefaultAnnotations.Builder annotations = DefaultAnnotations.builder() |
| 271 | .set(SERVICE_ID, vPort.networkId()) | 273 | .set(SERVICE_ID, vPort.networkId()) |
| 272 | .set(OPENSTACK_VM_ID, vPort.deviceId()) | 274 | .set(OPENSTACK_VM_ID, vPort.deviceId()) |
| ... | @@ -283,7 +285,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -283,7 +285,7 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
| 283 | mac, | 285 | mac, |
| 284 | VlanId.NONE, | 286 | VlanId.NONE, |
| 285 | new HostLocation(connectPoint, System.currentTimeMillis()), | 287 | new HostLocation(connectPoint, System.currentTimeMillis()), |
| 286 | - ip, | 288 | + fixedIp, |
| 287 | annotations.build()); | 289 | annotations.build()); |
| 288 | 290 | ||
| 289 | hostProvider.hostDetected(hostId, hostDesc, false); | 291 | hostProvider.hostDetected(hostId, hostDesc, false); |
| ... | @@ -357,6 +359,30 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -357,6 +359,30 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
| 357 | } | 359 | } |
| 358 | 360 | ||
| 359 | /** | 361 | /** |
| 362 | + * Returns public ip addresses of vSGs running inside a give vSG host. | ||
| 363 | + * | ||
| 364 | + * @param vSgHost vSG host | ||
| 365 | + * @return map of ip and mac address, or empty map | ||
| 366 | + */ | ||
| 367 | + private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) { | ||
| 368 | + String vPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID); | ||
| 369 | + String serviceVlan = vSgHost.annotations().value(S_TAG); | ||
| 370 | + | ||
| 371 | + OpenstackPort vPort = openstackService.port(vPortId); | ||
| 372 | + if (vPort == null) { | ||
| 373 | + log.warn("Failed to get OpenStack port {} for VM {}", vPortId, vSgHost.id()); | ||
| 374 | + return Maps.newHashMap(); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + if (!serviceVlan.equals(getServiceVlan(vPort))) { | ||
| 378 | + log.error("Host({}) s-tag does not match with vPort s-tag", vSgHost.id()); | ||
| 379 | + return Maps.newHashMap(); | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + return vPort.allowedAddressPairs(); | ||
| 383 | + } | ||
| 384 | + | ||
| 385 | + /** | ||
| 360 | * Returns CordService by service ID. | 386 | * Returns CordService by service ID. |
| 361 | * | 387 | * |
| 362 | * @param serviceId service id | 388 | * @param serviceId service id |
| ... | @@ -453,6 +479,16 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -453,6 +479,16 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
| 453 | } | 479 | } |
| 454 | 480 | ||
| 455 | /** | 481 | /** |
| 482 | + * Returns service ID of this host. | ||
| 483 | + * | ||
| 484 | + * @param host host | ||
| 485 | + * @return service id, or null if not found | ||
| 486 | + */ | ||
| 487 | + private String getServiceId(Host host) { | ||
| 488 | + return host.annotations().value(SERVICE_ID); | ||
| 489 | + } | ||
| 490 | + | ||
| 491 | + /** | ||
| 456 | * Returns hosts associated with a given OpenStack network. | 492 | * Returns hosts associated with a given OpenStack network. |
| 457 | * | 493 | * |
| 458 | * @param vNet openstack network | 494 | * @param vNet openstack network |
| ... | @@ -461,40 +497,10 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro | ... | @@ -461,40 +497,10 @@ public class CordVtn extends AbstractProvider implements CordVtnService, HostPro |
| 461 | private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) { | 497 | private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) { |
| 462 | checkNotNull(vNet); | 498 | checkNotNull(vNet); |
| 463 | 499 | ||
| 464 | - Set<Host> hosts = openstackService.ports(vNet.id()).stream() | 500 | + String vNetId = vNet.id(); |
| 465 | - .filter(port -> port.deviceOwner().contains("compute")) | 501 | + return StreamSupport.stream(hostService.getHosts().spliterator(), false) |
| 466 | - .map(port -> hostService.getHostsByMac(port.macAddress()) | 502 | + .filter(host -> Objects.equals(vNetId, getServiceId(host))) |
| 467 | - .stream() | ||
| 468 | - .findFirst() | ||
| 469 | - .orElse(null)) | ||
| 470 | .collect(Collectors.toSet()); | 503 | .collect(Collectors.toSet()); |
| 471 | - | ||
| 472 | - hosts.remove(null); | ||
| 473 | - return hosts; | ||
| 474 | - } | ||
| 475 | - | ||
| 476 | - /** | ||
| 477 | - * Returns public ip addresses of vSGs running inside a give vSG host. | ||
| 478 | - * | ||
| 479 | - * @param vSgHost vSG host | ||
| 480 | - * @return map of ip and mac address, or empty map | ||
| 481 | - */ | ||
| 482 | - private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) { | ||
| 483 | - String vPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID); | ||
| 484 | - String serviceVlan = vSgHost.annotations().value(S_TAG); | ||
| 485 | - | ||
| 486 | - OpenstackPort vPort = openstackService.port(vPortId); | ||
| 487 | - if (vPort == null) { | ||
| 488 | - log.warn("Failed to get OpenStack port {} for VM {}", vPortId, vSgHost.id()); | ||
| 489 | - return Maps.newHashMap(); | ||
| 490 | - } | ||
| 491 | - | ||
| 492 | - if (!serviceVlan.equals(getServiceVlan(vPort))) { | ||
| 493 | - log.error("Host({}) s-tag does not match with vPort s-tag", vSgHost.id()); | ||
| 494 | - return Maps.newHashMap(); | ||
| 495 | - } | ||
| 496 | - | ||
| 497 | - return vPort.allowedAddressPairs(); | ||
| 498 | } | 504 | } |
| 499 | 505 | ||
| 500 | /** | 506 | /** | ... | ... |
| ... | @@ -18,6 +18,7 @@ package org.onosproject.cordvtn; | ... | @@ -18,6 +18,7 @@ package org.onosproject.cordvtn; |
| 18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
| 19 | import com.google.common.collect.Maps; | 19 | import com.google.common.collect.Maps; |
| 20 | import com.google.common.collect.Sets; | 20 | import com.google.common.collect.Sets; |
| 21 | +import org.onlab.packet.Ip4Address; | ||
| 21 | import org.onlab.packet.IpAddress; | 22 | import org.onlab.packet.IpAddress; |
| 22 | import org.onlab.packet.MacAddress; | 23 | import org.onlab.packet.MacAddress; |
| 23 | import org.onlab.packet.TpPort; | 24 | import org.onlab.packet.TpPort; |
| ... | @@ -29,7 +30,6 @@ import org.slf4j.Logger; | ... | @@ -29,7 +30,6 @@ import org.slf4j.Logger; |
| 29 | import java.util.Map; | 30 | import java.util.Map; |
| 30 | import java.util.Set; | 31 | import java.util.Set; |
| 31 | 32 | ||
| 32 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
| 33 | import static org.slf4j.LoggerFactory.getLogger; | 33 | import static org.slf4j.LoggerFactory.getLogger; |
| 34 | 34 | ||
| 35 | /** | 35 | /** |
| ... | @@ -45,11 +45,12 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -45,11 +45,12 @@ public class CordVtnConfig extends Config<ApplicationId> { |
| 45 | public static final String GATEWAY_MAC = "gatewayMac"; | 45 | public static final String GATEWAY_MAC = "gatewayMac"; |
| 46 | public static final String LOCAL_MANAGEMENT_IP = "localManagementIp"; | 46 | public static final String LOCAL_MANAGEMENT_IP = "localManagementIp"; |
| 47 | public static final String OVSDB_PORT = "ovsdbPort"; | 47 | public static final String OVSDB_PORT = "ovsdbPort"; |
| 48 | + | ||
| 48 | public static final String SSH_PORT = "sshPort"; | 49 | public static final String SSH_PORT = "sshPort"; |
| 49 | public static final String SSH_USER = "sshUser"; | 50 | public static final String SSH_USER = "sshUser"; |
| 50 | public static final String SSH_KEY_FILE = "sshKeyFile"; | 51 | public static final String SSH_KEY_FILE = "sshKeyFile"; |
| 51 | - public static final String CORDVTN_NODES = "nodes"; | ||
| 52 | 52 | ||
| 53 | + public static final String CORDVTN_NODES = "nodes"; | ||
| 53 | public static final String HOSTNAME = "hostname"; | 54 | public static final String HOSTNAME = "hostname"; |
| 54 | public static final String HOST_MANAGEMENT_IP = "hostManagementIp"; | 55 | public static final String HOST_MANAGEMENT_IP = "hostManagementIp"; |
| 55 | public static final String DATA_PLANE_IP = "dataPlaneIp"; | 56 | public static final String DATA_PLANE_IP = "dataPlaneIp"; |
| ... | @@ -61,31 +62,70 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -61,31 +62,70 @@ public class CordVtnConfig extends Config<ApplicationId> { |
| 61 | * | 62 | * |
| 62 | * @return set of CordVtnNodeConfig or null | 63 | * @return set of CordVtnNodeConfig or null |
| 63 | */ | 64 | */ |
| 64 | - public Set<CordVtnNodeConfig> cordVtnNodes() { | 65 | + public Set<CordVtnNode> cordVtnNodes() { |
| 65 | - Set<CordVtnNodeConfig> nodes = Sets.newHashSet(); | ||
| 66 | 66 | ||
| 67 | + Set<CordVtnNode> nodes = Sets.newHashSet(); | ||
| 67 | JsonNode jsonNodes = object.get(CORDVTN_NODES); | 68 | JsonNode jsonNodes = object.get(CORDVTN_NODES); |
| 68 | if (jsonNodes == null) { | 69 | if (jsonNodes == null) { |
| 70 | + log.debug("No CORD VTN nodes found"); | ||
| 69 | return null; | 71 | return null; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | - jsonNodes.forEach(jsonNode -> { | 74 | + for (JsonNode jsonNode : jsonNodes) { |
| 73 | try { | 75 | try { |
| 74 | - nodes.add(new CordVtnNodeConfig( | 76 | + NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(jsonNode, HOST_MANAGEMENT_IP)); |
| 75 | - jsonNode.path(HOSTNAME).asText(), | 77 | + NetworkAddress localMgmt = NetworkAddress.valueOf(getConfig(object, LOCAL_MANAGEMENT_IP)); |
| 76 | - NetworkAddress.valueOf(jsonNode.path(HOST_MANAGEMENT_IP).asText()), | 78 | + if (hostMgmt.prefix().contains(localMgmt.prefix()) || |
| 77 | - NetworkAddress.valueOf(jsonNode.path(DATA_PLANE_IP).asText()), | 79 | + localMgmt.prefix().contains(hostMgmt.prefix())) { |
| 78 | - jsonNode.path(DATA_PLANE_INTF).asText(), | 80 | + log.error("hostMamt and localMgmt cannot be overlapped, skip this node"); |
| 79 | - DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText()))); | 81 | + continue; |
| 82 | + } | ||
| 83 | + | ||
| 84 | + Ip4Address hostMgmtIp = hostMgmt.ip().getIp4Address(); | ||
| 85 | + SshAccessInfo sshInfo = new SshAccessInfo( | ||
| 86 | + hostMgmtIp, | ||
| 87 | + TpPort.tpPort(Integer.parseInt(getConfig(object, SSH_PORT))), | ||
| 88 | + getConfig(object, SSH_USER), getConfig(object, SSH_KEY_FILE)); | ||
| 89 | + | ||
| 90 | + String hostname = getConfig(jsonNode, HOSTNAME); | ||
| 91 | + CordVtnNode newNode = new CordVtnNode( | ||
| 92 | + hostname, hostMgmt, localMgmt, | ||
| 93 | + NetworkAddress.valueOf(getConfig(jsonNode, DATA_PLANE_IP)), | ||
| 94 | + TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))), | ||
| 95 | + sshInfo, | ||
| 96 | + DeviceId.deviceId(getConfig(jsonNode, BRIDGE_ID)), | ||
| 97 | + getConfig(jsonNode, DATA_PLANE_INTF)); | ||
| 98 | + | ||
| 99 | + log.info("Successfully read {} from the config", hostname); | ||
| 100 | + nodes.add(newNode); | ||
| 80 | } catch (IllegalArgumentException | NullPointerException e) { | 101 | } catch (IllegalArgumentException | NullPointerException e) { |
| 81 | - log.error("Failed to read {}", e.toString()); | 102 | + log.error("{}", e.toString()); |
| 82 | } | 103 | } |
| 83 | - }); | 104 | + } |
| 84 | 105 | ||
| 85 | return nodes; | 106 | return nodes; |
| 86 | } | 107 | } |
| 87 | 108 | ||
| 88 | /** | 109 | /** |
| 110 | + * Returns value of a given path. If the path is missing, show log and return | ||
| 111 | + * null. | ||
| 112 | + * | ||
| 113 | + * @param path path | ||
| 114 | + * @return value or null | ||
| 115 | + */ | ||
| 116 | + private String getConfig(JsonNode jsonNode, String path) { | ||
| 117 | + jsonNode = jsonNode.path(path); | ||
| 118 | + | ||
| 119 | + if (jsonNode.isMissingNode()) { | ||
| 120 | + log.error("{} is not configured", path); | ||
| 121 | + return null; | ||
| 122 | + } else { | ||
| 123 | + log.debug("{} : {}", path, jsonNode.asText()); | ||
| 124 | + return jsonNode.asText(); | ||
| 125 | + } | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 89 | * Returns private network gateway MAC address. | 129 | * Returns private network gateway MAC address. |
| 90 | * | 130 | * |
| 91 | * @return mac address, or null | 131 | * @return mac address, or null |
| ... | @@ -112,7 +152,7 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -112,7 +152,7 @@ public class CordVtnConfig extends Config<ApplicationId> { |
| 112 | public Map<IpAddress, MacAddress> publicGateways() { | 152 | public Map<IpAddress, MacAddress> publicGateways() { |
| 113 | JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS); | 153 | JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS); |
| 114 | if (jsonNodes == null) { | 154 | if (jsonNodes == null) { |
| 115 | - return null; | 155 | + return Maps.newHashMap(); |
| 116 | } | 156 | } |
| 117 | 157 | ||
| 118 | Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap(); | 158 | Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap(); |
| ... | @@ -128,155 +168,5 @@ public class CordVtnConfig extends Config<ApplicationId> { | ... | @@ -128,155 +168,5 @@ public class CordVtnConfig extends Config<ApplicationId> { |
| 128 | 168 | ||
| 129 | return publicGateways; | 169 | return publicGateways; |
| 130 | } | 170 | } |
| 131 | - | ||
| 132 | - /** | ||
| 133 | - * Returns local management network address. | ||
| 134 | - * | ||
| 135 | - * @return network address | ||
| 136 | - */ | ||
| 137 | - public NetworkAddress localMgmtIp() { | ||
| 138 | - JsonNode jsonNode = object.get(LOCAL_MANAGEMENT_IP); | ||
| 139 | - if (jsonNode == null) { | ||
| 140 | - return null; | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - try { | ||
| 144 | - return NetworkAddress.valueOf(jsonNode.asText()); | ||
| 145 | - } catch (IllegalArgumentException e) { | ||
| 146 | - log.error("Wrong address format {}", jsonNode.asText()); | ||
| 147 | - return null; | ||
| 148 | - } | ||
| 149 | - } | ||
| 150 | - | ||
| 151 | - /** | ||
| 152 | - * Returns the port number used for OVSDB connection. | ||
| 153 | - * | ||
| 154 | - * @return port number, or null | ||
| 155 | - */ | ||
| 156 | - public TpPort ovsdbPort() { | ||
| 157 | - JsonNode jsonNode = object.get(OVSDB_PORT); | ||
| 158 | - if (jsonNode == null) { | ||
| 159 | - return null; | ||
| 160 | - } | ||
| 161 | - | ||
| 162 | - try { | ||
| 163 | - return TpPort.tpPort(jsonNode.asInt()); | ||
| 164 | - } catch (IllegalArgumentException e) { | ||
| 165 | - log.error("Wrong TCP port format {}", jsonNode.asText()); | ||
| 166 | - return null; | ||
| 167 | - } | ||
| 168 | - } | ||
| 169 | - | ||
| 170 | - /** | ||
| 171 | - * Returns the port number used for SSH connection. | ||
| 172 | - * | ||
| 173 | - * @return port number, or null | ||
| 174 | - */ | ||
| 175 | - public TpPort sshPort() { | ||
| 176 | - JsonNode jsonNode = object.get(SSH_PORT); | ||
| 177 | - if (jsonNode == null) { | ||
| 178 | - return null; | ||
| 179 | - } | ||
| 180 | - | ||
| 181 | - try { | ||
| 182 | - return TpPort.tpPort(jsonNode.asInt()); | ||
| 183 | - } catch (IllegalArgumentException e) { | ||
| 184 | - log.error("Wrong TCP port format {}", jsonNode.asText()); | ||
| 185 | - return null; | ||
| 186 | - } | ||
| 187 | - } | ||
| 188 | - | ||
| 189 | - /** | ||
| 190 | - * Returns the user name for SSH connection. | ||
| 191 | - * | ||
| 192 | - * @return user name, or null | ||
| 193 | - */ | ||
| 194 | - public String sshUser() { | ||
| 195 | - JsonNode jsonNode = object.get(SSH_USER); | ||
| 196 | - if (jsonNode == null) { | ||
| 197 | - return null; | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - return jsonNode.asText(); | ||
| 201 | - } | ||
| 202 | - | ||
| 203 | - /** | ||
| 204 | - * Returns the private key file for SSH connection. | ||
| 205 | - * | ||
| 206 | - * @return file path, or null | ||
| 207 | - */ | ||
| 208 | - public String sshKeyFile() { | ||
| 209 | - JsonNode jsonNode = object.get(SSH_KEY_FILE); | ||
| 210 | - if (jsonNode == null) { | ||
| 211 | - return null; | ||
| 212 | - } | ||
| 213 | - | ||
| 214 | - return jsonNode.asText(); | ||
| 215 | - } | ||
| 216 | - | ||
| 217 | - /** | ||
| 218 | - * Configuration for CordVtn node. | ||
| 219 | - */ | ||
| 220 | - public static class CordVtnNodeConfig { | ||
| 221 | - | ||
| 222 | - private final String hostname; | ||
| 223 | - private final NetworkAddress hostMgmtIp; | ||
| 224 | - private final NetworkAddress dpIp; | ||
| 225 | - private final String dpIntf; | ||
| 226 | - private final DeviceId bridgeId; | ||
| 227 | - | ||
| 228 | - public CordVtnNodeConfig(String hostname, NetworkAddress hostMgmtIp, NetworkAddress dpIp, | ||
| 229 | - String dpIntf, DeviceId bridgeId) { | ||
| 230 | - this.hostname = checkNotNull(hostname); | ||
| 231 | - this.hostMgmtIp = checkNotNull(hostMgmtIp); | ||
| 232 | - this.dpIp = checkNotNull(dpIp); | ||
| 233 | - this.dpIntf = checkNotNull(dpIntf); | ||
| 234 | - this.bridgeId = checkNotNull(bridgeId); | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | - /** | ||
| 238 | - * Returns hostname of the node. | ||
| 239 | - * | ||
| 240 | - * @return hostname | ||
| 241 | - */ | ||
| 242 | - public String hostname() { | ||
| 243 | - return this.hostname; | ||
| 244 | - } | ||
| 245 | - | ||
| 246 | - /** | ||
| 247 | - * Returns the host management network address of the node. | ||
| 248 | - * | ||
| 249 | - * @return management network address | ||
| 250 | - */ | ||
| 251 | - public NetworkAddress hostMgmtIp() { | ||
| 252 | - return this.hostMgmtIp; | ||
| 253 | - } | ||
| 254 | - | ||
| 255 | - /** | ||
| 256 | - * Returns the data plane network address. | ||
| 257 | - * | ||
| 258 | - * @return network address | ||
| 259 | - */ | ||
| 260 | - public NetworkAddress dpIp() { | ||
| 261 | - return this.dpIp; | ||
| 262 | - } | ||
| 263 | - | ||
| 264 | - /** | ||
| 265 | - * Returns the data plane interface name. | ||
| 266 | - * | ||
| 267 | - * @return interface name | ||
| 268 | - */ | ||
| 269 | - public String dpIntf() { | ||
| 270 | - return this.dpIntf; | ||
| 271 | - } | ||
| 272 | - | ||
| 273 | - /** | ||
| 274 | - * Returns integration bridge id of the node. | ||
| 275 | - * | ||
| 276 | - * @return device id | ||
| 277 | - */ | ||
| 278 | - public DeviceId bridgeId() { | ||
| 279 | - return this.bridgeId; | ||
| 280 | - } | ||
| 281 | - } | ||
| 282 | } | 171 | } |
| 172 | + | ... | ... |
| ... | @@ -24,7 +24,6 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -24,7 +24,6 @@ import org.apache.felix.scr.annotations.Reference; |
| 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 25 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
| 26 | import org.onlab.packet.IpAddress; | 26 | import org.onlab.packet.IpAddress; |
| 27 | -import org.onlab.packet.TpPort; | ||
| 28 | import org.onlab.util.ItemNotFoundException; | 27 | import org.onlab.util.ItemNotFoundException; |
| 29 | import org.onlab.util.KryoNamespace; | 28 | import org.onlab.util.KryoNamespace; |
| 30 | import org.onosproject.cluster.ClusterService; | 29 | import org.onosproject.cluster.ClusterService; |
| ... | @@ -64,6 +63,7 @@ import org.onosproject.store.serializers.KryoNamespaces; | ... | @@ -64,6 +63,7 @@ import org.onosproject.store.serializers.KryoNamespaces; |
| 64 | import org.onosproject.store.service.ConsistentMap; | 63 | import org.onosproject.store.service.ConsistentMap; |
| 65 | import org.onosproject.store.service.Serializer; | 64 | import org.onosproject.store.service.Serializer; |
| 66 | import org.onosproject.store.service.StorageService; | 65 | import org.onosproject.store.service.StorageService; |
| 66 | +import org.onosproject.store.service.Versioned; | ||
| 67 | import org.slf4j.Logger; | 67 | import org.slf4j.Logger; |
| 68 | 68 | ||
| 69 | import java.util.ArrayList; | 69 | import java.util.ArrayList; |
| ... | @@ -300,6 +300,22 @@ public class CordVtnNodeManager { | ... | @@ -300,6 +300,22 @@ public class CordVtnNodeManager { |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | /** | 302 | /** |
| 303 | + * Returns if current node state saved in nodeStore is COMPLETE or not. | ||
| 304 | + * | ||
| 305 | + * @param node cordvtn node | ||
| 306 | + * @return true if it's complete state, otherwise false | ||
| 307 | + */ | ||
| 308 | + private boolean isNodeStateComplete(CordVtnNode node) { | ||
| 309 | + checkNotNull(node); | ||
| 310 | + | ||
| 311 | + // the state saved in nodeStore can be wrong if IP address settings are changed | ||
| 312 | + // after the node init has been completed since there's no way to detect it | ||
| 313 | + // getNodeState and checkNodeInitState always return correct answer but can be slow | ||
| 314 | + Versioned<NodeState> state = nodeStore.get(node); | ||
| 315 | + return state != null && state.value().equals(NodeState.COMPLETE); | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + /** | ||
| 303 | * Returns detailed node initialization state. | 319 | * Returns detailed node initialization state. |
| 304 | * | 320 | * |
| 305 | * @param node cordvtn node | 321 | * @param node cordvtn node |
| ... | @@ -771,7 +787,7 @@ public class CordVtnNodeManager { | ... | @@ -771,7 +787,7 @@ public class CordVtnNodeManager { |
| 771 | log.debug("Port {} is added to {}", portName, node.hostname()); | 787 | log.debug("Port {} is added to {}", portName, node.hostname()); |
| 772 | 788 | ||
| 773 | if (portName.startsWith(VPORT_PREFIX)) { | 789 | if (portName.startsWith(VPORT_PREFIX)) { |
| 774 | - if (isNodeInitComplete(node)) { | 790 | + if (isNodeStateComplete(node)) { |
| 775 | cordVtnService.addServiceVm(node, getConnectPoint(port)); | 791 | cordVtnService.addServiceVm(node, getConnectPoint(port)); |
| 776 | } else { | 792 | } else { |
| 777 | log.debug("VM is detected on incomplete node, ignore it.", portName); | 793 | log.debug("VM is detected on incomplete node, ignore it.", portName); |
| ... | @@ -799,7 +815,7 @@ public class CordVtnNodeManager { | ... | @@ -799,7 +815,7 @@ public class CordVtnNodeManager { |
| 799 | log.debug("Port {} is removed from {}", portName, node.hostname()); | 815 | log.debug("Port {} is removed from {}", portName, node.hostname()); |
| 800 | 816 | ||
| 801 | if (portName.startsWith(VPORT_PREFIX)) { | 817 | if (portName.startsWith(VPORT_PREFIX)) { |
| 802 | - if (isNodeInitComplete(node)) { | 818 | + if (isNodeStateComplete(node)) { |
| 803 | cordVtnService.removeServiceVm(getConnectPoint(port)); | 819 | cordVtnService.removeServiceVm(getConnectPoint(port)); |
| 804 | } else { | 820 | } else { |
| 805 | log.debug("VM is vanished from incomplete node, ignore it.", portName); | 821 | log.debug("VM is vanished from incomplete node, ignore it.", portName); |
| ... | @@ -847,36 +863,12 @@ public class CordVtnNodeManager { | ... | @@ -847,36 +863,12 @@ public class CordVtnNodeManager { |
| 847 | */ | 863 | */ |
| 848 | private void readConfiguration() { | 864 | private void readConfiguration() { |
| 849 | CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class); | 865 | CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class); |
| 850 | - | ||
| 851 | if (config == null) { | 866 | if (config == null) { |
| 852 | log.debug("No configuration found"); | 867 | log.debug("No configuration found"); |
| 853 | return; | 868 | return; |
| 854 | } | 869 | } |
| 855 | 870 | ||
| 856 | - NetworkAddress localMgmtIp = config.localMgmtIp(); | 871 | + config.cordVtnNodes().forEach(this::addNode); |
| 857 | - TpPort ovsdbPort = config.ovsdbPort(); | ||
| 858 | - TpPort sshPort = config.sshPort(); | ||
| 859 | - String sshUser = config.sshUser(); | ||
| 860 | - String sshKeyFile = config.sshKeyFile(); | ||
| 861 | - | ||
| 862 | - config.cordVtnNodes().forEach(node -> { | ||
| 863 | - log.debug("Read node {}", node.hostname()); | ||
| 864 | - CordVtnNode cordVtnNode = new CordVtnNode( | ||
| 865 | - node.hostname(), | ||
| 866 | - node.hostMgmtIp(), | ||
| 867 | - localMgmtIp, | ||
| 868 | - node.dpIp(), | ||
| 869 | - ovsdbPort, | ||
| 870 | - new SshAccessInfo(node.hostMgmtIp().ip().getIp4Address(), | ||
| 871 | - sshPort, | ||
| 872 | - sshUser, | ||
| 873 | - sshKeyFile), | ||
| 874 | - node.bridgeId(), | ||
| 875 | - node.dpIntf()); | ||
| 876 | - | ||
| 877 | - addNode(cordVtnNode); | ||
| 878 | - }); | ||
| 879 | - | ||
| 880 | // TODO remove nodes if needed | 872 | // TODO remove nodes if needed |
| 881 | } | 873 | } |
| 882 | 874 | ... | ... |
| ... | @@ -21,6 +21,8 @@ import org.onlab.packet.TpPort; | ... | @@ -21,6 +21,8 @@ import org.onlab.packet.TpPort; |
| 21 | 21 | ||
| 22 | import java.util.Objects; | 22 | import java.util.Objects; |
| 23 | 23 | ||
| 24 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 25 | + | ||
| 24 | /** | 26 | /** |
| 25 | * Representation of SSH access information. | 27 | * Representation of SSH access information. |
| 26 | */ | 28 | */ |
| ... | @@ -40,10 +42,10 @@ public final class SshAccessInfo { | ... | @@ -40,10 +42,10 @@ public final class SshAccessInfo { |
| 40 | * @param privateKey path of ssh private key | 42 | * @param privateKey path of ssh private key |
| 41 | */ | 43 | */ |
| 42 | public SshAccessInfo(Ip4Address remoteIp, TpPort port, String user, String privateKey) { | 44 | public SshAccessInfo(Ip4Address remoteIp, TpPort port, String user, String privateKey) { |
| 43 | - this.remoteIp = remoteIp; | 45 | + this.remoteIp = checkNotNull(remoteIp); |
| 44 | - this.port = port; | 46 | + this.port = checkNotNull(port); |
| 45 | - this.user = user; | 47 | + this.user = checkNotNull(user); |
| 46 | - this.privateKey = privateKey; | 48 | + this.privateKey = checkNotNull(privateKey); |
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | /** | 51 | /** | ... | ... |
| ... | @@ -43,7 +43,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { | ... | @@ -43,7 +43,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { |
| 43 | @Consumes(MediaType.APPLICATION_JSON) | 43 | @Consumes(MediaType.APPLICATION_JSON) |
| 44 | @Produces(MediaType.APPLICATION_JSON) | 44 | @Produces(MediaType.APPLICATION_JSON) |
| 45 | public Response createNetwork(InputStream input) { | 45 | public Response createNetwork(InputStream input) { |
| 46 | - log.debug(String.format(NETWORKS_MESSAGE, "create")); | 46 | + log.trace(String.format(NETWORKS_MESSAGE, "create")); |
| 47 | return Response.status(Response.Status.OK).build(); | 47 | return Response.status(Response.Status.OK).build(); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| ... | @@ -52,7 +52,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { | ... | @@ -52,7 +52,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { |
| 52 | @Consumes(MediaType.APPLICATION_JSON) | 52 | @Consumes(MediaType.APPLICATION_JSON) |
| 53 | @Produces(MediaType.APPLICATION_JSON) | 53 | @Produces(MediaType.APPLICATION_JSON) |
| 54 | public Response updateNetwork(@PathParam("id") String id, InputStream input) { | 54 | public Response updateNetwork(@PathParam("id") String id, InputStream input) { |
| 55 | - log.debug(String.format(NETWORKS_MESSAGE, "update")); | 55 | + log.trace(String.format(NETWORKS_MESSAGE, "update")); |
| 56 | return Response.status(Response.Status.OK).build(); | 56 | return Response.status(Response.Status.OK).build(); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| ... | @@ -60,7 +60,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { | ... | @@ -60,7 +60,7 @@ public class NeutronMl2NetworksWebResource extends AbstractWebResource { |
| 60 | @Path("{id}") | 60 | @Path("{id}") |
| 61 | @Produces(MediaType.APPLICATION_JSON) | 61 | @Produces(MediaType.APPLICATION_JSON) |
| 62 | public Response deleteNetwork(@PathParam("id") String id) { | 62 | public Response deleteNetwork(@PathParam("id") String id) { |
| 63 | - log.debug(String.format(NETWORKS_MESSAGE, "delete")); | 63 | + log.trace(String.format(NETWORKS_MESSAGE, "delete")); |
| 64 | return Response.status(Response.Status.OK).build(); | 64 | return Response.status(Response.Status.OK).build(); |
| 65 | } | 65 | } |
| 66 | } | 66 | } | ... | ... |
| ... | @@ -63,7 +63,7 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { | ... | @@ -63,7 +63,7 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { |
| 63 | @Consumes(MediaType.APPLICATION_JSON) | 63 | @Consumes(MediaType.APPLICATION_JSON) |
| 64 | @Produces(MediaType.APPLICATION_JSON) | 64 | @Produces(MediaType.APPLICATION_JSON) |
| 65 | public Response createPorts(InputStream input) { | 65 | public Response createPorts(InputStream input) { |
| 66 | - log.debug(String.format(PORTS_MESSAGE, "create")); | 66 | + log.trace(String.format(PORTS_MESSAGE, "create")); |
| 67 | return Response.status(Response.Status.OK).build(); | 67 | return Response.status(Response.Status.OK).build(); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| ... | @@ -110,7 +110,7 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { | ... | @@ -110,7 +110,7 @@ public class NeutronMl2PortsWebResource extends AbstractWebResource { |
| 110 | @DELETE | 110 | @DELETE |
| 111 | @Produces(MediaType.APPLICATION_JSON) | 111 | @Produces(MediaType.APPLICATION_JSON) |
| 112 | public Response deletePorts(@PathParam("id") String id) { | 112 | public Response deletePorts(@PathParam("id") String id) { |
| 113 | - log.debug(String.format(PORTS_MESSAGE, "delete")); | 113 | + log.trace(String.format(PORTS_MESSAGE, "delete")); |
| 114 | return Response.status(Response.Status.OK).build(); | 114 | return Response.status(Response.Status.OK).build(); |
| 115 | } | 115 | } |
| 116 | } | 116 | } | ... | ... |
| ... | @@ -43,7 +43,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { | ... | @@ -43,7 +43,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { |
| 43 | @Consumes(MediaType.APPLICATION_JSON) | 43 | @Consumes(MediaType.APPLICATION_JSON) |
| 44 | @Produces(MediaType.APPLICATION_JSON) | 44 | @Produces(MediaType.APPLICATION_JSON) |
| 45 | public Response createSubnet(InputStream input) { | 45 | public Response createSubnet(InputStream input) { |
| 46 | - log.debug(String.format(SUBNETS_MESSAGE, "create")); | 46 | + log.trace(String.format(SUBNETS_MESSAGE, "create")); |
| 47 | return Response.status(Response.Status.OK).build(); | 47 | return Response.status(Response.Status.OK).build(); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| ... | @@ -53,7 +53,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { | ... | @@ -53,7 +53,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { |
| 53 | @Produces(MediaType.APPLICATION_JSON) | 53 | @Produces(MediaType.APPLICATION_JSON) |
| 54 | @Consumes(MediaType.APPLICATION_JSON) | 54 | @Consumes(MediaType.APPLICATION_JSON) |
| 55 | public Response updateSubnet(@PathParam("id") String id, InputStream input) { | 55 | public Response updateSubnet(@PathParam("id") String id, InputStream input) { |
| 56 | - log.debug(String.format(SUBNETS_MESSAGE, "update")); | 56 | + log.trace(String.format(SUBNETS_MESSAGE, "update")); |
| 57 | return Response.status(Response.Status.OK).build(); | 57 | return Response.status(Response.Status.OK).build(); |
| 58 | 58 | ||
| 59 | } | 59 | } |
| ... | @@ -62,7 +62,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { | ... | @@ -62,7 +62,7 @@ public class NeutronMl2SubnetsWebResource extends AbstractWebResource { |
| 62 | @Path("{id}") | 62 | @Path("{id}") |
| 63 | @Produces(MediaType.APPLICATION_JSON) | 63 | @Produces(MediaType.APPLICATION_JSON) |
| 64 | public Response deleteSubnet(@PathParam("id") String id) { | 64 | public Response deleteSubnet(@PathParam("id") String id) { |
| 65 | - log.debug(String.format(SUBNETS_MESSAGE, "delete")); | 65 | + log.trace(String.format(SUBNETS_MESSAGE, "delete")); |
| 66 | return Response.status(Response.Status.OK).build(); | 66 | return Response.status(Response.Status.OK).build(); |
| 67 | } | 67 | } |
| 68 | } | 68 | } | ... | ... |
-
Please register or login to post a comment