blob: b71b14573f33d6fe5c2362addcedfacc6d1d6f41 [file] [log] [blame]
HIGUCHI Yuta848324f2015-12-04 21:11:26 -08001/*
2 * Copyright 2015 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 * limitations under the License.
15 */
16package org.onosproject.cli.net;
17
18import static org.onosproject.net.DeviceId.deviceId;
19
Naoki Shiota784af312016-02-01 15:47:21 -080020import java.util.Arrays;
21import java.util.Collections;
22import java.util.HashSet;
23import java.util.Set;
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080024import java.util.stream.StreamSupport;
25
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080026import com.google.common.base.Strings;
Naoki Shiota784af312016-02-01 15:47:21 -080027import com.google.common.collect.ImmutableSet;
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080028import org.apache.karaf.shell.commands.Argument;
29import org.apache.karaf.shell.commands.Command;
30import org.apache.karaf.shell.commands.Option;
Naoki Shiota784af312016-02-01 15:47:21 -080031import org.onlab.packet.MplsLabel;
32import org.onlab.packet.VlanId;
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080033import org.onosproject.cli.AbstractShellCommand;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.OchSignal;
37import org.onosproject.net.Port;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.device.DeviceService;
Naoki Shiota784af312016-02-01 15:47:21 -080040import org.onosproject.net.intent.IntentId;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080041import org.onosproject.net.resource.Resources;
42import org.onosproject.net.resource.DiscreteResourceId;
43import org.onosproject.net.resource.ResourceAllocation;
44import org.onosproject.net.resource.ResourceService;
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080045
46/**
47 * Lists allocated resources.
48 */
49@Command(scope = "onos", name = "allocations",
50 description = "Lists allocated resources")
51public class AllocationsCommand extends AbstractShellCommand {
52
Naoki Shiota784af312016-02-01 15:47:21 -080053 @Option(name = "-t", aliases = "--type", description = "List of resource types",
54 required = false, multiValued = true)
55 String[] typeStrings = null;
56
57 Set<String> typesToPrint;
58
59 @Option(name = "-i", aliases = "--intentId", description = "Intent ID",
60 required = false, multiValued = true)
61 String[] intentStrings;
62
63 Set<String> intentsToPrint;
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080064
65 @Argument(index = 0, name = "deviceIdString", description = "Device ID",
66 required = false, multiValued = false)
67 String deviceIdStr = null;
68
69 @Argument(index = 1, name = "portNumberString", description = "PortNumber",
70 required = false, multiValued = false)
71 String portNumberStr = null;
72
73
74
75 private DeviceService deviceService;
76 private ResourceService resourceService;
77
78 @Override
79 protected void execute() {
80 deviceService = get(DeviceService.class);
81 resourceService = get(ResourceService.class);
82
Naoki Shiota784af312016-02-01 15:47:21 -080083 if (typeStrings != null) {
84 typesToPrint = new HashSet<>(Arrays.asList(typeStrings));
85 } else {
86 typesToPrint = Collections.emptySet();
87 }
88
89 if (intentStrings != null) {
90 intentsToPrint = new HashSet<>(Arrays.asList(intentStrings));
91 } else {
92 intentsToPrint = Collections.emptySet();
93 }
HIGUCHI Yuta848324f2015-12-04 21:11:26 -080094
95 if (deviceIdStr != null && portNumberStr != null) {
96 DeviceId deviceId = deviceId(deviceIdStr);
97 PortNumber portNumber = PortNumber.fromString(portNumberStr);
98
99 printAllocation(deviceId, portNumber, 0);
100 } else if (deviceIdStr != null) {
101 DeviceId deviceId = deviceId(deviceIdStr);
102
103 printAllocation(deviceId, 0);
104 } else {
105 printAllocation();
106 }
107
108 }
109
110 private void printAllocation() {
111 print("ROOT");
112 StreamSupport.stream(deviceService.getAvailableDevices().spliterator(), false)
113 .map(Device::id)
114 .forEach(did -> printAllocation(did, 1));
115 }
116
117 private void printAllocation(DeviceId did, int level) {
118 print("%s%s", Strings.repeat(" ", level), did);
119 StreamSupport.stream(deviceService.getPorts(did).spliterator(), false)
120 .map(Port::number)
121 .forEach(num -> printAllocation(did, num, level + 1));
122 }
123
124 private void printAllocation(DeviceId did, PortNumber num, int level) {
125 if (level == 0) {
126 // print DeviceId when Port was directly specified.
127 print("%s", did);
128 }
129 print("%s%s", Strings.repeat(" ", level), asVerboseString(num));
130
Naoki Shiota784af312016-02-01 15:47:21 -0800131 // FIXME: This workaround induces a lot of distributed store access.
132 // ResourceService should have an API to get all allocations under a parent resource.
133 Set<Class<?>> subResourceTypes = ImmutableSet.<Class<?>>builder()
134 .add(OchSignal.class)
135 .add(VlanId.class)
136 .add(MplsLabel.class)
137 .build();
HIGUCHI Yuta848324f2015-12-04 21:11:26 -0800138
Naoki Shiota784af312016-02-01 15:47:21 -0800139 DiscreteResourceId resourceId = Resources.discrete(did, num).id();
140 for (Class<?> t : subResourceTypes) {
141 resourceService.getResourceAllocations(resourceId, t).stream()
142 .filter(a -> isSubjectToPrint(a))
143 .forEach(a -> print("%s%s allocated by %s", Strings.repeat(" ", level + 1),
144 a.resource().valueAs(Object.class).orElse(""), asVerboseString(a.consumer())));
HIGUCHI Yuta848324f2015-12-04 21:11:26 -0800145
HIGUCHI Yuta848324f2015-12-04 21:11:26 -0800146 }
147 }
148
Naoki Shiota784af312016-02-01 15:47:21 -0800149 private boolean isSubjectToPrint(ResourceAllocation allocation) {
150 if (!intentsToPrint.isEmpty()
151 && allocation.consumer() instanceof IntentId
152 && !intentsToPrint.contains(allocation.consumer().toString())) {
153 return false;
154 }
155
156 if (!typesToPrint.isEmpty()
157 && !typesToPrint.contains(allocation.resource().simpleTypeName())) {
158 return false;
159 }
160
161 return true;
162 }
163
HIGUCHI Yuta848324f2015-12-04 21:11:26 -0800164 /**
165 * Add type name if the toString does not start with them.
166 *
167 * e.g., IntentId#toString result in "42"
168 * asVerboseString(id) will result in "IntentId:42"
169 *
170 * @param obj non-null Object to print.
171 * @return verbose String representation
172 */
173 private static String asVerboseString(Object obj) {
174 String name = obj.getClass().getSimpleName();
175 String toString = String.valueOf(obj);
176 if (toString.startsWith(name)) {
177 return toString;
178 } else {
179 return String.format("%s:%s", name, toString);
180 }
181 }
182
183}