Name

global.UpgradeClient

Description

Client Upgrade Process

Script

gs.include("PrototypeServer");

var UpgradeClient = Class.create();

// This variable is used in upgrade_complete.js to check if upgrade_complete was invoked from upgrade client or directly
var upgradeStartedByUpgradeClient = true;

/**
* There are several entry points on this script:
* 
* 1) process <- DistUpgrade, the process of upgrading code (ie: WAR)
* 2) upgradeScript <- DataUpgrade, the process of upgrading data on the first boot with the new code (ie: DB records, etc.)
* 3) runUpdateScript <- A partial DistUpgrade used for cluster upgrades (called via ClusterMessage)
* 
* This will be separated into two scripts (upgrade vs. update) when war upgrade functionality is removed (and only dist functionality is available).
*/
UpgradeClient.prototype = {
 UPGRADE_VERSION : 'glide.war.assigned',
 WAR_VERSION : 'glide.war',
 BUILD_VERSION: 'glide.node.dist',
 NO_UPGRADE_VERSION : 'glide.war.no_upgrade', // set by Rollback
 UPGRADE_SCRIPT : gs.getProperty("glide.sys.upgrade_script"),
 LOGGER : new UpgradeLogger(),
 
 initialize: function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    this.upgrade_server_url = gs.getProperty("upgrade_server_url");
    this.instance_id = gs.getProperty("instance_id");
 },
 
 // Called from event: Upgrade
 upgradeScript : function() {
  	gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
  	SNC.UpgradeAPI.dbUpgradeAfterCheck();
 },
 
 execUpgrade : function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release"); 
    gs.loadBatchScript("sys.scripts/" + this.UPGRADE_SCRIPT);
 },
 
 notifySuccess : function(desired) {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    SNC.UpgradeAPI.notifySuccess(desired);
 },
 
 // Since .zip.war's are not "first-class" artifacts, and since older glide
 // UpgradeClient versions (which cannot be changed since we must support a
 // one-step upgrade) write .zip.war into these DB properties, they need to 
 // be "corrected" to .zip before they are read by the new UpgradeClient
 // version.
 sanitizeDBProperties: function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    var war_version = gs.getProperty(this.WAR_VERSION)
    if (war_version != null && war_version.match(/\.zip\.war$/)) {
       this.LOGGER.log("Converting " + this.WAR_VERSION + " from .zip.war to a .zip (" + war_version + ")");
       war_version = war_version.replace(/\.zip\.war$/, ".zip");
       gs.setProperty(this.WAR_VERSION, war_version, "Current Version");
    }
    var upgrade_version = gs.getProperty(this.UPGRADE_VERSION)
    if (upgrade_version != null && upgrade_version.match(/\.zip\.war$/)) {
       this.LOGGER.log("Converting " + this.UPGRADE_VERSION + " from .zip.war to a .zip (" + upgrade_version + ")");
       upgrade_version = upgrade_version.replace(/\.zip\.war$/, ".zip");
       gs.setProperty(this.UPGRADE_VERSION, upgrade_version, "Assigned version");
    }	   
 },
 
 // Called from script include: UpgradeClient
 process: function() {
  	gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
  	SNC.UpgradeAPI.distDBUpgradeAfterCheck();
 },
 
 processWar: function(war_file) {
       gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
       var ujob = new GlideWarDownloader();
       var success = ujob.downloadWar(war_file);
       if (success)
          this.LOGGER.log("Successful download of " + war_file);
       else {
          this.LOGGER.log("Failed to download " + war_file + ". Will retry in 1 hour");
          return;
       }
       gs.setProperty(this.UPGRADE_VERSION, war_file, "Assigned version");
       new GlideWarDeleter().deleteOldWars(war_file);
       
       this.shutdownAndRestart(war_file);
 },
 
 processDist: function(dist_file) {
     gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
     var manager = new GlideUpgradeArtifactManager();
     var success = manager.download(dist_file);
     if (success)
  	   this.LOGGER.log("Successful download of " + dist_file);
     else {
  	   this.LOGGER.log("Failed to download " + dist_file + ". Will retry in 1 hour");
  	   return;
     }
     gs.setProperty(this.UPGRADE_VERSION, dist_file, "Assigned version");
     manager.deleteArtifactsExcept(dist_file);
     
     this.shutdownAndRestart(dist_file);
 },
 
 shutdownAndRestart : function(artifact_filename) {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    // find our startup Job and set it to run on our node on next restart
    this.LOGGER.log("Assigning upgrade startup job to this cluster node, " + GlideServlet.getSystemID());
    this.setStartupJob();
    
    // reschedule the upgrade job in the future... this needs to happen before the scheduler
    // is shutdown, otherwise the recover stuck jobs code will revert our schedule/claimed_by
    this.LOGGER.log("Rescheduling the upgrade job");
    this.setUpgradeJob();
    
    try {
          // Send a beat to indicate the node is still online
          new global.EventHeartbeat().beat();
    } catch (e) {
          this.LOGGER.warn(this.UPGRADE_SCRIPT + " Could not send Heartbeat before shutdownAndRestart: " + e.toString());
    }
    
    //report node.dist.upgrade OPEN event for this node, next server restart will report 
    //node.dist.upgrade close event from a sys_trigger
    SNC.UpgradeUtil.reportNodeDistUpgradeOpenEvent("Upgrading to " + artifact_filename);
    
    //record node upgrade start event
    SNC.UpgradeUtil.recordNodeUpgradeStartForLUA(artifact_filename);
    
    this.LOGGER.log("Shutting down workers and cluster synchronizer");
    // shut down everything
    GlideSystemStatus.setShuttingDown();
    GlideWorkerThreadManager.get().shutdownEverything();
    gs.sleep(10000); // wait 10 seconds to give things an opportunity to shut down gracefully
    
    // Tell our peer cluster nodes and replication slaves that a new war has arrived,
    // and they need to follow suit.
    this.notifyPeers(artifact_filename);
    
    this.runUpdateScript(artifact_filename);
 },
 
 // Tell our peer cluster nodes and replication slaves that a new war has arrived,
 // and they need to follow suit.
 notifyPeers: function(artifact_filename) {
  	gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
  	SNC.UpgradeAPI.notifyPeers(artifact_filename);
 },
 
 // Called from Upgrade
 runUpdateScript: function(artifact_filename) {
  	gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
  	SNC.UpgradeAPI.runDistUpgrade(artifact_filename);
 },
 
 setStartupJob : function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    var gr = new GlideRecord("sys_trigger");
    gr.addQuery("name", "Check database for possible upgrade");
    gr.query();
    if (gr.next()) {
       var myID = GlideServlet.getSystemID();
       gr.system_id = myID;
       gr.update();
    }
 },
 
 setUpgradeJob : function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    var nextAction = gs.hoursAgo(-1); // set the next action to be an hour ahead
    this.LOGGER.log('Rescheduling next action for ' + nextAction);

    // Access the global schedule record:
    if (typeof g_schedule_record != 'undefined') {
      var gr = g_schedule_record;

      gr.next_action.setValue(nextAction); 
      gr.claimed_by = null;
      gr.state = 0;
      gr.update();

    } else {
      gs.log("WARNING: 'g_schedule_record' is undefined, unable to reschedule upgrade job")
    }
 },
 
 getWarFile: function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    // create the soap document
    var soapdoc = new SOAPEnvelope("GetWarFile", "http://www.service-now.com/");
    soapdoc.setFunctionName("execute");
    soapdoc.addFunctionParameter("instance_id", this.instance_id);
    soapdoc.addFunctionParameter("current_war", SNC.UpgradeUtil.getCurrentBuild());
    
    // post the request
    var soapRequest = new SOAPRequest(this.upgrade_server_url + "GetWarFile.do?SOAP");
    var soapResponse = soapRequest.post(soapdoc);
    var war_file = gs.getXMLText(soapResponse, "//executeResponse/war_file");
    
    return war_file;
 },

 // Check if it is a developer instance or if the instance id is null.
 // Return true if the instance has no id or it is a developer instance, otherwise, return false.
 // Error will be logged in case of null instance id.
 _shouldSkip: function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    if (this._isDeveloperInstance()) {
      this.LOGGER.log("Developer instance - skipped upgrade");
      return true;
    } else if (GlideJSUtil.isNilJavaObject(this.instance_id)) {
      this.LOGGER.error("Instance ID is null - skipped upgrade");
      return true;
    }
    return false;
 },

 // Check if the instance is a developer instance - test seam
 _isDeveloperInstance: function() {
    gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
    return GlideUtil.isDeveloperInstance();
 },

  /**
   * Checks the current, assigned and revertedFrom WAR values and determines if upgrade needs to run
   * @returns {boolean} true if upgrade needs to be run, false otherwise
   */
  shouldRunUpgrade: function() {
  	gs.warn("DEPRECATED API: The UpgradeClient Script Include has been deprecated, and will be removed in a future release");
  	var desired = gs.getProperty(this.UPGRADE_VERSION);
  	if (!desired) {
  		this.LOGGER.log('No desired war specified. Upgrade will not run');
  		return false;
  	}
  	var current = gs.getProperty(this.WAR_VERSION);
  	var revertedFrom = gs.getProperty(this.NO_UPGRADE_VERSION);
  	if (!current) {
  		this.LOGGER.log('No current war specified. Upgrade will run and set current war');
  	} else if (current == desired) {
  		this.LOGGER.log('Already on desired war ' + desired +'. Upgrade will NOT run');
  		return false;
  	} else if (desired == revertedFrom) {
  		this.LOGGER.log('Desired war matches reverted war specified by property [' + this.NO_UPGRADE_VERSION + ']. Upgrade script will NOT run');
  		return false;
  	}

  	// check if glide.war.assigned matches the distribution build version in glide.node.dist.
  	var build_version = GlideProperties.get(this.BUILD_VERSION);
  	// skip comparing if build version is not set
  	if (!build_version)
  		return true;

  	// glide.node.dist doesn't contain .war or .zip suffix, so we ignore comparing that part
  	var desired_no_suffix = desired.replace(/\.war$/, "");
  	desired_no_suffix = desired_no_suffix.replace(/\.zip$/, "");
  	if (desired_no_suffix != build_version) {
  	    this.LOGGER.error('The desired war does not match the distribution build, desired war (without suffix): ' + desired_no_suffix + ', distribution build: ' + build_version + '. Upgrade will not run');
  		return false;
  	}
  	return true;
  },
 
};

Sys ID

955a5797c0a8006f002349c2505883ab

Offical Documentation

Official Docs: