blob: 02ea103fb48ef9263106891354a09ca1f075892c [file] [log] [blame]
/*
* Copyright 2016-present 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.sdxl2;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.store.primitives.DefaultDistributedSet;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.DistributedPrimitive;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* SDX-L2 Store implementation backed by different distributed primitives.
*/
@Component(immediate = true)
@Service
public class SdxL2DistributedStore implements SdxL2Store {
private static Logger log = LoggerFactory.getLogger(SdxL2DistributedStore.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private StorageService storageService;
private Set<String> sdxL2s;
private Map<SdxL2ConnectionPoint, String> sdxL2CPs;
private ConsistentMap<SdxL2ConnectionPoint, String> sdxL2cps;
private static String errorAddSdx = "It is not possible to add %s " +
"because it exists";
private static String errorRemoveSdx = "It is not possible to remove %s " +
"because it does not exist";
private static String errorAddSdxL2CPName = "It is not possible to add %s " +
"because there is a sdxl2cp with the same name";
private static String errorAddSdxL2CPVlans = "It is not possible to add %s " +
"because there is a conflict with %s on the vlan ids";
private static String errorAddSdxL2CPCP = "It is not possible to add %s " +
"because there is a conflict with %s on the connection point";
private static String errorAddSdxL2CPSdx = "It is not possible to add %s " +
"because the relative sdxl2 does not exist";
private static String errorGetSdxL2CPs = "It is not possible to list the sdxl2cps " +
"because sdxl2 %s does not exist";
private static String errorRemoveSdxL2CP = "It is not possible to remove %s " +
"because it does not exist";
private static String errorGetSdxL2CP = "It is not possible to retrieve %s " +
"because it does not exist";
public void initForTest() {
this.sdxL2s = Sets.newHashSet();
this.sdxL2CPs = new ConcurrentHashMap<SdxL2ConnectionPoint, String>();
}
@Activate
public void activate() {
KryoNamespace custom = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
.register(new SdxL2ConnectionPointSerializer(), new Class[]{SdxL2ConnectionPoint.class})
.build();
sdxL2s = new DefaultDistributedSet<>(this.storageService
.<String>setBuilder()
.withSerializer(Serializer.using(custom))
.withName("sdxl2s")
.build(), DistributedPrimitive.DEFAULT_OPERTATION_TIMEOUT_MILLIS);
sdxL2cps = this.storageService
.<SdxL2ConnectionPoint, String>consistentMapBuilder()
.withSerializer(Serializer.using(custom))
.withName("sdxl2cps")
.build();
sdxL2CPs = sdxL2cps.asJavaMap();
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
/**
* Creates a named SDX-L2.
*
* @param sdxl2 SDX-L2 name
* @throws SdxL2Exception if SDX-L2 exists
*/
@Override
public void putSdxL2(String sdxl2) throws SdxL2Exception {
boolean inserted = sdxL2s.add(sdxl2);
if (!inserted) {
throw new SdxL2Exception(String.format(errorAddSdx, sdxl2));
}
}
/**
* Removes a named SDX-L2.
*
* @param sdxl2 SDX-L2 name
* @throws SdxL2Exception if SDX-L2 does not exist
*/
@Override
public void removeSdxL2(String sdxl2) throws SdxL2Exception {
boolean removed = sdxL2s.remove(sdxl2);
if (!removed) {
throw new SdxL2Exception(String.format(errorRemoveSdx, sdxl2));
}
Set<Map.Entry<SdxL2ConnectionPoint, String>> toRemove = sdxL2CPs.entrySet().parallelStream().filter(
key_value -> {
String sdxl2Temp = key_value.getValue();
return sdxl2Temp.equals(sdxl2) ? true : false;
}).collect(Collectors.toSet());
toRemove.forEach(key_value -> sdxL2CPs.remove(key_value.getKey()));
}
/**
* Returns a set of SDX-L2 names.
*
* @return a set of SDX-L2 names
*/
@Override
public Set<String> getSdxL2s() {
return ImmutableSet.copyOf(sdxL2s);
}
/**
* Adds an SDX-L2 connection point to an SDX-L2.
*
* @param sdxl2 SDX-L2 name
* @param connectionPoint the connection point object
* @throws SdxL2Exception if it is not possible to add the SDX-L2 connection point
*/
@Override
public void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint connectionPoint) throws SdxL2Exception {
boolean exist = sdxL2s.contains(sdxl2);
if (!exist) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPSdx, connectionPoint.name()));
}
Set<SdxL2ConnectionPoint> sdxl2cpsTemp = ImmutableSet.copyOf(sdxL2CPs.keySet());
Set<SdxL2ConnectionPoint> sdxl2cpsTempByName = sdxl2cpsTemp.parallelStream().filter(
sdxl2cpTemp-> sdxl2cpTemp.name().equals(connectionPoint.name()
)
).collect(Collectors.toSet());
if (sdxl2cpsTempByName.size() != 0) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPName, connectionPoint.name()));
}
Set<SdxL2ConnectionPoint> sdxl2cpsByCP = sdxl2cpsTemp.parallelStream().filter(
sdxl2cp_temp-> sdxl2cp_temp.connectPoint().equals(connectionPoint.connectPoint()
)
).collect(Collectors.toSet());
String tempName;
List<VlanId> vlans = connectionPoint.vlanIds();
for (VlanId vlanId : vlans) {
Set<SdxL2ConnectionPoint> sdxl2cpsByVlan = sdxl2cpsByCP.parallelStream().filter(
sdxl2cp_by_vlan -> (
sdxl2cp_by_vlan.vlanIds().contains(vlanId) || sdxl2cp_by_vlan.vlanIds().size() == 0
)).collect(Collectors.toSet());
tempName = sdxl2cpsByVlan.iterator().hasNext() ? sdxl2cpsByVlan.iterator().next().name() : null;
if (sdxl2cpsByVlan.size() != 0) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPVlans, connectionPoint.name(), tempName));
}
}
tempName = sdxl2cpsByCP.iterator().hasNext() ? sdxl2cpsByCP.iterator().next().name() : null;
if (sdxl2cpsByCP.size() != 0 && vlans.size() == 0) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPCP, connectionPoint.name(), tempName));
}
sdxL2CPs.put(connectionPoint, sdxl2);
}
/**
* Returns all the SDX-L2 connection points names or the SDX-L2 2connection points names
* that are related to an SDX-L2.
*
* @param sdxl2 name (optional) of the SDX-L2
* @return a set of SDX-L2 connection points names, the result depends on the input parameter;
* @throws SdxL2Exception if SDX-L2 is present but it does not exist
*/
@Override
public Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) throws SdxL2Exception {
if (sdxl2.isPresent()) {
Set<Map.Entry<SdxL2ConnectionPoint, String>> toGet = sdxL2CPs.entrySet().parallelStream().filter(
key_value -> {
String sdxl2Temp = key_value.getValue();
return sdxl2Temp.equals(sdxl2.get()) ? true : false;
}).collect(Collectors.toSet());
Iterator<String> itsdxL2s = sdxL2s.iterator();
boolean found = false;
while (itsdxL2s.hasNext()) {
if (sdxl2.get().equals(itsdxL2s.next())) {
found = true;
}
}
if (!found) {
throw new SdxL2Exception(String.format(errorGetSdxL2CPs, sdxl2.get()));
}
Set<String> cpsTemp = Sets.newHashSet();
for (Map.Entry<SdxL2ConnectionPoint, String> cp : toGet) {
cpsTemp.add(cp.getKey().name());
}
return cpsTemp;
}
return ImmutableSet.copyOf(sdxL2CPs.keySet()).parallelStream().map(
SdxL2ConnectionPoint::name).collect(Collectors.toSet());
}
/**
* Removes a named SDX-L2 connection point in an SDX-L2.
*
* @param sdxl2cp the connection point name
* @throws SdxL2Exception if SDX-L2 connection point does not exist
*/
@Override
public void removeSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
Set<SdxL2ConnectionPoint> sdxl2cpsTemp = ImmutableSet.copyOf(sdxL2CPs.keySet());
Set<SdxL2ConnectionPoint> sdxl2cpsTempByName = sdxl2cpsTemp.parallelStream().filter(
sdxl2cpTemp -> sdxl2cpTemp.name().equals(sdxl2cp
)
).collect(Collectors.toSet());
if (sdxl2cpsTempByName.size() == 0) {
throw new SdxL2Exception(String.format(errorRemoveSdxL2CP, sdxl2cp));
}
for (SdxL2ConnectionPoint sdxl2cpTemp : sdxl2cpsTempByName) {
sdxL2CPs.remove(sdxl2cpTemp);
}
}
/**
* Returns an SDX-L2 connection point in a SDX-L2.
*
* @param sdxl2cp the connection point name
* @return the relative SDXL2ConnectionPoint object
* @throws SdxL2Exception if SDX-L2 connection point does not exist
*/
@Override
public SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
SdxL2ConnectionPoint sdxl2cpTemp = ImmutableSet.copyOf(sdxL2CPs.keySet()).parallelStream()
.filter(sdxl2cp_temp -> sdxl2cp_temp.name().equals(sdxl2cp)).findFirst().orElse(null);
if (sdxl2cpTemp == null) {
throw new SdxL2Exception(String.format(errorGetSdxL2CP, sdxl2cp));
}
return sdxl2cpTemp;
}
}