All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prerna.cluster.util.NginxClient Maven / Gradle / Ivy

The newest version!
package prerna.cluster.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.Version;
import prerna.util.Utility;
import prerna.util.Constants;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class NginxClient implements Watcher{
	
	protected static final Logger logger = LogManager.getLogger(NginxClient.class);

	/*
	// Environment Variables this depnds on
	 * zk - semicolon separated list of zk to use for registration
	 * home - what is the main registration root - default is assumed as /semoss_root
	 * app - The root for various apps - default is assumed as /app
	 * host -  ip and port - this is useful if you are running multiple containers on the same box
	
	// registers to semoss_root/semoss- as a ephemeral_sequential
	// the semoss_root is an environment variable - this will allow me to spin as many cluster as I want
	 * Major version
	 * minor version
	 * semoss_sequential node
	 * host ip and port
	 * number of cpus
	 * memory
	 * User who is booted on it
	 * The registration is typically 
	 * register_root / #cpu / #memory / semoss-node
	 * register_root / semoss-node
	 * nginx will only watch the resigter_root/semoss_node initially
	 *  I could even do this for specific databases so the same thing is not loaded multiple times
	// zk e
	
	*/

	public static final String ZK_SERVER = "zk";
	public static final String HOST = "host";
	public static final String TIMEOUT = "to";
	public static final String BOOTUSER = "bu";
	public static final String HOME = "home";
	public static final String APP_HOME = "app";

	
	ZooKeeper zk = null;
	Map  env = null;
	public String zkServer = "192.168.99.100:2181";
	public String host = "192.168.99.100:8888";
	public String user = "generic";
	public String home = "/semoss_root";
	public String app = "/app";
	//public String semossHome = "/opt/semosshome/";
	public String semossHome = "c:/users/pkapaleeswaran/workspacej3/docker/";
	
	
	boolean connected = false;
	
	public static NginxClient zkClient = null;
	
	
	
	int version = 0;

	protected NginxClient()
	{
		
	}
	
	public static NginxClient getInstance()
	{
		if(zkClient == null)
		{
			zkClient = new NginxClient();
			zkClient.init();
			if(zkClient.connected)
			{
				zkClient.watchForChildren();
				return zkClient;
			}
		}
		return null;
	}
	
//	public static void main(String [] args) throws Exception
//	{
//		NginxClient c = NginxClient.getInstance();
//		System.out.println("Wait here.. ");
//		c.waitHere();
//	}
	
	public void waitHere()
	{
		try {
			
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			br.readLine();
			
		}catch(Exception ignored)
		{
			
		}
	}
	
	public void init()
	{
		// initiates connection to zk and makes the connection
		try {
			env = System.getenv();
			if(env.containsKey(ZK_SERVER))
				zkServer = env.get(ZK_SERVER);
			
			if(env.containsKey(HOST))
				host = env.get(HOST);
			
			int timeout = (30 * 60 * 1000);

			if(env.containsKey(TIMEOUT))
				host = env.get(TIMEOUT);

			if(env.containsKey(BOOTUSER))
				user = env.get(BOOTUSER);

			if(env.containsKey(HOME))
				home = env.get(HOME);

			if(env.containsKey(APP_HOME))
				app = env.get(APP_HOME);

			if(zkServer != null && host != null)
			{
				// open zk
				// default time is 30 min
				zk = new ZooKeeper(zkServer, timeout, this);
				
				connected = true;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
	}
	
	public void publishNode()
	{
		// right now I dont have everything.. 
		// but this publishes, major, minor, ip:port, cpu, memory
		
		try {
			zk.create(home +"/semoss" , getPayload().getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
		// also need to publish to the user
		// usally this is home/user
	}
	
	// I need another where I say publish database
	public void publishDB(String engineID)
	{
		// so assume I tell this as /app/ - does that do the trick ?
		// so when I want to load a github I say /[email protected]/app/
		try {
			zk.create(home + app + "/" + engineID ,  host.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
	}
	
	public String getPayload()
	{
		// this will make all the major minor versions etc. 
		StringBuilder sb = new StringBuilder();
		sb.append("cpu=").append(Runtime.getRuntime().availableProcessors()).append("|");
		sb.append("memory=").append(Runtime.getRuntime().maxMemory()).append("|");
		sb.append("rver=").append("3.5").append("|");
		sb.append("semoss=").append("3.5").append("|"); // woo hoo.. same version as R
		sb.append("url=").append(host).append("|");
		sb.append("user").append(user).append("|");
		
		return sb.toString();
	}
	
	
	// watch the home and list things
	public void watchForChildren()
	{
		// watch the home
		// every event.. get the list of children compose the conf file
		// watch again
		// the event goes to processEvent
		try {
			zk.getChildren(home + app , true, null);
		} catch (KeeperException | InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
	}
	
	public void openZK()
	{
		try {
			zk = new ZooKeeper("192.168.99.100:6311", 6311, this);
			
			//Thread.sleep(60000);
			getVersion("/pk");
			List  aclList = ZooDefs.Ids.OPEN_ACL_UNSAFE;
			//zk.create("/pk", "helo".getBytes(), aclList, CreateMode.EPHEMERAL);
			Stat stat = new Stat();
			stat.setVersion(3);
			byte [] b = zk.getData("/pk", true, stat);
			String data = new String(b, "UTF-8");
			System.out.println(" >>" + data);
			Thread.sleep(2000);
			
			//zk.setData("/pk", "world".getBytes(), version);
			
			List  childs  = zk.getChildren("/pk", false);
			
			for(int childIndex = 0;childIndex < childs.size();childIndex++)
				System.out.println("Child >> " + childs.get(childIndex));
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
		
	}
	
	public void getVersion(String path)
	{
		try {
			version = zk.exists(path,true).getVersion();
			System.out.println("Running current version at " + version);
		} catch (KeeperException | InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
	}
	
	// bind events tos epcific things
	

	@Override
	public void process(WatchedEvent event) {	
		// TODO Auto-generated method stub
		// System.out.println("Ok.. something came back on this" + arg0);
		EventType type = event.getType();
		
		System.out.println("Some Event came in.. " + event.getType());
		
		if(type == EventType.NodeCreated)
			nodeChildChanged(Utility.getClassName(event.getPath()));
		
		else if(type == EventType.NodeDeleted)
			nodeChildChanged(Utility.getClassName(event.getPath()));

		else if(type == EventType.NodeChildrenChanged)
			nodeChildChanged(event.getPath());

		watchForChildren();
		
	}
	
	public void nodeCreated(String path)
	{
		System.out.println("Node Created..  " + path);
	}
	
	public void nodeDeleted(String path)
	{
		System.out.println("Node Deleted..  " + path);
	}
	
	public void nodeChildChanged(String path)
	{
		regenConfig(path);
	}
	
	public String getNodeData(String path)
	{
		String data = null;
		
		try {
			byte [] b = zk.getData(path, true, new Stat());
			data = new String(b, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
		
		return data;
	}
	
	public void regenConfig(String path)
	{
		Map  nameURL = new HashMap();
		try {
			List  children = zk.getChildren(path, null);
			
			
			// now for each children
			// get the data and pull it from there
			for(int childIndex = 0;childIndex < children.size();childIndex++)
			{
				String childName = children.get(childIndex);
				System.out.println("Child is.. " + childName);
				String output = getNodeData(home + app + "/" + childName);
				System.out.println("And the URL I need to register is.. " + output);
				nameURL.put(childName, output);
			}
			
			genNginx(nameURL);
			
		} catch (KeeperException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
		
		
	}
	
	public void genNginx(Map map)
	{
		//FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));
        try {
			Configuration cfg = new Configuration();

			cfg.setIncompatibleImprovements(new Version(2, 3, 20));
			cfg.setDefaultEncoding("UTF-8");
			cfg.setLocale(Locale.US);
			cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
			cfg.setDirectoryForTemplateLoading(new File(semossHome + "nginx/templates"));

			Map  input = new HashMap();
			

			Template t = cfg.getTemplate("upstream.conf");

			input.put("apps", map);
			backup();
			Writer out = new FileWriter(semossHome + "nginx/conf/nginx.conf");
			t.process(input, out);
			
			out.flush();
			out.close();
			//reloadNginx();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (TemplateException e) {
			// TODO Auto-generated catch block
			
			logger.error(Constants.STACKTRACE, e);
		}
	}
	
	public void backup()
	{
		try
		{
			String curConfig = semossHome + "nginx/conf/nginx.conf";
			String backConfig = semossHome + "nginx/conf/nginx-working.conf";
			
			if(Files.exists(Paths.get(backConfig)))
				Files.delete(Paths.get(backConfig));
			
			Files.copy(Paths.get(curConfig), Paths.get(backConfig));
			
			
		}catch (Exception ex)
		{
			logger.error(Constants.STACKTRACE, ex);
		}
	}
	
	public void reloadNginx()
	{
		// need to get the id - use the pidof
		// https://stackoverflow.com/questions/16965089/getting-pid-of-process-in-shell-script
		/*
		try {
			// and then execute a kill -HUP
			ProcessBuilder pb = new ProcessBuilder("pidof 'nginx: master process nginx' > " + semossHome + "nginxid");
			pb.start();
			
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(semossHome + "nginxid")));
			
			String nginxId = br.readLine();
			
			pb = new ProcessBuilder("kill -HUP " + nginxId);
			pb.start();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error(Constants.STACKTRACE, e);
		}
		*/
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy