def upgrade_tarball_install(config, new_tarball, preserve_old_install): """Performs an upgrade for an existing Scalyr Agent 2 that was previously installed using the tarball method. @param config: The configuration for this agent. @param new_tarball: The path to file containing the new tarball to install. @param preserve_old_install: If True, will move the old install directory to a new location rather than deleting it. @return: The exit status code. """ # Create a temporary directory hold the new install as we untar it and copy files into it. tmp_install_dir = tempfile.mkdtemp() # Some variables that capture some important state that we may need to unwind if we execute # out the installation along the way. # # If not None, then the directory we are currently holding the old installation directory in. preserve_dir = None # True if the agent was running when the install started. was_running = False # True if the agent was successfully restarted. was_restarted = False try: try: # Ensure that this is a tarball install if not config.is_tarball_install(): raise UpgradeFailure('The current agent was not installed using a tarball, so you may not use the ' 'upgrade tarball command.') # Ensure that the user has not changed the defaults for the config, data, and log directory. if Configuration.default_config_file_path() != config.file_path: raise UpgradeFailure('The agent is not using the default configuration file so you may not use the ' 'upgrade tarball command.') if Configuration.default_agent_data_path() != config.agent_data_path: raise UpgradeFailure('The agent is not using the default data directory so you may not use the upgrade ' 'tarball command.') if Configuration.default_agent_log_path() != config.agent_log_path: raise UpgradeFailure('The agent is not using the default log directory so you may not use the upgrade ' 'tarball command.') # We rely on the current installation being included in the PATH variable. if spawn.find_executable('scalyr-agent-2-config') is None: raise UpgradeFailure('Could not locate the scalyr-agent-2-config command from the current ' 'installation. Please ensure that the agent\'s bin directory is in the system\'s ' 'PATH variable.') if not os.path.isfile(new_tarball): raise UpgradeFailure('The tarball file %s does not exist.' % new_tarball) file_name = os.path.basename(new_tarball) if re.match('^scalyr-agent-2\..*\.tar\.gz$', file_name) is None: raise UpgradeFailure('The supplied tarball file name does not match the expected format.') tarball_directory = file_name[0:-7] # We will be installing in the same directory where scalyr-agent-2 is currently installed. That directory # should be 4 levels back from this file. # The path to this file looks like: scalyr-agent-2/py/scalyr_agent/config_main.py install_directory = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file_path__)))) if not os.path.isdir(os.path.join(install_directory, 'scalyr-agent-2')): raise UpgradeFailure('Could not determine the install directory. Either the main directory is no ' 'longer called scalyr-agent-2, or the directory structure has changed.') # Compute the full paths to the scalyr-agent-2 directories for both the new install and old install. tmp_new_install_location = os.path.join(tmp_install_dir, tarball_directory) old_install_location = os.path.join(install_directory, 'scalyr-agent-2') # Untar the new package into the temp location. tar = tarfile.open(new_tarball, 'r:gz') for member in tar.getmembers(): tar.extract(member, path=tmp_install_dir) # Check to see if the agent is running. If so, stop it. was_running = run_command('scalyr-agent-2 stop', grep_for='Agent has stopped', command_name='scalyr-agent-2 stop')[0] == 0 # Copy the config, data, and log directories. for dir_name in ['config', 'log', 'data']: copy_dir_to_new_agent(old_install_location, tmp_new_install_location, dir_name) # Allow the new agent code to perform any actions it deems necessary. We do the special commandline # here where to pass in both directories to the --upgrade-tarball-command result = subprocess.call([os.path.join(tmp_new_install_location, 'bin', 'scalyr-agent-2-config'), '--upgrade-tarball', '%s%s%s' % (old_install_location, os.pathsep, tmp_new_install_location)]) if result != 0: raise UpgradeFailure('New package failed to finish the upgrade process.') # Move the old install directory to a temporary location, so we can undo the next move if we need to. preserve_dir = tempfile.mkdtemp() shutil.move(old_install_location, preserve_dir) # Move the new install into place. success = False try: shutil.move(tmp_new_install_location, old_install_location) success = True finally: if not success: # Move the old install back in place just to be safe. shutil.move(os.path.join(preserve_dir, 'scalyr-agent-2'), old_install_location) if success and not preserve_old_install: shutil.rmtree(preserve_dir) preserve_dir = None print 'New agent installed.' # Start the agent if it was previously running. if was_running: if run_command('scalyr-agent-2 start', exit_on_fail=False, command_name='scalyr-agent-2 start')[0] == 0: print 'Agent has successfully restarted.' print ' You may execute the following command for status details: scalyr-agent-2 status -v' was_restarted = True else: raise UpgradeFailure('Could not start the agent. Execute the following command for more details: ' 'scalyr-agent-2 start') else: print 'Execute the following command to start the agent: scalyr-agent-2 start' return 0 except UpgradeFailure, error: print >>sys.stderr print >>sys.stderr, 'The upgrade failed due to the following reason: %s' % error.message return 1 finally: # Delete the temporary directory. shutil.rmtree(tmp_install_dir) # Warn if we should have restarted the agent but did not. if was_running and not was_restarted: print '' print ('WARNING, due to failure, the agent may no longer be running. Restart it with: scalyr-agent-2 ' 'start') # If there is still a preserve_directory, there must be a reason for it, so tell the user where it is. if preserve_dir is not None: print '' print 'The previous agent installation was left in \'%s\'' % preserve_dir print 'You should be sure to delete this directory once you no longer need it.'
parser.add_option("", "--preserve-old-install", action="store_true", dest="preserve_old_install", default=False, help="When performing a tarball upgrade, move the old install to a temporary directory " "instead of deleting it.") (options, args) = parser.parse_args() if len(args) > 1: print >> sys.stderr, 'Could not parse commandline arguments.' parser.print_help(sys.stderr) sys.exit(1) if options.executing_user and getpass.getuser() != 'root': print >> sys.stderr, 'You must be root to update the user account that is used to run the agent.' sys.exit(1) if options.config_filename is None: options.config_filename = Configuration.default_config_file_path() if not os.path.isabs(options.config_filename): options.config_filename = os.path.abspath(options.config_filename) try: config_file = Configuration(options.config_filename, None, None) config_file.parse() except Exception, e: print >> sys.stderr, 'Error reading configuration file: %s' % str(e) print >> sys.stderr, traceback.format_exc() print >> sys.stderr, 'Terminating, please fix the configuration file and restart agent.' sys.exit(1) if options.set_key_from_stdin: api_key = raw_input('Please enter key: ')