blob: c311889c7cb77f78a1e6e7e8e98475aaf7b59c2c [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;
sanghoa0ef13b2018-03-09 13:56:39 +090028import org.openstack4j.model.common.Identifier;
Hyunsun Moonc7219222017-03-27 11:05:59 +090029import org.openstack4j.model.network.IP;
30import org.openstack4j.model.network.NetFloatingIP;
31import org.openstack4j.model.network.Network;
32import org.openstack4j.model.network.Port;
33import org.openstack4j.model.network.Router;
34import org.openstack4j.model.network.RouterInterface;
35import org.openstack4j.model.network.Subnet;
36import org.openstack4j.openstack.OSFactory;
37import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
38
39import java.io.IOException;
40import java.util.List;
41import java.util.Objects;
42import java.util.stream.Collectors;
43
44import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
45
46/**
47 * Synchronizes OpenStack network states.
48 */
49@Command(scope = "onos", name = "openstack-sync-states",
50 description = "Synchronizes all OpenStack network states")
51public class OpenstackSyncStateCommand extends AbstractShellCommand {
52
53 @Argument(index = 0, name = "endpoint", description = "OpenStack service endpoint",
54 required = true, multiValued = false)
55 private String endpoint = null;
56
57 @Argument(index = 1, name = "tenant", description = "OpenStack admin tenant name",
58 required = true, multiValued = false)
59 private String tenant = null;
60
61 @Argument(index = 2, name = "user", description = "OpenStack admin user name",
62 required = true, multiValued = false)
63 private String user = null;
64
65 @Argument(index = 3, name = "password", description = "OpenStack admin user password",
66 required = true, multiValued = false)
67 private String password = null;
68
sanghoa0ef13b2018-03-09 13:56:39 +090069 private static final String DOMAIN_DEFUALT = "default";
70
Hyunsun Moonae51e732017-04-25 17:46:21 +090071 private static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
Hyunsun Moonc7219222017-03-27 11:05:59 +090072 private static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
73 private static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
74 private static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
75 private static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
76 private static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
77
78 private static final String DEVICE_OWNER_GW = "network:router_gateway";
79 private static final String DEVICE_OWNER_IFACE = "network:router_interface";
80
Jian Li8769d5b2018-03-09 21:55:40 +090081 private static final String KEYSTONE_V2 = "v2.0";
82 private static final String KEYSTONE_V3 = "v3";
83
Hyunsun Moonc7219222017-03-27 11:05:59 +090084 @Override
85 protected void execute() {
Hyunsun Moonae51e732017-04-25 17:46:21 +090086 OpenstackSecurityGroupAdminService osSgAdminService = get(OpenstackSecurityGroupAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090087 OpenstackNetworkAdminService osNetAdminService = get(OpenstackNetworkAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090088 OpenstackRouterAdminService osRouterAdminService = get(OpenstackRouterAdminService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090089
Jian Li8769d5b2018-03-09 21:55:40 +090090 OSClient osClient;
sanghoa0ef13b2018-03-09 13:56:39 +090091
Jian Li8769d5b2018-03-09 21:55:40 +090092 try {
93 if (endpoint != null) {
94 if (endpoint.contains(KEYSTONE_V2)) {
95 osClient = OSFactory.builderV2()
96 .endpoint(this.endpoint)
97 .tenantName(this.tenant)
98 .credentials(this.user, this.password)
99 .authenticate();
100 } else if (endpoint.contains(KEYSTONE_V3)) {
101
102 Identifier project = Identifier.byName(this.tenant);
103 Identifier domain = Identifier.byName(DOMAIN_DEFUALT);
104
105 osClient = OSFactory.builderV3()
106 .endpoint(this.endpoint)
107 .credentials(this.user, this.password, domain)
108 .scopeToProject(project, domain)
109 .authenticate();
110 } else {
111 print("Unrecognized keystone version type");
112 return;
113 }
114 } else {
115 print("Need to specify a valid endpoint");
116 return;
117 }
Hyunsun Moonc7219222017-03-27 11:05:59 +0900118 } catch (AuthenticationException e) {
119 print("Authentication failed");
120 return;
121 } catch (Exception e) {
122 print("Failed to access OpenStack service");
123 return;
124 }
125
Hyunsun Moonae51e732017-04-25 17:46:21 +0900126 print("Synchronizing OpenStack security groups");
127 print(SECURITY_GROUP_FORMAT, "ID", "Name");
128 osClient.networking().securitygroup().list().forEach(osSg -> {
Jian Li21536592018-03-06 15:10:55 +0900129 if (osSgAdminService.securityGroup(osSg.getId()) != null) {
Hyunsun Moonae51e732017-04-25 17:46:21 +0900130 osSgAdminService.updateSecurityGroup(osSg);
131 } else {
132 osSgAdminService.createSecurityGroup(osSg);
133 }
134 print(SECURITY_GROUP_FORMAT, osSg.getId(), osSg.getName());
135 });
136
137 print("\nSynchronizing OpenStack networks");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900138 print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
139 osClient.networking().network().list().forEach(osNet -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900140 if (osNetAdminService.network(osNet.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900141 osNetAdminService.updateNetwork(osNet);
142 } else {
143 osNetAdminService.createNetwork(osNet);
144 }
145 printNetwork(osNet);
146 });
147
Hyunsun Moonae51e732017-04-25 17:46:21 +0900148 print("\nSynchronizing OpenStack subnets");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900149 print(SUBNET_FORMAT, "ID", "Network", "CIDR");
150 osClient.networking().subnet().list().forEach(osSubnet -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900151 if (osNetAdminService.subnet(osSubnet.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900152 osNetAdminService.updateSubnet(osSubnet);
153 } else {
154 osNetAdminService.createSubnet(osSubnet);
155 }
Jian Li5a15fe62018-03-06 13:41:20 +0900156 printSubnet(osSubnet, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900157 });
158
Hyunsun Moonae51e732017-04-25 17:46:21 +0900159 print("\nSynchronizing OpenStack ports");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900160 print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
161 osClient.networking().port().list().forEach(osPort -> {
Jian Li5a15fe62018-03-06 13:41:20 +0900162 if (osNetAdminService.port(osPort.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900163 osNetAdminService.updatePort(osPort);
164 } else {
165 osNetAdminService.createPort(osPort);
166 }
Jian Li5a15fe62018-03-06 13:41:20 +0900167 printPort(osPort, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900168 });
169
Hyunsun Moonae51e732017-04-25 17:46:21 +0900170 print("\nSynchronizing OpenStack routers");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900171 print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
172 osClient.networking().router().list().forEach(osRouter -> {
Jian Lida7c6cb2018-03-06 14:58:54 +0900173 if (osRouterAdminService.router(osRouter.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900174 osRouterAdminService.updateRouter(osRouter);
175 } else {
176 osRouterAdminService.createRouter(osRouter);
177 }
178
179 // FIXME do we need to manage router interfaces separately?
Jian Li5a15fe62018-03-06 13:41:20 +0900180 osNetAdminService.ports().stream()
Hyunsun Moonc7219222017-03-27 11:05:59 +0900181 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
182 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
Jian Lida7c6cb2018-03-06 14:58:54 +0900183 .forEach(osPort -> addRouterIface(osPort, osRouterAdminService));
Hyunsun Moonc7219222017-03-27 11:05:59 +0900184
Jian Li5a15fe62018-03-06 13:41:20 +0900185 printRouter(osRouter, osNetAdminService);
Hyunsun Moonc7219222017-03-27 11:05:59 +0900186 });
187
Hyunsun Moonae51e732017-04-25 17:46:21 +0900188 print("\nSynchronizing OpenStack floating IPs");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900189 print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
190 osClient.networking().floatingip().list().forEach(osFloating -> {
Jian Lida7c6cb2018-03-06 14:58:54 +0900191 if (osRouterAdminService.floatingIp(osFloating.getId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900192 osRouterAdminService.updateFloatingIp(osFloating);
193 } else {
194 osRouterAdminService.createFloatingIp(osFloating);
195 }
196 printFloatingIp(osFloating);
197 });
198 }
199
200 // TODO fix the logic to add router interface to router
Jian Lida7c6cb2018-03-06 14:58:54 +0900201 private void addRouterIface(Port osPort, OpenstackRouterAdminService adminService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900202 osPort.getFixedIps().forEach(p -> {
203 JsonNode jsonTree = mapper().createObjectNode()
204 .put("id", osPort.getDeviceId())
205 .put("tenant_id", osPort.getTenantId())
206 .put("subnet_id", p.getSubnetId())
207 .put("port_id", osPort.getId());
208 try {
209 RouterInterface rIface = getContext(NeutronRouterInterface.class)
210 .readerFor(NeutronRouterInterface.class)
211 .readValue(jsonTree);
Jian Lida7c6cb2018-03-06 14:58:54 +0900212 if (adminService.routerInterface(rIface.getPortId()) != null) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900213 adminService.updateRouterInterface(rIface);
214 } else {
215 adminService.addRouterInterface(rIface);
216 }
217 } catch (IOException ignore) {
218 }
219 });
220 }
221
222 private void printNetwork(Network osNet) {
223 final String strNet = String.format(NETWORK_FORMAT,
224 osNet.getId(),
225 osNet.getName(),
226 osNet.getProviderSegID(),
227 osNet.getSubnets());
228 print(strNet);
229 }
230
Jian Li5a15fe62018-03-06 13:41:20 +0900231 private void printSubnet(Subnet osSubnet, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900232 final String strSubnet = String.format(SUBNET_FORMAT,
233 osSubnet.getId(),
234 osNetService.network(osSubnet.getNetworkId()).getName(),
235 osSubnet.getCidr());
236 print(strSubnet);
237 }
238
Jian Li5a15fe62018-03-06 13:41:20 +0900239 private void printPort(Port osPort, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900240 List<String> fixedIps = osPort.getFixedIps().stream()
241 .map(IP::getIpAddress)
242 .collect(Collectors.toList());
243 final String strPort = String.format(PORT_FORMAT,
244 osPort.getId(),
245 osNetService.network(osPort.getNetworkId()).getName(),
246 osPort.getMacAddress(),
247 fixedIps.isEmpty() ? "" : fixedIps);
248 print(strPort);
249 }
250
Jian Li5a15fe62018-03-06 13:41:20 +0900251 private void printRouter(Router osRouter, OpenstackNetworkAdminService osNetService) {
Hyunsun Moonc7219222017-03-27 11:05:59 +0900252 List<String> externals = osNetService.ports().stream()
253 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
254 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
255 .flatMap(osPort -> osPort.getFixedIps().stream())
256 .map(IP::getIpAddress)
257 .collect(Collectors.toList());
258
259 List<String> internals = osNetService.ports().stream()
260 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
261 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
262 .flatMap(osPort -> osPort.getFixedIps().stream())
263 .map(IP::getIpAddress)
264 .collect(Collectors.toList());
265
266 final String strRouter = String.format(ROUTER_FORMAT,
267 osRouter.getId(),
268 osRouter.getName(),
269 externals.isEmpty() ? "" : externals,
270 internals.isEmpty() ? "" : internals);
271 print(strRouter);
272 }
273
274 private void printFloatingIp(NetFloatingIP floatingIp) {
275 final String strFloating = String.format(FLOATING_IP_FORMAT,
276 floatingIp.getId(),
daniel parkeeb8e042018-02-21 14:06:58 +0900277 floatingIp.getFloatingIpAddress(),
Hyunsun Moonc7219222017-03-27 11:05:59 +0900278 Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
279 "" : floatingIp.getFixedIpAddress());
280 print(strFloating);
281 }
282}