blob: e89141b95c5a1a166e453f019481cbd89c1ed86b [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;
24import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
25import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
26import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moonae51e732017-04-25 17:46:21 +090027import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupAdminService;
28import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
Hyunsun Moonc7219222017-03-27 11:05:59 +090029import org.openstack4j.api.OSClient;
30import org.openstack4j.api.exceptions.AuthenticationException;
Jian Li02a94982018-02-03 02:49:07 +090031import org.openstack4j.model.identity.v2.Access;
Hyunsun Moonc7219222017-03-27 11:05:59 +090032import org.openstack4j.model.network.IP;
33import org.openstack4j.model.network.NetFloatingIP;
34import org.openstack4j.model.network.Network;
35import org.openstack4j.model.network.Port;
36import org.openstack4j.model.network.Router;
37import org.openstack4j.model.network.RouterInterface;
38import org.openstack4j.model.network.Subnet;
39import org.openstack4j.openstack.OSFactory;
40import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
41
42import java.io.IOException;
43import java.util.List;
44import java.util.Objects;
45import java.util.stream.Collectors;
46
47import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
48
49/**
50 * Synchronizes OpenStack network states.
51 */
52@Command(scope = "onos", name = "openstack-sync-states",
53 description = "Synchronizes all OpenStack network states")
54public class OpenstackSyncStateCommand extends AbstractShellCommand {
55
56 @Argument(index = 0, name = "endpoint", description = "OpenStack service endpoint",
57 required = true, multiValued = false)
58 private String endpoint = null;
59
60 @Argument(index = 1, name = "tenant", description = "OpenStack admin tenant name",
61 required = true, multiValued = false)
62 private String tenant = null;
63
64 @Argument(index = 2, name = "user", description = "OpenStack admin user name",
65 required = true, multiValued = false)
66 private String user = null;
67
68 @Argument(index = 3, name = "password", description = "OpenStack admin user password",
69 required = true, multiValued = false)
70 private String password = null;
71
Hyunsun Moonae51e732017-04-25 17:46:21 +090072 private static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
Hyunsun Moonc7219222017-03-27 11:05:59 +090073 private static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
74 private static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
75 private static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
76 private static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
77 private static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
78
79 private static final String DEVICE_OWNER_GW = "network:router_gateway";
80 private static final String DEVICE_OWNER_IFACE = "network:router_interface";
81
82 @Override
83 protected void execute() {
Hyunsun Moonae51e732017-04-25 17:46:21 +090084 OpenstackSecurityGroupAdminService osSgAdminService = get(OpenstackSecurityGroupAdminService.class);
85 OpenstackSecurityGroupService osSgService = get(OpenstackSecurityGroupService.class);
Hyunsun Moonc7219222017-03-27 11:05:59 +090086 OpenstackNetworkAdminService osNetAdminService = get(OpenstackNetworkAdminService.class);
87 OpenstackNetworkService osNetService = get(OpenstackNetworkService.class);
88 OpenstackRouterAdminService osRouterAdminService = get(OpenstackRouterAdminService.class);
89 OpenstackRouterService osRouterService = get(OpenstackRouterService.class);
90
91 Access osAccess;
92 try {
Jian Li02a94982018-02-03 02:49:07 +090093 osAccess = OSFactory.builderV2()
Hyunsun Moonc7219222017-03-27 11:05:59 +090094 .endpoint(this.endpoint)
95 .tenantName(this.tenant)
96 .credentials(this.user, this.password)
97 .authenticate()
98 .getAccess();
99 } catch (AuthenticationException e) {
100 print("Authentication failed");
101 return;
102 } catch (Exception e) {
103 print("Failed to access OpenStack service");
104 return;
105 }
106
107 OSClient osClient = OSFactory.clientFromAccess(osAccess);
108
Hyunsun Moonae51e732017-04-25 17:46:21 +0900109 print("Synchronizing OpenStack security groups");
110 print(SECURITY_GROUP_FORMAT, "ID", "Name");
111 osClient.networking().securitygroup().list().forEach(osSg -> {
112 if (osSgService.securityGroup(osSg.getId()) != null) {
113 osSgAdminService.updateSecurityGroup(osSg);
114 } else {
115 osSgAdminService.createSecurityGroup(osSg);
116 }
117 print(SECURITY_GROUP_FORMAT, osSg.getId(), osSg.getName());
118 });
119
120 print("\nSynchronizing OpenStack networks");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900121 print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
122 osClient.networking().network().list().forEach(osNet -> {
123 if (osNetService.network(osNet.getId()) != null) {
124 osNetAdminService.updateNetwork(osNet);
125 } else {
126 osNetAdminService.createNetwork(osNet);
127 }
128 printNetwork(osNet);
129 });
130
Hyunsun Moonae51e732017-04-25 17:46:21 +0900131 print("\nSynchronizing OpenStack subnets");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900132 print(SUBNET_FORMAT, "ID", "Network", "CIDR");
133 osClient.networking().subnet().list().forEach(osSubnet -> {
134 if (osNetService.subnet(osSubnet.getId()) != null) {
135 osNetAdminService.updateSubnet(osSubnet);
136 } else {
137 osNetAdminService.createSubnet(osSubnet);
138 }
139 printSubnet(osSubnet, osNetService);
140 });
141
Hyunsun Moonae51e732017-04-25 17:46:21 +0900142 print("\nSynchronizing OpenStack ports");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900143 print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
144 osClient.networking().port().list().forEach(osPort -> {
145 if (osNetService.port(osPort.getId()) != null) {
146 osNetAdminService.updatePort(osPort);
147 } else {
148 osNetAdminService.createPort(osPort);
149 }
150 printPort(osPort, osNetService);
151 });
152
Hyunsun Moonae51e732017-04-25 17:46:21 +0900153 print("\nSynchronizing OpenStack routers");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900154 print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
155 osClient.networking().router().list().forEach(osRouter -> {
156 if (osRouterService.router(osRouter.getId()) != null) {
157 osRouterAdminService.updateRouter(osRouter);
158 } else {
159 osRouterAdminService.createRouter(osRouter);
160 }
161
162 // FIXME do we need to manage router interfaces separately?
163 osNetService.ports().stream()
164 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
165 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
166 .forEach(osPort -> addRouterIface(osPort, osRouterService,
167 osRouterAdminService));
168
169 printRouter(osRouter, osNetService);
170 });
171
Hyunsun Moonae51e732017-04-25 17:46:21 +0900172 print("\nSynchronizing OpenStack floating IPs");
Hyunsun Moonc7219222017-03-27 11:05:59 +0900173 print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
174 osClient.networking().floatingip().list().forEach(osFloating -> {
175 if (osRouterService.floatingIp(osFloating.getId()) != null) {
176 osRouterAdminService.updateFloatingIp(osFloating);
177 } else {
178 osRouterAdminService.createFloatingIp(osFloating);
179 }
180 printFloatingIp(osFloating);
181 });
182 }
183
184 // TODO fix the logic to add router interface to router
185 private void addRouterIface(Port osPort, OpenstackRouterService service,
186 OpenstackRouterAdminService adminService) {
187 osPort.getFixedIps().forEach(p -> {
188 JsonNode jsonTree = mapper().createObjectNode()
189 .put("id", osPort.getDeviceId())
190 .put("tenant_id", osPort.getTenantId())
191 .put("subnet_id", p.getSubnetId())
192 .put("port_id", osPort.getId());
193 try {
194 RouterInterface rIface = getContext(NeutronRouterInterface.class)
195 .readerFor(NeutronRouterInterface.class)
196 .readValue(jsonTree);
197 if (service.routerInterface(rIface.getPortId()) != null) {
198 adminService.updateRouterInterface(rIface);
199 } else {
200 adminService.addRouterInterface(rIface);
201 }
202 } catch (IOException ignore) {
203 }
204 });
205 }
206
207 private void printNetwork(Network osNet) {
208 final String strNet = String.format(NETWORK_FORMAT,
209 osNet.getId(),
210 osNet.getName(),
211 osNet.getProviderSegID(),
212 osNet.getSubnets());
213 print(strNet);
214 }
215
216 private void printSubnet(Subnet osSubnet, OpenstackNetworkService osNetService) {
217 final String strSubnet = String.format(SUBNET_FORMAT,
218 osSubnet.getId(),
219 osNetService.network(osSubnet.getNetworkId()).getName(),
220 osSubnet.getCidr());
221 print(strSubnet);
222 }
223
224 private void printPort(Port osPort, OpenstackNetworkService osNetService) {
225 List<String> fixedIps = osPort.getFixedIps().stream()
226 .map(IP::getIpAddress)
227 .collect(Collectors.toList());
228 final String strPort = String.format(PORT_FORMAT,
229 osPort.getId(),
230 osNetService.network(osPort.getNetworkId()).getName(),
231 osPort.getMacAddress(),
232 fixedIps.isEmpty() ? "" : fixedIps);
233 print(strPort);
234 }
235
236 private void printRouter(Router osRouter, OpenstackNetworkService osNetService) {
237 List<String> externals = osNetService.ports().stream()
238 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
239 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
240 .flatMap(osPort -> osPort.getFixedIps().stream())
241 .map(IP::getIpAddress)
242 .collect(Collectors.toList());
243
244 List<String> internals = osNetService.ports().stream()
245 .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
246 Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
247 .flatMap(osPort -> osPort.getFixedIps().stream())
248 .map(IP::getIpAddress)
249 .collect(Collectors.toList());
250
251 final String strRouter = String.format(ROUTER_FORMAT,
252 osRouter.getId(),
253 osRouter.getName(),
254 externals.isEmpty() ? "" : externals,
255 internals.isEmpty() ? "" : internals);
256 print(strRouter);
257 }
258
259 private void printFloatingIp(NetFloatingIP floatingIp) {
260 final String strFloating = String.format(FLOATING_IP_FORMAT,
261 floatingIp.getId(),
262 floatingIp.getFixedIpAddress(),
263 Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
264 "" : floatingIp.getFixedIpAddress());
265 print(strFloating);
266 }
267}