def test_delete_service_props(self):
     '''verify delete_service_props'''
     svc = 'mysvc'
     props = {'fudge': 'brownie'}
     config._write_service_config(svc, props)
     self.assertTrue(config.is_service(svc))
     config.delete_service_props(svc)
     self.assertFalse(config.is_service(svc))
示例#2
0
def do_set_service(cmd_options=None):
    '''
    Set a property of a service
    '''
    # check that we are root
    if os.geteuid() != 0:
        raise SystemExit(_("Error: Root privileges are required for this "
                           "command."))

    options = parse_options(cmd_options)

    # validate service name
    try:
        validate_service_name(options.svcname)
    except ValueError as err:
        raise SystemExit(str(err))

    logging.debug("options %s", options)

    if not config.is_service(options.svcname):
        raise SystemExit(_('\nError: Service does not exist: %s\n') %
                         options.svcname)

    if options.prop == "default-manifest":
        do_set_service_default_manifest(options)
    elif options.prop == "aliasof":
        return set_aliasof(options)
    elif options.prop == "imagepath":
        return set_imagepath(options)
示例#3
0
def do_set_service(cmd_options=None):
    '''
    Set a property of a service
    '''
    # check for authorization and euid
    try:
        check_auth_and_euid(SERVICE_AUTH)
    except UnauthorizedUserError as err:
        raise SystemExit(err)

    options = parse_options(cmd_options)

    # validate service name
    try:
        validate_service_name(options.svcname)
    except ValueError as err:
        raise SystemExit(str(err))

    logging.debug("options %s", options)

    if not config.is_service(options.svcname):
        raise SystemExit(_('\nError: Service does not exist: %s\n') %
                         options.svcname)

    if options.prop == "default-manifest":
        do_set_service_default_manifest(options)
    elif options.prop == "aliasof":
        return set_aliasof(options)
    elif options.prop == "imagepath":
        return set_imagepath(options)
示例#4
0
def do_enable_service(cmd_options=None):
    ''' Enable a service

    Parse the supplied arguments then enable the specified service.

    Input:
        List of command line options
    Return:
        None
    Raises:
        SystemExit if missing permissions, invalid service name, or
        if attempt to enable the service or the smf service fails.

    '''
    logging.log(XDEBUG, '**** START do_enable_service ****')

    # check for authorization and euid
    try:
        check_auth_and_euid(SERVICE_AUTH)
    except UnauthorizedUserError as err:
        raise SystemExit(err)

    usage = '\n' + get_enable_usage()
    parser = OptionParser(usage=usage)

    args = parser.parse_args(cmd_options)[1]

    # Check for correct number of args
    if len(args) != 1:
        if len(args) == 0:
            parser.error(_("Missing required argument, <svcname>"))
        else:
            parser.error(_("Too many arguments: %s") % args)

    svcname = args[0]

    if not config.is_service(svcname):
        err_msg = _("The service does not exist: %s\n") % svcname
        parser.error(err_msg)

    # Verify that the server settings are not obviously broken.
    # These checks cannot be complete, but do check for things
    # which will definitely cause failure.
    ret = Popen([CHECK_SETUP_SCRIPT]).wait()
    if ret:
        return 1

    logging.log(XDEBUG, 'Enabling install service %s', svcname)
    try:
        service = AIService(svcname)
        service.enable()
    except (aismf.ServicesError, config.ServiceCfgError, ImageError,
            MountError) as err:
        raise SystemExit(err)
    except InvalidServiceError as err:
        raise SystemExit(
            cw(
                _("\nThis service may not be enabled until all "
                  "invalid manifests and profiles have been "
                  "corrected or removed.\n")))
示例#5
0
def parse_options(cmd_options=None):
    """
    Parse and validate options
    """

    usage = '\n' + get_usage()
    parser = OptionParser(usage=usage)

    parser.add_option("-m", "--manifest", dest="manifest_name",
                      default=None, help=_("Name of manifest"))
    parser.add_option("-n", "--service", dest="service_name",
                      default=None, help=_("Name of install service."))
    parser.add_option("-i", "--instance", dest="instance", default=None,
                      help=_("manifest instance to remove (internal option)"),
                      type="int", metavar="manifest instance")

    (options, args) = parser.parse_args(cmd_options)

    # check for required options
    if options.service_name is None:
        parser.error(_("Service name is required "
                       "(-n|--service <service name>)."))
    if options.manifest_name is None:
        parser.error(_("Manifest name is required "
                       "(-m|--manifest <manifest_name>)."))
    if args:
        parser.error(_("Unexpected argument(s): %s" % args))

    if not config.is_service(options.service_name):
        raise SystemExit(_("Not a valid service: %s") % options.service_name)

    options.svcdir_path = AIService(options.service_name).config_dir
    logging.debug("options = %s", options)
    return options
示例#6
0
def set_aliasof(options):
    '''Change a service's base service'''
    logging.debug("set alias %s's basesvc to %s", options.svcname,
                  options.value)
    basesvcname = options.value
    aliasname = options.svcname

    if not config.is_service(basesvcname):
        raise SystemExit(
            _('\nError: Service does not exist: %s\n') % basesvcname)

    if aliasname == basesvcname:
        raise SystemExit(
            _('\nError: Alias name same as service name: %s\n') % aliasname)

    aliassvc = svc.AIService(aliasname)
    if not aliassvc.is_alias():
        raise SystemExit(
            _('\nError: Service exists, but is not an '
              'alias: %s\n') % aliasname)

    basesvc_arch = svc.AIService(basesvcname).arch
    aliassvc_arch = aliassvc.arch
    if basesvc_arch != aliassvc_arch:
        raise SystemExit(
            _("\nError: Architectures of service and alias "
              "are different.\n"))

    if aliassvc.is_aliasof(basesvcname):
        raise SystemExit(
            _("\nError: %s is already an alias of %s\n") %
            (aliasname, basesvcname))

    if svc.AIService(basesvcname).is_alias():
        raise SystemExit(_("\nError: Cannot alias to another alias.\n"))

    # Make sure we aren't creating inter dependencies
    all_aliases = config.get_aliased_services(aliasname, recurse=True)
    if basesvcname in all_aliases:
        raise SystemExit(
            cw(
                _("\nError: %s can not be made an alias of %s "
                  "because %s is dependent on %s\n") %
                (aliasname, basesvcname, basesvcname, aliasname)))
    try:
        aliassvc.update_basesvc(basesvcname)
    except (OSError, config.ServiceCfgError) as err:
        raise SystemExit(
            _("Failed to set 'aliasof' property of : %s") % aliasname)
    except svc.MultipleUnmountError as err:
        print >> sys.stderr, _("Failed to disable alias")
        raise SystemExit(err)
    except svc.MountError as err:
        print >> sys.stderr, _("Failed to enable alias")
        raise SystemExit(err)
    except svc.UnsupportedAliasError as err:
        raise SystemExit(err)
