From e63291850fd0795c5700e25e67e5dee89ba54c5f Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Tue, 1 Dec 2015 05:49:27 -0800 Subject: onos commit hash c2999f30c69e50df905a9d175ef80b3f23a98514 Change-Id: I2bb8562c4942b6d6a6d60b663db2e17540477b81 Signed-off-by: Ashlee Young --- .../xosintegration/OnosXosIntegrationManager.java | 545 +++++++++++++++++++++ 1 file changed, 545 insertions(+) create mode 100644 framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java (limited to 'framework/src/onos/apps/xos-integration/src') diff --git a/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java b/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java new file mode 100644 index 00000000..32f2a680 --- /dev/null +++ b/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java @@ -0,0 +1,545 @@ +/* + * Copyright 2014-2015 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.xosintegration; + +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.google.common.collect.Maps; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientHandlerException; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Modified; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.VlanId; +import org.onlab.util.Tools; +import org.onosproject.cfg.ComponentConfigService; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flowobjective.DefaultForwardingObjective; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; + +import java.util.Dictionary; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.net.MediaType.JSON_UTF_8; +import static java.net.HttpURLConnection.HTTP_CREATED; +import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.net.HttpURLConnection.HTTP_OK; +import static org.slf4j.LoggerFactory.getLogger; + + +/** + * XOS interface application. + */ +@Component(immediate = true) +@Service +public class OnosXosIntegrationManager implements VoltTenantService { + private static final String XOS_SERVER_ADDRESS_PROPERTY_NAME = + "xosServerAddress"; + private static final String XOS_SERVER_PORT_PROPERTY_NAME = + "xosServerPort"; + private static final String XOS_PROVIDER_SERVICE_PROPERTY_NAME = + "xosProviderService"; + + private static final String TEST_XOS_SERVER_ADDRESS = "10.254.1.22"; + private static final int TEST_XOS_SERVER_PORT = 8000; + private static final String XOS_TENANT_BASE_URI = "/xoslib/volttenant/"; + private static final int TEST_XOS_PROVIDER_SERVICE = 1; + + private static final int PRIORITY = 50000; + private static final DeviceId FABRIC_DEVICE_ID = DeviceId.deviceId("of:5e3e486e73000187"); + private static final PortNumber FABRIC_OLT_CONNECT_POINT = PortNumber.portNumber(2); + private static final PortNumber FABRIC_VCPE_CONNECT_POINT = PortNumber.portNumber(3); + private static final String FABRIC_CONTROLLER_ADDRESS = "10.0.3.136"; + private static final int FABRIC_SERVER_PORT = 8181; + private static final String FABRIC_BASE_URI = "/onos/cordfabric/vlans/add"; + + private static final DeviceId OLT_DEVICE_ID = DeviceId.deviceId("of:90e2ba82f97791e9"); + private static final int OLT_UPLINK_PORT = 129; + + private static final ConnectPoint FABRIC_PORT = new ConnectPoint( + DeviceId.deviceId("of:000090e2ba82f974"), + PortNumber.portNumber(2)); + + private final Logger log = getLogger(getClass()); + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ComponentConfigService cfgService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FlowObjectiveService flowObjectiveService; + + @Property(name = XOS_SERVER_ADDRESS_PROPERTY_NAME, + value = TEST_XOS_SERVER_ADDRESS, + label = "XOS Server address") + protected String xosServerAddress = TEST_XOS_SERVER_ADDRESS; + + @Property(name = XOS_SERVER_PORT_PROPERTY_NAME, + intValue = TEST_XOS_SERVER_PORT, + label = "XOS Server port") + protected int xosServerPort = TEST_XOS_SERVER_PORT; + + @Property(name = XOS_PROVIDER_SERVICE_PROPERTY_NAME, + intValue = TEST_XOS_PROVIDER_SERVICE, + label = "XOS Provider Service") + protected int xosProviderService = TEST_XOS_PROVIDER_SERVICE; + + private ApplicationId appId; + private Map nodeToPort; + private Map portToVlan; + private Map portToSsid; + + @Activate + public void activate(ComponentContext context) { + log.info("XOS app is starting"); + cfgService.registerProperties(getClass()); + appId = coreService.registerApplication("org.onosproject.xosintegration"); + + setupMap(); + + readComponentConfiguration(context); + + log.info("XOS({}) started", appId.id()); + } + + @Deactivate + public void deactivate() { + cfgService.unregisterProperties(getClass(), false); + log.info("XOS({}) stopped", appId.id()); + } + + @Modified + public void modified(ComponentContext context) { + readComponentConfiguration(context); + } + + private void setupMap() { + nodeToPort = Maps.newHashMap(); + + nodeToPort.put("cordcompute01.onlab.us", new ConnectPoint(FABRIC_DEVICE_ID, + PortNumber.portNumber(4))); + + nodeToPort.put("cordcompute02.onlab.us", new ConnectPoint(FABRIC_DEVICE_ID, + PortNumber.portNumber(3))); + + portToVlan = Maps.newHashMap(); + portToVlan.putIfAbsent(1L, (short) 201); + portToVlan.putIfAbsent(6L, (short) 401); + + portToSsid = Maps.newHashMap(); + portToSsid.put(new ConnectPoint(OLT_DEVICE_ID, PortNumber.portNumber(1)), "0"); + portToSsid.put(new ConnectPoint(FABRIC_DEVICE_ID, PortNumber.portNumber(6)), "1"); + } + + /** + * Converts a JSON representation of a tenant into a tenant object. + * + * @param jsonTenant JSON object representing the tenant + * @return volt tenant object + */ + private VoltTenant jsonToTenant(JsonObject jsonTenant) { + return VoltTenant.builder() + .withHumanReadableName(jsonTenant.get("humanReadableName").asString()) + .withId(jsonTenant.get("id").asInt()) + .withProviderService(jsonTenant.get("provider_service").asInt()) + .withServiceSpecificId(jsonTenant.get("service_specific_id").asString()) + .withVlanId(jsonTenant.get("vlan_id").asString()) + .build(); + } + + /** + * Converts a tenant object into a JSON string. + * + * @param tenant volt tenant object to convert + * @return JSON string for the tenant + */ + private String tenantToJson(VoltTenant tenant) { + return "{" + + "\"humanReadableName\": \"" + tenant.humanReadableName() + "\"," + + "\"id\": \"" + tenant.id() + "\"," + + "\"provider_service\": \"" + tenant.providerService() + "\"," + + "\"service_specific_id\": \"" + tenant.serviceSpecificId() + "\"," + + "\"vlan_id\": \"" + tenant.vlanId() + "\"" + + "}"; + } + + /** + * Gets a client web resource builder for the base XOS REST API + * with no additional URI. + * + * @return web resource builder + * @deprecated in Cardinal Release + */ + @Deprecated + private WebResource.Builder getClientBuilder() { + return getClientBuilder(""); + } + + /** + * Gets a client web resource builder for the base XOS REST API + * with an optional additional URI. + * + * @return web resource builder + * @deprecated in Cardinal Release + */ + @Deprecated + private WebResource.Builder getClientBuilder(String uri) { + String baseUrl = "http://" + xosServerAddress + ":" + + Integer.toString(xosServerPort); + Client client = Client.create(); + client.addFilter(new HTTPBasicAuthFilter("padmin@vicci.org", "letmein")); + WebResource resource = client.resource(baseUrl + + XOS_TENANT_BASE_URI + uri); + return resource.accept(JSON_UTF_8.toString()) + .type(JSON_UTF_8.toString()); + } + + /** + * Performs a REST GET operation on the base XOS REST URI. + * + * @return JSON string fetched by the GET operation + * @deprecated in Cardinal Release + */ + @Deprecated + private String getRest() { + return getRest(""); + } + + /** + * Performs a REST GET operation on the base XOS REST URI with + * an optional additional URI. + * + * @return JSON string fetched by the GET operation + * @deprecated in Cardinal Release + */ + @Deprecated + private String getRest(String uri) { + WebResource.Builder builder = getClientBuilder(uri); + ClientResponse response = builder.get(ClientResponse.class); + + if (response.getStatus() != HTTP_OK) { + log.info("REST GET request returned error code {}", + response.getStatus()); + } + String jsonString = response.getEntity(String.class); + log.info("JSON read:\n{}", jsonString); + + return jsonString; + } + + /** + * Performs a REST POST operation of a json string on the base + * XOS REST URI with an optional additional URI. + * + * @param json JSON string to post + * @deprecated in Cardinal Release + */ + @Deprecated + private String postRest(String json) { + WebResource.Builder builder = getClientBuilder(); + ClientResponse response; + + try { + response = builder.post(ClientResponse.class, json); + } catch (ClientHandlerException e) { + log.warn("Unable to contact REST server: {}", e.getMessage()); + return "{ 'error' : 'oops no one home' }"; + } + + if (response.getStatus() != HTTP_CREATED) { + log.info("REST POST request returned error code {}", + response.getStatus()); + } + return response.getEntity(String.class); + } + + /** + * Performs a REST DELETE operation on the base + * XOS REST URI with an optional additional URI. + * + * @param uri optional additional URI + * @deprecated in Cardinal Release + */ + @Deprecated + private void deleteRest(String uri) { + WebResource.Builder builder = getClientBuilder(uri); + ClientResponse response = builder.delete(ClientResponse.class); + + if (response.getStatus() != HTTP_NO_CONTENT) { + log.info("REST DELETE request returned error code {}", + response.getStatus()); + } + } + + /** + * Deletes the tenant with the given ID. + * + * @param tenantId ID of tenant to delete + */ + private void deleteTenant(long tenantId) { + deleteRest(Long.toString(tenantId)); + } + + @Override + public Set getAllTenants() { + String jsonString = getRest(); + + JsonArray voltTenantItems = JsonArray.readFrom(jsonString); + + return IntStream.range(0, voltTenantItems.size()) + .mapToObj(index -> jsonToTenant(voltTenantItems.get(index).asObject())) + .collect(Collectors.toSet()); + } + + @Override + public void removeTenant(long id) { + deleteTenant(id); + } + + @Override + public VoltTenant addTenant(VoltTenant newTenant) { + long providerServiceId = newTenant.providerService(); + if (providerServiceId == -1) { + providerServiceId = xosProviderService; + } + + PortNumber onuPort = newTenant.port().port(); + VlanId subscriberVlan = VlanId.vlanId(portToVlan.get(onuPort.toLong())); + + VoltTenant tenantToCreate = VoltTenant.builder() + .withProviderService(providerServiceId) + .withServiceSpecificId(portToSsid.get(newTenant.port())) + .withVlanId(String.valueOf(subscriberVlan.toShort())) + .withPort(newTenant.port()) + .build(); + String json = tenantToJson(tenantToCreate); + + + provisionVlanOnPort(OLT_DEVICE_ID, OLT_UPLINK_PORT, onuPort, subscriberVlan.toShort()); + + String retJson = postRest(json); + + fetchCpeLocation(tenantToCreate, retJson); + + return newTenant; + } + + private void fetchCpeLocation(VoltTenant newTenant, String jsonString) { + JsonObject json = JsonObject.readFrom(jsonString); + + if (json.get("computeNodeName") != null) { + ConnectPoint point = nodeToPort.get(json.get("computeNodeName").asString()); + //ConnectPoint fromPoint = newTenant.port(); + ConnectPoint oltPort = new ConnectPoint(FABRIC_DEVICE_ID, FABRIC_OLT_CONNECT_POINT); + + provisionFabric(VlanId.vlanId(Short.parseShort(newTenant.vlanId())), + point, oltPort); + } + + } + + @Override + public VoltTenant getTenant(long id) { + String jsonString = getRest(Long.toString(id)); + JsonObject jsonTenant = JsonObject.readFrom(jsonString); + if (jsonTenant.get("id") != null) { + return jsonToTenant(jsonTenant); + } else { + return null; + } + } + + private void provisionVlanOnPort(DeviceId deviceId, int uplinkPort, PortNumber p, short vlanId) { + + TrafficSelector upstream = DefaultTrafficSelector.builder() + .matchVlanId(VlanId.ANY) + .matchInPort(p) + .build(); + + TrafficSelector downstream = DefaultTrafficSelector.builder() + .matchVlanId(VlanId.vlanId(vlanId)) + .matchInPort(PortNumber.portNumber(uplinkPort)) + .build(); + + TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder() + .setVlanId(VlanId.vlanId(vlanId)) + .setOutput(PortNumber.portNumber(uplinkPort)) + .build(); + + TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder() + .popVlan() + .setOutput(p) + .build(); + + + ForwardingObjective upFwd = DefaultForwardingObjective.builder() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(1000) + .makePermanent() + .withSelector(upstream) + .fromApp(appId) + .withTreatment(upstreamTreatment) + .add(); + + ForwardingObjective downFwd = DefaultForwardingObjective.builder() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(1000) + .makePermanent() + .withSelector(downstream) + .fromApp(appId) + .withTreatment(downstreamTreatment) + .add(); + + flowObjectiveService.forward(deviceId, upFwd); + flowObjectiveService.forward(deviceId, downFwd); + + } + + private void provisionDataPlane(VoltTenant tenant) { + VlanId vlan = VlanId.vlanId(Short.parseShort(tenant.vlanId())); + + TrafficSelector fromGateway = DefaultTrafficSelector.builder() + .matchInPhyPort(tenant.port().port()) + .build(); + + TrafficSelector fromFabric = DefaultTrafficSelector.builder() + .matchInPhyPort(FABRIC_PORT.port()) + .matchVlanId(vlan) + .build(); + + TrafficTreatment toFabric = DefaultTrafficTreatment.builder() + .pushVlan() + .setVlanId(vlan) + .setOutput(FABRIC_PORT.port()) + .build(); + + TrafficTreatment toGateway = DefaultTrafficTreatment.builder() + .popVlan() + .setOutput(tenant.port().port()) + .build(); + + ForwardingObjective forwardToFabric = DefaultForwardingObjective.builder() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .makePermanent() + .fromApp(appId) + .withSelector(fromGateway) + .withTreatment(toFabric) + .add(); + + ForwardingObjective forwardToGateway = DefaultForwardingObjective.builder() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .makePermanent() + .fromApp(appId) + .withSelector(fromFabric) + .withTreatment(toGateway) + .add(); + + flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToFabric); + flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToGateway); + } + + private void provisionFabric(VlanId vlanId, ConnectPoint point, ConnectPoint fromPoint) { + + long vlan = vlanId.toShort(); + + JsonObject node = new JsonObject(); + node.add("vlan", vlan); + if (vlan == 201) { + node.add("iptv", true); + } else { + node.add("iptv", false); + } + JsonArray array = new JsonArray(); + JsonObject cp1 = new JsonObject(); + JsonObject cp2 = new JsonObject(); + cp1.add("device", point.deviceId().toString()); + cp1.add("port", point.port().toLong()); + cp2.add("device", fromPoint.deviceId().toString()); + cp2.add("port", fromPoint.port().toLong()); + array.add(cp1); + array.add(cp2); + node.add("ports", array); + + + String baseUrl = "http://" + FABRIC_CONTROLLER_ADDRESS + ":" + + Integer.toString(FABRIC_SERVER_PORT); + Client client = Client.create(); + WebResource resource = client.resource(baseUrl + FABRIC_BASE_URI); + WebResource.Builder builder = resource.accept(JSON_UTF_8.toString()) + .type(JSON_UTF_8.toString()); + + try { + builder.post(ClientResponse.class, node.toString()); + } catch (ClientHandlerException e) { + log.warn("Unable to contact fabric REST server: {}", e.getMessage()); + return; + } + } + + /** + * Extracts properties from the component configuration context. + * + * @param context the component context + */ + private void readComponentConfiguration(ComponentContext context) { + Dictionary properties = context.getProperties(); + + String newXosServerAddress = + Tools.get(properties, XOS_SERVER_ADDRESS_PROPERTY_NAME); + if (!isNullOrEmpty(newXosServerAddress)) { + xosServerAddress = newXosServerAddress; + } + + String newXosServerPortString = + Tools.get(properties, XOS_SERVER_PORT_PROPERTY_NAME); + if (!isNullOrEmpty(newXosServerPortString)) { + xosServerPort = Integer.parseInt(newXosServerPortString); + } + + String newXosProviderServiceString = + Tools.get(properties, XOS_PROVIDER_SERVICE_PROPERTY_NAME); + if (!isNullOrEmpty(newXosProviderServiceString)) { + xosProviderService = Integer.parseInt(newXosProviderServiceString); + } + } +} + + -- cgit 1.2.3-korg