def test_is_iso(self): '''test is_iso''' tmpfile = tempfile.mktemp() with open(tmpfile, 'w') as myfile: myfile.write('this is myfile text.') self.assertFalse(image.is_iso(tmpfile)) os.remove(tmpfile)
def do_create_baseservice(options): ''' This method sets up the install service by: - creating the target image directory from an iso or pkg - creating the /var/ai service structure - enabling tftp service or configuring wanboot - configuring dhcp if desired ''' tempdir = None print _("\nCreating service from: %s") % options.srcimage if is_iso(options.srcimage): have_iso = True # get default service name, if needed logging.debug("Creating ISO based service") else: have_iso = False logging.debug("Creating pkg(5) based service") # If imagepath specified by user, use that. # If imagepath not specified by user: # a) if svcname specified by user, set up image in # <default image path>/<svcname> # b) if svcname not specified by user, set up image in # <tmp location> and move to <default image path>/<svcname> # once svcname is determined. # If imagepath not specified, verify that default image path is # ok with user if not options.imagepath: if options.svcname: imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) prompt = (_("OK to use default image path: %s? [y/N]: " % imagepath)) else: prompt = (_("OK to use subdir of %s to store image? [y/N]: " % BASE_IMAGE_DIR)) try: if not options.noprompt: if not com.ask_yes_or_no(prompt): raise SystemExit( _('\nPlease re-enter command with ' 'desired --imagepath\n')) except KeyboardInterrupt: raise SystemExit(1) # If we know the svcname, we know where to put the image. # Otherwise, put the image into a temp directory and move # it to correct location when we know it later if options.svcname: options.imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) try: check_imagepath(options.imagepath) except ValueError as error: raise SystemExit(error) else: try: os.makedirs(BASE_IMAGE_DIR) except OSError as err: if err.errno != errno.EEXIST: raise if not os.path.isdir(BASE_IMAGE_DIR): raise SystemExit( cw( _('\nThe default image base ' 'directory, %(dir)s, is not a directory. Check the ' 'SMF setting for property %(prop)s in servce ' '%(svc)s.') % { 'dir': BASE_IMAGE_DIR, 'prop': com.BASEDIR_PROP, 'svc': com.SRVINST })) tempdir = tempfile.mkdtemp(dir=BASE_IMAGE_DIR) options.imagepath = tempdir logging.debug('Using default image path: %s', options.imagepath) # create the image area if have_iso: try: image = InstalladmIsoImage.unpack(options.srcimage, options.imagepath) except CalledProcessError as err: raise SystemExit(err.popen.stderr) except ImageError as err: print >> sys.stderr, str(err) shutil.rmtree(options.imagepath, ignore_errors=True) raise SystemExit( cw( _('Please re-enter command and specify ' 'a valid Automated Installer ISO file'))) else: try: image = InstalladmPkgImage.image_create( options.srcimage, options.imagepath, arch=options.arch, publisher=options.publisher) except (ImageError, pkg.client.api_errors.ApiException) as err: print >> sys.stderr, cw(_("The specified data source, %s, " "for the service is not a path to an existing ISO image.") % \ options.srcimage) print >> sys.stderr, cw(_("Attempting to create the service from" " pkg(5) package, %s, failed for the following reasons:") % \ options.srcimage) if isinstance(err, pkg.client.api_errors.VersionException): print >> sys.stderr, cw( _("The IPS API version specified, " + str(err.received_version) + ", is incompatible with the expected version, " + str(err.expected_version) + ".")) elif isinstance(err, pkg.client.api_errors.CatalogRefreshException): for pub, error in err.failed: print >> sys.stderr, " " print >> sys.stderr, str(error) if err.errmessage: print >> sys.stderr, err.errmessage shutil.rmtree(options.imagepath, ignore_errors=True) raise SystemExit(err) # get default service name, if needed if not options.svcname: if tempdir and options.imagepath == tempdir: specified_path = None else: specified_path = options.imagepath options.svcname = get_default_service_name(specified_path, image=image, iso=have_iso) print _("\nCreating %(arch)s service: %(name)s\n") % \ {'arch': image.arch, 'name': options.svcname} # If image was created in temporary location, move to correct # location now that we know the svcname. if tempdir is not None: new_imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) try: check_imagepath(new_imagepath) except ValueError as error: # leave image in temp location so that service can be created logging.debug('unable to move image to %s: %s', new_imagepath, error) else: options.imagepath = image.move(new_imagepath) logging.debug('image moved to %s', options.imagepath) set_permissions(options.imagepath) print _("Image path: %s\n") % options.imagepath try: if options.dhcp_ip_start: service = AIService.create(options.svcname, image, options.dhcp_ip_start, options.dhcp_ip_count, options.dhcp_bootserver, bootargs=options.bootargs) else: service = AIService.create(options.svcname, image, bootargs=options.bootargs) except AIServiceError as err: raise SystemExit(err) # Register & enable service # (Also enables system/install/server, as needed) got_services_error = False try: service.enable() except (config.ServiceCfgError, MountError) as err: raise SystemExit(err) except aismf.ServicesError as svc_err: # Don't print the error now. It will either get printed out # upon exit or when services are enabled after creating the # alias got_services_error = True # create default-<arch> alias if this is the first aliasable # service of this architecture if should_be_default_for_arch(service): defaultarch = 'default-' + image.arch print(_("\nCreating %s alias.\n") % defaultarch) try: defaultarchsvc = AIService.create(defaultarch, image, bootargs=options.bootargs, alias=options.svcname) except AIServiceError as err: raise SystemExit(err) except UnsupportedAliasError as err: if got_services_error: # Print the services error string before printing the # unsupported alias error print svc_err, '\n' # Print the error, but have installadm exit successfully. # Since the user did not explicitly request this alias, # it's not a problem if an alias can't be made for this service print err return 0 # For sparc, create symlinks for default sparc service if image.arch == 'sparc': logging.debug("Creating default-sparc symlinks") defaultarchsvc.do_default_sparc_symlinks(defaultarch) # Register & enable default-<arch> service try: defaultarchsvc.enable() except (config.ServiceCfgError, MountError) as err: raise SystemExit(err) except aismf.ServicesError as err: print err elif got_services_error: # Print the services start error generated when creating the service print svc_err
def do_create_baseservice(options): ''' This method sets up the install service by: - creating the target image directory from an iso or pkg - creating the /var/ai service structure - enabling tftp service or configuring wanboot - configuring dhcp if desired ''' tempdir = None print _("\nCreating service from: %s") % options.srcimage if is_iso(options.srcimage): have_iso = True # get default service name, if needed logging.debug("Creating ISO based service") else: have_iso = False logging.debug("Creating pkg(5) based service") # If imagepath specified by user, use that. # If imagepath not specified by user: # a) if svcname specified by user, set up image in # <default image path>/<svcname> # b) if svcname not specified by user, set up image in # <tmp location> and move to <default image path>/<svcname> # once svcname is determined. # If imagepath not specified, verify that default image path is # ok with user if not options.imagepath: if options.svcname: imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) prompt = (_("OK to use default image path: %s? [y/N]: " % imagepath)) else: prompt = (_("OK to use subdir of %s to store image? [y/N]: " % BASE_IMAGE_DIR)) try: if not options.noprompt: if not com.ask_yes_or_no(prompt): raise SystemExit(_('\nPlease re-enter command with ' 'desired --imagepath\n')) except KeyboardInterrupt: raise SystemExit(1) # If we know the svcname, we know where to put the image. # Otherwise, put the image into a temp directory and move # it to correct location when we know it later if options.svcname: options.imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) try: check_imagepath(options.imagepath) except ValueError as error: raise SystemExit(error) else: try: os.makedirs(BASE_IMAGE_DIR) except OSError as err: if err.errno != errno.EEXIST: raise if not os.path.isdir(BASE_IMAGE_DIR): raise SystemExit(cw(_('\nThe default image base ' 'directory, %(dir)s, is not a directory. Check the ' 'SMF setting for property %(prop)s in servce ' '%(svc)s.') % {'dir': BASE_IMAGE_DIR, 'prop': com.BASEDIR_PROP, 'svc': com.SRVINST})) tempdir = tempfile.mkdtemp(dir=BASE_IMAGE_DIR) options.imagepath = tempdir logging.debug('Using default image path: %s', options.imagepath) # create the image area if have_iso: try: image = InstalladmIsoImage.unpack(options.srcimage, options.imagepath) except CalledProcessError as err: raise SystemExit(err.popen.stderr) except ImageError as err: print >> sys.stderr, str(err) shutil.rmtree(options.imagepath, ignore_errors=True) raise SystemExit(cw(_('Please re-enter command and specify ' 'a valid Automated Installer ISO file'))) else: try: image = InstalladmPkgImage.image_create(options.srcimage, options.imagepath, arch=options.arch, publisher=options.publisher) except (ImageError, pkg.client.api_errors.ApiException) as err: print >> sys.stderr, cw(_("The specified data source, %s, " "for the service is not a path to an existing ISO image.") % \ options.srcimage) print >> sys.stderr, cw(_("Attempting to create the service from" " pkg(5) package, %s, failed for the following reasons:") % \ options.srcimage) if isinstance(err, pkg.client.api_errors.VersionException): print >> sys.stderr, cw(_("The IPS API version specified, " + str(err.received_version) + ", is incompatible with the expected version, " + str(err.expected_version) + ".")) elif isinstance(err, pkg.client.api_errors.CatalogRefreshException): for pub, error in err.failed: print >> sys.stderr, " " print >> sys.stderr, str(error) if err.errmessage: print >> sys.stderr, err.errmessage shutil.rmtree(options.imagepath, ignore_errors=True) raise SystemExit(err) # get default service name, if needed if not options.svcname: if tempdir and options.imagepath == tempdir: specified_path = None else: specified_path = options.imagepath options.svcname = get_default_service_name(specified_path, image=image, iso=have_iso) print _("\nCreating %(arch)s service: %(name)s\n") % \ {'arch': image.arch, 'name': options.svcname} # If image was created in temporary location, move to correct # location now that we know the svcname. if tempdir is not None: new_imagepath = os.path.join(BASE_IMAGE_DIR, options.svcname) try: check_imagepath(new_imagepath) except ValueError as error: # leave image in temp location so that service can be created logging.debug('unable to move image to %s: %s', new_imagepath, error) else: options.imagepath = image.move(new_imagepath) logging.debug('image moved to %s', options.imagepath) set_permissions(options.imagepath) print _("Image path: %s\n") % options.imagepath try: if options.dhcp_ip_start: service = AIService.create(options.svcname, image, options.dhcp_ip_start, options.dhcp_ip_count, options.dhcp_bootserver, bootargs=options.bootargs) else: service = AIService.create(options.svcname, image, bootargs=options.bootargs) except AIServiceError as err: raise SystemExit(err) # Register & enable service # (Also enables system/install/server, as needed) got_services_error = False try: service.enable() except (config.ServiceCfgError, MountError) as err: raise SystemExit(err) except aismf.ServicesError as svc_err: # Don't print the error now. It will either get printed out # upon exit or when services are enabled after creating the # alias got_services_error = True # create default-<arch> alias if this is the first aliasable # service of this architecture if should_be_default_for_arch(service): defaultarch = 'default-' + image.arch print (_("\nCreating %s alias.\n") % defaultarch) try: defaultarchsvc = AIService.create(defaultarch, image, bootargs=options.bootargs, alias=options.svcname) except AIServiceError as err: raise SystemExit(err) except UnsupportedAliasError as err: if got_services_error: # Print the services error string before printing the # unsupported alias error print svc_err, '\n' # Print the error, but have installadm exit successfully. # Since the user did not explicitly request this alias, # it's not a problem if an alias can't be made for this service print err return 0 # For sparc, create symlinks for default sparc service if image.arch == 'sparc': logging.debug("Creating default-sparc symlinks") defaultarchsvc.do_default_sparc_symlinks(defaultarch) # Register & enable default-<arch> service try: defaultarchsvc.enable() except (config.ServiceCfgError, MountError) as err: raise SystemExit(err) except aismf.ServicesError as err: print err elif got_services_error: # Print the services start error generated when creating the service print svc_err
def parse_options(cmd_options=None): ''' Parse and validate options Returns: An options record containing arch aliasof bootargs dhcp_ip_count dhcp_ip_start dhcp_bootserver noprompt publisher srcimage svcname imagepath ''' logging.log(com.XDEBUG, '**** START installadm.create_service.' 'parse_options ****\n') usage = '\n' + get_usage() description = _('Establishes an Automated Install network service.') parser = OptionParser(usage=usage, prog="create-service", description=description) parser.add_option('-b', '--boot-args', dest='bootargs', action='append', default=list(), help=_('Comma separated list of <property>=<value>' ' pairs to add to the x86 Grub menu entry')) parser.add_option('-a', '--arch', dest='arch', default=None, choices=("i386", "sparc"), help=_("ARCHITECTURE (sparc or i386), desired " "architecture of resulting service when creating " "from a pkg.")) parser.add_option('-d', '--imagepath', dest='imagepath', default=None, help=_("Path at which to create the net image")) parser.add_option('-t', '--aliasof', dest='aliasof', default=None, help=_("Service being created is alias of this serivce")) parser.add_option('-n', '--service', dest='svcname', help=_('service name')) parser.add_option('-i', '--ip-start', dest='dhcp_ip_start', type='string', help=_('DHCP Starting IP Address'), action="callback", callback=check_ip_address) parser.add_option('-c', '--ip-count', dest='dhcp_ip_count', type='int', help=_('DHCP Count of IP Addresses')) parser.add_option('-B', '--bootfile-server', dest='dhcp_bootserver', type='string', help=_('DHCP Boot Server Address'), action="callback", callback=check_ip_address) parser.add_option('-s', '--source', dest='srcimage', type='string', help=_('FMRI or Auto Install ISO')) parser.add_option('-p', '--publisher', help=_( "A pkg(5) publisher, in the" " form '<prefix>=<uri>', from which to install the " "client image")) parser.add_option('-y', "--noprompt", action="store_true", dest="noprompt", default=False, help=_('Suppress confirmation prompts and proceed with ' 'service creation using default values')) options, args = parser.parse_args(cmd_options) if args: parser.error(_('Unexpected argument(s): %s') % args) # if service name provided, validate it if options.svcname: try: com.validate_service_name(options.svcname) except ValueError as err: parser.error(err) # Give error if service already exists if config.is_service(options.svcname): parser.error(_('\nService already exists: %s\n') % options.svcname) # If creating an alias, only allow additional options -n, -b, # and -y if options.aliasof: if (options.dhcp_ip_start or options.dhcp_ip_count or options.imagepath or options.srcimage): parser.error( _('\nOnly options -n|--service, -b|--boot-args, ' 'and -y|--noprompt\nmay be specified with ' '-t|--aliasof.')) if not options.svcname: parser.error( _('\nOption -n|--service is required with the ' '-t|--aliasof option')) else: name = options.svcname if name in DEFAULT_ARCH: raise SystemExit( _('\nDefault services must be created as ' 'aliases. Use -t|--aliasof.\n')) # provide default for srcimage, now that we're done option checking if options.srcimage is None: options.srcimage = "pkg:/install-image/solaris-auto-install" # check dhcp related options if options.dhcp_ip_start or options.dhcp_ip_count: if com.is_multihomed(): # don't allow DHCP setup if multihomed parser.error( cw( _('\nDHCP server configuration is unavailable on ' 'hosts with multiple network interfaces (-i and ' '-c options are disallowed).\n'))) # Confirm options -i and -c are both provided if options.dhcp_ip_count is None: parser.error( _('\nIf -i option is provided, -c option must ' 'also be provided\n')) if not options.dhcp_ip_start: parser.error( _('\nIf -c option is provided, -i option must ' 'also be provided\n')) # Confirm count of ip addresses is positive if options.dhcp_ip_count < 1: parser.error( _('\n"-c <count_of_ipaddr>" must be greater than ' 'zero.\n')) if options.dhcp_bootserver: # Confirm if the -B is provided, that -i/-c are also if options.dhcp_ip_count is None: parser.error( _('\nIf -B option is provided, -i option must ' 'also be provided\n')) if is_iso(options.srcimage): if options.arch is not None: parser.error( _("The --arch option is invalid for ISO-based " "services")) if options.publisher is not None: parser.error( _("The --publisher option is invalid for " "ISO-based services")) if options.publisher: # Convert options.publisher from a string of form 'prefix=uri' to a # tuple (prefix, uri) publisher = options.publisher.split("=") if len(publisher) != 2: parser.error( _('Publisher information must match the form: ' '"<prefix>=<URI>"')) options.publisher = publisher # Make sure imagepath meets requirements if options.imagepath: options.imagepath = options.imagepath.strip() if options.imagepath: if not options.imagepath == '/': options.imagepath = options.imagepath.rstrip('/') try: check_imagepath(options.imagepath) except ValueError as error: raise SystemExit(error) return options
def parse_options(cmd_options=None): ''' Parse and validate options Returns: An options record containing arch aliasof bootargs dhcp_ip_count dhcp_ip_start dhcp_bootserver noprompt publisher srcimage svcname imagepath ''' logging.log(com.XDEBUG, '**** START installadm.create_service.' 'parse_options ****\n') usage = '\n' + get_usage() description = _('Establishes an Automated Install network service.') parser = OptionParser(usage=usage, prog="create-service", description=description) parser.add_option('-b', '--boot-args', dest='bootargs', action='append', default=list(), help=_('Comma separated list of <property>=<value>' ' pairs to add to the x86 Grub menu entry')) parser.add_option('-a', '--arch', dest='arch', default=None, choices=("i386", "sparc"), help=_("ARCHITECTURE (sparc or i386), desired " "architecture of resulting service when creating " "from a pkg.")) parser.add_option('-d', '--imagepath', dest='imagepath', default=None, help=_("Path at which to create the net image")) parser.add_option('-t', '--aliasof', dest='aliasof', default=None, help=_("Service being created is alias of this serivce")) parser.add_option('-n', '--service', dest='svcname', help=_('service name')) parser.add_option('-i', '--ip-start', dest='dhcp_ip_start', type='string', help=_('DHCP Starting IP Address'), action="callback", callback=check_ip_address) parser.add_option('-c', '--ip-count', dest='dhcp_ip_count', type='int', help=_('DHCP Count of IP Addresses')) parser.add_option('-B', '--bootfile-server', dest='dhcp_bootserver', type='string', help=_('DHCP Boot Server Address'), action="callback", callback=check_ip_address) parser.add_option('-s', '--source', dest='srcimage', type='string', help=_('FMRI or Auto Install ISO')) parser.add_option('-p', '--publisher', help=_("A pkg(5) publisher, in the" " form '<prefix>=<uri>', from which to install the " "client image")) parser.add_option('-y', "--noprompt", action="store_true", dest="noprompt", default=False, help=_('Suppress confirmation prompts and proceed with ' 'service creation using default values')) options, args = parser.parse_args(cmd_options) if args: parser.error(_('Unexpected argument(s): %s') % args) # if service name provided, validate it if options.svcname: try: com.validate_service_name(options.svcname) except ValueError as err: parser.error(err) # Give error if service already exists if config.is_service(options.svcname): parser.error(_('\nService already exists: %s\n') % options.svcname) # If creating an alias, only allow additional options -n, -b, # and -y if options.aliasof: if (options.dhcp_ip_start or options.dhcp_ip_count or options.imagepath or options.srcimage): parser.error(_('\nOnly options -n|--service, -b|--boot-args, ' 'and -y|--noprompt\nmay be specified with ' '-t|--aliasof.')) if not options.svcname: parser.error(_('\nOption -n|--service is required with the ' '-t|--aliasof option')) else: name = options.svcname if name in DEFAULT_ARCH: raise SystemExit(_('\nDefault services must be created as ' 'aliases. Use -t|--aliasof.\n')) # provide default for srcimage, now that we're done option checking if options.srcimage is None: options.srcimage = "pkg:/install-image/solaris-auto-install" # check dhcp related options if options.dhcp_ip_start or options.dhcp_ip_count: if com.is_multihomed(): # don't allow DHCP setup if multihomed parser.error(cw(_('\nDHCP server configuration is unavailable on ' 'hosts with multiple network interfaces (-i and ' '-c options are disallowed).\n'))) # Confirm options -i and -c are both provided if options.dhcp_ip_count is None: parser.error(_('\nIf -i option is provided, -c option must ' 'also be provided\n')) if not options.dhcp_ip_start: parser.error(_('\nIf -c option is provided, -i option must ' 'also be provided\n')) # Confirm count of ip addresses is positive if options.dhcp_ip_count < 1: parser.error(_('\n"-c <count_of_ipaddr>" must be greater than ' 'zero.\n')) if options.dhcp_bootserver: # Confirm if the -B is provided, that -i/-c are also if options.dhcp_ip_count is None: parser.error(_('\nIf -B option is provided, -i option must ' 'also be provided\n')) if is_iso(options.srcimage): if options.arch is not None: parser.error(_("The --arch option is invalid for ISO-based " "services")) if options.publisher is not None: parser.error(_("The --publisher option is invalid for " "ISO-based services")) if options.publisher: # Convert options.publisher from a string of form 'prefix=uri' to a # tuple (prefix, uri) publisher = options.publisher.split("=") if len(publisher) != 2: parser.error(_('Publisher information must match the form: ' '"<prefix>=<URI>"')) options.publisher = publisher # Make sure imagepath meets requirements if options.imagepath: options.imagepath = options.imagepath.strip() if options.imagepath: if not options.imagepath == '/': options.imagepath = options.imagepath.rstrip('/') try: check_imagepath(options.imagepath) except ValueError as error: raise SystemExit(error) return options