示例#7
0
def parse_options(cmd_options=None):
    '''Parse and validate options
    Args: Optional cmd_options, used for unit testing. Otherwise, cmd line
          options handled by OptionParser
    Returns: options object

    '''
    usage = '\n' + get_usage()
    parser = OptionParser(usage=usage)
    parser.add_option('-s', '--source', dest='srcimage', help=_('FMRI'))
    parser.add_option(
        '-p',
        '--publisher',
        help=_("A pkg(5) publisher, in "
               "the form '<prefix>=<uri>', from which to update the "
               "image. Specified publisher becomes the sole publisher "
               "of the updated image."))

    # Get the parsed arguments using parse_args()
    options, args = parser.parse_args(cmd_options)

    # Confirm service name was passed in
    if not args:
        parser.error(_("Missing required argument, <svcname>"))
    elif len(args) > 1:
        parser.error(_("Too many arguments: %s") % args)

    options.service_name = args[0]

    # ensure service exists
    if not config.is_service(options.service_name):
        raise SystemExit(
            _("\nError: The specified service does "
              "not exist: %s\n") % options.service_name)

    service = svc.AIService(options.service_name,
                            image_class=InstalladmPkgImage)
    if not service.is_alias():
        raise SystemExit(
            cw(
                _("Error: '%s' is not an alias. The target of "
                  "'update-service' must be an alias.") % service.name))

    options.service = service

    if options.publisher is not None:
        # Convert options.publisher from a string of form 'prefix=uri' to a
        # tuple (prefix, uri) and strip each entry
        publisher = map(str.strip, options.publisher.split("="))
        if len(publisher) != 2:
            parser.error(
                _('Publisher information must match the form: '
                  '"<prefix>=<URI>"'))
        options.publisher = publisher

    logging.debug("options=%s", options)
    return options
示例#8
0
def do_alias_service(options):
    ''' Create an alias of a service

    '''
    # Ensure that the base service is a service
    if not config.is_service(options.aliasof):
        raise SystemExit(_("\nService does not exist: %s\n") % options.aliasof)

    basesvc = AIService(options.aliasof)

    # Ensure that the base service is not an alias
    if basesvc.is_alias():
        raise SystemExit(_("\nError: Cannot create alias of another alias.\n"))

    image = basesvc.image
    if options.svcname in DEFAULT_ARCH:
        if ((image.arch == 'sparc' and 'sparc' not in options.svcname)
                or (image.arch == 'i386' and 'i386' not in options.svcname)):
            raise SystemExit(
                cw(
                    _("\nError: %s can not be an alias of a "
                      "service with a different architecture.\n") %
                    options.svcname))

    logging.debug("Creating alias of service %s", options.aliasof)

    print _("\nCreating %(arch)s alias: %(name)s\n") % \
            {'arch': image.arch,
             'name': options.svcname}

    logging.debug("Creating AIService aliasname %s base svc=%s, bootargs=%s",
                  options.svcname, options.aliasof, options.bootargs)
    try:
        service = AIService.create(options.svcname,
                                   image,
                                   alias=options.aliasof,
                                   bootargs=options.bootargs)
    except AIServiceError as err:
        raise SystemExit(err)

    # if recreating default-sparc alias, recreate symlinks
    if service.is_default_arch_service() and image.arch == 'sparc':
        logging.debug("Recreating default-sparc symlinks")
        service.do_default_sparc_symlinks(options.svcname)

    # Register & enable service
    # (Also enables system/install/server, as needed)
    try:
        service.enable()
    except (config.ServiceCfgError, MountError) as err:
        raise SystemExit(err)
    except aismf.ServicesError as err:
        # don't error out if the service is successfully created
        # but the services fail to start - just print out the error
        # and proceed
        print err
 def test_is_service_and_is_enabled(self):
     '''test is_service() and is_enabled()'''
     svc = 'myservice'
     props = {config.PROP_STATUS: config.STATUS_ON}
     config._write_service_config(svc, props)
     self.assertTrue(config.is_service(svc))
     self.assertTrue(config.is_enabled(svc))
     props = {config.PROP_STATUS: config.STATUS_OFF}
     config.set_service_props(svc, props)
     self.assertFalse(config.is_enabled(svc))
def do_alias_service(options):
    ''' Create an alias of a service

    '''
    # Ensure that the base service is a service
    if not config.is_service(options.aliasof):
        raise SystemExit(_("\nService does not exist: %s\n") % options.aliasof)

    basesvc = AIService(options.aliasof)

    # Ensure that the base service is not an alias
    if basesvc.is_alias():
        raise SystemExit(_("\nError: Cannot create alias of another alias.\n"))

    image = basesvc.image
    if options.svcname in DEFAULT_ARCH:
        if ((image.arch == 'sparc' and 'sparc' not in options.svcname) or
            (image.arch == 'i386' and 'i386' not in options.svcname)):
            raise SystemExit(cw(_("\nError: %s can not be an alias of a "
                                  "service with a different architecture.\n") %
                                  options.svcname))
 
    logging.debug("Creating alias of service %s", options.aliasof)

    print _("\nCreating %(arch)s alias: %(name)s\n") % \
            {'arch': image.arch,
             'name': options.svcname}

    logging.debug("Creating AIService aliasname %s base svc=%s, bootargs=%s",
                  options.svcname, options.aliasof, options.bootargs)
    try:
        service = AIService.create(options.svcname, image,
                                   alias=options.aliasof,
                                   bootargs=options.bootargs)
    except AIServiceError as err:
        raise SystemExit(err)

    # if recreating default-sparc alias, recreate symlinks
    if service.is_default_arch_service() and image.arch == 'sparc':
        logging.debug("Recreating default-sparc symlinks")
        service.do_default_sparc_symlinks(options.svcname)

    # Register & enable service
    # (Also enables system/install/server, as needed)
    try:
        service.enable()
    except (config.ServiceCfgError, MountError) as err:
        raise SystemExit(err)
    except aismf.ServicesError as err:
        # don't error out if the service is successfully created
        # but the services fail to start - just print out the error
        # and proceed
        print err
def set_aliasof(options):
    '''Change a service's base service'''
    logging.debug("set alias %s's basesvc to %s",
                  options.svcname, options.value)
    basesvcname = options.value
    aliasname = options.svcname

    if not config.is_service(basesvcname):
        raise SystemExit(_('\nError: Service does not exist: %s\n') %
                         basesvcname)

    if aliasname == basesvcname:
        raise SystemExit(_('\nError: Alias name same as service name: %s\n') %
                         aliasname)

    aliassvc = svc.AIService(aliasname)
    if not aliassvc.is_alias():
        raise SystemExit(_('\nError: Service exists, but is not an '
                           'alias: %s\n') % aliasname)

    basesvc_arch = svc.AIService(basesvcname).arch
    aliassvc_arch = aliassvc.arch
    if basesvc_arch != aliassvc_arch:
        raise SystemExit(_("\nError: Architectures of service and alias "
                           "are different.\n"))

    if aliassvc.is_aliasof(basesvcname):
        raise SystemExit(_("\nError: %s is already an alias of %s\n") %
                         (aliasname, basesvcname))

    if svc.AIService(basesvcname).is_alias():
        raise SystemExit(_("\nError: Cannot alias to another alias.\n"))

    # Make sure we aren't creating inter dependencies
    all_aliases = config.get_aliased_services(aliasname, recurse=True)
    if basesvcname in all_aliases:
        raise SystemExit(cw(_("\nError: %s can not be made an alias of %s "
                              "because %s is dependent on %s\n") % (aliasname,
                              basesvcname, basesvcname, aliasname)))
    try:
        aliassvc.update_basesvc(basesvcname)
    except (OSError, config.ServiceCfgError) as err:
        raise SystemExit(_("Failed to set 'aliasof' property of : %s") %
                         aliasname)
    except svc.MultipleUnmountError as err:
        print >> sys.stderr, _("Failed to disable alias")
        raise SystemExit(err)
    except svc.MountError as err:
        print >> sys.stderr, _("Failed to enable alias")
        raise SystemExit(err)
    except svc.UnsupportedAliasError as err:
        raise SystemExit(err)
