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)
示例#2
0
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
示例#4
0
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