Esempio n. 1
0
    def setUpClass(cls):
        '''Class-level set up'''
        tempdirname = tempfile.mkdtemp(dir="/tmp")
        cls.config_svcdirpath = config.AI_SERVICE_DIR_PATH
        config.AI_SERVICE_DIR_PATH = tempdirname

        # create service
        cls.imagedir = tempfile.mkdtemp(dir="/tmp")
        props = {
            config.PROP_SERVICE_NAME: 'mysvc',
            config.PROP_STATUS: 'off',
            config.PROP_TXT_RECORD: 'aiwebserver=myserver:5555',
            config.PROP_IMAGE_PATH: cls.imagedir
        }

        config.create_service_props('mysvc', props)
        cls.myservice = service.AIService('mysvc')

        # create alias
        props = {
            config.PROP_SERVICE_NAME: 'myalias',
            config.PROP_STATUS: 'off',
            config.PROP_TXT_RECORD: 'aiwebserver=myserver:5555',
            config.PROP_ALIAS_OF: 'mysvc'
        }
        config.create_service_props('myalias', props)
        cls.myalias = service.AIService('myalias')
Esempio n. 2
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)
Esempio n. 3
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
Esempio n. 4
0
def do_create_client(cmd_options=None):
    '''Parse the user supplied arguments and create the specified client'''

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

    # parse server options
    options = parse_options(cmd_options)

    bootargs = ''
    if options.boot_args:
        bootargs = ",".join(options.boot_args).lstrip().rstrip() + ","
        logging.debug('bootargs=%s', bootargs)

    clientctrl.remove_client("01" + options.mac_address,
                             suppress_dhcp_msgs=True)

    # wrap the whole program's execution to catch exceptions as we should not
    # throw them anywhere
    service = svc.AIService(options.service_name)
    try:
        create_new_client(options.arch, service, options.mac_address, bootargs)
    except (OSError, BootmgmtError, aismf.ServicesError,
            config.ServiceCfgError, svc.MountError) as err:
        raise SystemExit(
            _('\nError: Unable to create client, '
              '%(mac)s:\n%(error)s') % {
                  'mac': options.mac_address,
                  'error': err
              })
Esempio n. 5
0
    def test_update_wanboot_imagepath(self):
        '''verify update_wanboot_imagepath updates imagepath correctly'''

        # create original wanboot.conf file
        wanboot_txt = (
            "root_server=http://10.134.125.136:5555/cgi-bin/wanboot-cgi\n"
            "root_file=%(path)s/boot/platform/sun4v/boot_archive\n"
            "boot_file=%(path)s/platform/sun4v/wanboot\n"
            "system_conf=system.conf\n"
            "encryption_type=\n"
            "signature_type=\n"
            "server_authentication=no\n"
            "client_authentication=no=\n") % {'path': self.imagedir}

        wanbootconf = os.path.join(self.imagedir, service.WANBOOTCONF)
        with open(wanbootconf, 'w') as wfp:
            wfp.write(wanboot_txt)

        # create service
        props = {config.PROP_SERVICE_NAME: 'mysvc',
                 config.PROP_STATUS: 'off',
                 config.PROP_TXT_RECORD: 'aiwebserver=myserver:5555',
                 config.PROP_IMAGE_PATH: self.imagedir}
        config.create_service_props('mysvc', props)
        myservice = service.AIService('mysvc')

        # Update path in wanboot file, read file back in, and
        # ensure file is updated properly.
        newpath = '/export/mydir/newpath'
        expected_text = wanboot_txt.replace(self.imagedir, newpath)
        myservice.update_wanboot_imagepath(self.imagedir, newpath)
        with open(wanbootconf, 'r') as wanboot_file:
            new_wanboot_txt = wanboot_file.read()
        self.assertEqual(new_wanboot_txt, expected_text)
Esempio n. 6
0
def set_imagepath(options):
    '''Change the location of a service's image'''

    logging.debug("set %s imagepath to %s",
                  options.svcname, options.value)
    new_imagepath = options.value.strip()

    service = svc.AIService(options.svcname)
    if service.is_alias():
        raise SystemExit(cw(_('\nError: Can not change the imagepath of an '
                           'alias.')))

    if not os.path.isabs(new_imagepath):
        raise SystemExit(_("\nError: A full pathname is required for the "
                           "imagepath.\n"))

    if os.path.exists(new_imagepath):
        raise SystemExit(_("\nError: The imagepath already exists: %s\n") %
                         new_imagepath)

    if os.path.islink(new_imagepath):
        raise SystemExit(_("\nError: The imagepath may not be a symlink.\n"))

    new_imagepath = new_imagepath.rstrip('/')
    try:
        service.relocate_imagedir(new_imagepath)
    except (svc.MountError, aismf.ServicesError) as error:
        raise SystemExit(error)
def do_create_client(cmd_options=None):
    '''Parse the user supplied arguments and create the specified client'''

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

    # parse server options
    options = parse_options(cmd_options)

    bootargs = ''
    if options.boot_args:
        bootargs = ",".join(options.boot_args).lstrip().rstrip() + ","
        logging.debug('bootargs=%s', bootargs)

    clientctrl.remove_client("01" + options.mac_address)

    # wrap the whole program's execution to catch exceptions as we should not
    # throw them anywhere
    service = svc.AIService(options.service_name)
    try:
        create_new_client(options.arch, service,
                          options.mac_address, bootargs)
    except OSError as err:
        raise SystemExit(err)
    except (aismf.ServicesError, config.ServiceCfgError,
            svc.MountError) as err:
        raise SystemExit(err)