示例#12
0
def parse_options(cmd_options=None):
    '''
    Parse and validate options when called as delete-service
    Args: None
    Returns: A tuple of a dictionary of service properties of service
             to delete and an options object

    '''
    usage = '\n' + get_usage()
    parser = OptionParser(usage=usage)
    parser.add_option("-r",
                      "--autoremove",
                      dest="autoremove",
                      action="store_true",
                      default=False,
                      help=_("Request removal of dependent alias services "
                             "and clients"))
    parser.add_option('-y',
                      "--noprompt",
                      action="store_true",
                      dest="noprompt",
                      default=False,
                      help=_('Suppress confirmation prompts and proceed with '
                             'service deletion'))

    (options, args) = parser.parse_args(cmd_options)

    # Confirm install service's name was passed in
    if not args:
        parser.error(_("Missing required argument, <svcname>"))
    elif len(args) > 1:
        parser.error(_("Too many arguments: %s") % args)

    service_name = args[0]

    # validate service name
    try:
        com.validate_service_name(service_name)
    except ValueError as err:
        raise SystemExit(err)
    if not config.is_service(service_name):
        raise SystemExit(
            _("\nError: The specified service does "
              "not exist: %s\n") % service_name)

    # add service_name to the options
    options.service_name = service_name
    logging.debug("options = %s", options)

    return options
示例#13
0
def set_aliasof(options):
    '''Change a service's base service'''
    logging.debug("set alias %s's basesvc to %s",
                  options.svcname, options.value)
    basesvcname = options.value
    aliasname = options.svcname

    if not config.is_service(basesvcname):
        raise SystemExit(_('\nError: Service does not exist: %s\n') %
                         basesvcname)

    if aliasname == basesvcname:
        raise SystemExit(_('\nError: Alias name same as service name: %s\n') %
                         aliasname)

    aliassvc = svc.AIService(aliasname)
    if not aliassvc.is_alias():
        raise SystemExit(_('\nError: Service exists, but is not an '
                           'alias: %s\n') % aliasname)

    basesvc_arch = svc.AIService(basesvcname).arch
    aliassvc_arch = aliassvc.arch
    if basesvc_arch != aliassvc_arch:
        raise SystemExit(_("\nError: Architectures of service and alias "
                           "are different.\n"))

    if aliassvc.is_aliasof(basesvcname):
        raise SystemExit(_("\nError: %(aliasname)s is already an alias "
                           "of %(svcname)s\n") % {'aliasname': aliasname,
                           'svcname': basesvcname})

    if svc.AIService(basesvcname).is_alias():
        raise SystemExit(_("\nError: Cannot alias to another alias.\n"))

    # Make sure we aren't creating inter dependencies
    all_aliases = config.get_aliased_services(aliasname, recurse=True)
    if basesvcname in all_aliases:
        raise SystemExit(cw(_("\nError: %(aliasname)s can not be made an "
                              "alias of %(svcname)s because %(svcname)s is "
                              "dependent on %(aliasname)s\n") %
                              {'aliasname': aliasname,
                               'svcname': basesvcname}))

    failures = do_update_basesvc(aliassvc, basesvcname)

    if failures:
        return 1
    return 0
def get_default_service_name(image_path=None, image=None, iso=False):
    ''' get default service name
    
    Input:   specified_path - imagepath, if specified by user
             image - image object created from image
             iso - boolean, True if service is iso based, False otherwise
    Returns: default name for service.
             For iso-based services, the default name is based
             on the SERVICE_NAME from the .image_info file if available,
             otherwise is BASE_DEF_SVC_NAME_<num>
             For pkg based services, the default name is obtained
             from pkg metadata, otherwise BASE_DEF_SVC_NAME_<num>

    '''
    if image:
        # Try to generate a name based on the metadata. If that
        # name exists, append a number until a unique name is found.
        count = 0
        if iso:
            basename = image.read_image_info().get('service_name')
        else:
            basename = image.get_basename()
        try:
            com.validate_service_name(basename)
            svc_name = basename
        except ValueError:
            basename = BASE_DEF_SVC_NAME
            count = 1
            svc_name = basename + "_" + str(count)
    else:
        count = 1
        basename = BASE_DEF_SVC_NAME
        svc_name = basename + "_" + str(count)
    
    while (config.is_service(svc_name) or
        not default_path_ok(svc_name, image_path)):
        count += 1
        svc_name = basename + "_" + str(count)
    return svc_name
示例#15
0
def get_default_service_name(image_path=None, image=None, iso=False):
    ''' get default service name
    
    Input:   specified_path - imagepath, if specified by user
             image - image object created from image
             iso - boolean, True if service is iso based, False otherwise
    Returns: default name for service.
             For iso-based services, the default name is based
             on the SERVICE_NAME from the .image_info file if available,
             otherwise is BASE_DEF_SVC_NAME_<num>
             For pkg based services, the default name is obtained
             from pkg metadata, otherwise BASE_DEF_SVC_NAME_<num>

    '''
    if image:
        # Try to generate a name based on the metadata. If that
        # name exists, append a number until a unique name is found.
        count = 0
        if iso:
            basename = image.read_image_info().get('service_name')
        else:
            basename = image.get_basename()
        try:
            com.validate_service_name(basename)
            svc_name = basename
        except ValueError:
            basename = BASE_DEF_SVC_NAME
            count = 1
            svc_name = basename + "_" + str(count)
    else:
        count = 1
        basename = BASE_DEF_SVC_NAME
        svc_name = basename + "_" + str(count)

    while (config.is_service(svc_name)
           or not default_path_ok(svc_name, image_path)):
        count += 1
        svc_name = basename + "_" + str(count)
    return svc_name
def parse_options(cmd_options=None):
    '''Parse commandline options for export command'''

    parser = OptionParser(usage=get_usage(), prog="export")
    parser.add_option('-p', '--profile', dest='pnames', action="append",
                      default=list(), help=_("Name of profile to export."))
    parser.add_option('-m', '--manifest', dest='mnames', action="append",
                      default=list(), help=_("Name of manifest to export."))
    parser.add_option('-n', '--service', dest='service_name',
                      default=None, help=_("Name of install service."))
    parser.add_option('-o', '--output', dest='output_name',
                      default=None, help=_("Name of output file."))

    (options, args) = parser.parse_args(cmd_options)

    if args:
        parser.error(_("Extra args given."))

    if not options.service_name:
        parser.error(_("Service name is required."))

    if not config.is_service(options.service_name):
        raise SystemExit(_("No such service: %s") % options.service_name)

    service = AIService(options.service_name)
    options.service = service

    if not len(options.mnames) and not len(options.pnames):
        parser.error(_("A manifest or profile name is required."))

    options.file_count = len(options.mnames) + len(options.pnames)

    if not options.output_name:
        options.output_name = SCREEN
        options.output_isdir = None

    else:
        # Non-stdout -o processing:
        # if output_name is an existing directory: write all files out to it.
        # if output_name is an existing file and output one file:
        #     overwrite the existing file.
        # if file exists with output_name and mult output files desired:
        #     error
        # if file or dir doesn't exist w/output name and mult files desired:
        #     create new directory with output name and write files there.
        # if file or dir doesn't exist with output name and one file desired:
        #     write the one file to that output name

        options.output_isdir = False
        if os.path.isdir(options.output_name):
            options.output_isdir = True
        elif os.path.exists(options.output_name):
            if (options.file_count > 1):
                parser.error(_("-o must specify a directory when multiple "
                               "files are requested."))
        else:
            if (options.file_count > 1):
                os.mkdir(options.output_name)
                options.output_isdir = True

    return options
