ONOS-5970 Added CLIs to purge and sync network states from Neutron
Change-Id: Icd1f4c174de20e261229f30ddfd6857c26cb038c
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPurgeStateCommand.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPurgeStateCommand.java
new file mode 100644
index 0000000..6f28590
--- /dev/null
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPurgeStateCommand.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
+
+/**
+ * Purges all existing network states.
+ */
+@Command(scope = "onos", name = "openstack-purge-states",
+ description = "Purges all OpenStack network states")
+public class OpenstackPurgeStateCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ get(OpenstackNetworkAdminService.class).clear();
+ get(OpenstackRouterAdminService.class).clear();
+ }
+}
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java
new file mode 100644
index 0000000..d07591e
--- /dev/null
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Strings;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterService;
+import org.openstack4j.api.OSClient;
+import org.openstack4j.api.exceptions.AuthenticationException;
+import org.openstack4j.model.identity.Access;
+import org.openstack4j.model.network.IP;
+import org.openstack4j.model.network.NetFloatingIP;
+import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.Port;
+import org.openstack4j.model.network.Router;
+import org.openstack4j.model.network.RouterInterface;
+import org.openstack4j.model.network.Subnet;
+import org.openstack4j.openstack.OSFactory;
+import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
+
+/**
+ * Synchronizes OpenStack network states.
+ */
+@Command(scope = "onos", name = "openstack-sync-states",
+ description = "Synchronizes all OpenStack network states")
+public class OpenstackSyncStateCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "endpoint", description = "OpenStack service endpoint",
+ required = true, multiValued = false)
+ private String endpoint = null;
+
+ @Argument(index = 1, name = "tenant", description = "OpenStack admin tenant name",
+ required = true, multiValued = false)
+ private String tenant = null;
+
+ @Argument(index = 2, name = "user", description = "OpenStack admin user name",
+ required = true, multiValued = false)
+ private String user = null;
+
+ @Argument(index = 3, name = "password", description = "OpenStack admin user password",
+ required = true, multiValued = false)
+ private String password = null;
+
+ private static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
+ private static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
+ private static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
+ private static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
+ private static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
+
+ private static final String DEVICE_OWNER_GW = "network:router_gateway";
+ private static final String DEVICE_OWNER_IFACE = "network:router_interface";
+
+ @Override
+ protected void execute() {
+ OpenstackNetworkAdminService osNetAdminService = get(OpenstackNetworkAdminService.class);
+ OpenstackNetworkService osNetService = get(OpenstackNetworkService.class);
+ OpenstackRouterAdminService osRouterAdminService = get(OpenstackRouterAdminService.class);
+ OpenstackRouterService osRouterService = get(OpenstackRouterService.class);
+
+ Access osAccess;
+ try {
+ osAccess = OSFactory.builder()
+ .endpoint(this.endpoint)
+ .tenantName(this.tenant)
+ .credentials(this.user, this.password)
+ .authenticate()
+ .getAccess();
+ } catch (AuthenticationException e) {
+ print("Authentication failed");
+ return;
+ } catch (Exception e) {
+ print("Failed to access OpenStack service");
+ return;
+ }
+
+ OSClient osClient = OSFactory.clientFromAccess(osAccess);
+
+ print("Synchronizing OpenStack networks...");
+ print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
+ osClient.networking().network().list().forEach(osNet -> {
+ if (osNetService.network(osNet.getId()) != null) {
+ osNetAdminService.updateNetwork(osNet);
+ } else {
+ osNetAdminService.createNetwork(osNet);
+ }
+ printNetwork(osNet);
+ });
+
+ print("\nSynchronizing OpenStack subnets...");
+ print(SUBNET_FORMAT, "ID", "Network", "CIDR");
+ osClient.networking().subnet().list().forEach(osSubnet -> {
+ if (osNetService.subnet(osSubnet.getId()) != null) {
+ osNetAdminService.updateSubnet(osSubnet);
+ } else {
+ osNetAdminService.createSubnet(osSubnet);
+ }
+ printSubnet(osSubnet, osNetService);
+ });
+
+ print("\nSynchronizing OpenStack ports...");
+ print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
+ osClient.networking().port().list().forEach(osPort -> {
+ if (osNetService.port(osPort.getId()) != null) {
+ osNetAdminService.updatePort(osPort);
+ } else {
+ osNetAdminService.createPort(osPort);
+ }
+ printPort(osPort, osNetService);
+ });
+
+ print("\nSynchronizing OpenStack routers...");
+ print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
+ osClient.networking().router().list().forEach(osRouter -> {
+ if (osRouterService.router(osRouter.getId()) != null) {
+ osRouterAdminService.updateRouter(osRouter);
+ } else {
+ osRouterAdminService.createRouter(osRouter);
+ }
+
+ // FIXME do we need to manage router interfaces separately?
+ osNetService.ports().stream()
+ .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
+ Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
+ .forEach(osPort -> addRouterIface(osPort, osRouterService,
+ osRouterAdminService));
+
+ printRouter(osRouter, osNetService);
+ });
+
+ print("\nSynchronizing OpenStack floating IPs...");
+ print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
+ osClient.networking().floatingip().list().forEach(osFloating -> {
+ if (osRouterService.floatingIp(osFloating.getId()) != null) {
+ osRouterAdminService.updateFloatingIp(osFloating);
+ } else {
+ osRouterAdminService.createFloatingIp(osFloating);
+ }
+ printFloatingIp(osFloating);
+ });
+ }
+
+ // TODO fix the logic to add router interface to router
+ private void addRouterIface(Port osPort, OpenstackRouterService service,
+ OpenstackRouterAdminService adminService) {
+ osPort.getFixedIps().forEach(p -> {
+ JsonNode jsonTree = mapper().createObjectNode()
+ .put("id", osPort.getDeviceId())
+ .put("tenant_id", osPort.getTenantId())
+ .put("subnet_id", p.getSubnetId())
+ .put("port_id", osPort.getId());
+ try {
+ RouterInterface rIface = getContext(NeutronRouterInterface.class)
+ .readerFor(NeutronRouterInterface.class)
+ .readValue(jsonTree);
+ if (service.routerInterface(rIface.getPortId()) != null) {
+ adminService.updateRouterInterface(rIface);
+ } else {
+ adminService.addRouterInterface(rIface);
+ }
+ } catch (IOException ignore) {
+ }
+ });
+ }
+
+ private void printNetwork(Network osNet) {
+ final String strNet = String.format(NETWORK_FORMAT,
+ osNet.getId(),
+ osNet.getName(),
+ osNet.getProviderSegID(),
+ osNet.getSubnets());
+ print(strNet);
+ }
+
+ private void printSubnet(Subnet osSubnet, OpenstackNetworkService osNetService) {
+ final String strSubnet = String.format(SUBNET_FORMAT,
+ osSubnet.getId(),
+ osNetService.network(osSubnet.getNetworkId()).getName(),
+ osSubnet.getCidr());
+ print(strSubnet);
+ }
+
+ private void printPort(Port osPort, OpenstackNetworkService osNetService) {
+ List<String> fixedIps = osPort.getFixedIps().stream()
+ .map(IP::getIpAddress)
+ .collect(Collectors.toList());
+ final String strPort = String.format(PORT_FORMAT,
+ osPort.getId(),
+ osNetService.network(osPort.getNetworkId()).getName(),
+ osPort.getMacAddress(),
+ fixedIps.isEmpty() ? "" : fixedIps);
+ print(strPort);
+ }
+
+ private void printRouter(Router osRouter, OpenstackNetworkService osNetService) {
+ List<String> externals = osNetService.ports().stream()
+ .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
+ Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
+ .flatMap(osPort -> osPort.getFixedIps().stream())
+ .map(IP::getIpAddress)
+ .collect(Collectors.toList());
+
+ List<String> internals = osNetService.ports().stream()
+ .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
+ Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
+ .flatMap(osPort -> osPort.getFixedIps().stream())
+ .map(IP::getIpAddress)
+ .collect(Collectors.toList());
+
+ final String strRouter = String.format(ROUTER_FORMAT,
+ osRouter.getId(),
+ osRouter.getName(),
+ externals.isEmpty() ? "" : externals,
+ internals.isEmpty() ? "" : internals);
+ print(strRouter);
+ }
+
+ private void printFloatingIp(NetFloatingIP floatingIp) {
+ final String strFloating = String.format(FLOATING_IP_FORMAT,
+ floatingIp.getId(),
+ floatingIp.getFixedIpAddress(),
+ Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
+ "" : floatingIp.getFixedIpAddress());
+ print(strFloating);
+ }
+}