Skip to Content
Author's profile photo Xiaoping Zheng

SDK: Run a script to stop the servers which are not essential for BI upgrade

In BI 4.x, most of the upgrade failure, or the issue such as after upgrade SIA/CMS cannot be started is caused by the upgrade best practice is not well followed.

An important step which is list in 1757132 – BI4 Support Pack Upgrade and Patch Install Best Practice Guide mentioned that you will need to stop all other BI servers, make only CMS, FRS, Tomcat running in the upgrade process. However, stop them one by one is boring. And during the upgrade process, the SIA will restart several times so to prevent further problems you may also need to set the auto start with SIA flag as false in the server properties page of CMC. What’s more, after the upgrade completed, you have to revert all the changes one by one.

For the above task, we can use BO SDK to build up a simple program to complete it. Below is an example:

  • In this sample, the input from the command line is as the below format:
    -cms <cms> -username <username> -password <password> -authentication <authentication> -mode <mode>
    Parameter authentication is optional. If no input it will use secEnterprise.
  • The available value for mode is that: 0 to print all the current server status.  It will give you the server name, the auto-start status and current running state; 1 to make the servers which are not CMS or FRS to Stopped status and also set it as not auto-start with SIA if it is not set already. Also, the change log will be recorded to a txt file in the same directory for revert usage; 2 to read the change log txt file and revert the changes back.
  • So before we run the upgrade process. We can run this script once and use -mode 1 to change all servers except CMS, FRS to Stopped and not auto-start with SIA status. After upgrade is finished, run this script again and at this time, use -mode 2 to revert all changes back to the original state.

source code is below:

package bosdk;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.crystaldecisions.sdk.framework.CrystalEnterprise;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.framework.ISessionMgr;
import com.crystaldecisions.sdk.occa.infostore.IInfoObjects;
import com.crystaldecisions.sdk.occa.infostore.IInfoStore;
import com.crystaldecisions.sdk.plugin.desktop.server.ExpectedRunState;
import com.crystaldecisions.sdk.plugin.desktop.server.IServer;
import com.crystaldecisions.sdk.plugin.desktop.server.ServerState;

public class ServerStatus {

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static void main(String[] args) {

		// Process the input parameter
		Map<String, String> m_args = null;
		if (args.length > 0) {
			m_args = new HashMap();
			parseArgs(args, m_args);
		} else {
			System.err.println(
					"Arguments not passed. Usage:-cms <cms> -username <username> -password <password> -mode <modeid> and -authentication <authentication> Note: authentication argument is optional");

			System.exit(0);
		}
		String cms = (String) m_args.get("cms");
		String username = (String) m_args.get("username");
		String password = (String) m_args.get("password");
		String modeid = (String) m_args.get("mode");

		if ((username == null) || (password == null) || (cms == null) || (modeid == null) || (username.length() == 0)
				|| (password.length() == 0) || (cms.length() == 0) || (modeid.length() == 0)) {
			System.err.println(
					"Arguments not passed. Usage:-cms <cms> -username <username> -password <password> -mode <modeid> and -authentication <authentication> Note: authentication argument is optional");

			System.exit(0);
		}
		String authentication = (String) m_args.get("authentication");
		if ((authentication == null) || (authentication.length() <= 0)) {
			authentication = "secEnterprise";
		}
		
		if (modeid.equals("0"))
		{
			getServerStatus(username, password, cms, authentication);
		}		
		else if (modeid.equals("1"))
		{
			changeServerStatus(username, password, cms, authentication);
		}
		else if (modeid.equals("2"))
		{
			rollbackServerStatus(username, password, cms, authentication);
		}
		else
		{
			System.err.println(
					"Mode is incorrect. Expect value is 0 for list server status, 1 for change server status, 2 for revert to the original status");

			System.exit(0);
		}
		
	}
	