示例#17
0
def list_manifests(service):
    '''Replies to the client with criteria list for a service.
       The output should be similar to installadm list.

    Args
        service - the name of the service being listed

    Returns
        None

    Raises
        None
    '''
    print 'Content-Type: text/html'  # HTML is following
    print  # blank line, end of headers
    print '<html>'
    print '<head>'
    sys.stdout.write('<title>%s %s</title>' %
                     (_('Manifest list for'), service))
    print '</head><body>'

    port = 0
    try:
        smf.AISCF(FMRI="system/install/server")
    except KeyError:
        # report the internal error to error_log and requesting client
        sys.stderr.write(
            _("error:The system does not have the "
              "system/install/server SMF service."))
        sys.stdout.write(
            _("error:The system does not have the "
              "system/install/server SMF service."))
        return
    services = config.get_all_service_names()
    if not services:
        # report the error to the requesting client only
        sys.stdout.write(_('error:no services on this server.\n'))
        return

    found = False
    if config.is_service(service):
        service_ctrl = AIService(service)
        found = True

        # assume new service setup
        path = service_ctrl.database_path
        if os.path.exists(path):
            try:
                aisql = AIdb.DB(path)
                aisql.verifyDBStructure()
            except StandardError as err:
                # report the internal error to error_log and
                # requesting client
                sys.stderr.write(
                    _('error:AI database access '
                      'error\n%s\n') % err)
                sys.stdout.write(
                    _('error:AI database access '
                      'error\n%s\n') % err)
                return

            # generate the list of criteria for the criteria table header
            criteria_header = E.TR()
            for crit in AIdb.getCriteria(aisql.getQueue(), strip=False):
                criteria_header.append(E.TH(crit))

            # generate the manifest rows for the criteria table body
            names = AIdb.getManNames(aisql.getQueue())
            table_body = E.TR()
            allcrit = AIdb.getCriteria(aisql.getQueue(), strip=False)
            colspan = str(max(len(list(allcrit)), 1))
            for manifest in names:

                # iterate through each manifest (and instance)
                for instance in range(
                        0, AIdb.numInstances(manifest, aisql.getQueue())):

                    table_body.append(E.TR())
                    # print the manifest name only once (from instance 0)
                    if instance == 0:
                        href = '../' + service + '/' + manifest
                        row = str(AIdb.numInstances(manifest,
                                                    aisql.getQueue()))
                        table_body.append(
                            E.TD(E.A(manifest, href=href, rowspan=row)))
                    else:
                        table_body.append(E.TD())

                    crit_pairs = AIdb.getManifestCriteria(manifest,
                                                          instance,
                                                          aisql.getQueue(),
                                                          onlyUsed=True,
                                                          humanOutput=True)

                    # crit_pairs is an SQLite3 row object which doesn't
                    # support iteritems(), etc.
                    for crit in crit_pairs.keys():
                        formatted_val = AIdb.formatValue(
                            crit, crit_pairs[crit])
                        # if we do not get back a valid value ensure a
                        # hyphen is printed (prevents "" from printing)
                        if formatted_val and crit_pairs[crit]:
                            table_body.append(
                                E.TD(formatted_val, align="center"))
                        else:
                            table_body.append(
                                E.TD(lxml.etree.Entity("nbsp"),
                                     align="center"))

            # print the default manifest at the end of the table,
            # which has the same colspan as the Criteria List label
            else:
                href = '../' + service + '/default.xml'
                table_body.append(
                    E.TR(
                        E.TD(E.A("Default", href=href)),
                        E.TD(lxml.etree.Entity("nbsp"),
                             colspan=colspan,
                             align="center")))
            web_page = E.HTML(
                E.HEAD(E.TITLE(_("OmniOS Automated "
                                 "Installation Webserver"))),
                E.BODY(
                    E.H1(
                        _("Welcome to the OmniOS "
                          "Automated Installation webserver!")),
                    E.P(
                        _("Service '%s' has the following "
                          "manifests available, served to clients "
                          "matching required criteria.") % service),
                    E.TABLE(E.TR(E.TH(_("Manifest"), rowspan="2"),
                                 E.TH(_("Criteria List"), colspan=colspan)),
                            criteria_header,
                            table_body,
                            border="1",
                            align="center"),
                ))
            print lxml.etree.tostring(web_page, pretty_print=True)

    # service is not found, provide available services on host
    if not found:
        sys.stdout.write(_('Service <i>%s</i> not found.  ') % service)
        sys.stdout.write(_('Available services are:<p><ol><i>'))
        host = socket.gethostname()
        for service_name in config.get_all_service_names():
            # assume new service setup
            port = config.get_service_port(service_name)
            sys.stdout.write(
                '<a href="http://%s:%d/cgi-bin/'
                'cgi_get_manifest.py?version=%s&service=%s">%s</a><br>\n' %
                (host, port, VERSION, service_name, service_name))
        sys.stdout.write('</i></ol>%s' % _('Please select a service '
                                           'from the above list.'))

    print '</body></html>'
示例#18
0
def do_rename_service(cmd_options=None):
    '''Rename a service.

    Note: Errors that occur during the various rename stages
    are printed, but the other stages will continue, with the hopes
    of leaving the final product as close to functional as possible

    '''
    # check that we are root
    if os.geteuid() != 0:
        raise SystemExit(_("Error: Root privileges are required for this "
                           "command.\n"))

    (svcname, newsvcname) = parse_options(cmd_options)

    # Ensure the service to rename is a valid service
    if not config.is_service(svcname):
        raise SystemExit(_("\nFailed to find service %s\n") % svcname)

    # Ensure the new name is not already a service
    if config.is_service(newsvcname):
        raise SystemExit(_("\nService or alias already exists: %s\n") %
                           newsvcname)

    # Don't allow renaming to/from the 'default-<arch>' aliases
    if svcname in DEFAULT_ARCH:
        raise SystemExit(_('\nYou may not rename the "%s" service.\n') %
                           svcname)

    if newsvcname in DEFAULT_ARCH:
        raise SystemExit(cw(_('\nYou may not rename a service to be the '
                              'default service for an architecture. To create '
                              'the default-sparc or default-i386 service '
                              'aliases, use "installadm create-service '
                              '-t|--aliasof."\n')))

    # Unmount old service
    was_mounted = False
    try:
        oldservice = AIService(svcname)
        if oldservice.mounted():
            was_mounted = True
            logging.debug("disabling %s", svcname)
            oldservice.disable(force=True)
    except (MountError, ImageError) as err:
        raise SystemExit(err)

    # remove old mountpoint
    try:
        os.rmdir(oldservice.mountpoint)
    except OSError as err:
        # Just make a note if unable to cleanup mountpoint
        logging.debug(err)

    # Remove clients whose base service has been renamed
    clients = config.get_clients(svcname)
    for clientid in clients.keys():
        clientctrl.remove_client(clientid)

    oldservice.rename(newsvcname)

    # Update aliases whose base service has been renamed
    aliases = config.get_aliased_services(svcname)
    failures = list()
    for alias in aliases:
        props = {config.PROP_ALIAS_OF: newsvcname}
        config.set_service_props(alias, props)

    # Mount the renamed service if it was mounted
    newservice = AIService(newsvcname)
    if was_mounted:
        try:
            logging.debug("enabling %s", newsvcname)
            newservice.enable()
        except (MountError, ImageError) as err:
            failures.append(err)
            print >> sys.stderr, err

    # Re-add clients whose base service has been renamed
    arch = newservice.arch
    for clientid in clients.keys():
        # strip off leading '01'
        client = clientid[2:]
        bootargs = None
        if config.BOOTARGS in clients[clientid]:
            bootargs = clients[clientid][config.BOOTARGS]
        create_client.create_new_client(arch, newservice, client,
                                        bootargs=bootargs)

    if failures:
        return 1
    else:
        return 0
