Thomas Vachuska

Adding commands for managing layouts.

Adding support for wiping out regions and layouts.
Refactored UI layout manager to allow public knowledge of default layout id.
Enhanced test topo for layout hierarchy.

Change-Id: I254fd494175e753f542f12a664618c1a83f72127
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.net;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionService;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.model.topo.UiTopoLayoutId;
import static org.onosproject.net.region.RegionId.regionId;
import static org.onosproject.ui.model.topo.UiTopoLayoutId.layoutId;
/**
* Creates a new UI layout.
*/
@Command(scope = "onos", name = "layout-add",
description = "Creates a new UI layout")
public class LayoutAddCommand extends AbstractShellCommand {
private static final String FMT = "id=%s, name=%s, type=%s";
private static final String FMT_MASTER = " master=%s";
@Argument(index = 0, name = "id", description = "Layout ID",
required = true, multiValued = false)
String id = null;
@Argument(index = 1, name = "id", description = "Region ID (optional)",
required = false, multiValued = false)
String regionId = null;
@Argument(index = 2, name = "id", description = "Parent layout ID (optional)",
required = false, multiValued = false)
String parentId = null;
private RegionService regionService;
@Override
protected void execute() {
UiTopoLayoutService service = get(UiTopoLayoutService.class);
RegionService regionService = get(RegionService.class);
Region region = regionId == null ? null : regionService.getRegion(regionId(regionId));
UiTopoLayoutId pid = parentId == null ? UiTopoLayoutId.DEFAULT_ID : layoutId(parentId);
UiTopoLayout layout = new UiTopoLayout(layoutId(id), region, pid);
service.addLayout(layout);
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli.net;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.ui.UiTopoLayoutService;
import org.onosproject.ui.model.topo.UiTopoLayout;
import org.onosproject.ui.model.topo.UiTopoLayoutId;
import org.onosproject.utils.Comparators;
import java.util.Collections;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
/**
* List layout details.
*/
@Command(scope = "onos", name = "layouts",
description = "List layout details")
public class LayoutListCommand extends AbstractShellCommand {
private static final String FMT = "id=%s, region=%s, parent=%s";
@Argument(index = 0, name = "id", description = "Layout ID",
required = false, multiValued = false)
String id = null;
private UiTopoLayoutService layoutService;
@Override
protected void execute() {
layoutService = get(UiTopoLayoutService.class);
if (id == null) {
for (UiTopoLayout layout : getSortedLayouts(layoutService)) {
printLayout(layout);
}
} else {
UiTopoLayout layout = layoutService.getLayout(UiTopoLayoutId.layoutId(id));
if (layout == null) {
error("No such region %s", id);
} else {
printLayout(layout);
}
}
}
private List<UiTopoLayout> getSortedLayouts(UiTopoLayoutService service) {
List<UiTopoLayout> layouts = newArrayList(service.getLayouts());
Collections.sort(layouts, Comparators.LAYOUT_COMPARATOR);
return layouts;
}
private void printLayout(UiTopoLayout layout) {
print(FMT, layout.id(), layout.regionId(),
layout.parent() != null ? layout.parent().id() : "none");
}
}
......@@ -26,6 +26,8 @@ import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.link.LinkAdminService;
import org.onosproject.net.region.RegionAdminService;
import org.onosproject.ui.UiTopoLayoutService;
/**
* Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
......@@ -51,6 +53,9 @@ public class WipeOutCommand extends ClustersListCommand {
wipeOutHosts();
wipeOutDevices();
wipeOutLinks();
wipeOutLayouts();
wipeOutRegions();
}
private void wipeOutIntents() {
......@@ -106,4 +111,16 @@ public class WipeOutCommand extends ClustersListCommand {
}
}
}
private void wipeOutLayouts() {
print("Wiping UI layouts");
UiTopoLayoutService service = get(UiTopoLayoutService.class);
service.getLayouts().forEach(service::removeLayout);
}
private void wipeOutRegions() {
print("Wiping regions");
RegionAdminService service = get(RegionAdminService.class);
service.getRegions().forEach(r -> service.removeRegion(r.id()));
}
}
......
......@@ -631,6 +631,19 @@
</completers>
</command>
<!-- UI Layout commands -->
<command>
<action class="org.onosproject.cli.net.LayoutListCommand"/>
</command>
<command>
<action class="org.onosproject.cli.net.LayoutAddCommand"/>
</command>
<!--TODO: add this + completers
<command>
<action class="org.onosproject.cli.net.LayoutRemoveCommand"/>
</command>
-->
<!--virtual network commands -->
<command>
<action class="org.onosproject.cli.net.vnet.TenantListCommand"/>
......
......@@ -23,6 +23,11 @@ import org.onlab.util.Identifier;
*/
public final class UiTopoLayoutId extends Identifier<String> {
/**
* Default topology layout identifier.
*/
public static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
// For serialization
private UiTopoLayoutId() {
}
......
......@@ -33,6 +33,7 @@ import org.onosproject.net.group.Group;
import org.onosproject.net.region.Region;
import org.onosproject.net.statistic.TypedFlowEntryWithLoad;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.ui.model.topo.UiTopoLayout;
import java.util.Comparator;
......@@ -154,6 +155,12 @@ public final class Comparators {
}
};
public static final Comparator<UiTopoLayout> LAYOUT_COMPARATOR = new Comparator<UiTopoLayout>() {
@Override
public int compare(UiTopoLayout l1, UiTopoLayout l2) {
return l1.id().toString().compareTo(l2.id().toString());
}
};
public static final Comparator<TenantId> TENANT_ID_COMPARATOR = new Comparator<TenantId>() {
@Override
public int compare(TenantId tenant1, TenantId tenant2) {
......
......@@ -195,6 +195,9 @@ import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.DefaultPacketRequest;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.resource.ContinuousResource;
import org.onosproject.net.resource.ContinuousResourceId;
import org.onosproject.net.resource.DiscreteResource;
......@@ -504,6 +507,10 @@ public final class KryoNamespaces {
.register(new AnnotationsSerializer(), DefaultAnnotations.class)
.register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class)
.register(new ExtensionCriterionSerializer(), ExtensionCriterion.class)
.register(Region.class)
.register(Region.Type.class)
.register(RegionId.class)
.register(DefaultRegion.class)
.register(ExtensionSelectorType.class)
.register(ExtensionTreatmentType.class)
.register(TransactionId.class)
......
#!/bin/bash
# Test topology
host=${1:-127.0.0.1}
......@@ -6,8 +7,6 @@ onos ${host} null-simulation stop custom
onos ${host} wipe-out please
onos ${host} null-simulation start custom
sleep 1
onos ${host} <<-EOF
null-create-device switch s1 10 0 0
......@@ -35,8 +34,6 @@ null-create-link direct s8 s7
EOF
onos ${host} <<-EOF
region-add r1 Region1 METRO ${host}
......@@ -58,4 +55,10 @@ region-add-devices r3 \
of:0000000000000009
regions
layout-add l1 r1
layout-add l2 r2
layout-add l3 r3 l2
layouts
EOF
\ No newline at end of file
......
......@@ -40,6 +40,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.ui.model.topo.UiTopoLayoutId.DEFAULT_ID;
/**
* Manages the user interface topology layouts.
......@@ -54,8 +55,6 @@ public class UiTopoLayoutManager implements UiTopoLayoutService {
private static final String ID_NULL = "Layout ID cannot be null";
private static final String LAYOUT_NULL = "Layout cannot be null";
private static final UiTopoLayoutId DEFAULT_ID = UiTopoLayoutId.layoutId("_default_");
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
......