usr/src/cmd/auto-install/auto_install.py
changeset 1160 6f7e708c38ec
parent 1154 8cb36a37e75d
child 1162 a4dac96d1eaa
equal deleted inserted replaced
1159:fbde90ccfae9 1160:6f7e708c38ec
    41 
    41 
    42 from osol_install.liberrsvc import ES_DATA_EXCEPTION
    42 from osol_install.liberrsvc import ES_DATA_EXCEPTION
    43 
    43 
    44 from solaris_install import \
    44 from solaris_install import \
    45     ApplicationData, system_temp_path, post_install_logs_path, Popen
    45     ApplicationData, system_temp_path, post_install_logs_path, Popen
       
    46 from solaris_install.auto_install import TRANSFER_FILES_CHECKPOINT
    46 from solaris_install.auto_install.ai_instance import AIInstance
    47 from solaris_install.auto_install.ai_instance import AIInstance
    47 from solaris_install.auto_install.checkpoints.dmm import \
    48 from solaris_install.auto_install.checkpoints.dmm import \
    48     DERIVED_MANIFEST_DATA, DerivedManifestData
    49     DERIVED_MANIFEST_DATA, DerivedManifestData
    49 from solaris_install.auto_install.checkpoints.target_selection import \
    50 from solaris_install.auto_install.checkpoints.target_selection import \
    50     SelectionError, TargetSelection
    51     SelectionError, TargetSelection
       
    52 from solaris_install.auto_install.checkpoints.target_selection_zone import \
       
    53     TargetSelectionZone
       
    54 from solaris_install.auto_install.checkpoints.ai_configuration import \
       
    55     AI_SERVICE_LIST_FILE, AIConfigurationError
    51 from solaris_install.auto_install.utmpx import users_on_console
    56 from solaris_install.auto_install.utmpx import users_on_console
    52 from solaris_install.boot import boot
    57 from solaris_install.boot import boot
    53 from solaris_install.data_object import ParsingError, \
    58 from solaris_install.data_object import ParsingError, \
    54     DataObject, ObjectNotFoundError
    59     DataObject, ObjectNotFoundError
    55 from solaris_install.data_object.data_dict import DataObjectDict
    60 from solaris_install.data_object.data_dict import DataObjectDict
    57 from solaris_install.engine import UnknownChkptError, UsageError, \
    62 from solaris_install.engine import UnknownChkptError, UsageError, \
    58     RollbackError
    63     RollbackError
    59 from solaris_install.ict import initialize_smf, update_dumpadm, ips, \
    64 from solaris_install.ict import initialize_smf, update_dumpadm, ips, \
    60     device_config, apply_sysconfig, boot_archive, transfer_files, \
    65     device_config, apply_sysconfig, boot_archive, transfer_files, \
    61     create_snapshot, setup_swap
    66     create_snapshot, setup_swap
       
    67 from solaris_install.ict.apply_sysconfig import APPLY_SYSCONFIG_DICT, \
       
    68     APPLY_SYSCONFIG_PROFILE_KEY
    62 from solaris_install.logger import FileHandler, ProgressHandler, MAX_INT
    69 from solaris_install.logger import FileHandler, ProgressHandler, MAX_INT
    63 from solaris_install.logger import INSTALL_LOGGER_NAME
    70 from solaris_install.logger import INSTALL_LOGGER_NAME
    64 from solaris_install.manifest.parser import ManifestError, \
    71 from solaris_install.manifest.parser import ManifestError, \
    65     MANIFEST_PARSER_DATA
    72     MANIFEST_PARSER_DATA
    66 from solaris_install.target import Target, discovery, instantiation
    73 from solaris_install.target import Target, discovery, instantiation
       
    74 from solaris_install.target.instantiation_zone import ALT_POOL_DATASET
    67 from solaris_install.target.logical import BE, Logical
    75 from solaris_install.target.logical import BE, Logical
    68 from solaris_install.transfer import create_checkpoint
    76 from solaris_install.transfer import create_checkpoint
    69 from solaris_install.transfer.info import Software, Destination, Image, \
    77 from solaris_install.transfer.info import Software, Destination, Image, \
    70     ImType, Dir, INSTALL, IPSSpec, CPIOSpec, SVR4Spec
    78     ImType, Dir, INSTALL, IPSSpec, CPIOSpec, SVR4Spec
    71 from solaris_install.transfer.ips import AbstractIPS
    79 from solaris_install.transfer.ips import AbstractIPS
    83     AI_EXIT_FAILURE = 1
    91     AI_EXIT_FAILURE = 1
    84     AI_EXIT_AUTO_REBOOT = 64
    92     AI_EXIT_AUTO_REBOOT = 64
    85     TARGET_INSTANTIATION_CHECKPOINT = 'target-instantiation'
    93     TARGET_INSTANTIATION_CHECKPOINT = 'target-instantiation'
    86     FIRST_TRANSFER_CHECKPOINT = 'first-transfer'
    94     FIRST_TRANSFER_CHECKPOINT = 'first-transfer'
    87     MANIFEST_CHECKPOINTS = ["derived-manifest", "manifest-parser"]
    95     MANIFEST_CHECKPOINTS = ["derived-manifest", "manifest-parser"]
    88     CHECKPOINTS_BEFORE_TI = ["target-discovery", "target-selection",
    96     CHECKPOINTS_BEFORE_TI = ["target-discovery", "target-selection", \
    89                              TARGET_INSTANTIATION_CHECKPOINT]
    97         "ai-configuration", TARGET_INSTANTIATION_CHECKPOINT]
    90     CHECKPOINTS_BEFORE_TI.extend(MANIFEST_CHECKPOINTS)
    98     CHECKPOINTS_BEFORE_TI.extend(MANIFEST_CHECKPOINTS)
    91     CHECKPOINTS_BEFORE_IPS = list(CHECKPOINTS_BEFORE_TI)
    99     CHECKPOINTS_BEFORE_IPS = list(CHECKPOINTS_BEFORE_TI)
    92     TRANSFER_FILES_CHECKPOINT = 'transfer-ai-files'
       
    93     INSTALLED_ROOT_DIR = "/a"
   100     INSTALLED_ROOT_DIR = "/a"
    94 
   101 
    95     def __init__(self, args=None):
   102     def __init__(self, args=None):
    96         """
   103         """
    97         Class constructor
   104         Class constructor
    98         """
   105         """
       
   106         self.installed_root_dir = self.INSTALLED_ROOT_DIR
    99         self.auto_reboot = False
   107         self.auto_reboot = False
   100         self.doc = None
   108         self.doc = None
   101         self.exitval = self.AI_EXIT_SUCCESS
   109         self.exitval = self.AI_EXIT_SUCCESS
   102         self.derived_script = None
   110         self.derived_script = None
   103         self.manifest = None
   111         self.manifest = None
   110 
   118 
   111         # Initialize Install Engine
   119         # Initialize Install Engine
   112         self.engine = InstallEngine(debug=True, stop_on_error=True)
   120         self.engine = InstallEngine(debug=True, stop_on_error=True)
   113         self.doc = self.engine.data_object_cache
   121         self.doc = self.engine.data_object_cache
   114 
   122 
   115         # Add ApplicationData to the DOC
   123         if self.options.zone_pool_dataset is not None:
   116         self._app_data = ApplicationData("auto-install")
   124             # If we're installing a zone root, generate a work_dir
       
   125             # location based on the current PID.
       
   126             work_dir = "/system/volatile/install." + str(os.getpid())
       
   127 
       
   128             # Add ApplicationData to the DOC
       
   129             self._app_data = ApplicationData("auto-install", work_dir=work_dir)
       
   130             self._app_data.data_dict[ALT_POOL_DATASET] = \
       
   131                 self.options.zone_pool_dataset
       
   132 
       
   133             # Set installed_root_dir to be based off work_dir
       
   134             self.installed_root_dir = work_dir + self.INSTALLED_ROOT_DIR
       
   135         else:
       
   136             # Add ApplicationData to the DOC
       
   137             self._app_data = ApplicationData("auto-install")
       
   138 
       
   139         # Add profile location to the ApplySysconfig checkpoint's data dict.
       
   140         if self.options.profile is not None:
       
   141             # Try to find the ApplySysconfig data dict from
       
   142             # the DOC in case it already exists.
       
   143             as_doc_dict = None
       
   144             as_doc_dict = self.doc.volatile.get_first_child( \
       
   145                 name=APPLY_SYSCONFIG_DICT)
       
   146 
       
   147             if as_doc_dict is None:
       
   148                 # Initialize new dictionary in DOC
       
   149                 as_dict = {APPLY_SYSCONFIG_PROFILE_KEY : self.options.profile}
       
   150                 as_doc_dict = DataObjectDict(APPLY_SYSCONFIG_DICT, as_dict)
       
   151                 self.doc.volatile.insert_children(as_doc_dict)
       
   152             else:
       
   153                 # Add to existing dictionary in DOC
       
   154                 as_doc_dict.data_dict[APPLY_SYSCONFIG_PROFILE_KEY] = \
       
   155                     self.options.profile
       
   156 
       
   157         # Add service list file to ApplicationData
       
   158         if self.options.service_list_file is not None:
       
   159             self._app_data.data_dict[AI_SERVICE_LIST_FILE] = \
       
   160                 self.options.service_list_file
       
   161 
   117         self.doc.persistent.insert_children(self._app_data)
   162         self.doc.persistent.insert_children(self._app_data)
   118 
   163 
   119         # Clear error service
   164         # Clear error service
   120         errsvc.clear_error_list()
   165         errsvc.clear_error_list()
   121 
   166 
   131         if self.options.stop_checkpoint:
   176         if self.options.stop_checkpoint:
   132             self.logger.debug("Pausing AI install before checkpoint: %s" % \
   177             self.logger.debug("Pausing AI install before checkpoint: %s" % \
   133                 (self.options.stop_checkpoint))
   178                 (self.options.stop_checkpoint))
   134 
   179 
   135         if not self.options.list_checkpoints:
   180         if not self.options.list_checkpoints:
   136 
   181             if self.manifest:
   137             if self.options.manifest:
   182                 self.logger.info("Using XML Manifest: %s" % (self.manifest))
   138                 self.logger.info("Using Profile: %s" % (self.options.manifest))
       
   139 
   183 
   140             if self.derived_script:
   184             if self.derived_script:
   141                 self.logger.info("Using Derived Script: %s" % \
   185                 self.logger.info("Using Derived Script: %s" % \
   142                     (self.derived_script))
   186                     (self.derived_script))
   143 
   187 
   144             if self.manifest:
   188             if self.options.profile:
   145                 self.logger.info("Using Manifest: %s" % (self.manifest))
   189                 self.logger.info("Using profile specification: %s" % \
       
   190                     (self.options.profile))
       
   191 
       
   192             if self.options.service_list_file:
       
   193                 self.logger.info("Using service list file: %s" % \
       
   194                     (self.options.service_list_file))
       
   195 
       
   196             if self.options.zone_pool_dataset:
       
   197                 self.logger.info("Installing zone under dataset: %s" % \
       
   198                     (self.options.zone_pool_dataset))
   146 
   199 
   147             if self.options.dry_run:
   200             if self.options.dry_run:
   148                 self.logger.info("Dry Run mode enabled")
   201                 self.logger.info("Dry Run mode enabled")
   149 
   202 
   150     def parse_args(self, args):
   203     def parse_args(self, args):
   151         """
   204         """
   152         Method to parse command line arguments
   205         Method to parse command line arguments
   153         """
   206         """
   154 
   207 
   155         usage = "%prog -m <manifest>\n" + \
   208         usage = "%prog -m <manifest> [-c <profile/dir>]\n"\
   156             "\t[-i - Stop installation before Target Instantiation |\n" + \
   209             "\t[-i - Stop installation before Target Instantiation |\n" + \
   157             "\t -I - Stop installation after Target Instantiation]\n" + \
   210             "\t -I - Stop installation after Target Instantiation]\n" + \
   158             "\t[-n - Enable dry run mode]"
   211             "\t[-n - Enable dry run mode]\n" + \
       
   212             "\t[-r <service_list_file>]" + \
       
   213             "\t[-Z <zone_pool_dataset]"
   159 
   214 
   160         parser = optparse.OptionParser(usage=usage)
   215         parser = optparse.OptionParser(usage=usage)
   161 
   216 
   162         parser.add_option("-m", "--manifest", dest="manifest",
   217         parser.add_option("-m", "--manifest", dest="manifest",
   163             help="Specify script or XML manifest to use")
   218             help="Specify script or XML manifest to use")
       
   219 
       
   220         parser.add_option("-c", "--profile", dest="profile",
       
   221             help="Specify a profile or directory of profiles")
   164 
   222 
   165         parser.add_option("-i", "--break-before-ti", dest="break_before_ti",
   223         parser.add_option("-i", "--break-before-ti", dest="break_before_ti",
   166             action="store_true", default=False,
   224             action="store_true", default=False,
   167             help="Break execution before Target Instantiation, testing only")
   225             help="Break execution before Target Instantiation, testing only")
   168 
   226 
   172 
   230 
   173         parser.add_option("-n", "--dry-run", dest="dry_run",
   231         parser.add_option("-n", "--dry-run", dest="dry_run",
   174             action="store_true", default=False,
   232             action="store_true", default=False,
   175             help="Enable dry-run mode for testing")
   233             help="Enable dry-run mode for testing")
   176 
   234 
   177         parser.add_option("-l", "--list-checkpoints",  dest="list_checkpoints",
   235         parser.add_option("-l", "--list-checkpoints", dest="list_checkpoints",
   178             action="store_true", default=False,
   236             action="store_true", default=False,
   179             help=optparse.SUPPRESS_HELP)
   237             help=optparse.SUPPRESS_HELP)
   180 
   238 
   181         parser.add_option("-s", "--stop-checkpoint", dest="stop_checkpoint",
   239         parser.add_option("-s", "--stop-checkpoint", dest="stop_checkpoint",
   182             help=optparse.SUPPRESS_HELP)
   240             help=optparse.SUPPRESS_HELP)
   183 
   241 
       
   242         parser.add_option("-r", "--service-list-file",
       
   243             dest="service_list_file", help="Specify service list file")
       
   244 
       
   245         parser.add_option("-Z", "--zone-pool-dataset",
       
   246             dest="zone_pool_dataset",
       
   247             help="Specify zone pool dataset to install into")
       
   248 
   184         (options, args) = parser.parse_args(args)
   249         (options, args) = parser.parse_args(args)
   185 
   250 
   186         # If manifest argument provided, determine if script or manifest
   251         # If manifest argument provided, determine if script or XML manifest
   187         if options.manifest:
   252         if options.manifest:
   188             (self.derived_script, self.manifest) =  \
   253             (self.derived_script, self.manifest) =  \
   189                 self.determine_manifest_type(options.manifest)
   254                 self.determine_manifest_type(options.manifest)
   190             if not self.derived_script and not self.manifest:
   255             if not self.derived_script and not self.manifest:
   191                 parser.error("Must specify manifest with -m option")
   256                 parser.error("Must specify manifest with -m option")
   215         return (options, args)
   280         return (options, args)
   216 
   281 
   217     @staticmethod
   282     @staticmethod
   218     def determine_manifest_type(manifest):
   283     def determine_manifest_type(manifest):
   219         """
   284         """
   220         Determine of manifest file argument is a script or xml manifest.
   285         Determine if manifest file argument is a script or xml manifest.
   221         Simply check reading first two characters of file for #!
   286         Simply check reading first two characters of file for #!
   222         """
   287         """
   223         derived_script = None
   288         derived_script = None
   224         xml_manifest = None
   289         xml_manifest = None
   225 
   290 
   278         # Create logger for AI
   343         # Create logger for AI
   279         self.logger = logging.getLogger(INSTALL_LOGGER_NAME)
   344         self.logger = logging.getLogger(INSTALL_LOGGER_NAME)
   280 
   345 
   281         # Log progress and info messages to the console.
   346         # Log progress and info messages to the console.
   282         self.progress_ph = AIProgressHandler(self.logger,
   347         self.progress_ph = AIProgressHandler(self.logger,
   283             skip_console_msg=self.options.list_checkpoints)
   348             skip_console_msg=(self.options.list_checkpoints or \
       
   349                               self.options.zone_pool_dataset))
   284         self.progress_ph.start_progress_server()
   350         self.progress_ph.start_progress_server()
   285         self.logger.addHandler(self.progress_ph)
   351         self.logger.addHandler(self.progress_ph)
   286 
   352 
   287         # Only ever send debug info to the logs, use INFO for console
   353         # Only ever send debug info to the logs, use INFO for console
   288         self.progress_ph.removeFilter(self.logger._prog_filter)
   354         self.progress_ph.removeFilter(self.logger._prog_filter)
   293         self.progress_ph.setFormatter(formatter)
   359         self.progress_ph.setFormatter(formatter)
   294 
   360 
   295         # create a install_log file handler and add it to the ai_logger
   361         # create a install_log file handler and add it to the ai_logger
   296 
   362 
   297         # set the logfile names
   363         # set the logfile names
   298         install_log = self._app_data.work_dir + self.INSTALL_LOG
   364         install_log = os.path.join(self._app_data.work_dir, self.INSTALL_LOG)
   299         self.install_log_fh = FileHandler(install_log)
   365         self.install_log_fh = FileHandler(install_log)
   300 
   366 
   301         self.install_log_fh.setLevel(logging.DEBUG)
   367         self.install_log_fh.setLevel(logging.DEBUG)
   302         if not self.options.list_checkpoints:
   368         if not self.options.list_checkpoints:
   303             self.logger.info("Install Log: %s" % install_log)
   369             self.logger.info("Install Log: %s" % install_log)
   325     def __transfer_install_log(self):
   391     def __transfer_install_log(self):
   326         """If BE exists, then transfer Log Files to New BE"""
   392         """If BE exists, then transfer Log Files to New BE"""
   327         new_be = self.be
   393         new_be = self.be
   328 
   394 
   329         if new_be is not None:
   395         if new_be is not None:
   330             if new_be.exists:
   396             # Assumes BE is still mounted, should be, if it exists.
   331                 # Assumes BE is still mounted, should be, if it exists.
   397             self.logger.debug("Transferring log to %s" %
   332                 self.logger.info("Transferring log to %s" %
   398                 new_be.mountpoint + self.BE_LOG_DIR)
   333                     new_be.mountpoint + self.BE_LOG_DIR)
   399             self.install_log_fh.transfer_log(
   334                 self.install_log_fh.transfer_log(
   400                 new_be.mountpoint + self.BE_LOG_DIR, isdir=True)
   335                     new_be.mountpoint + self.BE_LOG_DIR, isdir=True)
       
   336             else:
       
   337                 self.logger.error(
       
   338                     "Unable to determine BE mountpoint")
       
   339                 return False
       
   340         else:
   401         else:
   341             self.logger.error(
   402             self.logger.error(
   342                 "Unable to determine location to transfer logs to")
   403                 "Unable to determine location to transfer logs to")
   343             return False
   404             return False
   344 
   405 
   346 
   407 
   347     def __cleanup_before_exit(self, error_val):
   408     def __cleanup_before_exit(self, error_val):
   348         """Do some clean up and set exit code.
   409         """Do some clean up and set exit code.
   349         """
   410         """
   350 
   411 
       
   412         unmount_be = False
       
   413 
   351         self.exitval = error_val
   414         self.exitval = error_val
   352         if not self.options.list_checkpoints:
   415         if not self.options.list_checkpoints:
   353             if error_val in [self.AI_EXIT_SUCCESS, self.AI_EXIT_AUTO_REBOOT]:
   416             if error_val in [self.AI_EXIT_SUCCESS, self.AI_EXIT_AUTO_REBOOT]:
   354                 if error_val == self.AI_EXIT_AUTO_REBOOT:
   417                 self.logger.info("Automated Installation succeeded.")
   355                     self.logger.info("Automated Installation succeeded.")
   418                 if self.options.zone_pool_dataset is None:
   356                     self.logger.info("System will be rebooted now")
   419                     if error_val == self.AI_EXIT_AUTO_REBOOT:
   357                 else:
   420                         self.logger.info("System will be rebooted now")
   358                     self.logger.info("Automated Installation succeeded.")
   421                     else:
   359                     self.logger.info("You may wish to reboot the system at "
   422                         self.logger.info("You may wish to reboot the system at "
   360                                      "this time.")
   423                                          "this time.")
       
   424                 unmount_be = True
   361             else:
   425             else:
   362                 # error_val == self.AI_EXIT_FAILURE:
   426                 # error_val == self.AI_EXIT_FAILURE:
   363                 self.logger.info("Automated Installation Failed")
   427                 self.logger.info("Automated Installation Failed")
   364                 self.logger.info("Please see logs for more information")
   428                 self.logger.info("Please see logs for more information")
   365 
   429 
   368         self.progress_ph.stop_progress_server()
   432         self.progress_ph.stop_progress_server()
   369         self.logger.close()
   433         self.logger.close()
   370 
   434 
   371         # Only attempt to unmount BE if Target Instantiation has completed
   435         # Only attempt to unmount BE if Target Instantiation has completed
   372         if self.options.stop_checkpoint not in self.CHECKPOINTS_BEFORE_TI:
   436         if self.options.stop_checkpoint not in self.CHECKPOINTS_BEFORE_TI:
   373             # Unmount the BE now.
   437             # If we didn't fail unmount the BE now.
   374             if self.be is not None:
   438             if unmount_be:
   375                 try:
   439                 if self.be is not None:
   376                     self.be.unmount(self.options.dry_run)
   440                     try:
   377                 except (RuntimeError) as ex:
   441                         self.be.unmount(self.options.dry_run,
   378                     print ex  # Print since logger is closed now.
   442                             altpool=self.options.zone_pool_dataset)
   379                     self.exitval = self.AI_EXIT_FAILURE
   443                     except RuntimeError as ex:
       
   444                         # Use print since logger is now closed.
       
   445                         print >> sys.stderr, str(ex)
       
   446                         self.exitval = self.AI_EXIT_FAILURE        
   380 
   447 
   381     def import_preserved_zpools(self):
   448     def import_preserved_zpools(self):
   382         '''
   449         '''
   383         Check if we are preserving Zpools in manifest.
   450         Check if we are preserving Zpools in manifest.
   384         If we are ensure any referenced zpools are imported.
   451         If we are ensure any referenced zpools are imported.
   493                 self.logger.error("Invalid stop checkpoint specified: %s" % \
   560                 self.logger.error("Invalid stop checkpoint specified: %s" % \
   494                     self.options.stop_checkpoint)
   561                     self.options.stop_checkpoint)
   495                 self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   562                 self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   496                 return
   563                 return
   497 
   564 
   498         # specifying to list checkpoints, do so then exit
   565         # If specifying to list checkpoints, do so then exit
   499         # List of checkpoints available depend on what has just been
   566         # List of checkpoints available depend on what has just been
   500         # registered.
   567         # registered.
   501         if self.options.list_checkpoints:
   568         if self.options.list_checkpoints:
   502             self.list_checkpoints()
   569             self.list_checkpoints()
   503             self.__cleanup_before_exit(self.AI_EXIT_SUCCESS)
   570             self.__cleanup_before_exit(self.AI_EXIT_SUCCESS)
   512             if ai_instance.http_proxy is not None and \
   579             if ai_instance.http_proxy is not None and \
   513                len(ai_instance.http_proxy) > 0:
   580                len(ai_instance.http_proxy) > 0:
   514                 # Set the HTTP Proxy environment variable
   581                 # Set the HTTP Proxy environment variable
   515                 os.environ["http_proxy"] = ai_instance.http_proxy
   582                 os.environ["http_proxy"] = ai_instance.http_proxy
   516 
   583 
   517         self.logger.info("Auto Reboot set to : %s" % (self.auto_reboot))
   584         self.logger.debug("Auto Reboot set to: %s" % (self.auto_reboot))
   518 
   585 
   519         # Ensure preserved zpools are online (imported)
   586         # Ensure preserved zpools are online (imported)
   520         if not self.import_preserved_zpools():
   587         if not self.import_preserved_zpools():
   521             self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   588             self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   522             return
   589             return
   531 
   598 
   532             if self.options.stop_checkpoint not in self.CHECKPOINTS_BEFORE_IPS:
   599             if self.options.stop_checkpoint not in self.CHECKPOINTS_BEFORE_IPS:
   533                 if not self.__transfer_install_log():
   600                 if not self.__transfer_install_log():
   534                     self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   601                     self.__cleanup_before_exit(self.AI_EXIT_FAILURE)
   535                 else:
   602                 else:
   536                     if self.auto_reboot:
   603                     if self.auto_reboot and \
       
   604                         self.options.zone_pool_dataset is None:
   537                         self.__cleanup_before_exit(self.AI_EXIT_AUTO_REBOOT)
   605                         self.__cleanup_before_exit(self.AI_EXIT_AUTO_REBOOT)
   538                     else:
   606                     else:
   539                         self.__cleanup_before_exit(self.AI_EXIT_SUCCESS)
   607                         self.__cleanup_before_exit(self.AI_EXIT_SUCCESS)
   540 
   608 
   541             # Successful Execution
   609             # Successful Execution
   609             else:
   677             else:
   610                 # No manifest specified to parse
   678                 # No manifest specified to parse
   611                 return True
   679                 return True
   612 
   680 
   613             if not self.options.list_checkpoints:
   681             if not self.options.list_checkpoints:
   614                 self.logger.info("Registering Manifest Parser Checkpoint")
   682                 self.logger.debug("Registering Manifest Parser Checkpoint")
   615 
   683 
   616             self.engine.register_checkpoint("manifest-parser",
   684             self.engine.register_checkpoint("manifest-parser",
   617                                     "solaris_install.manifest.parser",
   685                                     "solaris_install.manifest.parser",
   618                                     "ManifestParser", args=args, kwargs=kwargs)
   686                                     "ManifestParser", args=args, kwargs=kwargs)
   619             return True
   687             return True
   631             manifest as an explicit argument. (This is not implemented yet)
   699             manifest as an explicit argument. (This is not implemented yet)
   632         """
   700         """
   633         # Execute Checkpoints
   701         # Execute Checkpoints
   634         if not self.options.list_checkpoints:
   702         if not self.options.list_checkpoints:
   635             if self.derived_script:
   703             if self.derived_script:
   636                 self.logger.info("Executing Derived Manifest and Manifest " \
   704                 self.logger.debug("Executing Derived Manifest and Manifest " \
   637                         "Parser Checkpoints")
   705                         "Parser Checkpoints")
   638             else:
   706             else:
   639                 self.logger.info("Executing Manifest Parser Checkpoint")
   707                 self.logger.debug("Executing Manifest Parser Checkpoint")
   640 
   708 
   641         if self.options.stop_checkpoint in self.MANIFEST_CHECKPOINTS:
   709         if self.options.stop_checkpoint in self.MANIFEST_CHECKPOINTS:
   642             pause_cp = self.options.stop_checkpoint
   710             pause_cp = self.options.stop_checkpoint
   643         else:
   711         else:
   644             pause_cp = None
   712             pause_cp = None
   707             return False
   775             return False
   708         except (ValueError) as ex:
   776         except (ValueError) as ex:
   709             self.logger.error("Value errors occured :")
   777             self.logger.error("Value errors occured :")
   710             print "\t\t%s" % str(ex)
   778             print "\t\t%s" % str(ex)
   711             return False
   779             return False
       
   780         except (AIConfigurationError) as ex:
       
   781             self.logger.error("AI Configuration checkpoint error :")
       
   782             print "\t\t%s" % str(ex)
       
   783             return False
   712         except (RollbackError, UnknownChkptError, UsageError) as ex:
   784         except (RollbackError, UnknownChkptError, UsageError) as ex:
   713             self.logger.error("RollbackError, UnknownChkptError, UsageError :")
   785             self.logger.error("RollbackError, UnknownChkptError, UsageError :")
   714             print "\t\t%s" % str(ex)
   786             print "\t\t%s" % str(ex)
   715             raise RuntimeError(str(ex))
   787             raise RuntimeError(str(ex))
   716         except Exception, ex:
   788         except Exception, ex:
   735     def configure_checkpoints(self):
   807     def configure_checkpoints(self):
   736         """
   808         """
   737         Wrapper to configure required checkpoints for performing an
   809         Wrapper to configure required checkpoints for performing an
   738         automated installation
   810         automated installation
   739         """
   811         """
   740         # Need to set following Checkpoints for installation
   812         # Need to set following Checkpoints for installation.  Checkpoints
   741         #   Derived Manifest (If script passed as argument)
   813         # marked with a 'G' are applicable when installing a global zone.
   742         #   Manifest Parser (If manifest passed or derived)
   814         # Checkpoings marked with a 'N' are application when installing a
   743         #   Target Discovery
   815         # non-global zone.
   744         #   Target Selection
   816         #   G- -- Derived Manifest (If script passed as argument)
   745         #   Device Driver Update - Install Root
   817         #   GN -- Manifest Parser (If manifest passed or derived)
   746         #   Target Instantiation
   818         #   G- -- Target Discovery
   747         #   Transfer
   819         #   G- -- Target Selection
   748         #   Target Configuration
   820         #   -N -- Target Selection Zone
   749         #   Device Driver Update - New BE
   821         #   GN -- AI Configuration
       
   822         #   G- -- Device Driver Update - Install Root
       
   823         #   G- -- Target Instantiation
       
   824         #   -N -- Target Instantiation Zone
       
   825         #   GN -- Transfer
       
   826         #   GN -- Target Configuration
       
   827         #   G- -- Device Driver Update - New BE
   750 
   828 
   751         try:
   829         try:
   752             if not self.options.list_checkpoints:
   830             if not self.options.list_checkpoints:
   753                 self.logger.info("Configuring Checkpoints")
   831                 self.logger.info("Configuring Checkpoints")
   754 
   832 
   755             # Register TargetDiscovery
   833             # Register TargetDiscovery
   756             self.engine.register_checkpoint("target-discovery",
   834             if self.options.zone_pool_dataset is None:
       
   835                 self.engine.register_checkpoint("target-discovery",
   757                                 "solaris_install.target.discovery",
   836                                 "solaris_install.target.discovery",
   758                                 "TargetDiscovery", args=None, kwargs=None)
   837                                 "TargetDiscovery", args=None, kwargs=None)
   759 
   838 
   760             # Register TargetSelection
   839             # Register TargetSelection
   761             self.logger.debug("Adding Target Selection Checkpoint")
   840             if self.options.zone_pool_dataset is None:
   762             self.engine.register_checkpoint("target-selection",
   841                 self.logger.debug("Adding Target Selection Checkpoint")
   763                 "solaris_install.auto_install.checkpoints.target_selection",
   842                 self.engine.register_checkpoint("target-selection",
   764                 "TargetSelection", args=None, kwargs=None)
   843                     "solaris_install.auto_install.checkpoints."
       
   844                     "target_selection", "TargetSelection", args=None,
       
   845                     kwargs=None)
       
   846             else:
       
   847                 self.logger.debug("Adding Target Selection Zone Checkpoint")
       
   848                 self.engine.register_checkpoint("target-selection",
       
   849                     "solaris_install.auto_install.checkpoints."
       
   850                     "target_selection_zone", "TargetSelectionZone", args=None,
       
   851                     kwargs={"be_mountpoint": self.installed_root_dir})
       
   852 
       
   853             # Register AIConfiguration
       
   854             self.logger.debug("Adding AI Configuration Checkpoint")
       
   855             self.engine.register_checkpoint("ai-configuration",
       
   856                 "solaris_install.auto_install.checkpoints.ai_configuration",
       
   857                 "AIConfiguration", args=None, kwargs=None)
   765 
   858 
   766             # Register TargetInstantiation
   859             # Register TargetInstantiation
   767             self.logger.debug("Adding Target Instantiation Checkpoint")
   860             if self.options.zone_pool_dataset is None:
   768             self.engine.register_checkpoint(self.TARGET_INSTANTIATION_CHECKPOINT,
   861                 self.logger.debug("Adding Target Instantiation Checkpoint")
       
   862                 self.engine.register_checkpoint(self.TARGET_INSTANTIATION_CHECKPOINT,
   769                                 "solaris_install.target.instantiation",
   863                                 "solaris_install.target.instantiation",
   770                                 "TargetInstantiation", args=None, kwargs=None)
   864                                 "TargetInstantiation", args=None, kwargs=None)
       
   865             else:
       
   866                 self.logger.debug("Adding Target Instantiation Zone "
       
   867                     "Checkpoint")
       
   868                 self.engine.register_checkpoint("target-instantiation",
       
   869                                 "solaris_install/target/instantiation_zone",
       
   870                                 "TargetInstantiationZone", args=None,
       
   871                                 kwargs=None)
   771 
   872 
   772             # Add destination for transfer nodes, and register checkpoints.
   873             # Add destination for transfer nodes, and register checkpoints.
   773             sw_nodes = self.doc.volatile.get_descendants(class_type=Software)
   874             sw_nodes = self.doc.volatile.get_descendants(class_type=Software)
   774             image_action = AbstractIPS.CREATE  # For first IPS only
   875             image_action = AbstractIPS.CREATE  # For first IPS only
   775             transfer_count = 0  # For generating names if none provided
   876             transfer_count = 0  # For generating names if none provided
   786                     self.CHECKPOINTS_BEFORE_IPS.append(sw.name)
   887                     self.CHECKPOINTS_BEFORE_IPS.append(sw.name)
   787                     if self.options.stop_checkpoint is not None:
   888                     if self.options.stop_checkpoint is not None:
   788                         if self.options.stop_checkpoint == \
   889                         if self.options.stop_checkpoint == \
   789                             self.FIRST_TRANSFER_CHECKPOINT:
   890                             self.FIRST_TRANSFER_CHECKPOINT:
   790                             self.options.stop_checkpoint = sw.name
   891                             self.options.stop_checkpoint = sw.name
   791 
       
   792 
   892 
   793                 # Ensure there is at least one software_data element with
   893                 # Ensure there is at least one software_data element with
   794                 # Install action exists, and that all software_data elements
   894                 # Install action exists, and that all software_data elements
   795                 # contain at least one 'name' sub element.
   895                 # contain at least one 'name' sub element.
   796                 found_install_sw_data = False
   896                 found_install_sw_data = False
   800                     if tran_type == "IPS" and isinstance(sw_child, IPSSpec):
   900                     if tran_type == "IPS" and isinstance(sw_child, IPSSpec):
   801                         found_sw_data = True
   901                         found_sw_data = True
   802                         if sw_child.action == IPSSpec.INSTALL:
   902                         if sw_child.action == IPSSpec.INSTALL:
   803                             found_install_sw_data = True
   903                             found_install_sw_data = True
   804                     elif tran_type == "CPIO" and \
   904                     elif tran_type == "CPIO" and \
   805                          isinstance(sw_child, CPIOSpec):
   905                         isinstance(sw_child, CPIOSpec):
   806                         found_sw_data = True
   906                         found_sw_data = True
   807                         if sw_child.action == CPIOSpec.INSTALL:
   907                         if sw_child.action == CPIOSpec.INSTALL:
   808                             found_install_sw_data = True
   908                             found_install_sw_data = True
   809                     elif tran_type == "SVR4" and \
   909                     elif tran_type == "SVR4" and \
   810                          isinstance(sw_child, SVR4Spec):
   910                         isinstance(sw_child, SVR4Spec):
   811                         found_sw_data = True
   911                         found_sw_data = True
   812                         if sw_child.action == SVR4Spec.INSTALL:
   912                         if sw_child.action == SVR4Spec.INSTALL:
   813                             found_install_sw_data = True
   913                             found_install_sw_data = True
   814 
   914 
   815                     if found_sw_data and len(sw_child.contents) == 0:
   915                     if found_sw_data and len(sw_child.contents) == 0:
   823                         "Manifest must contain at least one <software_data> "
   923                         "Manifest must contain at least one <software_data> "
   824                         "element with 'install' action.")
   924                         "element with 'install' action.")
   825                     return False
   925                     return False
   826 
   926 
   827                 self.logger.debug("Setting destination for transfer: %s to %s"
   927                 self.logger.debug("Setting destination for transfer: %s to %s"
   828                     % (sw.name, self.INSTALLED_ROOT_DIR))
   928                     % (sw.name, self.installed_root_dir))
   829                 dst = sw.get_first_child(class_type=Destination)
   929                 dst = sw.get_first_child(class_type=Destination)
   830                 if dst is None:
   930                 if dst is None:
   831                     dst = Destination()
   931                     dst = Destination()
   832                     if sw.tran_type.upper() == "IPS":
   932                     if sw.tran_type.upper() == "IPS":
   833                         image = Image(self.INSTALLED_ROOT_DIR, image_action)
   933                         image = Image(self.installed_root_dir, image_action)
   834                         img_type = ImType("full")
   934 
       
   935                         if self.options.zone_pool_dataset is None:
       
   936                             img_type = ImType("full", zone=False)
       
   937                         else:
       
   938                             img_type = ImType("full", zone=True)
       
   939 
   835                         image.insert_children(img_type)
   940                         image.insert_children(img_type)
   836                         dst.insert_children(image)
   941                         dst.insert_children(image)
   837                         image_action = AbstractIPS.EXISTING
   942                         image_action = AbstractIPS.EXISTING
   838                     else:
   943                     else:
   839                         directory = Dir(self.INSTALLED_ROOT_DIR)
   944                         directory = Dir(self.installed_root_dir)
   840                         dst.insert_children(directory)
   945                         dst.insert_children(directory)
   841                     sw.insert_children(dst)
   946                     sw.insert_children(dst)
   842                     # Next images are use_existing, not create.
   947                     # Next images are use_existing, not create.
   843                 else:
   948                 else:
   844                     raise RuntimeError(
   949                     raise RuntimeError(
   854                     self.engine.register_checkpoint(*ckpt_info)
   959                     self.engine.register_checkpoint(*ckpt_info)
   855 
   960 
   856             # Register ICT Checkpoints
   961             # Register ICT Checkpoints
   857             #=========================
   962             #=========================
   858             # 1. Initialize SMF Repository
   963             # 1. Initialize SMF Repository
   859             self.engine.register_checkpoint("initialize-smf",
   964             if self.options.zone_pool_dataset is None:
   860                 "solaris_install.ict.initialize_smf",
   965                 self.engine.register_checkpoint("initialize-smf",
   861                 "InitializeSMF", args=None, kwargs=None)
   966                     "solaris_install.ict.initialize_smf",
       
   967                     "InitializeSMF", args=None, kwargs=None)
       
   968             else:
       
   969                 self.engine.register_checkpoint("initialize-smf-zone",
       
   970                     "solaris_install.ict.initialize_smf",
       
   971                     "InitializeSMFZone", args=None, kwargs=None)
   862 
   972 
   863             # 2. Boot Configuration
   973             # 2. Boot Configuration
   864             self.engine.register_checkpoint("boot-configuration",
   974             if self.options.zone_pool_dataset is None:
   865                 "solaris_install.boot.boot",
   975                 self.engine.register_checkpoint("boot-configuration",
   866                 "SystemBootMenu", args=None, kwargs=None)
   976                     "solaris_install.boot.boot",
       
   977                     "SystemBootMenu", args=None, kwargs=None)
   867 
   978 
   868             # 3. Update dumpadm / Dump Configuration
   979             # 3. Update dumpadm / Dump Configuration
   869             self.engine.register_checkpoint("update-dump-adm",
   980             if self.options.zone_pool_dataset is None:
   870                 "solaris_install.ict.update_dumpadm",
   981                 self.engine.register_checkpoint("update-dump-adm",
   871                 "UpdateDumpAdm", args=None, kwargs=None)
   982                     "solaris_install.ict.update_dumpadm",
       
   983                     "UpdateDumpAdm", args=None, kwargs=None)
   872 
   984 
   873             # 4. Setup Swap in Vfstab
   985             # 4. Setup Swap in Vfstab
   874             self.engine.register_checkpoint("setup-swap",
   986             self.engine.register_checkpoint("setup-swap",
   875                 "solaris_install.ict.setup_swap",
   987                 "solaris_install.ict.setup_swap",
   876                 "SetupSwap", args=None, kwargs=None)
   988                 "SetupSwap", args=None, kwargs=None)
   879             self.engine.register_checkpoint("set-flush-ips-content-cache",
   991             self.engine.register_checkpoint("set-flush-ips-content-cache",
   880                 "solaris_install.ict.ips",
   992                 "solaris_install.ict.ips",
   881                 "SetFlushContentCache", args=None, kwargs=None)
   993                 "SetFlushContentCache", args=None, kwargs=None)
   882 
   994 
   883             # 6. Device Configuration / Create Device Namespace
   995             # 6. Device Configuration / Create Device Namespace
   884             self.engine.register_checkpoint("device-config",
   996             if self.options.zone_pool_dataset is None:
   885                 "solaris_install.ict.device_config",
   997                 self.engine.register_checkpoint("device-config",
   886                 "DeviceConfig", args=None, kwargs=None)
   998                     "solaris_install.ict.device_config",
   887 
   999                     "DeviceConfig", args=None, kwargs=None)
   888             # 7. Transfer System Configuration To BE / ApplyStsConfig
  1000 
   889             self.engine.register_checkpoint("apply-sysconfig",
  1001             # 7. Transfer System Configuration To BE / ApplySysConfig
   890                 "solaris_install.ict.apply_sysconfig",
  1002             if self.options.profile is not None:
   891                 "ApplySysConfig", args=None, kwargs=None)
  1003                 self.engine.register_checkpoint("apply-sysconfig",
       
  1004                     "solaris_install.ict.apply_sysconfig",
       
  1005                     "ApplySysConfig", args=None, kwargs=None)
   892 
  1006 
   893             # 8. Boot Archive
  1007             # 8. Boot Archive
   894             self.engine.register_checkpoint("boot-archive",
  1008             if self.options.zone_pool_dataset is None:
   895                 "solaris_install.ict.boot_archive",
  1009                 self.engine.register_checkpoint("boot-archive",
   896                 "BootArchive", args=None, kwargs=None)
  1010                     "solaris_install.ict.boot_archive",
       
  1011                     "BootArchive", args=None, kwargs=None)
   897 
  1012 
   898             # 9. Transfer Files to New BE
  1013             # 9. Transfer Files to New BE
   899             self.add_transfer_files()
  1014             self.add_transfer_files()
   900             self.engine.register_checkpoint(self.TRANSFER_FILES_CHECKPOINT,
  1015             self.engine.register_checkpoint(TRANSFER_FILES_CHECKPOINT,
   901                 "solaris_install.ict.transfer_files",
  1016                 "solaris_install.ict.transfer_files",
   902                 "TransferFiles", args=None, kwargs=None)
  1017                 "TransferFiles", args=None, kwargs=None)
   903 
  1018 
   904             # 10. CreateSnapshot before reboot
  1019             # 10. CreateSnapshot before reboot
   905             self.engine.register_checkpoint("create-snapshot",
  1020             self.engine.register_checkpoint("create-snapshot",
   922         """
  1037         """
   923         # Check for existence of transfer-ai-files data object dictionary,
  1038         # Check for existence of transfer-ai-files data object dictionary,
   924         # insert if not found
  1039         # insert if not found
   925         tf_doc_dict = None
  1040         tf_doc_dict = None
   926         tf_doc_dict = self.doc.volatile.get_first_child( \
  1041         tf_doc_dict = self.doc.volatile.get_first_child( \
   927             name=self.TRANSFER_FILES_CHECKPOINT)
  1042             name=TRANSFER_FILES_CHECKPOINT)
   928 
  1043 
   929         if tf_doc_dict is None:
  1044         if tf_doc_dict is None:
   930             # Initialize dictionary in DOC
  1045             # Initialize dictionary in DOC
   931             tf_dict = dict()
  1046             tf_dict = dict()
   932             tf_doc_dict = DataObjectDict(self.TRANSFER_FILES_CHECKPOINT,
  1047             tf_doc_dict = DataObjectDict(TRANSFER_FILES_CHECKPOINT,
   933                 tf_dict)
  1048                 tf_dict)
   934             self.doc.volatile.insert_children(tf_doc_dict)
  1049             self.doc.volatile.insert_children(tf_doc_dict)
   935         else:
  1050         else:
   936             tf_dict = tf_doc_dict.data_dict
  1051             tf_dict = tf_doc_dict.data_dict
   937 
  1052 
   945 
  1060 
   946             mp = self.doc.volatile.get_first_child(name=MANIFEST_PARSER_DATA)
  1061             mp = self.doc.volatile.get_first_child(name=MANIFEST_PARSER_DATA)
   947             if mp is not None and mp.manifest is not None:
  1062             if mp is not None and mp.manifest is not None:
   948                 tf_dict[mp.manifest] = \
  1063                 tf_dict[mp.manifest] = \
   949                     post_install_logs_path('derived/manifest.xml')
  1064                     post_install_logs_path('derived/manifest.xml')
       
  1065         # Else transfer the XML manifest passed in
       
  1066         else:
       
  1067             tf_dict[self.manifest] = post_install_logs_path('ai.xml')
   950 
  1068 
   951         # Transfer smf logs
  1069         # Transfer smf logs
   952         tf_dict['/var/svc/log/application-auto-installer:default.log'] = \
  1070         tf_dict['/var/svc/log/application-auto-installer:default.log'] = \
   953             post_install_logs_path('application-auto-installer:default.log')
  1071             post_install_logs_path('application-auto-installer:default.log')
   954         tf_dict['/var/svc/log/application-manifest-locator:default.log'] = \
  1072         tf_dict['/var/svc/log/application-manifest-locator:default.log'] = \
   955             post_install_logs_path('application-manifest-locator:default.log')
  1073             post_install_logs_path('application-manifest-locator:default.log')
   956 
       
   957         # Transfer default manifest
       
   958         tf_dict[system_temp_path('ai.xml')] = post_install_logs_path('ai.xml')
       
   959 
  1074 
   960         # Transfer AI Service Discovery Log
  1075         # Transfer AI Service Discovery Log
   961         tf_dict[system_temp_path('ai_sd_log')] = \
  1076         tf_dict[system_temp_path('ai_sd_log')] = \
   962             post_install_logs_path('ai_sd_log')
  1077             post_install_logs_path('ai_sd_log')
   963 
  1078