示例#19
0
def parse_options(do_create, cmd_options=None):
    """ Parse and validate options
    Args:  - do_create (True) or do_update (False) 
           - cmd_options - command line handled by OptionParser

    Returns: options
    """

    if do_create:
        usage = '\n' + get_create_usage()
    else:
        usage = '\n' + get_update_usage()

    parser = OptionParser(usage=usage)

    if do_create:
        parser.add_option("-C",
                          "--criteria-file",
                          dest="criteria_file",
                          default='',
                          help=_("Name of criteria XML file."))
        parser.add_option("-c",
                          "--criteria",
                          dest="criteria_c",
                          action="append",
                          default=list(),
                          metavar="CRITERIA",
                          help=_("Criteria: <-c criteria=value|range> ..."))

    parser.add_option("-f",
                      "--file",
                      dest="profile_file",
                      action="append",
                      default=list(),
                      help=_("Path to profile file"))
    parser.add_option("-p",
                      "--profile",
                      dest="profile_name",
                      default='',
                      help=_("Name of profile"))
    parser.add_option("-n",
                      "--service",
                      dest="service_name",
                      default="",
                      help=_("Name of install service."))

    options, args = parser.parse_args(cmd_options)

    if len(args):
        parser.error(_("Unexpected arguments: %s" % args))

    if not do_create:
        options.criteria_file = None
        options.criteria_c = None
        if len(options.profile_file) > 1:
            parser.error(_("Provide only one file name (-f)."))

    if not options.service_name:
        parser.error(_("Service name is required (-n <service name>)."))
    if not options.profile_file:
        parser.error(_("Profile file is required (-f <profile file>)."))
    if options.profile_name and len(options.profile_file) > 1:
        parser.error(
            _("If a profile name is specified (-p), only one file "
              "name may be specified (-f)."))

    if not config.is_service(options.service_name):
        raise SystemExit(_("No such service: %s") % options.service_name)

    return options
def do_rename_service(cmd_options=None):
    '''Rename a service.

    Note: Errors that occur during the various rename stages
    are printed, but the other stages will continue, with the hopes
    of leaving the final product as close to functional as possible

    '''
    # check that we are root
    if os.geteuid() != 0:
        raise SystemExit(_("Error: Root privileges are required for this "
                           "command.\n"))

    (svcname, newsvcname) = parse_options(cmd_options)

    # Ensure the service to rename is a valid service
    if not config.is_service(svcname):
        raise SystemExit(_("\nFailed to find service %s\n") % svcname)

    # Ensure the new name is not already a service
    if config.is_service(newsvcname):
        raise SystemExit(_("\nService or alias already exists: %s\n") %
                           newsvcname)

    # Don't allow renaming to/from the 'default-<arch>' aliases
    if svcname in DEFAULT_ARCH:
        raise SystemExit(_('\nYou may not rename the "%s" service.\n') %
                           svcname)

    if newsvcname in DEFAULT_ARCH:
        raise SystemExit(cw(_('\nYou may not rename a service to be the '
                              'default service for an architecture. To create '
                              'the default-sparc or default-i386 service '
                              'aliases, use "installadm create-service '
                              '-t|--aliasof."\n')))

    # Unmount old service
    was_mounted = False
    try:
        oldservice = AIService(svcname)
        if oldservice.mounted():
            was_mounted = True
            logging.debug("disabling %s", svcname)
            oldservice.disable(force=True)
    except (MountError, ImageError) as err:
        raise SystemExit(err)

    # remove old mountpoint
    try:
        os.rmdir(oldservice.mountpoint)
    except OSError as err:
        # Just make a note if unable to cleanup mountpoint
        logging.debug(err)

    # Remove clients whose base service has been renamed
    clients = config.get_clients(svcname)
    for clientid in clients.keys():
        clientctrl.remove_client(clientid)

    oldservice.rename(newsvcname)

    # Update aliases whose base service has been renamed
    aliases = config.get_aliased_services(svcname)
    failures = list()
    for alias in aliases:
        props = {config.PROP_ALIAS_OF: newsvcname}
        config.set_service_props(alias, props)

    # Mount the renamed service if it was mounted
    newservice = AIService(newsvcname)
    if was_mounted:
        try:
            logging.debug("enabling %s", newsvcname)
            newservice.enable()
        except (MountError, ImageError) as err:
            failures.append(err)
            print >> sys.stderr, err

    # Re-add clients whose base service has been renamed
    arch = newservice.arch
    for clientid in clients.keys():
        # strip off leading '01'
        client = clientid[2:]
        bootargs = None
        if config.BOOTARGS in clients[clientid]:
            bootargs = clients[clientid][config.BOOTARGS]
        create_client.create_new_client(arch, newservice, client,
                                        bootargs=bootargs)

    if failures:
        return 1
    else:
        return 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
示例#22
0
def do_set_criteria(cmd_options=None):
    '''
    Modify the criteria associated with a manifest.

    '''
    # check that we are root
    if os.geteuid() != 0:
        raise SystemExit(
            _("Error: Root privileges are required for "
              "this command."))

    options = parse_options(cmd_options)

    # Get the install service's properties.
    if not config.is_service(options.service_name):
        raise SystemExit(_("Failed to find service %s") % options.service_name)

    service = AIService(options.service_name)
    database = service.database_path

    # Open the database
    dbn = AIdb.DB(database, commit=True)

    # Check to make sure that the manifest whose criteria we're
    # updating exists in the install service.
    if (options.manifest_name and
            not check_published_manifest(service, dbn, options.manifest_name)):
        raise SystemExit(1)

    # Process and validate criteria from -a, -c, or -C, and store
    # store the criteria in a Criteria object.
    try:
        if options.criteria_file:
            root = df.verifyCriteria(df.DataFiles.criteriaSchema,
                                     options.criteria_file, dbn,
                                     AIdb.MANIFESTS_TABLE)
        elif options.criteria_a:
            criteria_dict = pub_man.criteria_to_dict(options.criteria_a)
            root = df.verifyCriteriaDict(df.DataFiles.criteriaSchema,
                                         criteria_dict, dbn,
                                         AIdb.MANIFESTS_TABLE)
        elif options.criteria_c:
            criteria_dict = pub_man.criteria_to_dict(options.criteria_c)
            root = df.verifyCriteriaDict(df.DataFiles.criteriaSchema,
                                         criteria_dict, dbn,
                                         AIdb.MANIFESTS_TABLE)
        else:
            raise SystemExit("Error: Missing required criteria.")

    except (AssertionError, IOError, ValueError) as err:
        raise SystemExit(err)
    except (lxml.etree.LxmlError) as err:
        raise SystemExit(_("Error:\tmanifest error: %s") % err)

    # Instantiate a Criteria object with the XML DOM of the criteria.
    criteria = df.Criteria(root)

    if options.manifest_name:
        # Ensure the criteria we're adding/setting for this manifest doesn't
        # cause a criteria collision in the DB.
        colliding_criteria = pub_man.find_colliding_criteria(
            criteria, dbn, exclude_manifests=[options.manifest_name])
        # If we're appending criteria pass the manifest name
        if options.criteria_a:
            pub_man.find_colliding_manifests(
                criteria,
                dbn,
                colliding_criteria,
                append_manifest=options.manifest_name)
        else:
            pub_man.find_colliding_manifests(criteria,
                                             dbn,
                                             colliding_criteria,
                                             append_manifest=None)
    # validate criteria for profile
    for pname in options.profile_name:
        if not sc.is_name_in_table(pname, dbn.getQueue(), AIdb.PROFILES_TABLE):
            raise SystemExit(
                _("Error:\tservice has no profile named %s." % pname))
        # Validate profile criteria
        sc.validate_criteria_from_user(criteria, dbn, AIdb.PROFILES_TABLE)

    # all validation complete - update database

    # indicate whether criteria are added or replaced
    if options.criteria_a:
        append = True  # add new criteria
    else:
        append = False  # replace any existing criteria with new
    if options.manifest_name:
        # Update the criteria for manifest
        set_criteria(criteria, options.manifest_name, dbn,
                     AIdb.MANIFESTS_TABLE, append)
        print >> sys.stderr, _("Criteria updated for manifest %s.") % \
                options.manifest_name
    for pname in options.profile_name:
        # Update the criteria for profile
        set_criteria(criteria, pname, dbn, AIdb.PROFILES_TABLE, append)
        print >> sys.stderr, _("Criteria updated for profile %s.") % pname
示例#23
0
文件: export.py 项目: alhazred/caiman
def parse_options(cmd_options=None):
    '''Parse commandline options for export command'''

    parser = OptionParser(usage=get_usage(), prog="export")
    parser.add_option('-p', '--profile', dest='pnames', action="append",
                      default=list(), help=_("Name of profile to export."))
    parser.add_option('-m', '--manifest', dest='mnames', action="append",
                      default=list(), help=_("Name of manifest to export."))
    parser.add_option('-n', '--service', dest='service_name',
                      default=None, help=_("Name of install service."))
    parser.add_option('-o', '--output', dest='output_name',
                      default=None, help=_("Name of output file."))

    (options, args) = parser.parse_args(cmd_options)

    if args:
        parser.error(_("Extra args given."))

    if not options.service_name:
        parser.error(_("Service name is required."))

    if not config.is_service(options.service_name):
        raise SystemExit(_("No such service: %s") % options.service_name)

    service = AIService(options.service_name)
    options.service = service

    if not len(options.mnames) and not len(options.pnames):
        parser.error(_("A manifest or profile name is required."))

    # based on the argument, check for authorization and euid
    try:
        if len(options.mnames):
            check_auth_and_euid(MANIFEST_AUTH)
      
        if len(options.pnames):
            check_auth_and_euid(PROFILE_AUTH)
    except UnauthorizedUserError as err:
        raise SystemExit(err)

    options.file_count = len(options.mnames) + len(options.pnames)

    if not options.output_name:
        options.output_name = SCREEN
        options.output_isdir = None

    else:
        # Non-stdout -o processing:
        # if output_name is an existing directory: write all files out to it.
        # if output_name is an existing file and output one file:
        #     overwrite the existing file.
        # if file exists with output_name and mult output files desired:
        #     error
        # if file or dir doesn't exist w/output name and mult files desired:
        #     create new directory with output name and write files there.
        # if file or dir doesn't exist with output name and one file desired:
        #     write the one file to that output name

        options.output_isdir = False
        if os.path.isdir(options.output_name):
            options.output_isdir = True
        elif os.path.exists(options.output_name):
            if (options.file_count > 1):
                parser.error(_("-o must specify a directory when multiple "
                               "files are requested."))
        else:
            if (options.file_count > 1):
                os.mkdir(options.output_name)
                options.output_isdir = True

    return options
示例#24
0
def parse_options(do_create, cmd_options=None):
    """
    Parse and validate options
    Args: - do_create (True) or do_update (False)
          - Optional cmd_options, used for unit testing. Otherwise, cmd line
            options handled by OptionParser
    Returns: the DataFiles object populated and initialized
    Raises: The DataFiles initialization of manifest(s) A/I, SC, SMF looks for
            many error conditions and, when caught, are flagged to the user
            via raising SystemExit exceptions.

    """
    if do_create:
        usage = '\n' + get_create_usage()
    else:
        usage = '\n' + get_update_usage()
    parser = OptionParser(usage=usage)
    if do_create:
        parser.add_option("-c",
                          "--criteria",
                          dest="criteria_c",
                          action="append",
                          default=list(),
                          help=_("Criteria: "
                                 "<-c criteria=value|range> ..."),
                          metavar="CRITERIA")
        parser.add_option("-C",
                          "--criteria-file",
                          dest="criteria_file",
                          default=None,
                          help=_("Path to criteria XML file."))
        parser.add_option("-d",
                          "--default",
                          dest="set_as_default",
                          default=False,
                          action='store_true',
                          help=_("Set manifest as default "))
    parser.add_option("-f",
                      "--file",
                      dest="manifest_path",
                      default=None,
                      help=_("Path to manifest file "))
    parser.add_option("-m",
                      "--manifest",
                      dest="manifest_name",
                      default=None,
                      help=_("Name of manifest"))
    parser.add_option("-n",
                      "--service",
                      dest="service_name",
                      default=None,
                      help=_("Name of install service."))

    # Get the parsed options using parse_args().  We know we don't have
    # args, so we're just grabbing the first item of the tuple returned.
    options, args = parser.parse_args(cmd_options)

    if len(args):
        parser.error(_("Unexpected argument(s): %s" % args))

    if not do_create:
        options.criteria_file = None
        options.criteria_c = None
        options.set_as_default = False

    # options are:
    #    -c  criteria=<value/range> ...       (create only)
    #    -C  XML file with criteria specified (create only)
    #    -d  set manifest as default          (create only)
    #    -n  service name
    #    -f  path to manifest file
    #    -m  manifest name

    # check that we got the install service's name and an AI manifest.
    if options.manifest_path is None or options.service_name is None:
        parser.error(_("Missing one or more required options."))

    logging.debug("options = %s", options)

    criteria_dict = None
    if do_create:
        # check that we aren't mixing -c and -C
        # Note: -c and -C will be accepted for create, not for update.
        if options.criteria_c and options.criteria_file:
            parser.error(_("Options used are mutually exclusive."))

        # if we have criteria from cmd line, convert into dictionary
        if options.criteria_c:
            try:
                criteria_dict = criteria_to_dict(options.criteria_c)
            except ValueError as err:
                parser.error(err)

        elif options.criteria_file:
            if not os.path.exists(options.criteria_file):
                parser.error(
                    _("Unable to find criteria file: %s") %
                    options.criteria_file)

    if not config.is_service(options.service_name):
        raise SystemExit(_("Failed to find service %s") % options.service_name)

    # Get the service's imagepath. If service is an alias, the
    # base service's imagepath is obtained.
    service = AIService(options.service_name)
    try:
        image_path = service.image.path
    except KeyError as err:
        raise SystemExit(
            _("Data for service %s is corrupt. Missing "
              "property: %s\n") % (options.service_name, err))

    service_dir = service.config_dir
    dbname = service.database_path

    try:
        files = df.DataFiles(service_dir=service_dir,
                             image_path=image_path,
                             database_path=dbname,
                             manifest_file=options.manifest_path,
                             manifest_name=options.manifest_name,
                             criteria_dict=criteria_dict,
                             criteria_file=options.criteria_file,
                             service_name=options.service_name,
                             set_as_default=options.set_as_default)
    except (AssertionError, IOError, ValueError) as err:
        raise SystemExit(err)
    except (lxml.etree.LxmlError) as err:
        raise SystemExit(_("Error:\tmanifest error: %s") % err)

    return (files)