Esempio n. 8
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
Esempio n. 9
0
def do_set_service_default_manifest(options):
    '''
    Handle default_manifest property processing.
    '''
    service = svc.AIService(options.svcname)
    try:
        service.set_default_manifest(options.value)
    except ValueError as error:
        raise SystemExit(error)
Esempio n. 10
0
def do_update_service(cmd_options=None):
    '''Update a service - currently only an alias

    Copy the baseservice of an alias, update it, create a service using
    the updated image, and re-alias the alias to the new 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)

    service = options.service
    try:
        if not service.image.is_pkg_based():
            raise SystemExit(
                cw(
                    _("\nError: '%s' is aliased to an iso based service. Only "
                      "aliases of pkg(5) based services are updatable.") %
                    options.service_name))
    except pkg.client.api_errors.VersionException as err:
        print >> sys.stderr, cw(
            _("The IPS API version specified, %(specver)s,"
              " is incompatible with the expected version, %(expver)s.") % {
                  'specver': str(err.received_version),
                  'expver': str(err.expected_version)
              })
        raise SystemExit()

    fmri = [options.srcimage] if options.srcimage else None
    base_svc = svc.AIService(service.basesvc, image_class=InstalladmPkgImage)

    new_image = None
    try:
        print _("Copying image ...")
        new_image = base_svc.image.copy(prefix=base_svc.name)
        print _('Updating image ...')
        update_needed = new_image.update(fmri=fmri,
                                         publisher=options.publisher)
    except (ValueError, img.ImageError,
            pkg.client.api_errors.ApiException) as err:
        # clean up copied image
        if new_image:
            new_image.delete()
        print >> sys.stderr, cw(
            _("Attempting to update the service %s"
              " failed for the following reasons:") % service.name)
        if 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
        raise SystemExit(err)

    if not update_needed:
        # No update needed, remove copied image
        new_image.delete()
        print _("No updates are available.")
        return 4

    # Get the service name from the updated image metadata
    new_svcname = img.get_default_service_name(image=new_image)

    # Determine imagepath and move image there
    new_path = new_image.path
    new_imagepath = os.path.join(os.path.dirname(new_path), new_svcname)
    try:
        img.check_imagepath(new_imagepath)
    except ValueError as error:
        # Leave image in temp location rather than fail. User can
        # update imagepath later if desired.
        logging.debug('unable to move image from %s to %s: %s', new_path,
                      new_imagepath, error)
    else:
        new_path = new_image.move(new_imagepath)
        logging.debug('image moved to %s', new_path)
    finally:
        img.set_permissions(new_path)

    # create new service based on updated image
    print _("Creating new %(arch)s service: %(newsvc)s") % \
            {'arch': new_image.arch, 'newsvc': new_svcname}
    new_service = svc.AIService.create(new_svcname, new_image)

    # Register & enable service
    # (Also enables system/install/server, as needed)
    try:
        service.enable()
    except (config.ServiceCfgError, svc.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

    print _("Aliasing %(alename)s to %(newsvc)s ...\n") % \
            {'alename': service.name, 'newsvc': new_svcname}
    failures = setsvc.do_update_basesvc(service, new_service.name)
    if failures:
        return 1
    return 0
Esempio n. 11
0
def parse_options(cmd_options=None):
    '''
    Parse and validate options
    '''
    def check_MAC_address(option, opt_str, value, parser):
        '''
        Check MAC address as an OptionParser callback
        Postcondition: sets value to proper option if check passes
        Raises: OptionValueError if MAC address is malformed
        '''
        try:
            value = str(com.MACAddress(value))
        except com.MACAddress.MACAddressError as err:
            raise OptionValueError(str(err))
        setattr(parser.values, option.dest, value)

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

    # accept multiple -b options (so append to a list)
    parser.add_option("-b",
                      "--boot-args",
                      dest="boot_args",
                      action="append",
                      type="string",
                      nargs=1,
                      help=_("boot arguments to pass to Solaris kernel"))
    parser.add_option("-e",
                      "--macaddr",
                      dest="mac_address",
                      action="callback",
                      nargs=1,
                      type="string",
                      help=_("MAC address of client to add"),
                      callback=check_MAC_address)
    parser.add_option("-n",
                      "--service",
                      dest="service_name",
                      action="store",
                      type="string",
                      help=_("Service to associate client with"),
                      nargs=1)
    (options, args) = parser.parse_args(cmd_options)

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

    # check that we got a service name and mac address
    if options.service_name is None:
        parser.error(
            _("Service name is required "
              "(-n|--service <service name>)."))
    if options.mac_address is None:
        parser.error(_("MAC address is required (-e|--macaddr <macaddr>)."))

    # Verify that the server settings are not obviously broken.
    # These checks cannot be complete, but check for things which
    # will definitely cause failure.
    logging.debug("Calling %s", com.CHECK_SETUP_SCRIPT)
    ret = Popen([com.CHECK_SETUP_SCRIPT]).wait()
    if ret:
        raise SystemExit(1)

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

    # check that the service exists
    service_props = config.get_service_props(options.service_name)
    if not service_props:
        raise SystemExit(
            _("The specified service does not exist: %s\n") %
            options.service_name)

    # get the image_path from the service
    try:
        # set image to be a InstalladmImage object
        image = svc.AIService(options.service_name).image
    except KeyError:
        raise SystemExit(
            _("\nThe specified service does not have an "
              "image_path property.\n"))

    # ensure we are not passed bootargs for a SPARC as we do not
    # support that
    if options.boot_args and image.arch == "sparc":
        parser.error(_("Boot arguments not supported for SPARC clients.\n"))

    options.arch = image.arch

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

    return options