net.es.enos.esnet.OSCARSTopologyPublisher.java Source code

Java tutorial

Introduction

Here is the source code for net.es.enos.esnet.OSCARSTopologyPublisher.java

Source

/*
 * ESnet Network Operating System (ENOS) Copyright (c) 2015, The Regents
 * of the University of California, through Lawrence Berkeley National
 * Laboratory (subject to receipt of any required approvals from the
 * U.S. Dept. of Energy).  All rights reserved.
 *
 * If you have questions about your rights to use or distribute this
 * software, please contact Berkeley Lab's Innovation & Partnerships
 * Office at IPO@lbl.gov.
 *
 * NOTICE.  This Software was developed under funding from the
 * U.S. Department of Energy and the U.S. Government consequently retains
 * certain rights. As such, the U.S. Government has been granted for
 * itself and others acting on its behalf a paid-up, nonexclusive,
 * irrevocable, worldwide license in the Software to reproduce,
 * distribute copies to the public, prepare derivative works, and perform
 * publicly and display publicly, and to permit other to do so.
 */
package net.es.enos.esnet;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import net.es.netshell.api.PersistentObject;
import net.es.netshell.api.TopologyFactory;
import net.es.netshell.boot.BootStrap;
import org.apache.commons.io.IOUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.nio.file.Paths;
import java.security.cert.CertificateException;

/**
 * Implements the retrival, parsing and archiving of the topology published by OSCARS. It contains the topology that
 * reservable by OSCARS as well as the layer 3 topology.
 */
public class OSCARSTopologyPublisher {
    public static final String ESNET_DEFAULT_URL = "https://oscars.es.net/topology-publisher";
    public static final String CACHE_DIR = "cache";
    public static final String CACHE_FILE_PREFIX = "oscars";
    private final Logger logger = LoggerFactory.getLogger(OSCARSTopologyPublisher.class);
    private DateTime date;

    public class TopologyTrustManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)
                throws CertificateException {

        }

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)
                throws CertificateException {

        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[0];
        }
    }

    public OSCARSTopologyPublisher() {
        this.date = DateTime.now();
    }

    public OSCARSTopologyPublisher(String date) {
        DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
        this.date = formatter.parseDateTime(date);
    }

    public String toString() {
        // Check if we have today's topology already cached
        if (!BootStrap.getBootStrap().isStandAlone() && this.isCached()) {
            try {
                logger.info("Loading topology from cache");
                return this.loadTopology();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // If date is not today and there was no archive, return null
        if (!this.isToday()) {
            return null;
        }
        // Today's topology has not yet been downloaded or there was a problem reading it from file. Download
        // from URL.
        String topology = this.loadFromUrl();
        if (topology == null) {
            return null;
        }
        if (!BootStrap.getBootStrap().isStandAlone()) {
            // Save it into the cache / archive
            try {
                this.saveTopology(topology);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return topology;
    }

    public boolean isToday() {
        DateTime now = DateTime.now();
        return this.date.withTimeAtStartOfDay().isEqual(now.withTimeAtStartOfDay());
    }

    /**
     * This method reads the provided file to load the topology in the wire format, instead of
     * downloading it from the topology service. This is useful when network is not available and only
     * a cached version of the topology can be used.
     * @param file
     * @throws java.io.IOException
     */
    private String loadFromFile(File file) throws IOException {
        InputStream in = new FileInputStream(file);
        StringBuffer stringbuffer = new StringBuffer();
        byte[] buffer = new byte[4096];
        while (true) {
            int r = in.read(buffer);
            if (r <= 0) {
                // EOF
                break;
            }
            new String(buffer, 0, r);
            stringbuffer.append(new String(buffer, 0, r));
        }
        return stringbuffer.toString();
    }

    private String loadTopology() throws IOException {
        File file = this.buildCachedFile();
        return this.loadFromFile(file);
    }

    private void saveTopology(String topology) throws IOException {
        File file = this.buildCachedFile();
        this.saveToFile(file, topology);
    }

    private void saveToFile(File file, String wireFormat) throws IOException {
        if ((wireFormat == null) || (wireFormat.length() == 0)) {
            // Nothing to save, just return
            logger.warn("Topology wire format is empty or null");
            return;
        }
        /* Make sure all directories exist */
        file.getParentFile().mkdirs();
        OutputStream out = new FileOutputStream(file);
        out.write(wireFormat.getBytes());
        out.flush();
    }

    /**
     * Check if there is topology in the cache that was retrieved from the URL today.
     * @return
     */
    private boolean isCached() {
        File file = this.buildCachedFile();
        return file.exists();
    }

    public File buildCachedFile() {

        String fileName = CACHE_FILE_PREFIX + "." + this.date.getYear() + "-" + this.date.getMonthOfYear() + "-"
                + this.date.getDayOfMonth();

        String filePath = Paths.get(TopologyFactory.FACTORY_DIR, CACHE_DIR, fileName).toString();
        // Get the Operating System absolute path
        File file = PersistentObject.buildFile(filePath);
        return file;
    }

    /**
     * Loads the topology from the ESnet URL. The result is in JSON format.
     * @return a single string that contains the whole topology in its wire format.
     */
    private String loadFromUrl() {

        try {
            ClientConfig clientConfig = new DefaultClientConfig();

            SSLContext sslcontext = null;
            TrustManager[] trustAllCerts = new TrustManager[] { new TopologyTrustManager() };

            HTTPSProperties httpsProperties = new HTTPSProperties(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    // whatever your matching policy states
                    logger.info("Verifying SSL Session");
                    return true;
                }
            });

            clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, httpsProperties);
            sslcontext = httpsProperties.getSSLContext();
            sslcontext.init(null, trustAllCerts, null);
            Client client = Client.create(clientConfig);
            clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

            WebResource webResource = client.resource(OSCARSTopologyPublisher.ESNET_DEFAULT_URL);
            ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
            }
            String txt = IOUtils.toString(response.getEntityInputStream());
            String output = this.normalize(txt);
            return output;

        } catch (Exception e) {
            logger.warn("Cannot retrieve the topology");
            return null;
        }
    }

    /**
     * ESnet esnet uses two different format in ID:
     *    1) urn:ogf:network:domain=es.net:node=sunn-cr5:port=to_sunn-ixia-mgmt:link=*
     *    2) urn:ogf:network:es.net:sunn-cr5:to_sunn-ixia-mgmt:*
     */
    public String normalize(String wireformat) {
        wireformat = wireformat.replaceAll("(?:domain=)", "");
        wireformat = wireformat.replaceAll("(?:node=)", "");
        wireformat = wireformat.replaceAll("(?:link=)", "");
        wireformat = wireformat.replaceAll("(?:port=)", "");
        return wireformat;
    }

    public ESnetJSONTopology toJSON() {
        ObjectMapper mapper = new ObjectMapper();

        try {
            String json = this.toString();
            if ((json == null) || (json.length() == 0)) {
                return null;
            }
            JSONObject jsonObj = new JSONObject(this.toString());
            ESnetJSONTopology jsonTopology = mapper.readValue(jsonObj.toString(),
                    new TypeReference<ESnetJSONTopology>() {
                    });
            return jsonTopology;
        } catch (JsonGenerationException e) {

            e.printStackTrace();

        } catch (JsonMappingException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

}