示例#25
0
def do_disable_service(cmd_options=None):
    ''' Disable a service

    Disable the specified service and optionally update the service's
    properties to reflect the new status.

    Input:
        List of command line options
    Return:
        None
    Raises:
        SystemExit if missing permissions, invalid service name, or
        if attempt to place smf service in maintenance fails.

    '''
    logging.debug('**** START do_disable_service ****')

    # check for authorization and euid
    try:
        check_auth_and_euid(SERVICE_AUTH)
    except UnauthorizedUserError as err:
        raise SystemExit(err)

    usage = '\n' + get_disable_usage()
    parser = OptionParser(usage=usage)

    (options, args) = parser.parse_args(cmd_options)

    # Check for correct number of args
    if len(args) != 1:
        if len(args) == 0:
            parser.error(_("Missing required argument, <svcname>"))
        else:
            parser.error(_("Too many arguments: %s") % args)

    svcname = args[0]

    # validate service name
    try:
        validate_service_name(svcname)
    except ValueError as err:
        raise SystemExit(err)

    if not config.is_service(svcname):
        err_msg = _("The service does not exist: %s\n") % svcname
        parser.error(err_msg)

    prop_data = config.get_service_props(svcname)

    if prop_data and config.PROP_STATUS not in prop_data:
        err_msg = _("The property, status, is missing for %s.\n") % svcname
        parser.error(err_msg)

    if prop_data[config.PROP_STATUS] == config.STATUS_OFF:
        err_msg = _("The service is not running: %s\n") % svcname
        parser.error(err_msg)

    try:
        logging.debug("Disabling install service %s", svcname)
        service = AIService(svcname)
        service.disable(force=True)
    except (config.ServiceCfgError, aismf.ServicesError, MountError) as err:
        raise SystemExit(err)
    except CalledProcessError:
        return 1
示例#26
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(do_create, cmd_options=None):
    """
    Parse and validate options
    Args: - do_create (True) or do_update (False)
          - Optional cmd_options, used for unit testing. Otherwise, cmd line
            options handled by OptionParser
    Returns: the DataFiles object populated and initialized
    Raises: The DataFiles initialization of manifest(s) A/I, SC, SMF looks for
            many error conditions and, when caught, are flagged to the user
            via raising SystemExit exceptions.

    """
    if do_create:
        usage = '\n' + get_create_usage()
    else:
        usage = '\n' + get_update_usage()
    parser = OptionParser(usage=usage)
    if do_create:
        parser.add_option("-c", "--criteria", dest="criteria_c",
                          action="append", default=list(), help=_("Criteria: "
                          "<-c criteria=value|range> ..."), metavar="CRITERIA")
        parser.add_option("-C", "--criteria-file", dest="criteria_file",
                          default=None, help=_("Path to criteria XML file."))
        parser.add_option("-d", "--default", dest="set_as_default",
                          default=False, action='store_true',
                          help=_("Set manifest as default "))
    parser.add_option("-f", "--file", dest="manifest_path",
                      default=None, help=_("Path to manifest file "))
    parser.add_option("-m", "--manifest", dest="manifest_name",
                      default=None, help=_("Name of manifest"))
    parser.add_option("-n", "--service", dest="service_name",
                      default=None, help=_("Name of install service."))

    # Get the parsed options using parse_args().  We know we don't have
    # args, so we're just grabbing the first item of the tuple returned.
    options, args = parser.parse_args(cmd_options)

    if len(args):
        parser.error(_("Unexpected argument(s): %s" % args))

    if not do_create:
        options.criteria_file = None
        options.criteria_c = None
        options.set_as_default = False

    # options are:
    #    -c  criteria=<value/range> ...       (create only)
    #    -C  XML file with criteria specified (create only)
    #    -d  set manifest as default          (create only)
    #    -n  service name
    #    -f  path to manifest file
    #    -m  manifest name

    # check that we got the install service's name and an AI manifest.
    if options.manifest_path is None or options.service_name is None:
        parser.error(_("Missing one or more required options."))

    logging.debug("options = %s", options)

    criteria_dict = None
    if do_create:
        # check that we aren't mixing -c and -C
        # Note: -c and -C will be accepted for create, not for update.
        if options.criteria_c and options.criteria_file:
            parser.error(_("Options used are mutually exclusive."))

        # if we have criteria from cmd line, convert into dictionary
        if options.criteria_c:
            try:
                criteria_dict = criteria_to_dict(options.criteria_c)
            except ValueError as err:
                parser.error(err)

        elif options.criteria_file:
            if not os.path.exists(options.criteria_file):
                parser.error(_("Unable to find criteria file: %s") %
                             options.criteria_file)

    if not config.is_service(options.service_name):
        raise SystemExit(_("Failed to find service %s") % options.service_name)

    # Get the service's imagepath. If service is an alias, the
    # base service's imagepath is obtained.
    service = AIService(options.service_name)
    try:
        image_path = service.image.path
    except KeyError as err:
        raise SystemExit(_("Data for service %s is corrupt. Missing "
                           "property: %s\n") % (options.service_name, err))

    service_dir = service.config_dir
    dbname = service.database_path

    try:
        files = df.DataFiles(service_dir=service_dir, image_path=image_path,
                             database_path=dbname,
                             manifest_file=options.manifest_path,
                             manifest_name=options.manifest_name,
                             criteria_dict=criteria_dict,
                             criteria_file=options.criteria_file,
                             service_name=options.service_name,
                             set_as_default=options.set_as_default)
    except (AssertionError, IOError, ValueError) as err:
        raise SystemExit(err)
    except (lxml.etree.LxmlError) as err:
        raise SystemExit(_("Error:\tmanifest error: %s") % err)

    return(files)