	// list current server status
	private static void getServerStatus(String username, String password, String cms, String authentication)
	{
		try
		{
			IEnterpriseSession enterpriseSession = null;
			ISessionMgr enterpriseSessionMgr;
			// Login and get the server infoobject
			enterpriseSessionMgr = CrystalEnterprise.getSessionMgr();
			enterpriseSession = enterpriseSessionMgr.logon(username, password, cms, authentication);
			IInfoStore infostore = (IInfoStore) enterpriseSession.getService("InfoStore");
			String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_KIND='server'";
			IInfoObjects servers = infostore.query(serverQuery);
			for (int i = 0; i < servers.size(); i++)
			{
				IServer server = (IServer) infostore.query(serverQuery).get(i);
				// Get the server status
				if (server.getServerKind().equals("aps") || server.getServerKind().equals("fileserver"))
				{
					System.out.println("Server: " + server.getTitle() + ", Autostart: " + server.getAutoBoot() + ", IsCMSorFRS: True.");
				}
				else
				{
					System.out.println("Server: " + server.getTitle() + ", Autostart: " + server.getAutoBoot() + ", IsCMSorFRS: False.");
				}
			}
			enterpriseSession.logoff();
		}
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
		}
	}
	
	// change server status to make other servers (expect CMS and FRS) stopped and not auto-start with SIA
	private static void changeServerStatus(String username, String password, String cms, String authentication)
	{		
		try 
		{
			File changelog = new File("changelog.txt");
			if (changelog.exists())
			{
				System.err.println(
						"Changelog already exists. You cannot do the operation now.");

				System.exit(0);
			}
			
			IEnterpriseSession enterpriseSession = null;
			ISessionMgr enterpriseSessionMgr;
			
			// Login and get the server infoobject
			enterpriseSessionMgr = CrystalEnterprise.getSessionMgr();
			enterpriseSession = enterpriseSessionMgr.logon(username, password, cms, authentication);
			IInfoStore infostore = (IInfoStore) enterpriseSession.getService("InfoStore");
			String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_KIND='server'";
			IInfoObjects servers = infostore.query(serverQuery);
			
			// create changelog.txt file
			// log format is 3 columns, split by comma
			// first column is server's SI_ID
			// second column: 1 means server is auto-start with SIA, otherwise it is blank
			// third column: RUNNING means server is not stopped status, otherwise it is blank
			changelog.createNewFile();
			OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(changelog), "UTF-8");
			
			for (int i = 0; i < servers.size(); i++)
			{
				IServer server = (IServer) infostore.query(serverQuery).get(i);
				
				// For servers which is not CMS or FRS, stop them and change to not auto-start
				if ((server.getServerKind().equals("aps") || server.getServerKind().equals("fileserver")) != true)
				{
					if (server.getAutoBoot() == false && server.getState() == ServerState.STOPPED)
					{
						// no change is needed
						System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": no change is required.");
					}
					else if (server.getAutoBoot() == false)
					{
						// save the current status to log file
						writer.write(server.getID() + ",,RUNNING\r\n");
						// change server as Stopped
						server.setExpectedRunState(ExpectedRunState.STOPPED);
						server.save();						
						System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": server is stopped.");
					}
					else if (server.getState() == ServerState.STOPPED)
					{
						// save the current status to log file
						writer.write(server.getID() + ",1,\r\n");
						// change server as not auto-start
						server.setAutoBoot(false);
						server.save();
						System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": server is set as not auto-start with SIA.");
					}
					else
					{
						// save the current status to log file
						writer.write(server.getID() + ",1," + server.getState().toString() + "\r\n");
						// change server as Stopped and not auto-start
						server.setAutoBoot(false);
						server.setExpectedRunState(ExpectedRunState.STOPPED);
						server.save();
						System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": server is stopped and set as not auto-start with SIA.");
					}
				}
			}
			
			writer.close();
			enterpriseSession.logoff();
			
		} 
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
		}
	}
	
	// revert changes
	private static void rollbackServerStatus(String username, String password, String cms, String authentication)
	{		
		try
		{
			File changelog = new File("changelog.txt");
			if (changelog.exists() == false)
			{
				System.err.println(
						"Changelog didn't exists. You cannot do the operation now.");

				System.exit(0);
			}
			IEnterpriseSession enterpriseSession = null;
			ISessionMgr enterpriseSessionMgr;
			
			// Login and get the server infoobject
			enterpriseSessionMgr = CrystalEnterprise.getSessionMgr();
			enterpriseSession = enterpriseSessionMgr.logon(username, password, cms, authentication);
			IInfoStore infostore = (IInfoStore) enterpriseSession.getService("InfoStore");
			String serverQuery = "select * from CI_SYSTEMOBJECTS where SI_KIND='server'";
			IInfoObjects servers = infostore.query(serverQuery);
			
			

			InputStreamReader reader = new InputStreamReader(new FileInputStream(changelog), "UTF-8");
			BufferedReader br = new BufferedReader(reader);
			
			ArrayList<String[]> changelist = new ArrayList<String[]>();
			String line = "";
			
			while((line=br.readLine())!= null) 
			{
				String[] tmp = line.split(",");
				changelist.add(tmp);
			}
			br.close();
			reader.close();
			
			for (int i = 0; i < servers.size(); i++)
			{
				IServer server = (IServer) infostore.query(serverQuery).get(i);
				
				// For servers which is not CMS or FRS, stop them and change to not auto-start
				if ((server.getServerKind().equals("aps") || server.getServerKind().equals("fileserver")) != true)
				{
					for (int j = 0; j < changelist.size(); j++)
					{
						if (changelist.get(j)[0].equals(String.valueOf(server.getID())))
						{
							if (changelist.get(j)[1].equals("1") == true)
							{
								// need to rollback as auto-start
								server.setAutoBoot(true);
								System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": change back as auto-start with SIA.");
							}
							if (changelist.get(j)[2] != null && changelist.get(j)[2].equals("") == false)
							{
								// need to rollback as Running
								server.setExpectedRunState(ExpectedRunState.RUNNING);
								System.out.println("Server: " + server.getTitle() + ", ID: " + server.getID() + ": change back as Running.");
							}
							server.save();	
							break;
						}								
					}
				}
			}
			
			changelog.delete();
			enterpriseSession.logoff();
			
		} 
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
		}
	}

	// process input parameters
	private static void parseArgs(String[] args, Map<String, String> m_args) {
		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-")) {
				String arg = trimArg(args[i]);
				if (arg.length() != 0) {
					i++;
					String value = "";
					if (i < args.length) {
						value = args[i];
						if (value.startsWith("-")) {
							value = "";
							i--;
						}
					}
					m_args.put(arg, value);
				}
			}
		}
	}

	private static String trimArg(String arg) {
		if (arg == null) {
			return arg;
		}
		int i = 0;
		for (i = 0; i < arg.length(); i++) {
			if (arg.charAt(i) != '-') {
				break;
			}
		}
		String trimmedArg = arg.substring(i);
		return trimmedArg;
	}

}

 

