blob: ddabb6225df74d4c912a2d8535a2b1497c7a10d6 [file] [log] [blame]
Hyunsun Moonc7219222017-03-27 11:05:59 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moonc7219222017-03-27 11:05:59 +09003 *
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 */
16package org.onosproject.openstacknetworking.cli;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.google.common.base.Strings;
20import org.apache.karaf.shell.commands.Argument;
21import org.apache.karaf.shell.commands.Command;
22import org.onosproject.cli.AbstractShellCommand;
23import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
Hyunsun Moonc7219222017-03-27 11:05:59 +090024import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
Hyunsun Moonae51e732017-04-25 17:46:21 +090025import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupAdminService;
Hyunsun Moonc7219222017-03-27 11:05:59 +090026import org.openstack4j.api.OSClient;
27import org.openstack4j.api.exceptions.AuthenticationException;
Jian Li1a9e71c2018-04-03 19:00:29 +090028import org.openstack4j.core.transport.Config;
sanghoa0ef13b2018-03-09 13:56:39 +090029import org.openstack4j.model.common.Identifier;
Hyunsun Moonc7219222017-03-27 11:05:59 +090030import org.openstack4j.model.network.IP;
31import org.openstack4j.model.network.NetFloatingIP;
32import org.openstack4j.model.network.Network;
33import org.openstack4j.model.network.Port;
34import org.openstack4j.model.network.Router;
35import org.openstack4j.model.network.RouterInterface;
36import org.openstack4j.model.network.Subnet;
37import org.openstack4j.openstack.OSFactory;
38import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
39
Jian Li1a9e71c2018-04-03 19:00:29 +090040import javax.net.ssl.HostnameVerifier;
41import javax.net.ssl.HttpsURLConnection;
42import javax.net.ssl.SSLContext;
43import javax.net.ssl.TrustManager;
Hyunsun Moonc7219222017-03-27 11:05:59 +090044import java.io.IOException;
45import java.util.List;
46import java.util.Objects;
47import java.util.stream.Collectors;
48
Jian Li1a9e71c2018-04-03 19:00:29 +090049import javax.net.ssl.X509TrustManager;
50import java.security.cert.X509Certificate;
51
Hyunsun Moonc7219222017-03-27 11:05:59 +090052import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
53
54/**
55 * Synchronizes OpenStack network states.
56 */
57@Command(scope = "onos", name = "openstack-sync-states",
58 description = "Synchronizes all OpenStack network states")
59public class OpenstackSyncStateCommand extends AbstractShellCommand {
60
61 @Argument(index = 0, name = "endpoint", description = "OpenStack service endpoint",
62 required = true, multiValued = false)
63 private String endpoint = null;
64
65 @Argument(index = 1, name = "tenant", description = "OpenStack admin tenant name",
66 required = true, multiValued = false)
67 private String tenant = null;
68
69 @Argument(index = 2, name = "user", description = "OpenStack admin user name",
70 required = true, multiValued = false)
71 private String user = null;
72
73 @Argument(index = 3, name = "password", description = "OpenStack admin user password",
74 required = true, multiValued = false)
75 private String password = null;
76
sanghoa0ef13b2018-03-09 13:56:39 +090077 private static final String DOMAIN_DEFUALT = "default";
78
Hyunsun Moonae51e732017-04-25 17:46:21 +090079 private static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
Hyunsun Moonc7219222017-03-27 11:05:59 +090080 private static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
81 private static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
82 private static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
83 private static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
84 private static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
85
86 private static final String DEVICE_OWNER_GW = "network:router_gateway";
87 private static final String DEVICE_OWNER_IFACE = "network:router_interface";
88
Jian Li8769d5b2018-03-09 21:55:40 +090089 private static final String KEYSTONE_V2 = "v2.0";
90 private static final String KEYSTONE_V3 = "v3";
91
Hyunsun Moonc7219222017-03-27 11:05:59 +090092 @Override
93 protected void execute() {
Hyunsun Moonae51e732017-04-25 17:46:21 +090094 OpenstackSecurityGroupAdminService osSgAdminService = get(OpenstackSecurityGroupAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090095 OpenstackNetworkAdminService osNetAdminService = get(OpenstackNetworkAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090096 OpenstackRouterAdminService osRouterAdminService = get(OpenstackRouterAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090097
Jian Li8769d5b2018-03-09 21:55:40 +090098 OSClient osClient;
sanghoa0ef13b2018-03-09 13:56:39 +090099
Jian Li1a9e71c2018-04-03 19:00:29 +0900100 Config config = Config.newConfig().withSSLVerificationDisabled();
101
102 TrustManager[] trustAllCerts = new TrustManager[]{
103 new X509TrustManager() {
104 public X509Certificate[] getAcceptedIssuers() {
105 return null;
106 }
107
108 public void checkClientTrusted(X509Certificate[] certs, String authType) {
109 }
110
111 public void checkServerTrusted(X509Certificate[] certs, String authType) {
112 }
113 }
114 };
115
116 HostnameVerifier allHostsValid = (hostname, session) -> true;
117
Jian Li8769d5b2018-03-09 21:55:40 +0900118 try {
Jian Li1a9e71c2018-04-03 19:00:29 +0900119 SSLContext sc = SSLContext.getInstance("SSL");
120 sc.init(null, trustAllCerts, new java.security.SecureRandom());
121 HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
122 HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
123
124 config.withSSLContext(sc);
125
Jian Li8769d5b2018-03-09 21:55:40 +0900126 if (endpoint != null) {
127 if (endpoint.contains(KEYSTONE_V2)) {
128 osClient = OSFactory.builderV2()
129 .endpoint(this.endpoint)
130 .tenantName(this.tenant)
131 .credentials(this.user, this.password)
Jian Li1a9e71c2018-04-03 19:00:29 +0900132 .withConfig(config)
Jian Li8769d5b2018-03-09 21:55:40 +0900133 .authenticate();
134 } else if (endpoint.contains(KEYSTONE_V3)) {
135
136 Identifier project = Identifier.byName(this.tenant);
137 Identifier domain = Identifier.byName(DOMAIN_DEFUALT);
138
139 osClient = OSFactory.builderV3()
140 .endpoint(this.endpoint)
141 .credentials(this.user, this.password, domain)
142 .scopeToProject(project, domain)
Jian Li1a9e71c2018-04-03 19:00:29 +0900143 .withConfig(config)
Jian Li8769d5b2018-03-09 21:55:40 +0900144 .authenticate();
145 } else {
146 print("Unrecognized keystone version type");
147 return;
148 }
149 } else {
150 print("Need to specify a valid endpoint");
151 return;
152 }
Hyunsun Moonc7219222017-03-27 11:05:59 +0900153 } catch (AuthenticationException e) {
154 print("Authentication failed");
155 return;
156 } catch (Exception e) {
157 print("Failed to access OpenStack service");
158 return;
159 }
160
Hyunsun Moonae51e732017-04-25 17:46:21 +0900161 print("Synchronizing OpenStack security groups");
162 print(SECURITY_GROUP_FORMAT, "ID", "Name");
163 osClient.networking().securitygroup().list().forEach(osSg -> {
Jian Li21536592018-03-06 15:10:55 +0900164 if (osSgAdminService.securityGroup(osSg.getId()) != null) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900165 osSgAdminService.updateSecurityGroup(osSg);
166 } else {
167 osSgAdminService.createSecurityGroup(osSg);
168 }
169 print(SECURITY_GROUP_FORMAT, osSg.getId(), osSg.getName());
170 });
171
172 print("\nSynchronizing OpenStack networks");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900173 print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
174 osClient.networking().network().list().forEach(osNet -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900175 if (osNetAdminService.network(osNet.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900176 osNetAdminService.updateNetwork(osNet);
177 } else {
178 osNetAdminService.createNetwork(osNet);
179 }
180 printNetwork(osNet);
181 });
182
Hyunsun Moonae51e732017-04-25 17:46:21 +0900183 print("\nSynchronizing OpenStack subnets");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900184 print(SUBNET_FORMAT, "ID", "Network", "CIDR");
185 osClient.networking().subnet().list().forEach(osSubnet -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900186 if (osNetAdminService.subnet(osSubnet.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900187 osNetAdminService.updateSubnet(osSubnet);
188 } else {
189 osNetAdminService.createSubnet(osSubnet);
190 }
Jian Li5a15fe62018-03-06 13:41:20 +0900191 printSubnet(osSubnet, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900192 });
193
Hyunsun Moonae51e732017-04-25 17:46:21 +0900194 print("\nSynchronizing OpenStack ports");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900195 print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
196 osClient.networking().port().list().forEach(osPort -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900197 if (osNetAdminService.port(osPort.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900198 osNetAdminService.updatePort(osPort);
199 } else {
200 osNetAdminService.createPort(osPort);
201 }
Jian Li5a15fe62018-03-06 13:41:20 +0900202 printPort(osPort, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900203 });
204
Hyunsun Moonae51e732017-04-25 17:46:21 +0900205 print("\nSynchronizing OpenStack routers");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900206 print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
207 osClient.networking().router().list().forEach(osRouter -> {
Jian Lida7c6cb2018-03-06 14:58:54 +0900208 if (osRouterAdminService.router(osRouter.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900209 osRouterAdminService.updateRouter(osRouter);
210 } else {
211 osRouterAdminService.createRouter(osRouter);
212 }
213
214 // FIXME do we need to manage router interfaces separately?
Jian Li5a15fe62018-03-06 13:41:20 +0900215 osNetAdminService.ports().stream()
Hyunsun Moonc7219222017-03-27 11:05:59 +0900216 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
217 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
Jian Lida7c6cb2018-03-06 14:58:54 +0900218 .forEach(osPort -> addRouterIface(osPort, osRouterAdminService));
Hyunsun Moonc7219222017-03-27 11:05:59 +0900219
Jian Li5a15fe62018-03-06 13:41:20 +0900220 printRouter(osRouter, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900221 });
222
Hyunsun Moonae51e732017-04-25 17:46:21 +0900223 print("\nSynchronizing OpenStack floating IPs");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900224 print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
225 osClient.networking().floatingip().list().forEach(osFloating -> {
Jian Lida7c6cb2018-03-06 14:58:54 +0900226 if (osRouterAdminService.floatingIp(osFloating.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900227 osRouterAdminService.updateFloatingIp(osFloating);
228 } else {
229 osRouterAdminService.createFloatingIp(osFloating);
230 }
231 printFloatingIp(osFloating);
232 });
233 }
234
235 // TODO fix the logic to add router interface to router
Jian Lida7c6cb2018-03-06 14:58:54 +0900236 private void addRouterIface(Port osPort, OpenstackRouterAdminService adminService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900237 osPort.getFixedIps().forEach(p -> {
238 JsonNode jsonTree = mapper().createObjectNode()
239 .put("id", osPort.getDeviceId())
240 .put("tenant_id", osPort.getTenantId())
241 .put("subnet_id", p.getSubnetId())
242 .put("port_id", osPort.getId());
243 try {
244 RouterInterface rIface = getContext(NeutronRouterInterface.class)
245 .readerFor(NeutronRouterInterface.class)
246 .readValue(jsonTree);
Jian Lida7c6cb2018-03-06 14:58:54 +0900247 if (adminService.routerInterface(rIface.getPortId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900248 adminService.updateRouterInterface(rIface);
249 } else {
250 adminService.addRouterInterface(rIface);
251 }
252 } catch (IOException ignore) {
253 }
254 });
255 }
256
257 private void printNetwork(Network osNet) {
258 final String strNet = String.format(NETWORK_FORMAT,
259 osNet.getId(),
260 osNet.getName(),
261 osNet.getProviderSegID(),
262 osNet.getSubnets());
263 print(strNet);
264 }
265
Jian Li5a15fe62018-03-06 13:41:20 +0900266 private void printSubnet(Subnet osSubnet, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900267 final String strSubnet = String.format(SUBNET_FORMAT,
268 osSubnet.getId(),
269 osNetService.network(osSubnet.getNetworkId()).getName(),
270 osSubnet.getCidr());
271 print(strSubnet);
272 }
273
Jian Li5a15fe62018-03-06 13:41:20 +0900274 private void printPort(Port osPort, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900275 List<String> fixedIps = osPort.getFixedIps().stream()
276 .map(IP::getIpAddress)
277 .collect(Collectors.toList());
278 final String strPort = String.format(PORT_FORMAT,
279 osPort.getId(),
280 osNetService.network(osPort.getNetworkId()).getName(),
281 osPort.getMacAddress(),
282 fixedIps.isEmpty() ? "" : fixedIps);
283 print(strPort);
284 }
285
Jian Li5a15fe62018-03-06 13:41:20 +0900286 private void printRouter(Router osRouter, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900287 List<String> externals = osNetService.ports().stream()
288 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
289 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
290 .flatMap(osPort -> osPort.getFixedIps().stream())
291 .map(IP::getIpAddress)
292 .collect(Collectors.toList());
293
294 List<String> internals = osNetService.ports().stream()
295 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
296 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
297 .flatMap(osPort -> osPort.getFixedIps().stream())
298 .map(IP::getIpAddress)
299 .collect(Collectors.toList());
300
301 final String strRouter = String.format(ROUTER_FORMAT,
302 osRouter.getId(),
303 osRouter.getName(),
304 externals.isEmpty() ? "" : externals,
305 internals.isEmpty() ? "" : internals);
306 print(strRouter);
307 }
308
309 private void printFloatingIp(NetFloatingIP floatingIp) {
310 final String strFloating = String.format(FLOATING_IP_FORMAT,
311 floatingIp.getId(),
daniel parkeeb8e042018-02-21 14:06:58 +0900312 floatingIp.getFloatingIpAddress(),
Hyunsun Moonc7219222017-03-27 11:05:59 +0900313 Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
314 "" : floatingIp.getFixedIpAddress());
315 print(strFloating);
316 }
317}