def list_manifests(service):
    '''Replies to the client with criteria list for a service.
       The output should be similar to installadm list.

    Args
        service - the name of the service being listed

    Returns
        None

    Raises
        None
    '''
    print 'Content-Type: text/html'     # HTML is following
    print                               # blank line, end of headers
    print '<html>'
    print '<head>'
    sys.stdout.write('<title>%s %s</title>' %
                     (_('Manifest list for'), service))
    print '</head><body>'

    port = 0
    try:
        smf.AISCF(FMRI="system/install/server")
    except KeyError:
        # report the internal error to error_log and requesting client
        sys.stderr.write(_("error:The system does not have the "
                           "system/install/server SMF service."))
        sys.stdout.write(_("error:The system does not have the "
                           "system/install/server SMF service."))
        return
    services = config.get_all_service_names()
    if not services:
        # report the error to the requesting client only
        sys.stdout.write(_('error:no services on this server.\n'))
        return

    found = False
    if config.is_service(service):
        service_ctrl = AIService(service)
        found = True

        # assume new service setup
        path = service_ctrl.database_path
        if os.path.exists(path):
            try:
                aisql = AIdb.DB(path)
                aisql.verifyDBStructure()
            except StandardError as err:
                # report the internal error to error_log and
                # requesting client
                sys.stderr.write(_('error:AI database access '
                                   'error\n%s\n') % err)
                sys.stdout.write(_('error:AI database access '
                                   'error\n%s\n') % err)
                return

            # generate the list of criteria for the criteria table header
            criteria_header = E.TR()
            for crit in AIdb.getCriteria(aisql.getQueue(), strip=False):
                criteria_header.append(E.TH(crit))

            # generate the manifest rows for the criteria table body
            names = AIdb.getManNames(aisql.getQueue())
            table_body = E.TR()
            allcrit = AIdb.getCriteria(aisql.getQueue(), strip=False)
            colspan = str(max(len(list(allcrit)), 1))
            for manifest in names:

                # iterate through each manifest (and instance)
                for instance in range(0,
                        AIdb.numInstances(manifest, aisql.getQueue())):

                    table_body.append(E.TR())
                    # print the manifest name only once (from instance 0)
                    if instance == 0:
                        href = '../' + service + '/' + manifest
                        row = str(AIdb.numInstances(manifest,
                                                    aisql.getQueue()))
                        table_body.append(E.TD(
                                   E.A(manifest, href=href, rowspan=row)))
                    else:
                        table_body.append(E.TD())

                    crit_pairs = AIdb.getManifestCriteria(manifest,
                                                          instance,
                                                          aisql.getQueue(),
                                                          onlyUsed=True,
                                                          humanOutput=True)

                    # crit_pairs is an SQLite3 row object which doesn't
                    # support iteritems(), etc.
                    for crit in crit_pairs.keys():
                        formatted_val = AIdb.formatValue(crit,
                                                         crit_pairs[crit])
                        # if we do not get back a valid value ensure a
                        # hyphen is printed (prevents "" from printing)
                        if formatted_val and crit_pairs[crit]:
                            table_body.append(E.TD(formatted_val,
                                                   align="center"))
                        else:
                            table_body.append(E.TD(lxml.etree.Entity("nbsp"),
                                                   align="center"))

            # print the default manifest at the end of the table,
            # which has the same colspan as the Criteria List label
            else:
                href = '../' + service + '/default.xml'
                table_body.append(E.TR(E.TD(E.A("Default", href=href)),
                                       E.TD(lxml.etree.Entity("nbsp"),
                                            colspan=colspan,
                                            align="center")))
            web_page = E.HTML(
                         E.HEAD(
                            E.TITLE(_("OmniOS Automated "
                                      "Installation Webserver"))
                            ),
                         E.BODY(
                            E.H1(_("Welcome to the OmniOS "
                                   "Automated Installation webserver!")),
                            E.P(_("Service '%s' has the following "
                                "manifests available, served to clients "
                                "matching required criteria.") % service),
                            E.TABLE(
                               E.TR(
                                    E.TH(_("Manifest"), rowspan="2"),
                                    E.TH(_("Criteria List"),
                                        colspan=colspan)),
                                    criteria_header,
                                    table_body,
                                    border="1", align="center"),
                          )
                     )
            print lxml.etree.tostring(web_page, pretty_print=True)

    # service is not found, provide available services on host
    if not found:
        sys.stdout.write(_('Service <i>%s</i> not found.  ') % service)
        sys.stdout.write(_('Available services are:<p><ol><i>'))
        host = socket.gethostname()
        for service_name in config.get_all_service_names():
            # assume new service setup
            port = config.get_service_port(service_name)
            sys.stdout.write('<a href="http://%s:%d/cgi-bin/'
                   'cgi_get_manifest.py?version=%s&service=%s">%s</a><br>\n' %
                   (host, port, VERSION, service_name, service_name))
        sys.stdout.write('</i></ol>%s' % _('Please select a service '
                   'from the above list.'))

    print '</body></html>'
def do_set_criteria(cmd_options=None):
    '''
    Modify the criteria associated with a manifest.

    '''
    # check that we are root
    if os.geteuid() != 0:
        raise SystemExit(_("Error: Root privileges are required for "
                           "this command."))

    options = parse_options(cmd_options)

   # Get the install service's properties.
    if not config.is_service(options.service_name):
        raise SystemExit(_("Failed to find service %s") % options.service_name)
    
    service = AIService(options.service_name)
    database = service.database_path
    
    # Open the database
    dbn = AIdb.DB(database, commit=True)
    
    # Check to make sure that the manifest whose criteria we're
    # updating exists in the install service.
    if (options.manifest_name and not
        check_published_manifest(service, dbn, options.manifest_name)):
        raise SystemExit(1)

    # Process and validate criteria from -a, -c, or -C, and store
    # store the criteria in a Criteria object.
    try:
        if options.criteria_file:
            root = df.verifyCriteria(df.DataFiles.criteriaSchema,
                    options.criteria_file, dbn, AIdb.MANIFESTS_TABLE)
        elif options.criteria_a:
            criteria_dict = pub_man.criteria_to_dict(options.criteria_a)
            root = df.verifyCriteriaDict(df.DataFiles.criteriaSchema,
                    criteria_dict, dbn, AIdb.MANIFESTS_TABLE)
        elif options.criteria_c:
            criteria_dict = pub_man.criteria_to_dict(options.criteria_c)
            root = df.verifyCriteriaDict(df.DataFiles.criteriaSchema,
                    criteria_dict, dbn, AIdb.MANIFESTS_TABLE)
        else:
            raise SystemExit("Error: Missing required criteria.")

    except (AssertionError, IOError, ValueError) as err:
        raise SystemExit(err)
    except (lxml.etree.LxmlError) as err:
        raise SystemExit(_("Error:\tmanifest error: %s") % err)

    # Instantiate a Criteria object with the XML DOM of the criteria.
    criteria = df.Criteria(root)

    if options.manifest_name:
        # Ensure the criteria we're adding/setting for this manifest doesn't
        # cause a criteria collision in the DB.
        colliding_criteria = pub_man.find_colliding_criteria(criteria, dbn,
                             exclude_manifests=[options.manifest_name])
        # If we're appending criteria pass the manifest name
        if options.criteria_a:
            pub_man.find_colliding_manifests(criteria, dbn, colliding_criteria,
                    append_manifest=options.manifest_name)
        else:
            pub_man.find_colliding_manifests(criteria, dbn, colliding_criteria,
                                             append_manifest=None)
    # validate criteria for profile
    for pname in options.profile_name:
        if not sc.is_name_in_table(pname, dbn.getQueue(), AIdb.PROFILES_TABLE):
            raise SystemExit(_("Error:\tservice has no profile named %s." %
                             pname))
        # Validate profile criteria
        sc.validate_criteria_from_user(criteria, dbn, AIdb.PROFILES_TABLE)

    # all validation complete - update database

    # indicate whether criteria are added or replaced
    if options.criteria_a:
        append = True # add new criteria
    else:
        append = False # replace any existing criteria with new
    if options.manifest_name:
        # Update the criteria for manifest
        set_criteria(criteria, options.manifest_name, dbn,
                AIdb.MANIFESTS_TABLE, append)
        print >> sys.stderr, _("Criteria updated for manifest %s.") % \
                options.manifest_name
    for pname in options.profile_name:
        # Update the criteria for profile
        set_criteria(criteria, pname, dbn, AIdb.PROFILES_TABLE, append)
        print >> sys.stderr, _("Criteria updated for profile %s.") % pname