Java tutorial
/* * 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 kr.ac.postech.lispconfig; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Lists; import com.google.common.collect.Maps; 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.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.packet.IpAddress; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord; import org.onosproject.lisp.msg.protocols.LispLocatorRecord; import org.onosproject.lisp.msg.protocols.LispMapRecord; import org.onosproject.lisp.msg.types.LispIpv4Address; import org.onosproject.net.DeviceId; import org.onosproject.net.config.NetworkConfigService; import org.onosproject.net.driver.DriverHandler; import org.onosproject.net.driver.DriverService; import org.onosproject.netconf.NetconfController; import org.onosproject.netconf.NetconfException; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * NetConf/Yang base LISP data plane configuration tool. * The all methods are base on lispsimple.yang model file. * * See {https://github.com/OpenOverlayRouter/oor/blob/master/netconf/lispsimple.yang} */ @Component(immediate = true) @Service public class LispConfigManager implements LispConfigService { private final Logger log = LoggerFactory.getLogger(getClass()); private final static String APP_SUBJECT_CLASS_KEY = "apps"; private final static String DEVICE_SUBJECT_CLASS_KEY = "devices"; private final static String APP_CONFIG_KEY = "devices"; private final static String DEVICE_CONFIG_KEY = "basic"; private final static String DEVICE_CFG_JSON = "netconf-cfg.json"; private final static String NETCONF_APP_NAME = "org.onosproject.netconf"; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected NetworkConfigService cfgService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected CoreService coreService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DriverService driverService; ComponentContext context; Map<DeviceId, List<String>> mapResolverMap; Map<DeviceId, List<LispMapRecord>> eidDbMap; private final static String ITR_HEADER = "<itr-cfg xmlns=\"urn:ietf:params:" + "xml:ns:yang:lispsimple\">\n<map-resolvers>\n<map-resolver>"; private final static String ITR_FOOTER = "</map-resolver>\n</map-resolvers>\n</itr-cfg>\n"; private final static String RESOLVER_BEGIN_TAG = "<map-resolver-address>"; private final static String RESOLVER_END_TAG = "</map-resolver-address>\n"; private final static String ETR_HEADER = "<etr-cfg xmlns=\"urn:ietf:params:" + "xml:ns:yang:lispsimple\">"; private final static String ETR_FOOTER = "</etr-cfg>\n"; private final static String LOCAL_EIDS_HEADER = "<local-eids>"; private final static String LOCAL_EIDS_FOOTER = "</local-eids>"; @Activate protected void activate(ComponentContext context) { this.context = context; mapResolverMap = Maps.newConcurrentMap(); eidDbMap = Maps.newConcurrentMap(); log.info("Started"); } @Deactivate protected void deactivate() { log.info("Stopped"); } @Override public String getConfig(DeviceId deviceId) { DriverHandler handler = driverService.createHandler(deviceId); NetconfController controller = handler.get(NetconfController.class); try { return controller.getNetconfDevice(deviceId).getSession().getConfig("running"); } catch (NetconfException e) { e.printStackTrace(); } return "Error to obtain GET_CONFIG"; } @Override public String getConfigWithFilter(DeviceId deviceId, String filter) { DriverHandler handler = driverService.createHandler(deviceId); NetconfController controller = handler.get(NetconfController.class); try { return controller.getNetconfDevice(deviceId).getSession().getConfig("running", filter); } catch (NetconfException e) { e.printStackTrace(); } return "Error to obtain GET_CONFIG for ITR"; } @Override public boolean addItrMapResolver(DeviceId deviceId, String address) { List<String> resolverList = mapResolverMap.get(deviceId); if (resolverList == null) { resolverList = Lists.newLinkedList(); mapResolverMap.put(deviceId, resolverList); } if (resolverList.stream().filter(s -> s.equals(address)).count() == 0) { resolverList.add(address); return updateItrMapResolver(deviceId); } else { log.info("Map resolver {} is already exist", address); } return false; } @Override public boolean removeItrMapResolver(DeviceId deviceId, String address) { List<String> resolverList = mapResolverMap.get(deviceId); if (resolverList != null) { resolverList.remove(address); return updateItrMapResolver(deviceId); } else { log.info("Map resolver {} is not exist on {}", address, deviceId); } return false; } @Override public boolean addEtrEidDataBase(DeviceId deviceId, LispMapRecord record) { log.info(record.toString()); List<LispMapRecord> eidDb = eidDbMap.get(deviceId); if (eidDb == null) { eidDb = Lists.newLinkedList(); eidDbMap.put(deviceId, eidDb); } log.info("Trace Point 1"); List<LispMapRecord> records = eidDb.stream() .filter(s -> s.getEidPrefixAfi().equals(record.getEidPrefixAfi())).collect(Collectors.toList()); if (records.size() == 0) { log.info("Add new map record"); eidDb.add(record); } else { log.info("Update new map record"); LispMapRecord oldRecord = records.get(0); List<LispLocatorRecord> newLocators = record.getLocators(); List<LispLocatorRecord> oldLocators = oldRecord.getLocators(); List<LispLocatorRecord> actualLocators = Lists.newArrayList(); actualLocators.addAll(newLocators); actualLocators.addAll(oldLocators); for (LispLocatorRecord loc : newLocators) { for (LispLocatorRecord ol : oldLocators) { if (loc.getLocatorAfi().equals(ol.getLocatorAfi())) { actualLocators.remove(ol); } } } DefaultLispMapRecord.DefaultMapRecordBuilder builder = new DefaultLispMapRecord.DefaultMapRecordBuilder(); builder.withEidPrefixAfi(record.getEidPrefixAfi()); builder.withMaskLength(record.getMaskLength()); builder.withRecordTtl(record.getRecordTtl()); builder.withLocators(actualLocators); eidDb.remove(oldRecord); eidDb.add(builder.build()); } return updateEtrEidDatabase(deviceId); } @Override public boolean removeEtrEidDataBase(DeviceId deviceId, LispMapRecord record) { List<LispMapRecord> eidDb = eidDbMap.get(deviceId); if (eidDb != null) { eidDb.remove(record); return updateEtrEidDatabase(deviceId); } else { log.info("EID-RLOC mapping record {} is not exist", record.toString()); } return false; } @Override public boolean connectDevice(String name, String password, String address, String port) { boolean registered = registerDevice(address, port); boolean configured = configureDevice(name, password, address, port); if (registered && configured) { return true; } else { return false; } } public boolean registerDevice(String address, String port) { log.info("{} {}", address, port); InputStream is = null; try { is = context.getBundleContext().getBundle().getEntry(DEVICE_CFG_JSON).openStream(); } catch (IOException e) { e.printStackTrace(); } ObjectMapper mapper = new ObjectMapper(); JsonFactory jsonFactory = mapper.getFactory(); JsonParser jsonParser = null; try { jsonParser = jsonFactory.createParser(is); } catch (IOException e) { e.printStackTrace(); } JsonNode jsonNode = null; try { jsonNode = mapper.readTree(jsonParser); } catch (IOException e) { e.printStackTrace(); } JsonNode deviceRoot = jsonNode.get(DEVICE_SUBJECT_CLASS_KEY); String deviceName = deviceRoot.fieldNames().next(); JsonNode removed = ((ObjectNode) deviceRoot).remove(deviceName); String newDeviceName = "netconf:" + address + ":" + port; ((ObjectNode) deviceRoot).set(newDeviceName, removed); DeviceId deviceId = DeviceId.deviceId(newDeviceName); JsonNode subjectNode = deviceRoot.path(newDeviceName); Object result = cfgService.applyConfig(DEVICE_SUBJECT_CLASS_KEY, deviceId, DEVICE_CONFIG_KEY, subjectNode.get(DEVICE_CONFIG_KEY)); return result != null ? true : false; } public boolean configureDevice(String name, String password, String address, String port) { ApplicationId netConfAppId = coreService.getAppId(NETCONF_APP_NAME); InputStream is = null; try { is = context.getBundleContext().getBundle().getEntry(DEVICE_CFG_JSON).openStream(); } catch (IOException e) { e.printStackTrace(); } ObjectMapper mapper = new ObjectMapper(); JsonFactory jsonFactory = mapper.getFactory(); JsonParser jsonParser = null; try { jsonParser = jsonFactory.createParser(is); } catch (IOException e) { e.printStackTrace(); } JsonNode jsonNode = null; try { jsonNode = mapper.readTree(jsonParser); } catch (IOException e) { e.printStackTrace(); } JsonNode appRoot = jsonNode.get(APP_SUBJECT_CLASS_KEY); appRoot = appRoot.get(NETCONF_APP_NAME); jsonNode = appRoot.get(APP_CONFIG_KEY).get(0); ((ObjectNode) jsonNode).put("name", name); ((ObjectNode) jsonNode).put("password", password); ((ObjectNode) jsonNode).put("ip", address); ((ObjectNode) jsonNode).put("port", port); log.info(appRoot.toString()); Object result = cfgService.applyConfig(APP_SUBJECT_CLASS_KEY, netConfAppId, APP_CONFIG_KEY, appRoot.path(APP_CONFIG_KEY)); return result != null ? true : false; } private boolean updateItrMapResolver(DeviceId deviceId) { List<String> resolverList = mapResolverMap.get(deviceId); StringBuilder builder = new StringBuilder(ITR_HEADER); resolverList.forEach(r -> { builder.append(RESOLVER_BEGIN_TAG); if (IpAddress.valueOf(r).isIp4()) { builder.append("<ipv4>"); builder.append(r); builder.append("</ipv4>"); } else { builder.append("<ipv6>"); builder.append(r); builder.append("</ipv6>"); } builder.append(RESOLVER_END_TAG); }); builder.append(ITR_FOOTER); DriverHandler handler = driverService.createHandler(deviceId); NetconfController controller = handler.get(NetconfController.class); try { return controller.getNetconfDevice(deviceId).getSession().copyConfig("running", builder.toString()); } catch (NetconfException e) { e.printStackTrace(); } return false; } private boolean updateEtrEidDatabase(DeviceId deviceId) { List<LispMapRecord> eidDb = eidDbMap.get(deviceId); StringBuilder builder = new StringBuilder(ETR_HEADER); builder.append(LOCAL_EIDS_HEADER); eidDb.forEach(record -> builder.append(serializeMapRecord(record))); builder.append(LOCAL_EIDS_FOOTER); builder.append(ETR_FOOTER); DriverHandler handler = driverService.createHandler(deviceId); NetconfController controller = handler.get(NetconfController.class); try { log.info(builder.toString()); return controller.getNetconfDevice(deviceId).getSession().copyConfig("running", builder.toString()); } catch (NetconfException e) { e.printStackTrace(); } return false; } private String serializeMapRecord(LispMapRecord mapRecord) { StringBuilder strBuilder = new StringBuilder(); strBuilder.append("<local-eid>"); //Todo: now only support IPv4 strBuilder.append("<eid-address>"); if (mapRecord.getEidPrefixAfi().getAfi().getIanaCode() == 1) { strBuilder.append("<afi>").append("ipv4").append("</afi>"); strBuilder.append("<ipv4>").append(mapRecord.getEidPrefixAfi().toString()).append("</ipv4>"); } strBuilder.append("</eid-address>"); strBuilder.append("<rlocs>"); mapRecord.getLocators().forEach(l -> { strBuilder.append("<rloc>"); if (l.getLocatorAfi().getAfi().getIanaCode() == 1) { strBuilder.append("<locator-address>"); strBuilder.append("<afi>").append("ipv4").append("</afi>"); strBuilder.append("<ipv4>").append(l.getLocatorAfi().toString()).append("</ipv4>"); strBuilder.append("</locator-address>"); } strBuilder.append("<priority>").append(l.getPriority()).append("</priority>"); strBuilder.append("<weight>").append(l.getWeight()).append("</weight>"); strBuilder.append("</rloc>"); }); strBuilder.append("</rlocs>"); strBuilder.append("<record-ttl>").append(mapRecord.getRecordTtl()).append("</record-ttl>"); strBuilder.append("</local-eid>"); return strBuilder.toString(); } }