blob: b52415926689fb3c4a6268137f2f27e87836f382 [file] [log] [blame]
Jian Lic87b23b2017-04-24 15:28:10 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jian Lic87b23b2017-04-24 15:28:10 +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.mapping.cli;
17
Jian Lida1dfa62017-04-25 01:56:19 +090018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.fasterxml.jackson.databind.node.ObjectNode;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070022import org.apache.karaf.shell.api.action.Argument;
23import org.apache.karaf.shell.api.action.Command;
Ray Milkey01ad6a42018-10-09 14:08:21 -070024import org.apache.karaf.shell.api.action.Completion;
Ray Milkey86ad7bb2018-09-27 12:32:28 -070025import org.apache.karaf.shell.api.action.Option;
Ray Milkey7a2dee52018-09-28 10:58:28 -070026import org.apache.karaf.shell.api.action.lifecycle.Service;
Jian Lic87b23b2017-04-24 15:28:10 +090027import org.onosproject.cli.AbstractShellCommand;
Ray Milkey01ad6a42018-10-09 14:08:21 -070028import org.onosproject.cli.net.DeviceIdCompleter;
Jian Lida1dfa62017-04-25 01:56:19 +090029import org.onosproject.mapping.MappingEntry;
Jian Lic87b23b2017-04-24 15:28:10 +090030import org.onosproject.mapping.MappingKey;
31import org.onosproject.mapping.MappingTreatment;
32import org.onosproject.mapping.MappingValue;
33import org.onosproject.mapping.MappingService;
34import org.onosproject.mapping.MappingStore;
35import org.onosproject.net.Device;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.device.DeviceService;
38
39import java.util.List;
40
41import static com.google.common.collect.Lists.newArrayList;
42
43/**
44 * A command for querying mapping information.
45 */
Ray Milkey7a2dee52018-09-28 10:58:28 -070046@Service
Jian Lic87b23b2017-04-24 15:28:10 +090047@Command(scope = "onos", name = "mappings",
48 description = "Lists mappings")
49public class MappingsListCommand extends AbstractShellCommand {
50
Jian Li6e960ef2017-05-03 16:38:19 +090051 private static final String DB = "database";
52 private static final String CACHE = "cache";
Jian Lic87b23b2017-04-24 15:28:10 +090053
54 private static final String SUMMARY_FORMAT = "deviceId=%s, mappingCount=%d";
55 private static final String MAPPING_ID_FORMAT = " id=%s";
Jian Lida1dfa62017-04-25 01:56:19 +090056 private static final String MAPPING_STATE_FORMAT = " state=%s";
Jian Lic87b23b2017-04-24 15:28:10 +090057 private static final String MAPPING_KEY_FORMAT = " key=%s";
58 private static final String MAPPING_VALUE_FORMAT = " value=";
59 private static final String MAPPING_ACTION_FORMAT = " action=%s";
60 private static final String MAPPING_TREATMENTS_FORMAT = " treatments=";
61 private static final String MAPPING_TREATMENT_LONG_FORMAT =
62 " address=%s, instructions=%s";
63 private static final String MAPPING_TREATMENT_SHORT_FORMAT = " %s";
Jian Lida1dfa62017-04-25 01:56:19 +090064 private static final String JSON_FORMAT = "%s";
Jian Lic87b23b2017-04-24 15:28:10 +090065
Jian Li6e960ef2017-05-03 16:38:19 +090066 private static final String TYPE_NOT_NULL = "Mapping store type should not be null";
67 private static final String TYPE_ILLEGAL = "Mapping store type is not correct";
68
Jian Lic87b23b2017-04-24 15:28:10 +090069 @Argument(index = 0, name = "type",
70 description = "Shows mappings with specified type",
71 required = true, multiValued = false)
Ray Milkey01ad6a42018-10-09 14:08:21 -070072 @Completion(MappingStoreTypeCompleter.class)
Jian Lic87b23b2017-04-24 15:28:10 +090073 private String type = null;
74
75 @Argument(index = 1, name = "deviceId", description = "Device identity",
76 required = false, multiValued = false)
Ray Milkey01ad6a42018-10-09 14:08:21 -070077 @Completion(DeviceIdCompleter.class)
Jian Lic87b23b2017-04-24 15:28:10 +090078 private String deviceId = null;
79
80 @Option(name = "-s", aliases = "--short",
81 description = "Print more succinct output for each mapping",
82 required = false, multiValued = false)
83 private boolean shortOutput = false;
84
85 private MappingService mappingService =
86 AbstractShellCommand.get(MappingService.class);
Jian Lida1dfa62017-04-25 01:56:19 +090087 private List<MappingEntry> mappings;
Jian Lic87b23b2017-04-24 15:28:10 +090088
89 @Override
Ray Milkey86ad7bb2018-09-27 12:32:28 -070090 protected void doExecute() {
Jian Lic87b23b2017-04-24 15:28:10 +090091
Jian Li6e960ef2017-05-03 16:38:19 +090092 MappingStore.Type typeEnum = getTypeEnum(type);
Jian Lic87b23b2017-04-24 15:28:10 +090093
94 DeviceService deviceService = get(DeviceService.class);
95 Iterable<Device> devices = deviceService.getDevices();
96
Jian Lida1dfa62017-04-25 01:56:19 +090097 if (outputJson()) {
98 print(JSON_FORMAT, json(typeEnum, devices));
Jian Lic87b23b2017-04-24 15:28:10 +090099 } else {
Jian Lida1dfa62017-04-25 01:56:19 +0900100 if (deviceId != null) {
101 mappings = newArrayList(mappingService.getMappingEntries(typeEnum,
102 DeviceId.deviceId(deviceId)));
103 printMappings(DeviceId.deviceId(deviceId), mappings);
Jian Lic87b23b2017-04-24 15:28:10 +0900104
Jian Lida1dfa62017-04-25 01:56:19 +0900105 } else {
106
107 for (Device d : devices) {
108 mappings = newArrayList(mappingService.getMappingEntries(typeEnum, d.id()));
109 printMappings(d.id(), mappings);
110 }
Jian Lic87b23b2017-04-24 15:28:10 +0900111 }
112 }
113 }
114
115 /**
116 * Prints out mapping information.
117 *
118 * @param deviceId device identifier
119 * @param mappings a collection of mapping
120 */
Jian Lida1dfa62017-04-25 01:56:19 +0900121 private void printMappings(DeviceId deviceId, List<MappingEntry> mappings) {
Jian Lic87b23b2017-04-24 15:28:10 +0900122
123 print(SUMMARY_FORMAT, deviceId, mappings.size());
124
Jian Lida1dfa62017-04-25 01:56:19 +0900125 for (MappingEntry m : mappings) {
Jian Lic87b23b2017-04-24 15:28:10 +0900126 print(MAPPING_ID_FORMAT, Long.toHexString(m.id().value()));
Jian Lida1dfa62017-04-25 01:56:19 +0900127 print(MAPPING_STATE_FORMAT, m.state().name());
Jian Lic87b23b2017-04-24 15:28:10 +0900128 print(MAPPING_KEY_FORMAT, printMappingKey(m.key()));
129 printMappingValue(m.value());
130 }
131 }
132
133 /**
134 * Prints out mapping key.
135 *
136 * @param key mapping key
137 * @return string format of mapping key
138 */
139 private String printMappingKey(MappingKey key) {
140 StringBuilder builder = new StringBuilder();
141
142 if (key.address() != null) {
143 builder.append(key.address().toString());
144 }
145
146 return builder.toString();
147 }
148
149 /**
150 * Prints out mapping value.
151 *
152 * @param value mapping value
153 * @return string format of mapping value
154 */
155 private void printMappingValue(MappingValue value) {
156
157 print(MAPPING_VALUE_FORMAT);
158
159 if (value.action() != null) {
160 print(MAPPING_ACTION_FORMAT, value.action().toString());
161 }
162
163 if (!value.treatments().isEmpty()) {
164 print(MAPPING_TREATMENTS_FORMAT);
165 for (MappingTreatment treatment : value.treatments()) {
166 printMappingTreatment(treatment);
167 }
168 }
169
170 }
171
172 /**
173 * Prints out mapping treatment.
174 *
175 * @param treatment mapping treatment
176 * @return string format of mapping treatment
177 */
178 private void printMappingTreatment(MappingTreatment treatment) {
179 if (treatment != null) {
180 if (shortOutput) {
181 print(MAPPING_TREATMENT_SHORT_FORMAT, treatment.address());
182 } else {
183 print(MAPPING_TREATMENT_LONG_FORMAT, treatment.address(),
184 treatment.instructions());
185 }
186 }
187 }
Jian Lida1dfa62017-04-25 01:56:19 +0900188
189 /**
Jian Li6e960ef2017-05-03 16:38:19 +0900190 * Returns corresponding type enumeration based on the given
191 * string formatted type.
192 *
193 * @param type string formatted type
194 * @return type enumeration
195 */
196 private MappingStore.Type getTypeEnum(String type) {
197
198 if (type == null) {
199 throw new IllegalArgumentException(TYPE_NOT_NULL);
200 }
201
202 switch (type) {
203 case DB:
204 return MappingStore.Type.MAP_DATABASE;
205 case CACHE:
206 return MappingStore.Type.MAP_CACHE;
207 default:
208 throw new IllegalArgumentException(TYPE_ILLEGAL);
209 }
210 }
211
212 /**
Jian Lida1dfa62017-04-25 01:56:19 +0900213 * Generates JSON object with the mappings of the given device.
214 *
215 * @param mapper object mapper
216 * @param device device
217 * @param mappings a collection of mappings
218 * @return JSON object
219 */
220 private ObjectNode json(ObjectMapper mapper, Device device, List<MappingEntry> mappings) {
221 ObjectNode result = mapper.createObjectNode();
222 ArrayNode array = mapper.createArrayNode();
223
224 mappings.forEach(mapping -> array.add(jsonForEntity(mapping, MappingEntry.class)));
225
226 result.put("device", device.id().toString())
227 .put("mappingCount", mappings.size())
228 .set("mappings", array);
229 return result;
230 }
231
232 /**
233 * Generates JSON object with the mappings of all devices.
234 *
235 * @param type mapping store type
236 * @param devices a collection of devices
237 * @return JSON object
238 */
239 private JsonNode json(MappingStore.Type type, Iterable<Device> devices) {
240 ObjectMapper mapper = new ObjectMapper();
241 ArrayNode result = mapper.createArrayNode();
242 for (Device device : devices) {
243 result.add(json(mapper, device,
244 newArrayList(mappingService.getMappingEntries(type, device.id()))));
245 }
246 return result;
247 }
248}