blob: 8263373ae5303050d36d0cea2091463b5fdb1f62 [file] [log] [blame]
Luca Pretedce16f82016-11-22 13:11:56 -08001/*
2 * Copyright 2016-present Open Networking Laboratory
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 */
15package org.onosproject.vpls.cli;
16
17import com.google.common.collect.Lists;
18import com.google.common.collect.SetMultimap;
19import com.google.common.collect.Sets;
20import org.apache.karaf.shell.commands.Argument;
21import org.apache.karaf.shell.commands.Command;
22import org.onosproject.cli.AbstractShellCommand;
23import org.onosproject.incubator.net.intf.Interface;
24import org.onosproject.incubator.net.intf.InterfaceService;
25import org.onosproject.net.EncapsulationType;
26import org.onosproject.vpls.config.VplsConfigService;
27
28import java.util.Collections;
29import java.util.List;
30import java.util.Map;
31import java.util.Optional;
32import java.util.Set;
33
34import static com.google.common.base.Strings.isNullOrEmpty;
35
36/**
37 * CLI to interact with the VPLS application.
38 */
39@Command(scope = "onos", name = "vpls",
40 description = "Manages the VPLS application")
41public class VplsCommand extends AbstractShellCommand {
42
43 // Color codes and style
44 private static final String BOLD = "\u001B[1m";
45 private static final String COLOR_ERROR = "\u001B[31m";
46 private static final String RESET = "\u001B[0m";
47
48 // Messages and string formatter
49 private static final String ENCAP_NOT_FOUND =
50 COLOR_ERROR + "Encapsulation type " + BOLD + "%s" + RESET +
51 COLOR_ERROR + " not found" + RESET;
52
53 private static final String IFACE_NOT_FOUND =
54 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
55 " not found" + RESET;
56
57 private static final String IFACE_ALREADY_ASSOCIATED =
58 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
59 " already associated to VPLS " + BOLD + "%s" + RESET +
60 COLOR_ERROR + "" + RESET;
61
62 private static final String SEPARATOR = "----------------";
63
64 private static final String VPLS_ALREADY_EXISTS =
65 COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
66 " already exists" + RESET;
67
68 private static final String VPLS_COMMAND_NOT_FOUND =
69 COLOR_ERROR + "VPLS command " + BOLD + "%s" + RESET + COLOR_ERROR +
70 " not found" + RESET;
71
72 private static final String VPLS_DISPLAY = "VPLS name: " + BOLD +
73 "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s";
74
75 private static final String VPLS_LIST_TITLE =
76 BOLD + "Configured VPLSs" + RESET;
77
78 private static final String VPLS_NOT_FOUND =
79 COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
80 " not found" + RESET;
81
82 private static final String IFACE_NOT_ASSOCIATED =
83 COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
84 " cannot be removed from VPLS " + BOLD + "%s" + RESET +
85 COLOR_ERROR + ". The interface is associated to another" +
86 "VPLS (" + BOLD + "%s" + RESET + COLOR_ERROR + ")" + RESET;
87
88 private static VplsConfigService vplsConfigService =
89 get(VplsConfigService.class);
90 private static InterfaceService interfaceService =
91 get(InterfaceService.class);
92
93 @Argument(index = 0, name = "command", description = "Command name (add|" +
94 "clean|create|delete|list|removeIface|set-encap|show)",
95 required = true, multiValued = false)
96 String command = null;
97
98 @Argument(index = 1, name = "vplsName", description = "The name of the VPLS",
99 required = false, multiValued = false)
100 String vplsName = null;
101
102 @Argument(index = 2, name = "optArg", description = "The interface name for" +
103 "all commands; the encapsulation type for set-encap",
104 required = false, multiValued = false)
105 String optArg = null;
106
107 @Override
108 protected void execute() {
109 VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
110 if (enumCommand != null) {
111 switch (enumCommand) {
112 case ADD_IFACE:
113 addIface(vplsName, optArg);
114 break;
115 case CLEAN:
116 clean();
117 break;
118 case CREATE:
119 create(vplsName);
120 break;
121 case DELETE:
122 delete(vplsName);
123 break;
124 case LIST:
125 list();
126 break;
127 case REMOVE_IFACE:
128 removeIface(vplsName, optArg);
129 break;
130 case SET_ENCAP:
131 setEncap(vplsName, optArg);
132 break;
133 case SHOW:
134 show(vplsName);
135 break;
136 default:
137 print(VPLS_COMMAND_NOT_FOUND, command);
138 }
139 }
140 }
141
142 /**
143 * Adds an inteterface to a VPLS.
144 *
145 * @param vplsName the name of the VLPS
146 * @param ifaceName the name of the interface to add
147 */
148 private void addIface(String vplsName, String ifaceName) {
149 // Check if the VPLS exists
150 if (!vplsExists(vplsName)) {
151 print(VPLS_NOT_FOUND, vplsName);
152 return;
153 }
154 // Check if the interface exists
155 if (!ifaceExists(ifaceName)) {
156 print(IFACE_NOT_FOUND, ifaceName);
157 return;
158 }
159 // Check if the interface is already associated to a VPLS
160 if (isIfaceAssociated(ifaceName)) {
161 print(IFACE_ALREADY_ASSOCIATED,
162 ifaceName, vplsNameFromIfaceName(ifaceName));
163 return;
164 }
165
166 vplsConfigService.addIface(vplsName, ifaceName);
167 }
168
169 /**
170 * Cleans the VPLS configuration.
171 */
172 private void clean() {
173 vplsConfigService.cleanVplsConfig();
174 }
175
176 /**
177 * Creates a new VPLS.
178 *
179 * @param vplsName the name of the VLPS
180 */
181 private void create(String vplsName) {
182 if (vplsExists(vplsName)) {
183 print(VPLS_ALREADY_EXISTS, vplsName);
184 return;
185 }
186 vplsConfigService.addVpls(vplsName, Sets.newHashSet(), null);
187 }
188
189 /**
190 * Deletes a VPLS.
191 *
192 * @param vplsName the name of the VLPS
193 */
194 private void delete(String vplsName) {
195 if (!vplsExists(vplsName)) {
196 print(VPLS_NOT_FOUND, vplsName);
197 return;
198 }
199 vplsConfigService.removeVpls(vplsName);
200 }
201
202 /**
203 * Lists the configured VPLSs.
204 */
205 private void list() {
206 List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
207 Collections.sort(vplsNames);
208
209 print(VPLS_LIST_TITLE);
210 print(SEPARATOR);
211 vplsNames.forEach(vpls -> {
212 print(vpls);
213 });
214 }
215
216 /**
217 * Removes an interface from a VPLS.
218 *
219 * @param vplsName the name of the VLPS
220 * @param ifaceName the name of the interface to remove
221 */
222 private void removeIface(String vplsName, String ifaceName) {
223 if (!vplsExists(vplsName)) {
224 print(VPLS_NOT_FOUND, vplsName);
225 return;
226 }
227 if (!ifaceExists(ifaceName)) {
228 print(IFACE_NOT_FOUND, ifaceName);
229 return;
230 }
231 String vplsNameFromIfaceName = vplsNameFromIfaceName(ifaceName);
232 if (!vplsNameFromIfaceName.equals(vplsName)) {
233 print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName, vplsNameFromIfaceName);
234 return;
235 }
236 vplsConfigService.removeIface(ifaceName);
237 }
238
239 /**
240 * Sets the encapsulation type for a VPLS.
241 *
242 * @param vplsName the name of the VPLS
243 * @param encap the encapsulation type
244 */
245 private void setEncap(String vplsName, String encap) {
246 if (!vplsExists(vplsName)) {
247 print(VPLS_NOT_FOUND, vplsName);
248 return;
249 }
250 EncapsulationType encapType = EncapsulationType.enumFromString(encap);
251 if (encapType.equals(EncapsulationType.NONE) &&
252 !encapType.toString().equals(encap)) {
253 print(ENCAP_NOT_FOUND, encap);
254 return;
255 }
256 vplsConfigService.setEncap(vplsName, encap);
257 }
258
259 /**
260 * Shows the details of one or more VPLSs.
261 *
262 * @param vplsName the name of the VPLS
263 */
264 private void show(String vplsName) {
265 List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
266 Collections.sort(vplsNames);
267
268 Map<String, EncapsulationType> encapByVplsName =
269 vplsConfigService.encapByVplsName();
270
271 print(VPLS_LIST_TITLE);
272 print(SEPARATOR);
273 if (!isNullOrEmpty(vplsName)) {
274 // A VPLS name is provided. Check first if the VPLS exists
275 if (vplsExists(vplsName)) {
276 print(VPLS_DISPLAY,
277 vplsName,
278 ifacesFromVplsName(vplsName).toString(),
279 encapByVplsName.get(vplsName).toString());
280 } else {
281 print(VPLS_NOT_FOUND, vplsName);
282 }
283 } else {
284 // No VPLS names are provided. Display all VPLSs configured
285 vplsNames.forEach(v -> {
286 print(VPLS_DISPLAY,
287 v,
288 ifacesFromVplsName(v).toString(),
289 encapByVplsName.get(v).toString());
290 print(SEPARATOR);
291 });
292 }
293 }
294
295 /**
296 * States if a VPLS exists or not.
297 *
298 * @param vplsName the name of the VPLS
299 * @return true if the VPLS exists; false otherwise
300 */
301 private static boolean vplsExists(String vplsName) {
302 return vplsConfigService.vplsNames().contains(vplsName);
303 }
304
305 /**
306 * States if an interface is defined or not in the system.
307 *
308 * @param ifaceName the name of the interface
309 * @return true if the interface is defined; false otherwise
310 */
311 private static boolean ifaceExists(String ifaceName) {
312 return vplsConfigService.allIfaces()
313 .stream()
314 .anyMatch(iface -> iface.name().equals(ifaceName));
315 }
316
317 /**
318 * States if an interface is already associated to a VPLS.
319 *
320 * @param ifaceName the name of the interface
321 * @return true if the interface is already associated to a VPLS; false
322 * otherwise
323 */
324 private static boolean isIfaceAssociated(String ifaceName) {
325 return vplsConfigService.ifaces()
326 .stream()
327 .anyMatch(iface -> iface.name().equals(ifaceName));
328 }
329
330 /**
331 * Returns the name of a VPLS, given the name of an interface associated to
332 * it.
333 *
334 * @param ifaceName the name of the interface
335 * @return the name of the VPLS that has the interface configured; null if
336 * the interface does not exist or is not associated to any VPLS
337 */
338 private static String vplsNameFromIfaceName(String ifaceName) {
339 String vplsName = null;
340
341 Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
342 .entries()
343 .stream()
344 .filter((entry -> entry.getValue().name().equals(ifaceName)))
345 .map(Map.Entry::getKey)
346 .findFirst();
347
348 if (optVplsName.isPresent()) {
349 vplsName = optVplsName.get();
350 }
351
352 return vplsName;
353 }
354
355 /**
356 * Returns a list of interfaces associated to a VPLS, given a VPLS name.
357 *
358 * @param vplsName the name of the VPLS
359 * @return the set of interfaces associated to the given VPLS; null if the
360 * VPLS is not found
361 */
362 private static Set<String> ifacesFromVplsName(String vplsName) {
363 if (!vplsExists(vplsName)) {
364 return null;
365 }
366 SetMultimap<String, Interface> ifacesByVplsName =
367 vplsConfigService.ifacesByVplsName();
368 Set<String> ifaceNames = Sets.newHashSet();
369
370 ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));
371
372 return ifaceNames;
373 }
374}