package com.c2kernel.process; import java.net.InetAddress; import java.util.Enumeration; import java.util.StringTokenizer; import com.c2kernel.common.ObjectNotFoundException; import com.c2kernel.entity.TraceableEntity; import com.c2kernel.entity.proxy.ItemProxy; import com.c2kernel.events.Event; import com.c2kernel.events.History; import com.c2kernel.lifecycle.CompositeActivityDef; import com.c2kernel.lifecycle.instance.CompositeActivity; import com.c2kernel.lifecycle.instance.Workflow; import com.c2kernel.lifecycle.instance.predefined.PredefinedStepContainer; import com.c2kernel.lifecycle.instance.predefined.ServerPredefinedStepContainer; import com.c2kernel.lifecycle.instance.stateMachine.States; import com.c2kernel.lifecycle.instance.stateMachine.Transitions; import com.c2kernel.lookup.AgentPath; import com.c2kernel.lookup.DomainPath; import com.c2kernel.lookup.EntityPath; import com.c2kernel.lookup.LDAPLookup; import com.c2kernel.lookup.Path; import com.c2kernel.lookup.RolePath; import com.c2kernel.persistency.ClusterStorage; import com.c2kernel.persistency.outcome.Outcome; import com.c2kernel.persistency.outcome.Viewpoint; import com.c2kernel.property.Property; import com.c2kernel.property.PropertyArrayList; import com.c2kernel.property.PropertyDescription; import com.c2kernel.property.PropertyDescriptionList; import com.c2kernel.utils.CastorXMLUtility; import com.c2kernel.utils.FileStringUtility; import com.c2kernel.utils.LocalObjectLoader; import com.c2kernel.utils.Logger; import com.c2kernel.utils.Resource; /** * @version $Revision: 1.25 $ $Date: 2006/01/10 09:48:32 $ * @author $Author: abranson $ */ public class Bootstrap { static DomainPath thisServerPath; /** * Run everything without timing-out the service wrapper */ public static void run() throws Exception { // check for system agents checkAdminAgents(); // create the server's mother item createServerItem(); new Thread(new Runnable() { @Override public void run() { try { Thread.currentThread().setName("Bootstrapper"); // make sure all of the boot items are up-to-date Logger.msg("Bootstrap.run() - Verifying kernel boot data items"); verifyBootDataItems(); // verify the server item's wf Logger.msg("Bootstrap.run() - Initialising Server Item Workflow"); initServerItemWf(); // register modules Gateway.getModuleManager().registerModules(); Logger.msg("Bootstrap.run() - Bootstrapping complete"); } catch (Exception e) { Logger.error(e); Logger.die("Exception performing bootstrap. Check that everything is OK."); } } }).start(); } /************************************************************************** * Checks all kernel descriptions, stored in resources **************************************************************************/ public static void verifyBootDataItems() throws Exception { String bootItems; Logger.msg(1, "Verifying kernel boot items"); bootItems = FileStringUtility.url2String(Resource.getKernelResourceURL("boot/allbootitems.txt")); verifyBootDataItems(bootItems, null); Logger.msg(1, "Boot data items complete"); } private static void verifyBootDataItems(String bootList, String ns) { StringTokenizer str = new StringTokenizer(bootList, "\n\r"); while (str.hasMoreTokens()) { String thisItem = str.nextToken(); int delim = thisItem.indexOf('/'); String itemType = thisItem.substring(0,delim); String itemName = thisItem.substring(delim+1); try { String data = Resource.getTextResource(ns, "boot/"+thisItem+(itemType.equals("OD")?".xsd":".xml")); if (data == null) Logger.die("No data found for "+getDataType(itemType)+" "+itemName); verifyResource(ns, itemName, itemType, data); } catch (Exception e) { Logger.error(e); Logger.die("Error importing bootstrap items. Unsafe to continue."); } } } public static void verifyResource(String ns, String itemName, String itemType, String data) throws Exception { Logger.msg(1, "Bootstrap.verifyResource() - Verifying data of "+getDataType(itemType)+" "+itemName); Enumeration en = Gateway.getLDAPLookup().search(getTypeRoot(itemType), itemName); ItemProxy thisProxy; if (!en.hasMoreElements()) { Logger.msg("Bootstrap.verifyResource() - "+getDataType(itemType)+" "+itemName+" not found. Creating new."); thisProxy = createResourceItem(itemType, itemName, ns); } else { DomainPath path = (DomainPath)en.nextElement(); thisProxy = (ItemProxy)Gateway.getProxyManager().getProxy(path); try { Viewpoint currentData = (Viewpoint)thisProxy.getObject(ClusterStorage.VIEWPOINT+"/"+getDataType(itemType)+"/last"); String oldData = currentData.getOutcome().getData(); if (data.equals(oldData)) { Logger.msg(5, "Bootstrap.verifyResource() - Data identical, no update required"); return; } } catch (ObjectNotFoundException ex) { Logger.error("Bootstrap.verifyResource() - Item exists but no data found! Attempting to insert new."); } } // data was missing or doesn't match Logger.msg("Bootstrap.verifyResource() - Writing new data to "+getDataType(itemType)+" "+itemName); History hist = new History(thisProxy.getSystemKey(), thisProxy); Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", States.FINISHED); Outcome newOutcome = new Outcome(newEvent.getID(), data, getDataType(itemType), 0); Viewpoint newLastView = new Viewpoint(thisProxy.getSystemKey(), getDataType(itemType), "last", 0, newEvent.getID()); Viewpoint newZeroView = new Viewpoint(thisProxy.getSystemKey(), getDataType(itemType), "0", 0, newEvent.getID()); Gateway.getStorage().put(thisProxy.getSystemKey(), newOutcome, thisProxy); Gateway.getStorage().put(thisProxy.getSystemKey(), newLastView, thisProxy); Gateway.getStorage().put(thisProxy.getSystemKey(), newZeroView, thisProxy); Gateway.getStorage().commit(thisProxy); } /** * @param itemType * @param itemName * @param data */ private static ItemProxy createResourceItem(String itemType, String itemName, String ns) throws Exception { // create props PropertyDescriptionList pdList = (PropertyDescriptionList)CastorXMLUtility.unmarshall(Resource.getTextResource(null, "boot/property/"+itemType+"Prop.xml")); PropertyArrayList props = new PropertyArrayList(); for (int i = 0; i < pdList.list.size(); i++) { PropertyDescription pd = pdList.list.get(i); String propName = pd.getName(); String propVal = propName.equals("Name")?itemName:pd.getDefaultValue(); props.list.add(new Property(propName, propVal)); } // HACK: this gives all module resources a workflow. Maybe have a 'debug' flag in the module xml or server config to do this. Normally module resources should be read-only, as they would be reset at next boot. CompositeActivity ca = new CompositeActivity(); if (ns!=null) { String wf; if (itemType.equals("CA")) wf = "ManageCompositeActDef"; else if (itemType.equals("EA")) wf = "ManageElementaryActDef"; else if (itemType.equals("OD")) wf = "ManageSchema"; else if (itemType.equals("SC")) wf = "ManageScript"; else throw new Exception("Unknown bootstrap item type: "+itemType); ca = (CompositeActivity) ((CompositeActivityDef)LocalObjectLoader.getActDef(wf, "last")).instantiate(); } EntityPath entityPath = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey(); TraceableEntity newItem = (TraceableEntity)Gateway.getCorbaServer().createEntity(entityPath); Gateway.getLDAPLookup().add(entityPath); newItem.initialise( 1, CastorXMLUtility.marshall(props), CastorXMLUtility.marshall(ca)); DomainPath newDomPath = new DomainPath(getTypeRoot(itemType).toString()+"/system/"+(ns==null?"kernel":ns)+"/"+itemName); newDomPath.setEntity(entityPath); Gateway.getLDAPLookup().add(newDomPath); return (ItemProxy)Gateway.getProxyManager().getProxy(entityPath); } public static DomainPath getTypeRoot(String type) throws Exception { if (type.equals("CA") || type.equals("EA")) return new DomainPath("/desc/ActivityDesc/"); if (type.equals("SC")) return new DomainPath("/desc/Script/"); if (type.equals("OD")) return new DomainPath("/desc/OutcomeDesc/"); throw new Exception("Unknown bootstrap item type: "+type); } private static String getDataType(String type) throws Exception { if (type.equals("CA")) return "CompositeActivityDef"; if (type.equals("EA")) return "ElementaryActivityDef"; if (type.equals("OD")) return "Schema"; if (type.equals("SC")) return "Script"; throw new Exception("Unknown bootstrap item type: "+type); } /************************************************************************** * Checks for the existence of the admin users so you can use Cristal **************************************************************************/ private static void checkAgent(String name, String pass, String role, boolean joblist) throws Exception { Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user."); LDAPLookup lookup = Gateway.getLDAPLookup(); try { lookup.getRoleManager().getAgentPath(name); Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found."); return; } catch (ObjectNotFoundException ex) { } Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating."); RolePath rolePath; try { rolePath = lookup.getRoleManager().getRolePath(role); } catch (ObjectNotFoundException ex) { rolePath = lookup.getRoleManager().createRole(role, joblist); } try { EntityPath entityPath = lookup.getNextKeyManager().generateNextEntityKey(); AgentPath agentPath = new AgentPath(entityPath.getSysKey(), name); agentPath.setPassword(pass); Gateway.getCorbaServer().createEntity(agentPath); Gateway.getLDAPLookup().add(agentPath); // assign admin role Logger.msg("Bootstrap.checkAgent() - Assigning role '"+role+"'"); rolePath.addAgent(agentPath); Gateway.getStorage().put(agentPath.getSysKey(), new Property("Name", name), null); Gateway.getStorage().put(agentPath.getSysKey(), new Property("Type", "Agent"), null); Logger.msg("Bootstrap.checkAgent() - Done"); } catch (Exception ex) { Logger.error("Unable to create "+name+" user."); throw ex; } } /** * */ public static void checkAdminAgents() throws Exception { // check for administrative user String adminPassword = Gateway.getProperty("AdminPassword", "admin12345"); checkAgent("admin", adminPassword, "Admin", false); // check for import user checkAgent("system", adminPassword, "Admin", false); // check for local usercode user checkAgent(InetAddress.getLocalHost().getHostName(), "uc", "UserCode", true); } public static void createServerItem() throws Exception { String serverName = Gateway.getProperty("ItemServer.name"); thisServerPath = new DomainPath("/servers/"+serverName); EntityPath serverEntity; try { serverEntity = thisServerPath.getEntity(); } catch (ObjectNotFoundException ex) { Logger.msg("Creating server item "+thisServerPath); serverEntity = Gateway.getLDAPLookup().getNextKeyManager().generateNextEntityKey(); Gateway.getCorbaServer().createEntity(serverEntity); Gateway.getLDAPLookup().add(serverEntity); thisServerPath.setEntity(serverEntity); Gateway.getLDAPLookup().add(thisServerPath); } Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Name", serverName), null); Gateway.getStorage().put(serverEntity.getSysKey(), new Property("Type", "Server"), null); Gateway.getStorage().put(serverEntity.getSysKey(), new Property("KernelVersion", Resource.getKernelVersion()), null); if (Gateway.getProperty("ItemServer.Proxy.port") != null) Gateway.getStorage().put(serverEntity.getSysKey(), new Property("ProxyPort", Gateway.getProperty("ItemServer.Proxy.port")), null); if (Gateway.getProperty("ItemServer.Console.port") != null) Gateway.getStorage().put(serverEntity.getSysKey(), new Property("ConsolePort", Gateway.getProperty("ItemServer.Console.port")), null); Gateway.getProxyManager().connectToProxyServer(Gateway.getProperty("ItemServer.name"), Integer.parseInt(Gateway.getProperty("ItemServer.Proxy.port"))); } public static void initServerItemWf() throws Exception { CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", "last"); Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate()); PredefinedStepContainer predef = (PredefinedStepContainer)wf.search("workflow/predefined"); wf.getChildGraphModel().removeVertex(predef); wf.addChild(new ServerPredefinedStepContainer(), predef.getCentrePoint()); wf.initialise(thisServerPath.getSysKey(), Gateway.getLDAPLookup().getRoleManager().getAgentPath("system")); Gateway.getStorage().put(thisServerPath.getSysKey(), wf, null); // add this proxy server in case it was just registered, or the port has changed } }