001/* 002 * #%L 003 * Netarchivesuite - deploy 004 * %% 005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.deploy; 024 025import java.io.File; 026import java.io.IOException; 027import java.io.PrintWriter; 028import java.util.ArrayList; 029import java.util.List; 030 031import org.dom4j.Attribute; 032import org.dom4j.Element; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import dk.netarkivet.common.exceptions.ArgumentNotValid; 037import dk.netarkivet.common.exceptions.IOFailure; 038import dk.netarkivet.common.exceptions.IllegalState; 039import dk.netarkivet.common.utils.FileUtils; 040 041/** 042 * Machine defines an abstract representation of a physical computer at a physical location. The actual instances are 043 * depending on the operation system: LinuxMachine and WindowsMachine. All non-OS specific methods are implemented this 044 * machine class. 045 */ 046public abstract class Machine { 047 048 /** the log, for logging stuff instead of displaying them directly. */ 049 protected static final Logger log = LoggerFactory.getLogger(Machine.class); 050 /** The root-branch for this machine in the XML tree. */ 051 protected Element machineRoot; 052 /** The settings, inherited from parent and overwritten. */ 053 protected XmlStructure settings; 054 /** The machine parameters. */ 055 protected Parameters machineParameters; 056 /** The list of the application on this machine. */ 057 protected List<Application> applications; 058 /** The name of this machine. */ 059 protected String hostname; 060 /** The operating system on this machine: 'windows' or 'linux'. */ 061 protected String operatingSystem; 062 /** The extension on the script files (specified by operating system). */ 063 protected String scriptExtension; 064 /** The name of the NetarchiveSuite.zip file. */ 065 protected String netarchiveSuiteFileName; 066 /** The inherited SLF4J config file. */ 067 protected File inheritedSlf4jConfigFile; 068 /** The inherited security.policy file. */ 069 protected File inheritedSecurityPolicyFile; 070 /** The inherited database file name. */ 071 protected File databaseFile; 072 /** The inherited archive database file name. */ 073 protected File arcDatabaseFile; 074 /** The directory for this machine. */ 075 protected File machineDirectory; 076 /** Whether the temp dir should be cleaned. */ 077 protected boolean resetTempDir; 078 /** The folder containing the external jar library files. */ 079 protected File jarFolder; 080 /** The encoding to use when writing files. */ 081 protected String targetEncoding; 082 /** user specific logo png file */ 083 protected File logoFile; 084 /** user specific menulogo png file */ 085 protected File menulogoFile; 086 087 /** 088 * A machine is referring to an actual computer at a physical location, which can have independent applications from 089 * the other machines at the same location. 090 * 091 * @param subTreeRoot The root of this instance in the XML document. 092 * @param parentSettings The setting inherited by the parent. 093 * @param param The machine parameters inherited by the parent. 094 * @param netarchiveSuiteSource The name of the NetarchiveSuite package file. 095 * @param securityPolicy The security policy file. 096 * @param dbFileName The name of the database file. 097 * @param archiveDbFileName The name of the archive database file. 098 * @param resetDir Whether the temporary directory should be reset. 099 * @param externalJarFolder The folder containing the external jar library files. 100 * @throws ArgumentNotValid If one of the following arguments are null: subTreeRoot, parentSettings, param, 101 * netarchiveSuiteSource, logProp, securityPolicy. 102 */ 103 public Machine(Element subTreeRoot, XmlStructure parentSettings, Parameters param, String netarchiveSuiteSource, 104 File slf4JConfig, File securityPolicy, File dbFileName, File archiveDbFileName, 105 boolean resetDir, File externalJarFolder, File aLogoFile, File aMenulogoFile) throws ArgumentNotValid { 106 ArgumentNotValid.checkNotNull(subTreeRoot, "Element subTreeRoot"); 107 ArgumentNotValid.checkNotNull(parentSettings, "XmlStructure parentSettings"); 108 ArgumentNotValid.checkNotNull(param, "Parameters param"); 109 ArgumentNotValid.checkNotNull(netarchiveSuiteSource, "String netarchiveSuiteSource"); 110 ArgumentNotValid.checkNotNull(slf4JConfig, "File slf4JConfig"); 111 ArgumentNotValid.checkNotNull(securityPolicy, "File securityPolicy"); 112 113 settings = new XmlStructure(parentSettings.getRoot()); 114 machineRoot = subTreeRoot; 115 machineParameters = new Parameters(param); 116 netarchiveSuiteFileName = netarchiveSuiteSource; 117 inheritedSlf4jConfigFile = slf4JConfig; 118 inheritedSecurityPolicyFile = securityPolicy; 119 databaseFile = dbFileName; 120 arcDatabaseFile = archiveDbFileName; 121 resetTempDir = resetDir; 122 jarFolder = externalJarFolder; 123 logoFile = aLogoFile; 124 menulogoFile = aMenulogoFile; 125 126 // Retrieve machine encoding 127 targetEncoding = machineRoot.attributeValue(Constants.MACHINE_ENCODING_ATTRIBUTE); 128 String msgTail = ""; 129 if (targetEncoding == null || targetEncoding.isEmpty()) { 130 targetEncoding = Constants.MACHINE_ENCODING_DEFAULT; 131 msgTail = " (defaulted)"; 132 } 133 System.out.println("Machine '" + machineRoot.attributeValue(Constants.MACHINE_NAME_ATTRIBUTE) 134 + "' configured with encoding '" + targetEncoding + "'" + msgTail); 135 136 // retrieve the specific settings for this instance 137 Element tmpSet = machineRoot.element(Constants.COMPLETE_SETTINGS_BRANCH); 138 // Generate the specific settings by combining the general settings 139 // and the specific, (only if this instance has specific settings) 140 if (tmpSet != null) { 141 settings.overWrite(tmpSet); 142 } 143 144 // check if new machine parameters 145 machineParameters.newParameters(machineRoot); 146 // Retrieve the variables for this instance. 147 extractVariables(); 148 // generate the machines on this instance 149 extractApplications(); 150 } 151 152 /** 153 * Extract the local variables from the root. Currently, this is the name and the operating system. 154 */ 155 private void extractVariables() { 156 // retrieve name 157 Attribute at = machineRoot.attribute(Constants.MACHINE_NAME_ATTRIBUTE); 158 if (at != null) { 159 hostname = at.getText().trim(); 160 } else { 161 throw new IllegalState("A Machine instance has no name!"); 162 } 163 } 164 165 /** 166 * Extracts the XML for the applications from the root, creates the applications and puts them into the list. 167 */ 168 @SuppressWarnings("unchecked") 169 private void extractApplications() { 170 applications = new ArrayList<Application>(); 171 List<Element> le = machineRoot.elements(Constants.DEPLOY_APPLICATION_NAME); 172 for (Element e : le) { 173 applications.add(new Application(e, settings, machineParameters, targetEncoding)); 174 } 175 } 176 177 /** 178 * Create the directory for the specific configurations of this machine and call the functions for creating all the 179 * scripts in this directory. 180 * 181 * @param parentDirectory The directory where to write the files. 182 * @throws ArgumentNotValid If the parenteDirectory is null. 183 */ 184 public void write(File parentDirectory) throws ArgumentNotValid { 185 ArgumentNotValid.checkNotNull(parentDirectory, "File parentDirectory"); 186 187 // create the directory for this machine 188 machineDirectory = new File(parentDirectory, hostname); 189 FileUtils.createDir(machineDirectory); 190 191 // 192 // create the content in the directory 193 // 194 195 // Create kill scripts 196 createApplicationKillScripts(machineDirectory); 197 createOSLocalKillAllScript(machineDirectory); 198 createHarvestDatabaseKillScript(machineDirectory); 199 createArchiveDatabaseKillScript(machineDirectory); 200 // create start scripts 201 createApplicationStartScripts(machineDirectory); 202 createOSLocalStartAllScript(machineDirectory); 203 createHarvestDatabaseStartScript(machineDirectory); 204 createArchiveDatabaseStartScript(machineDirectory); 205 createHarvestDatabaseUpdateScript(machineDirectory, false); 206 // create restart script 207 createRestartScript(machineDirectory); 208 // copy the security policy file 209 createSecurityPolicyFile(machineDirectory); 210 // create the SLF4J property files 211 createSlf4jConfigFiles(machineDirectory); 212 // create the jmx remote files 213 createJmxRemotePasswordFile(machineDirectory); 214 createJmxRemoteAccessFile(machineDirectory); 215 // create the installCreateDir script 216 createInstallDirScript(parentDirectory); 217 218 // write the settings for all application at this machine 219 for (Application app : applications) { 220 app.createSettingsFile(machineDirectory); 221 } 222 } 223 224 /** 225 * Make the script for killing this machine. This is put into the entire kill all script for the physical location. 226 * 227 * @return The script to kill this machine. 228 */ 229 public String writeToGlobalKillScript() { 230 StringBuilder res = new StringBuilder(); 231 res.append(ScriptConstants.writeKillMachineHeader(machineUserLogin())); 232 // write the operating system dependent part of the kill script 233 res.append(osKillScript()); 234 return res.toString(); 235 } 236 237 /** 238 * Make the script for installing this machine. This is put into the entire install script for the physical 239 * location. 240 * 241 * @return The script to make the installation on this machine 242 */ 243 public String writeToGlobalInstallScript() { 244 StringBuilder res = new StringBuilder(); 245 res.append(ScriptConstants.writeInstallMachineHeader(machineUserLogin())); 246 // write the operating system dependent part of the install script 247 res.append(osInstallScript()); 248 return res.toString(); 249 } 250 251 /** 252 * Make the script for starting this machine. This is put into the entire startall script for the physical location. 253 * 254 * @return The script to start this machine. 255 */ 256 public String writeToGlobalStartScript() { 257 StringBuilder res = new StringBuilder(); 258 res.append(ScriptConstants.writeStartMachineHeader(machineUserLogin())); 259 // write the operating system dependent part of the start script 260 res.append(osStartScript()); 261 return res.toString(); 262 } 263 264 /** 265 * Copy inherited securityPolicyFile to local directory. 266 * 267 * @param directory The local directory for this machine. 268 * @throws IOFailure If an error occurred during the creation of the security policy file. 269 */ 270 protected void createSecurityPolicyFile(File directory) throws IOFailure { 271 // make file 272 File secPolFile = new File(directory, Constants.SECURITY_POLICY_FILE_NAME); 273 try { 274 // init writer 275 PrintWriter secPrinter = new PrintWriter(secPolFile, getTargetEncoding()); 276 try { 277 // read the inherited security policy file. 278 String prop = FileUtils.readFile(inheritedSecurityPolicyFile); 279 280 // change the jmx monitor role (if defined in settings) 281 String monitorRole = settings.getLeafValue(Constants.SETTINGS_MONITOR_JMX_NAME_LEAF); 282 if (monitorRole != null) { 283 prop = prop.replace(Constants.SECURITY_JMX_PRINCIPAL_NAME_TAG, monitorRole); 284 } 285 286 // Change the common temp dir (if defined in settings) 287 String ctd = settings.getLeafValue(Constants.SETTINGS_TEMPDIR_LEAF); 288 if (ctd != null) { 289 prop = prop.replace(Constants.SECURITY_COMMON_TEMP_DIR_TAG, ctd); 290 } 291 292 // write to file. 293 secPrinter.write(prop); 294 295 // initialise list of directories to add 296 List<String> dirs = new ArrayList<String>(); 297 298 // get all directories to add and put them into the list 299 for (Application app : applications) { 300 // get archive.fileDir directory. 301 String[] tmpDirs = app.getSettingsValues(Constants.SETTINGS_BITARCHIVE_BASEFILEDIR_LEAF); 302 if (tmpDirs != null && tmpDirs.length > 0) { 303 for (String st : tmpDirs) { 304 dirs.add(st); 305 } 306 } 307 } 308 309 // append file directories 310 if (!dirs.isEmpty()) { 311 secPrinter.write("grant {" + "\n"); 312 for (String dir : dirs) { 313 secPrinter.write(ScriptConstants 314 .writeSecurityPolicyDirPermission(changeFileDirPathForSecurity(dir))); 315 } 316 secPrinter.write("};"); 317 } 318 } finally { 319 secPrinter.close(); 320 } 321 } catch (IOException e) { 322 log.warn("IOException while creating security policy file: ", e); 323 throw new IOFailure("Cannot create security policy file.", e); 324 } 325 } 326 327 /** 328 * Creates a the SLF4J config file for every application. This is done by taking the inherited log file and changing 329 * "APPID" in the file into the identification of the application. 330 * 331 * @param directory The local directory for this machine 332 * @throws IOFailure If an error occurred during the creationg of the log property file. 333 */ 334 protected void createSlf4jConfigFiles(File directory) throws IOFailure { 335 // make config file for every application 336 for (Application app : applications) { 337 // make file 338 File logProp = new File(directory, Constants.SLF4J_CONFIG_APPLICATION_PREFIX + app.getIdentification() 339 + Constants.SLF4J_CONFIG_APPLICATION_SUFFIX); 340 try { 341 // init writer 342 PrintWriter logPrinter = new PrintWriter(logProp, getTargetEncoding()); 343 344 try { 345 // read the inherited log property file. 346 String prop = FileUtils.readFile(inheritedSlf4jConfigFile); 347 348 // append stuff! 349 prop = prop.replace(Constants.LOG_PROPERTY_APPLICATION_ID_TAG, app.getIdentification()); 350 prop = modifyLogProperties(prop); 351 // write to file. 352 logPrinter.write(prop); 353 } finally { 354 logPrinter.close(); 355 } 356 } catch (IOException e) { 357 log.warn("IOException while creating SLF4J config file:", e); 358 throw new IOFailure("Cannot create SLF4J config file.", e); 359 } 360 } 361 } 362 363 /** 364 * Make any OS-specific modifications to logging properties. The default makes no modifications, but this can be 365 * overridden in subclasses. 366 * 367 * @param logProperties the contents of the logging properties file. 368 * @return the contents of the logging properties file with any desired modifications. 369 */ 370 protected String modifyLogProperties(String logProperties) { 371 return logProperties; 372 } 373 374 /** 375 * Creates the jmxremote.password file, based on the settings. 376 * 377 * @param directory The local directory for this machine 378 * @throws IOFailure If an error occurred during the creation of the jmx remote password file. 379 */ 380 protected void createJmxRemotePasswordFile(File directory) throws IOFailure { 381 // make file 382 File jmxFile = new File(directory, Constants.JMX_PASSWORD_FILE_NAME); 383 try { 384 // init writer 385 PrintWriter jw = new PrintWriter(jmxFile, getTargetEncoding()); 386 try { 387 // Write the header of the jmxremote.password file. 388 jw.print(ScriptConstants.JMXREMOTE_PASSWORD_HEADER); 389 390 // Get the username and password for monitor and heritrix. 391 StringBuilder logins = new StringBuilder(); 392 393 // Append the jmx logins for monitor and heritrix. 394 logins.append(getMonitorLogin()); 395 logins.append(getHeritrixLogin()); 396 397 jw.print(logins.toString()); 398 } finally { 399 jw.close(); 400 } 401 } catch (IOException e) { 402 log.trace("IOException while creating jmxremote.password:", e); 403 throw new IOFailure("Cannot create jmxremote.password.", e); 404 } 405 } 406 407 /** 408 * Creates the jmxremote.password file, based on the settings. 409 * 410 * @param directory The local directory for this machine 411 * @throws IOFailure If an error occurred during the creation of the jmx remote access file. 412 */ 413 protected void createJmxRemoteAccessFile(File directory) throws IOFailure { 414 // make file 415 File jmxFile = new File(directory, Constants.JMX_ACCESS_FILE_NAME); 416 try { 417 // init writer 418 PrintWriter jw = new PrintWriter(jmxFile, getTargetEncoding()); 419 try { 420 // Write the header of the jmxremote.password file. 421 jw.print(ScriptConstants.JMXREMOTE_ACCESS_HEADER); 422 423 // Get the username and password for monitor and heritrix. 424 StringBuilder logins = new StringBuilder(); 425 426 // Append the jmx logins for monitor and heritrix. 427 logins.append(getMonitorUsername()); 428 logins.append(getHeritrixUsername()); 429 430 jw.print(logins.toString()); 431 } finally { 432 jw.close(); 433 } 434 } catch (IOException e) { 435 log.trace("IOException while creating jmxremote.access file:", e); 436 throw new IOFailure("Cannot create jmxremote.access file.", e); 437 } 438 } 439 440 /** 441 * For finding the jmxUsernames and jmxPasswords under the monitor branch in the settings. Goes through all 442 * applications, which all must have the same username and the same passwords. 443 * 444 * @return The string to add to the jmxremote.password file. 445 * @throws IllegalState If there is a different amount of usernames and passwords, or if two application has 446 * different values for their username or passwords (applications without values are ignored). 447 */ 448 protected String getMonitorLogin() throws IllegalState { 449 StringBuilder res = new StringBuilder(); 450 // initialise list of usernames and passwords to add 451 List<String> usernames = new ArrayList<String>(); 452 List<String> passwords = new ArrayList<String>(); 453 String[] tmpVals; 454 455 // get values from applications and put them into the lists 456 for (Application app : applications) { 457 // get monitor.jmxUsername 458 tmpVals = app.getSettingsValues(Constants.SETTINGS_MONITOR_JMX_NAME_LEAF); 459 if (tmpVals != null && tmpVals.length > 0) { 460 for (String st : tmpVals) { 461 usernames.add(st); 462 } 463 } 464 // get monitor.jmxPassword 465 tmpVals = app.getSettingsValues(Constants.SETTINGS_MONITOR_JMX_PASSWORD_LEAF); 466 if (tmpVals != null && tmpVals.length > 0) { 467 for (String st : tmpVals) { 468 passwords.add(st); 469 } 470 } 471 } 472 473 // if different amount of usernames and passwords => DIE 474 if (usernames.size() != passwords.size()) { 475 String msg = "Different amount of usernames and passwords in monitor under applications on machine: '" 476 + hostname + "'"; 477 log.warn(msg); 478 throw new IllegalState(msg); 479 } 480 481 // warn if no usernames for monitor. 482 if (usernames.size() == 0) { 483 log.warn("No usernames or passwords for monitor on machine: '{}'", hostname); 484 } 485 486 // check if the usernames and passwords are the same. 487 for (int i = 1; i < usernames.size(); i++) { 488 if (!usernames.get(0).equals(usernames.get(i)) || !passwords.get(0).equals(passwords.get(i))) { 489 String msg = "Different usernames or passwords under monitor on the same machine: '" + hostname + "'"; 490 log.warn(msg); 491 throw new IllegalState(msg); 492 } 493 } 494 495 // make the resulting string 496 if (usernames.size() > 0) { 497 res.append(usernames.get(0)); 498 res.append(Constants.SPACE); 499 res.append(passwords.get(0)); 500 res.append(Constants.NEWLINE); 501 } 502 return res.toString(); 503 } 504 505 /** 506 * For retrieving the monitor username for the jmxremote.access file. This will have the rights 'readonly'. 507 * 508 * @return The string for the jmxremote.access file for allowing the monitor user to readonly. 509 * @throws IllegalState If different applications on the machine have different user names. 510 */ 511 protected String getMonitorUsername() throws IllegalState { 512 StringBuilder res = new StringBuilder(); 513 // initialise list of usernames and passwords to add 514 List<String> usernames = new ArrayList<String>(); 515 String[] tmpVals; 516 517 // get values from applications and put them into the lists 518 for (Application app : applications) { 519 // get monitor.jmxUsername 520 tmpVals = app.getSettingsValues(Constants.SETTINGS_MONITOR_JMX_NAME_LEAF); 521 if (tmpVals != null && tmpVals.length > 0) { 522 for (String st : tmpVals) { 523 usernames.add(st); 524 } 525 } 526 } 527 528 // check if the usernames and passwords are the same. 529 for (int i = 1; i < usernames.size(); i++) { 530 if (!usernames.get(0).equals(usernames.get(i))) { 531 String msg = "Different usernames for the monitor on the same machine: '" + hostname + "'"; 532 log.warn(msg); 533 throw new IllegalState(msg); 534 } 535 } 536 537 // make the resulting string 538 if (usernames.size() > 0) { 539 res.append(usernames.get(0)); 540 res.append(Constants.SPACE); 541 res.append(ScriptConstants.JMXREMOTE_MONITOR_PRIVILEGES); 542 res.append(Constants.NEWLINE); 543 } 544 return res.toString(); 545 } 546 547 /** 548 * For finding the jmxUsernames and jmxPasswords under the harvest.harvesting.heritrix branch under in the settings. 549 * Goes through all applications, which all must have the same username and the same passwords. 550 * 551 * @return The string to add to the jmxremote.password file. 552 * @throws IllegalState If there is a different amount of usernames and passwords, or if two application has 553 * different values for their username or passwords (applications without values are ignored). 554 */ 555 protected String getHeritrixLogin() throws IllegalState { 556 StringBuilder res = new StringBuilder(); 557 // initialise list of usernames and passwords to add 558 List<String> usernames = new ArrayList<String>(); 559 List<String> passwords = new ArrayList<String>(); 560 String[] tmpVals; 561 562 // get values from applications and put them into the lists 563 for (Application app : applications) { 564 // get heritrix.jmxUsername 565 tmpVals = app.getSettingsValues(Constants.SETTINGS_HERITRIX_JMX_USERNAME_LEAF); 566 if (tmpVals != null && tmpVals.length > 0) { 567 for (String st : tmpVals) { 568 usernames.add(st); 569 } 570 } 571 // get heritrix.jmxPassword 572 tmpVals = app.getSettingsValues(Constants.SETTINGS_HERITRIX_JMX_PASSWORD_LEAF); 573 if (tmpVals != null && tmpVals.length > 0) { 574 for (String st : tmpVals) { 575 passwords.add(st); 576 } 577 } 578 } 579 580 // if different amount of usernames and passwords. DIE 581 if (usernames.size() != passwords.size()) { 582 String msg = "Different amount of usernames and passwords in heritrix under applications on machine: '" 583 + hostname + "'"; 584 log.warn(msg); 585 throw new IllegalState(msg); 586 } 587 588 // if no usernames, and thus no passwords, finish! 589 if (usernames.size() == 0) { 590 return ""; 591 } 592 593 // check if the usernames and passwords are the same. 594 for (int i = 1; i < usernames.size(); i++) { 595 if (!usernames.get(0).equals(usernames.get(i)) || !passwords.get(0).equals(passwords.get(i))) { 596 String msg = "Different usernames or passwords " + "under heritrix on machine: '" + hostname + "'"; 597 log.warn(msg); 598 throw new IllegalState(msg); 599 } 600 } 601 602 // make the resulting string 603 if (usernames.size() > 0) { 604 res.append(usernames.get(0)); 605 res.append(Constants.SPACE); 606 res.append(passwords.get(0)); 607 res.append(Constants.NEWLINE); 608 } 609 return res.toString(); 610 } 611 612 /** 613 * For retrieving the Heritrix username for the jmxremote.access file. This will have the rights 'readwrite'. 614 * 615 * @return The string for the jmxremote.access file for allowing the heritrix user to readonly. 616 */ 617 protected String getHeritrixUsername() { 618 StringBuilder res = new StringBuilder(); 619 // initialise list of usernames and passwords to add 620 List<String> usernames = new ArrayList<String>(); 621 String[] tmpVals; 622 623 // get values from applications and put them into the lists 624 for (Application app : applications) { 625 // get heritrix.jmxUsername 626 tmpVals = app.getSettingsValues(Constants.SETTINGS_HERITRIX_JMX_USERNAME_LEAF); 627 if (tmpVals != null && tmpVals.length > 0) { 628 for (String st : tmpVals) { 629 usernames.add(st); 630 } 631 } 632 } 633 634 // check if the usernames and passwords are the same. 635 for (int i = 1; i < usernames.size(); i++) { 636 if (!usernames.get(0).equals(usernames.get(i))) { 637 String msg = "Different usernames for Heritrix on the same machine: '" + hostname + "'"; 638 log.warn(msg); 639 throw new IllegalState(msg); 640 } 641 } 642 643 // make the resulting string 644 if (usernames.size() > 0) { 645 res.append(usernames.get(0)); 646 res.append(Constants.SPACE); 647 res.append(ScriptConstants.JMXREMOTE_HERITRIX_PRIVILEGES); 648 res.append(Constants.NEWLINE); 649 } 650 return res.toString(); 651 } 652 653 protected StringBuilder updateLogofileInWarFiles(StringBuilder aRes, File aLogofile, String aDestinationFilename) { 654 aRes.append("scp " + aLogofile.getAbsolutePath() + " " + machineUserLogin() + ":" + getInstallDirPath() + "/" + Constants.WEBPAGESDIR + "/" + aDestinationFilename + Constants.NEWLINE); 655 656 for (String war : Constants.WARFILENAMES) { 657 aRes.append("ssh " + machineUserLogin() + " \"cd " + getInstallDirPath() + "/" + Constants.WEBPAGESDIR + "; zip -r " + war + " " + aDestinationFilename + "\"" + Constants.NEWLINE); 658 } 659 660 aRes.append("ssh " + machineUserLogin() + " \"rm " + getInstallDirPath() + "/" + Constants.WEBPAGESDIR + "/" + aDestinationFilename + "\"" + Constants.NEWLINE); 661 662 return aRes; 663 } 664 665 /** 666 * The string for accessing this machine through SSH. 667 * 668 * @return The access through SSH to the machine 669 */ 670 protected String machineUserLogin() { 671 return machineParameters.getMachineUserName().getStringValue().trim() + Constants.AT + hostname; 672 } 673 674 /** 675 * For retrieving the environment name variable. 676 * 677 * @return The environment name. 678 */ 679 protected String getEnvironmentName() { 680 return settings.getSubChildValue(Constants.SETTINGS_ENVIRONMENT_NAME_LEAF); 681 } 682 683 /** 684 * Creates the kill scripts for all the applications. 685 * 686 * @param directory The directory for this machine (use global variable?). 687 */ 688 protected abstract void createApplicationKillScripts(File directory); 689 690 /** 691 * Creates the start scripts for all the applications. 692 * 693 * @param directory The directory for this machine (use global variable?). 694 */ 695 protected abstract void createApplicationStartScripts(File directory); 696 697 /** 698 * This function creates the script to start all applications on this machine. The scripts calls all the start 699 * script for each application. 700 * 701 * @param directory The directory for this machine (use global variable?). 702 */ 703 protected abstract void createOSLocalStartAllScript(File directory); 704 705 /** 706 * This function creates the script to kill all applications on this machine. The scripts calls all the kill script 707 * for each application. 708 * 709 * @param directory The directory for this machine (use global variable?). 710 */ 711 protected abstract void createOSLocalKillAllScript(File directory); 712 713 /** 714 * The operation system specific path to the installation directory. 715 * 716 * @return Install path. 717 */ 718 protected abstract String getInstallDirPath(); 719 720 /** 721 * The operation system specific path to the conf directory. 722 * 723 * @return Conf path. 724 */ 725 protected abstract String getConfDirPath(); 726 727 /** 728 * The operation system specific path to the lib directory. 729 * 730 * @return Lib path. 731 */ 732 protected abstract String getLibDirPath(); 733 734 /** 735 * Creates the operation system specific killing script for this machine. 736 * 737 * @return Operation system specific part of the killscript. 738 */ 739 protected abstract String osKillScript(); 740 741 /** 742 * Creates the operation system specific installation script for this machine. 743 * 744 * @return Operation system specific part of the installscript. 745 */ 746 protected abstract String osInstallScript(); 747 748 /** 749 * Creates the specified directories in the deploy-configuration file. 750 * 751 * @return The script for creating the directories. 752 */ 753 protected abstract String osInstallScriptCreateDir(); 754 755 /** 756 * Updates user specific Logos in all war files. 757 * 758 * @return The script for updating logos in all war files. 759 */ 760 protected abstract String osUpdateLogos(); 761 762 /** 763 * Creates the operation system specific starting script for this machine. 764 * 765 * @return Operation system specific part of the startscript. 766 */ 767 protected abstract String osStartScript(); 768 769 /** 770 * Makes all the class paths into the operation system specific syntax, and puts them into a string where they are 771 * separated by the operation system specific separator (':' for linux, ';' for windows). 772 * 773 * @param app The application which has the class paths. 774 * @return The class paths in operation system specific syntax. 775 */ 776 protected abstract String osGetClassPath(Application app); 777 778 /** 779 * Checks if a specific directory for the database is given in the settings, and thus if the database should be 780 * installed on this machine. 781 * <p> 782 * If no specific database is given as deploy argument (databaseFileName = null) then use the standard database 783 * extracted from NetarchiveSuite.zip. Else send the given new database to the standard database location. 784 * <p> 785 * Extract the database in the standard database location to the specified database directory. 786 * 787 * @return The script for installing the database (if needed). 788 */ 789 protected abstract String osInstallDatabase(); 790 791 /** 792 * Checks if a specific directory for the archive database is given in the settings, and thus if the archive 793 * database should be installed on this machine. 794 * <p> 795 * If not specific database is given (adminDatabaseFileName = null) then use the default in the NetarchiveSuite.zip 796 * package. Else send the new archive database to the standard database location, and extract it to the given 797 * location. 798 * 799 * @return The script for installing the archive database (if needed). 800 */ 801 protected abstract String osInstallArchiveDatabase(); 802 803 /** 804 * This function makes the part of the install script for installing the external jar files from within the 805 * jarFolder. If the jarFolder is null, then no action will be performed. 806 * 807 * @return The script for installing the external jar files (if needed). 808 */ 809 protected abstract String osInstallExternalJarFiles(); 810 811 /** 812 * This functions makes the script for creating the new directories. 813 * <p> 814 * Linux creates directories directly through ssh. Windows creates an install a script file for installing the 815 * directories, which has to be sent to the machine, then executed and finally deleted. 816 * 817 * @param dir The name of the directory to create. 818 * @param clean Whether the directory should be cleaned\reset. 819 * @return The lines of code for creating the directories. 820 * @see #createInstallDirScript(File) 821 */ 822 protected abstract String scriptCreateDir(String dir, boolean clean); 823 824 /** 825 * Creates the script for creating the application specified directories. Also creates the directories along the 826 * path to the directories. 827 * 828 * @return The script for creating the application specified directories. 829 */ 830 protected abstract String getAppDirectories(); 831 832 /** 833 * This method does the following: Retrieves the path to the jmxremote.access and jmxremote.password files. Moves 834 * these files, if they are different from standard. Makes the jmxremote.access and jmxremote.password files 835 * readonly. 836 * 837 * @return The commands for handling the jmxremote files. 838 */ 839 protected abstract String getJMXremoteFilesCommand(); 840 841 /** 842 * Function to create the script which installs the new directories. This is only used for windows machines! 843 * 844 * @param dir The directory to put the file 845 */ 846 protected abstract void createInstallDirScript(File dir); 847 848 /** 849 * Creates a script for restating all the applications on a given machine. 850 * 851 * @param dir The directory where the script will be placed. 852 */ 853 protected abstract void createRestartScript(File dir); 854 855 /** 856 * Creates a script for starting the archive database on a given machine. This is only created if the 857 * <globalArchiveDatabaseDir> parameter is defined on the machine level. 858 * 859 * @param dir The directory where the script will be placed. 860 */ 861 protected abstract void createArchiveDatabaseStartScript(File dir); 862 863 /** 864 * Creates a script for killing the archive database on a given machine. This is only created if the 865 * <globalArchiveDatabaseDir> parameter is defined on the machine level. 866 * 867 * @param dir The directory where the script will be placed. 868 */ 869 protected abstract void createArchiveDatabaseKillScript(File dir); 870 871 /** 872 * Creates a script for starting the harvest database on a given machine. This is only created if the 873 * <deployHarvestDatabaseDir> parameter is defined on the machine level. 874 * 875 * @param dir The directory where the script will be placed. 876 */ 877 protected abstract void createHarvestDatabaseStartScript(File dir); 878 879 /** 880 * Creates a script for killing the harvest database on a given machine. This is only created if the 881 * <globalHarvestDatabaseDir> parameter is defined on the machine level. 882 * 883 * @param dir The directory where the script will be placed. 884 */ 885 protected abstract void createHarvestDatabaseKillScript(File dir); 886 887 /** 888 * Changes the file directory path to the format used in the security policy. 889 * 890 * @param path The current path. 891 * @return The formatted path. 892 */ 893 protected abstract String changeFileDirPathForSecurity(String path); 894 895 /** 896 * create a harvestDatabaseUpdatescript in the given machineDirectory. 897 * 898 * @param machineDirectory a given MachineDirectory. 899 * @param forceCreate 900 */ 901 protected abstract void createHarvestDatabaseUpdateScript(File machineDirectory, boolean forceCreate); 902 903 protected String getTargetEncoding() { 904 return targetEncoding; 905 } 906 907}