/**
*
*/
package org.opennaas.extensions.vcpe.manager.templates.mp;
import java.util.ArrayList;
import java.util.List;
import org.opennaas.extensions.vcpe.manager.VCPENetworkManagerException;
import org.opennaas.extensions.vcpe.manager.templates.ITemplate;
import org.opennaas.extensions.vcpe.model.IPNetworkDomain;
import org.opennaas.extensions.vcpe.model.Interface;
import org.opennaas.extensions.vcpe.model.LogicalRouter;
import org.opennaas.extensions.vcpe.model.Router;
import org.opennaas.extensions.vcpe.model.VCPENetworkElement;
import org.opennaas.extensions.vcpe.model.VCPENetworkModel;
import org.opennaas.extensions.vcpe.model.helper.VCPENetworkModelHelper;
import org.opennaas.extensions.vcpe.model.routing.RoutingConfiguration;
import org.opennaas.extensions.vcpe.model.routing.StaticRouteConfiguration;
import com.google.common.collect.Iterables;
/**
* @author Isart Canyameres Gimenez (i2cat Foundation)
* @author Jordi
*/
public class MultipleProviderTemplate implements ITemplate {
/**
* FIXME TO BE REMOVED
*/
private static final boolean APPLY_WORKAROUND = true;
private String templateType = ITemplate.MP_VCPE_TEMPLATE;
private MPTemplateSuggestor suggestor;
/**
* @throws VCPENetworkManagerException
*
*/
public MultipleProviderTemplate() throws VCPENetworkManagerException {
suggestor = new MPTemplateSuggestor();
suggestor.initialize();
}
public String getTemplateType() {
return templateType;
}
/**
*
* @param initialModel
* model with user preferences. It MAY not contain all elements, but MUST contain every configurable element (including physical
* infrastructure)
* @return complete model with all required values.
*/
@Override
public VCPENetworkModel buildModel(VCPENetworkModel initialModel) {
// WORKAROUND starts here
// When given initialModel does not contain physical elements, this workaround must be executed
if (APPLY_WORKAROUND) {
initialModel = buildModelWithPhyInfrastructureWorkaround(initialModel);
}
// WORKAROUND ends here
VCPENetworkModel model = MPTemplateModelBuilder.generateModel();
model = partialCopy(initialModel, model);
model = hierarchicalLRnames(model);
model = configureRouting(model);
return model;
}
@Override
public VCPENetworkModel getPhysicalInfrastructureSuggestion() throws VCPENetworkManagerException {
VCPENetworkModel generated = MPTemplateModelBuilder.generatePhysicalElements();
VCPENetworkModel suggestion = suggestor.getSuggestionForPhysicalModel(generated);
return suggestion;
}
@Override
public VCPENetworkModel getLogicalInfrastructureSuggestion(VCPENetworkModel physicalInfrastructure) throws VCPENetworkManagerException {
// assuming given physicalInfrastructure is complete
return getLogicalInfrastructureSuggestionFromCompletePhysical(physicalInfrastructure);
}
private VCPENetworkModel getLogicalInfrastructureSuggestionFromCompletePhysical(VCPENetworkModel physicalInfrastructure) {
VCPENetworkModel generatedLogical = MPTemplateModelBuilder.generateLogicalElements();
VCPENetworkModel suggestedLogical = suggestor.getSuggestionForLogicalModel(physicalInfrastructure, generatedLogical);
VCPENetworkModel completeSuggestion = MPTemplateModelBuilder.mapLogicalAndPhysical(physicalInfrastructure, suggestedLogical);
return completeSuggestion;
}
/**
* Copies data in elements from given source to elements in given destination with same templateName. No element is created within this method.
* Does not copy references to other elements (interfaces, physicalRouter, etc.)
*
* @param source
* @param destination
* @return destination updated with values in source.
*/
private VCPENetworkModel partialCopy(VCPENetworkModel source, VCPENetworkModel destination) {
destination.setName(source.getName());
destination.setId(source.getId());
VCPENetworkElement dstElement;
for (VCPENetworkElement srcElement : source.getElements()) {
dstElement = VCPENetworkModelHelper.getElementByTemplateName(destination.getElements(), srcElement.getTemplateName());
if (dstElement != null) {
dstElement.setName(srcElement.getName());
if (srcElement instanceof Interface && dstElement instanceof Interface) {
VCPENetworkModelHelper.copyInterface((Interface) dstElement, (Interface) srcElement);
} else if (srcElement instanceof IPNetworkDomain && dstElement instanceof IPNetworkDomain) {
((IPNetworkDomain) dstElement).setOwner(((IPNetworkDomain) srcElement).getOwner());
((IPNetworkDomain) dstElement).setASNumber(((IPNetworkDomain) srcElement).getASNumber());
((IPNetworkDomain) dstElement).setIPAddressRanges(((IPNetworkDomain) srcElement).getIPAddressRanges());
}
}
}
return destination;
}
private VCPENetworkModel hierarchicalLRnames(VCPENetworkModel model) {
for (LogicalRouter lr : Iterables.filter(VCPENetworkModelHelper.getRouters(model.getElements()), LogicalRouter.class)) {
lr.setName(model.getName() + "-" + lr.getName());
}
return model;
}
/**
* FIXME TO BE REMOVED, part of WORKAROUND
*
* @param initialModel
* model with user preferences. Without physicalInfrastructure elements
* @return given initialModel merged with suggested physical one.
*/
private VCPENetworkModel buildModelWithPhyInfrastructureWorkaround(VCPENetworkModel initialModelLogical) {
// Merge initialModelLogical with suggested physical
VCPENetworkModel phy = MPTemplateModelBuilder.generatePhysicalElements();
phy = suggestor.getSuggestionForPhysicalModel(phy);
VCPENetworkModel logical = MPTemplateModelBuilder.generateLogicalElements();
logical = partialCopy(initialModelLogical, logical);
VCPENetworkModel logicalWithSuggestedPhysical = MPTemplateModelBuilder.mapLogicalAndPhysical(phy, logical);
return logicalWithSuggestedPhysical;
}
private VCPENetworkModel configureRouting(VCPENetworkModel model) {
// reset routing configuration for LRs
for (LogicalRouter lr : Iterables.filter(VCPENetworkModelHelper.getRouters(model.getElements()), LogicalRouter.class)) {
lr.setRoutingConfiguration(new RoutingConfiguration());
}
configureStaticRoutes(model);
return model;
}
/**
* Creates MP-template required static routes in given model.
*
* Creates following static routes:
*
* in LR1: <br/>
* static route LAN_CLIENT.getIPAddressRange() next-hop LR_CLIENT_IFACE_UP1.getIPAddress() (through LR_1_IFACE_DOWN) <br/>
* static route 0.0.0.0/0 next-hop WAN1_IFACE_DOWN.getIPAddress() (through LR_1_IFACE_UP) <br/>
*
* in LR2: <br/>
* static route LAN_CLIENT.getIPAddressRange() next-hop LR_CLIENT_IFACE_UP2.getIPAddress() (through LR_2_IFACE_DOWN) <br/>
* static route 0.0.0.0/0 next-hop WAN2_IFACE_DOWN.getIPAddress() (through LR_2_IFACE_UP) <br/>
*
* in LR_CLIENT: <br/>
* static route LAN_CLIENT.getIPAddressRange() next-hop LAN_CLIENT_IFACE_UP.getIPAddress() (through LR_CLIENT_IFACE_DOWN) <br/>
* static route WAN1.getIPAddressRange() next-hop LR_1_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP1) <br/>
* static route WAN2.getIPAddressRange() next-hop LR_2_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP2) <br/>
* static route 0.0.0.0/0 next-hop LR_1_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP1) //default provider is WAN1 <br/>
*
* Documented in issue OPENNAAS-869.
*
* @param model
* @return given model with required static routes included
*/
private VCPENetworkModel configureStaticRoutes(VCPENetworkModel model) {
String allRoutes = "0.0.0.0/0";
RoutingConfiguration config;
List<String> clientIPRanges = ((IPNetworkDomain) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LAN_CLIENT))
.getIPAddressRanges();
List<String> wan1IPRanges = ((IPNetworkDomain) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.WAN1))
.getIPAddressRanges();
List<String> wan2IPRanges = ((IPNetworkDomain) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.WAN2))
.getIPAddressRanges();
// LR_1
config = ((Router) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_1_ROUTER))
.getRoutingConfiguration();
config.setStaticRoutes(new ArrayList<StaticRouteConfiguration>(2));
// static route LAN_CLIENT.getIPAddressRange() next-hop LR_CLIENT_IFACE_UP1.getIPAddress() (through LR_1_IFACE_DOWN)
for (String ipRange : clientIPRanges) {
config.getStaticRoutes().add(new StaticRouteConfiguration(
ipRange,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_CLIENT_IFACE_UP1)).getIpAddress()
, false));
}
// static route 0.0.0.0/0 next-hop WAN1_IFACE_DOWN.getIPAddress() (through LR_1_IFACE_UP)
config.getStaticRoutes().add(new StaticRouteConfiguration(
allRoutes,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.WAN1_IFACE_DOWN)).getIpAddress()
, false));
// LR_2
config = ((Router) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_2_ROUTER))
.getRoutingConfiguration();
config.setStaticRoutes(new ArrayList<StaticRouteConfiguration>(2));
// static route LAN_CLIENT.getIPAddressRange() next-hop LR_CLIENT_IFACE_UP2.getIPAddress() (through LR_2_IFACE_DOWN)
for (String ipRange : clientIPRanges) {
config.getStaticRoutes().add(new StaticRouteConfiguration(
ipRange,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_CLIENT_IFACE_UP2)).getIpAddress()
, false));
}
// static route 0.0.0.0/0 next-hop WAN2_IFACE_DOWN.getIPAddress() (through LR_2_IFACE_UP)
config.getStaticRoutes().add(new StaticRouteConfiguration(
allRoutes,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.WAN2_IFACE_DOWN)).getIpAddress()
, false));
// LR_CLIENT
config = ((Router) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_CLIENT_ROUTER))
.getRoutingConfiguration();
config.setStaticRoutes(new ArrayList<StaticRouteConfiguration>(4));
// static route LAN_CLIENT.getIPAddressRange() next-hop LAN_CLIENT_IFACE_UP.getIPAddress() (through LR_CLIENT_IFACE_DOWN)
for (String ipRange : clientIPRanges) {
config.getStaticRoutes().add(new StaticRouteConfiguration(
ipRange,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LAN_CLIENT_IFACE_UP)).getIpAddress()
, false));
}
// static route WAN1.getIPAddressRange() next-hop LR_1_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP1)
for (String ipRange : wan1IPRanges) {
config.getStaticRoutes().add(new StaticRouteConfiguration(
ipRange,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_1_IFACE_DOWN)).getIpAddress()
, false));
}
// static route WAN2.getIPAddressRange() next-hop LR_2_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP2)
for (String ipRange : wan2IPRanges) {
config.getStaticRoutes().add(new StaticRouteConfiguration(
ipRange,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_2_IFACE_DOWN)).getIpAddress()
, false));
}
// static route 0.0.0.0/0 next-hop LR_1_IFACE_DOWN.getIPAddress() (through LR_CLIENT_IFACE_UP1) //default provider is WAN1
config.getStaticRoutes().add(new StaticRouteConfiguration(
allRoutes,
((Interface) VCPENetworkModelHelper.getElementByTemplateName(model, TemplateConstants.LR_1_IFACE_DOWN)).getIpAddress()
, false));
return model;
}
}