Skip to content

Commit 40f032a

Browse files
committed
Adds a CLI to show/clear cached openstack states with neutron DB
Change-Id: I270c27affc669d10236ce94ec7a546a4f85aea88
1 parent e39aa1c commit 40f032a

File tree

6 files changed

+410
-82
lines changed

6 files changed

+410
-82
lines changed

apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,12 @@ private static Map<String, String> createPortNamePrefixMap() {
147147

148148
public static final boolean DEFAULT_HA_STATUS = false;
149149
public static final IpAddress DEFAULT_ACTIVE_IP_ADDRESS = IpAddress.valueOf("127.0.0.1");
150+
151+
public static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
152+
public static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
153+
public static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
154+
public static final String ROUTER_INTF_FORMAT = "%-40s%-20s%-20s";
155+
public static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
156+
public static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
157+
public static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
150158
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* Copyright 2019-present Open Networking Foundation
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.openstacknetworking.cli;
17+
18+
import org.apache.karaf.shell.api.action.Command;
19+
import org.apache.karaf.shell.api.action.Option;
20+
import org.apache.karaf.shell.api.action.lifecycle.Service;
21+
import org.onosproject.cli.AbstractShellCommand;
22+
import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
23+
import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
24+
import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupAdminService;
25+
import org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil;
26+
import org.onosproject.openstacknode.api.OpenstackNode;
27+
import org.onosproject.openstacknode.api.OpenstackNodeService;
28+
import org.openstack4j.api.OSClient;
29+
import org.openstack4j.model.common.IdEntity;
30+
import org.openstack4j.model.network.NetFloatingIP;
31+
import org.openstack4j.model.network.RouterInterface;
32+
33+
import java.util.HashMap;
34+
import java.util.Map;
35+
import java.util.Optional;
36+
import java.util.Set;
37+
import java.util.stream.Collectors;
38+
39+
import static org.onosproject.openstacknetworking.api.Constants.FLOATING_IP_FORMAT;
40+
import static org.onosproject.openstacknetworking.api.Constants.NETWORK_FORMAT;
41+
import static org.onosproject.openstacknetworking.api.Constants.PORT_FORMAT;
42+
import static org.onosproject.openstacknetworking.api.Constants.ROUTER_FORMAT;
43+
import static org.onosproject.openstacknetworking.api.Constants.ROUTER_INTF_FORMAT;
44+
import static org.onosproject.openstacknetworking.api.Constants.SECURITY_GROUP_FORMAT;
45+
import static org.onosproject.openstacknetworking.api.Constants.SUBNET_FORMAT;
46+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printFloatingIp;
47+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printNetwork;
48+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printPort;
49+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printRouter;
50+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printRouterIntf;
51+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSecurityGroup;
52+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSubnet;
53+
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
54+
55+
/**
56+
* Compares cached network state diff against neutron database.
57+
*/
58+
@Service
59+
@Command(scope = "onos", name = "openstack-diff-state",
60+
description = "Compares cached network state with neutron database.")
61+
public class OpenstackDiffStateCommand extends AbstractShellCommand {
62+
63+
private static final String HTTP_HEADER_ACCEPT = "accept";
64+
private static final String HTTP_HEADER_VALUE_JSON = "application/json";
65+
66+
@Option(name = "-s", aliases = "--show",
67+
description = "Shows the differences between cached network state with neutron database.",
68+
required = false, multiValued = false)
69+
private boolean show = false;
70+
71+
@Option(name = "-c", aliases = "--clear",
72+
description = "Clears the differences between cached network state with neutron database.",
73+
required = false, multiValued = false)
74+
private boolean clear = false;
75+
76+
@Override
77+
protected void doExecute() {
78+
OpenstackSecurityGroupAdminService osSgService =
79+
get(OpenstackSecurityGroupAdminService.class);
80+
OpenstackNetworkAdminService osNetService =
81+
get(OpenstackNetworkAdminService.class);
82+
OpenstackRouterAdminService osRouterService =
83+
get(OpenstackRouterAdminService.class);
84+
OpenstackNodeService osNodeService = get(OpenstackNodeService.class);
85+
86+
Map<String, String> headerMap = new HashMap<>();
87+
headerMap.put(HTTP_HEADER_ACCEPT, HTTP_HEADER_VALUE_JSON);
88+
89+
Optional<OpenstackNode> node = osNodeService.nodes(CONTROLLER).stream().findFirst();
90+
if (!node.isPresent()) {
91+
error("Keystone auth info has not been configured. " +
92+
"Please specify auth info via network-cfg.json.");
93+
return;
94+
}
95+
96+
OSClient osClient = OpenstackNetworkingUtil.getConnectedClient(node.get());
97+
98+
if (osClient == null) {
99+
return;
100+
}
101+
102+
if (!clear) {
103+
show = true;
104+
}
105+
106+
if (show && clear) {
107+
error("Either --show (-s) or --clear (-c) option should be specified.");
108+
}
109+
110+
if (show) {
111+
print("\nComparing OpenStack floating IPs");
112+
} else if (clear) {
113+
print("\nClearing OpenStack floating IPs");
114+
}
115+
Set<String> cachedFips = osRouterService.floatingIps().stream()
116+
.map(NetFloatingIP::getId).collect(Collectors.toSet());
117+
Set<String> osFips = osClient.headers(headerMap).networking()
118+
.floatingip().list().stream().map(NetFloatingIP::getId)
119+
.collect(Collectors.toSet());
120+
121+
print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
122+
getDiff(cachedFips, osFips).forEach(fipId -> {
123+
printFloatingIp(osRouterService.floatingIp(fipId));
124+
if (clear) {
125+
osRouterService.removeFloatingIp(fipId);
126+
}
127+
});
128+
129+
Set<String> cachedPorts = osNetService.ports().stream()
130+
.map(IdEntity::getId).collect(Collectors.toSet());
131+
Set<String> osPorts = osClient.headers(headerMap).networking()
132+
.port().list().stream().map(IdEntity::getId)
133+
.collect(Collectors.toSet());
134+
135+
if (show) {
136+
print("\nComparing OpenStack router interfaces");
137+
} else if (clear) {
138+
print("\nClearing OpenStack router interfaces");
139+
}
140+
print(ROUTER_INTF_FORMAT, "ID", "Tenant ID", "Subnet ID");
141+
getDiff(cachedPorts, osPorts).forEach(portId -> {
142+
RouterInterface ri = osRouterService.routerInterface(portId);
143+
if (ri != null) {
144+
printRouterIntf(ri);
145+
if (clear) {
146+
osRouterService.removeRouterInterface(portId);
147+
}
148+
}
149+
});
150+
151+
if (show) {
152+
print("\nComparing OpenStack ports");
153+
} else if (clear) {
154+
print("\nClearing OpenStack ports");
155+
}
156+
print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
157+
getDiff(cachedPorts, osPorts).forEach(portId -> {
158+
printPort(osNetService.port(portId), osNetService);
159+
if (clear) {
160+
osNetService.removePort(portId);
161+
}
162+
});
163+
164+
if (show) {
165+
print("\nComparing OpenStack routers");
166+
} else if (clear) {
167+
print("\nClearing OpenStack routers");
168+
}
169+
Set<String> cachedRouters = osRouterService.routers().stream()
170+
.map(IdEntity::getId).collect(Collectors.toSet());
171+
Set<String> osRouters = osClient.headers(headerMap).networking()
172+
.router().list().stream().map(IdEntity::getId)
173+
.collect(Collectors.toSet());
174+
175+
print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
176+
getDiff(cachedRouters, osRouters).forEach(routerId -> {
177+
printRouter(osRouterService.router(routerId), osNetService);
178+
if (clear) {
179+
osRouterService.removeRouter(routerId);
180+
}
181+
});
182+
183+
if (show) {
184+
print("\nComparing OpenStack subnets");
185+
} else if (clear) {
186+
print("\nClearing OpenStack subnets");
187+
}
188+
Set<String> cachedSubnets = osNetService.subnets().stream()
189+
.map(IdEntity::getId).collect(Collectors.toSet());
190+
Set<String> osSubnets = osClient.headers(headerMap).networking()
191+
.subnet().list().stream().map(IdEntity::getId)
192+
.collect(Collectors.toSet());
193+
194+
print(SUBNET_FORMAT, "ID", "Network", "CIDR");
195+
getDiff(cachedSubnets, osSubnets).forEach(subnetId -> {
196+
printSubnet(osNetService.subnet(subnetId), osNetService);
197+
if (clear) {
198+
osNetService.removeSubnet(subnetId);
199+
}
200+
});
201+
202+
if (show) {
203+
print("\nComparing OpenStack networks");
204+
} else if (clear) {
205+
print("\nClearing OpenStack networks");
206+
}
207+
Set<String> cachedNets = osNetService.networks().stream()
208+
.map(IdEntity::getId).collect(Collectors.toSet());
209+
Set<String> osNets = osClient.headers(headerMap).networking()
210+
.network().list().stream().map(IdEntity::getId)
211+
.collect(Collectors.toSet());
212+
213+
print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
214+
getDiff(cachedNets, osNets).forEach(netId -> {
215+
printNetwork(osNetService.network(netId));
216+
if (clear) {
217+
osNetService.removeNetwork(netId);
218+
}
219+
});
220+
221+
if (show) {
222+
print("\nComparing OpenStack security groups");
223+
} else if (clear) {
224+
print("\nClearing OpenStack security groups");
225+
}
226+
Set<String> cachedSgs = osSgService.securityGroups().stream()
227+
.map(IdEntity::getId).collect(Collectors.toSet());
228+
Set<String> osSgs = osClient.headers(headerMap).networking()
229+
.securitygroup().list().stream().map(IdEntity::getId)
230+
.collect(Collectors.toSet());
231+
232+
print(SECURITY_GROUP_FORMAT, "ID", "Name");
233+
getDiff(cachedSgs, osSgs).forEach(sgId -> {
234+
printSecurityGroup(osSgService.securityGroup(sgId));
235+
if (clear) {
236+
osSgService.removeSecurityGroup(sgId);
237+
}
238+
});
239+
}
240+
241+
private Set<String> getDiff(Set<String> orig, Set<String> comp) {
242+
return orig.stream().filter(id -> !comp.contains(id))
243+
.collect(Collectors.toSet());
244+
}
245+
}

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPortListCommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.util.List;
3434
import java.util.stream.Collectors;
3535

36-
import static org.onosproject.cli.AbstractShellCommand.get;
3736
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.modelEntityToJson;
3837
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.prettyJson;
3938

@@ -71,8 +70,9 @@ protected void doExecute() {
7170
.map(IP::getIpAddress)
7271
.collect(Collectors.toList());
7372
Network osNet = service.network(port.getNetworkId());
73+
String netName = osNet == null ? "N/A" : osNet.getName();
7474
print(FORMAT, port.getId(),
75-
osNet.getName(),
75+
netName,
7676
port.getMacAddress(),
7777
fixedIps.isEmpty() ? "" : fixedIps);
7878
}

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSubnetListCommand.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
import org.apache.karaf.shell.api.action.lifecycle.Service;
2323
import org.onosproject.cli.AbstractShellCommand;
2424
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
25+
import org.openstack4j.model.network.Network;
2526
import org.openstack4j.model.network.Subnet;
2627
import org.openstack4j.openstack.networking.domain.NeutronSubnet;
2728

2829
import java.util.Comparator;
2930
import java.util.List;
3031

31-
import static org.onosproject.cli.AbstractShellCommand.get;
3232
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.modelEntityToJson;
3333
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.prettyJson;
3434

@@ -55,13 +55,15 @@ protected void doExecute() {
5555
"NetworkName", "HostRoutes");
5656

5757
for (Subnet subnet: subnets) {
58+
Network osNet = service.network(subnet.getNetworkId());
59+
String netName = osNet == null ? "N/A" : osNet.getName();
5860
print(FORMAT,
5961
subnet.getId(),
6062
subnet.getName(),
6163
subnet.getCidr(),
6264
subnet.getGateway(),
6365
subnet.getNetworkId(),
64-
service.network(subnet.getNetworkId()).getName(),
66+
netName,
6567
subnet.getHostRoutes());
6668
}
6769
}

0 commit comments

Comments
 (0)