To run this code, you will also need to include the basic jar files, such as: cecore.jar, celib.jar. cesdk.jar, cesession.jar and etc. All the jar files can be found in the BO installation folder as the following path in a windows installation:
<bo installation>\SAP BusinessObjects Enterprise XI 4.0\java\lib

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Moritz Hoedel
      Moritz Hoedel

      Hi Xiaoping Zheng,

      Thanks for sharing the script.
      I'm using this already in our BIP update, which is ongoing at the moment.

      I guess it's just provided as it is and it's helpful already,
      but I have just some suggestions to even improve it:
      - It would be nice if the script would also create a changelog.txt file when using mode 0 (e.g. for inventory reasons)
      - There should be a confirmation prompt (e.g. Y/N) before actually executing,
      at least when using mode 1, for safety reasons
      - I have observed that the script is quite slow in some cases.
      At a first glance it looks like this happens mainly in clustered environments.
      Maybe the performance can be optimized.
      - The changelog.txt should be an xml file or similar
      - It would be helpful if the changelog file would be human-readable (which could be achieved by changing to the xml format)
      - The naming of the changelog file should include the SIA Name or SAP SID, for example to avoid the risk of overwriting it by accident.
      - The stopping/starting is based on the Server IDs, which is not a big issue, but a bit confusing.
      Based on the default order in the CMC's Servers view would feel more natural to the user,
      e.g. when checking the actual process via the CMC in parallel.
      - A kind of finish message would be helpful, too. (for all modes)
      - The script should check if the processes are actually stopped on the OS level, since there are some processes which get stuck quite often, like the ConnectionServer32, for example.
      -> I can imagine this last one is quite hard to achieve or even out of the scope of BI4 SDK,
      due to the different architectures, etc., but actually it's critical.

      And the end the biggest wish, which is not so easy to achieve I guess:
      - Add this to the official release, in form of a button or menu, since it's actually a mandatory feature which should be available in enterprise software like this. 🙂
      We have similar things in SAP ECC, too (e.g. stop_sap+ start_sap or BTCTRNS1 and BTCTRNS2).

      Best Regards
      Moritz

      Author's profile photo Xiaoping Zheng
      Xiaoping Zheng
      Blog Post Author

       

      Hi Moritz,

      Thanks a lot for your comment and advise.
      This sample code is a very simple example which just did the basic things to change the servers.
      Of course some more complex logic can be added with the user's actual needs.

      For the performance issue, I am afraid this is more about the server's actual state but is difficult to adjust in this program code level. You can see this code logic is very simple and it is just using the basic SDK library method. There is less thing can be done here.

      Regards,
      Xiaoping