def test_clients(self): '''test clients''' props = {config.PROP_SERVICE_NAME: 's1'} config._write_service_config('s1', props) config.add_client_info( 's1', '01AABBCCDDAABB', { config.FILES: ['/tmp/foo', '/tmp/bar'], config.BOOTARGS: 'console=ttya' }) self.assertTrue(config.is_client('01AABBCCDDAABB')) self.assertFalse(config.is_client('01AABBCCDDAABC')) svc, clientdict = config.find_client('01AABBCCDDAABB') self.assertEqual(svc, 's1') self.assertEqual(clientdict[config.FILES], ['/tmp/foo', '/tmp/bar']) self.assertEqual(clientdict[config.BOOTARGS], 'console=ttya') config.add_client_info('s1', '01AAAAAAAAAAAA', {config.FILES: ['/tmp/aaa', '/tmp/AAA']}) clientdict = config.get_clients('s1') self.assertEqual(clientdict.keys(), ['01AABBCCDDAABB', '01AAAAAAAAAAAA']) self.assertEqual(clientdict['01AAAAAAAAAAAA'][config.FILES], ['/tmp/aaa', '/tmp/AAA']) config.remove_client_from_config('s1', '01AABBCCDDAABB') clientdict = config.get_clients('s1') self.assertTrue('01AABBCCDDAABB' not in clientdict)
def do_update_basesvc(aliassvc, basesvcname): '''Updates the baseservice of an alias Input: aliassvc - service object of alias basesvcname - name of baseservice Returns: failures - list of errs encountered ''' logging.debug('do_update_basesvc: alias=%s, basename=%s', aliassvc.name, basesvcname) # Remove clients of alias clients = config.get_clients(aliassvc.name) for clientid in clients: logging.debug('removing client %s', clientid) clientctrl.remove_client(clientid, suppress_dhcp_msgs=True) failures = list() try: aliassvc.update_basesvc(basesvcname) except (OSError, config.ServiceCfgError, BootmgmtError) as err: print >> sys.stderr, \ (_("Failed to set %(aliasname)s as alias of: %(bname)s") % {'aliasname': aliassvc.name, 'bname': basesvcname}) print >> sys.stderr, err failures.append(err) except svc.MultipleUnmountError as err: print >> sys.stderr, _("Failed to disable alias") print >> sys.stderr, err failures.append(err) except svc.MountError as err: print >> sys.stderr, _("Failed to enable alias") print >> sys.stderr, err failures.append(err) except svc.UnsupportedAliasError as err: print >> sys.stderr, err failures.append(err) # Re-add clients to updated alias arch = aliassvc.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] logging.debug('re-adding clientid=%s, bootargs=%s', clientid, bootargs) # Don't suppress messages, because user may need to update # DHCP configuration try: create_client.create_new_client(arch, aliassvc, client, bootargs=bootargs, suppress_dhcp_msgs=False) except BootmgmtError as err: failures.append(err) print >> sys.stderr, (_('\nError: Unable to recreate client, ' '%(client)s:\n%(error)s') % {'client': client, 'error': err}) return failures
def find_clients(lservices, sname=None): """ find_clients() returns a dictionary that contains a list of dictionaries. The service name is the key for the main dictionary and the client, image path, and arch are members of the subdictionary, as follows: { 'service1': [ { 'ipath':<path1>, 'client':<client1>, 'arch': <arch>}, .... ], .... } Args lservices = config.get_all_service_props() sname - service name, if only interesetd in clients of a specific service Returns dictionary of a list of dictionaries Raises None """ sdict = dict() for servicename in lservices.keys(): if sname and sname != servicename: continue try: service = AIService(servicename) except VersionError as version_err: warn_version(version_err) continue arch = which_arch(service) image_path = [service.image.path] client_info = config.get_clients(servicename) for clientkey in client_info: # strip off the leading '01' and reinsert ':'s client = AIdb.formatValue('mac', clientkey[2:]) tdict = {'client': client, 'ipath': image_path, 'arch': arch} if servicename in sdict: # existing service name slist = sdict[servicename] slist.extend([tdict]) sdict[servicename] = slist else: # new service name key sdict[servicename] = [tdict] return sdict
def find_clients(lservices, sname=None): """ find_clients() returns a dictionary that contains a list of dictionaries. The service name is the key for the main dictionary and the client, image path, and arch are members of the subdictionary, as follows: { 'service1': [ { 'ipath':<path1>, 'client':<client1>, 'arch': <arch>}, .... ], .... } Args lservices = config.get_all_service_props() sname - service name, if only interesetd in clients of a specific service Returns dictionary of a list of dictionaries Raises None """ sdict = dict() for servicename in lservices.keys(): if sname and sname != servicename: continue try: service = AIService(servicename) except VersionError as version_err: warn_version(version_err) continue arch = which_arch(service) image_path = [service.image.path] client_info = config.get_clients(servicename) for clientkey in client_info: # strip off the leading '01' and reinsert ':'s client = AIdb.formatValue('mac', clientkey[2:]) tdict = {'client': client, 'ipath': image_path, 'arch': arch} if servicename in sdict: # existing service name slist = sdict[servicename] slist.extend([tdict]) sdict[servicename] = slist else: # new service name key sdict[servicename] = [tdict] return sdict
def delete_specified_service(service_name, auto_remove, noprompt): ''' Delete the specified Automated Install Service Input: service_name - service name auto_remove - boolean, True if dep. aliases and clients should be removed, False otherwise noprompt - boolean, True if warning about removing default-<arch> service should be suppressed ''' logging.debug("delete_specified_service %s %s %s", service_name, auto_remove, noprompt) service = AIService(service_name) # If the '-r' option has not been specified, look for all # dependent aliases and clients all_aliases = config.get_aliased_services(service_name, recurse=True) if not auto_remove: all_clients = config.get_clients(service_name).keys() for ale in all_aliases: all_clients.extend(config.get_clients(ale).keys()) # if any aliases or clients are dependent on this service, exit if all_aliases or all_clients: raise SystemExit( cw( _("\nError: The following aliases and/or " "clients are dependent on this service:\n\n" "%s\n\nPlease update or delete them prior " "to deleting this service or rerun this " "command using the -r|--autoremove option " "to have them automatically removed.\n") % '\n'.join(all_aliases + all_clients))) # Prompt user if they are deleting the default-sparc or default-i386 alias if not noprompt: sname = None if service_name in DEFAULT_ARCH: sname = service_name else: default_alias = set(DEFAULT_ARCH) & set(all_aliases) if default_alias: sname = ''.join(default_alias) if sname: arch = sname.split('default-')[1] _warning = """ WARNING: The service you are deleting, or a dependent alias, is the alias for the default %(arch)s service. Without the '%(name)s' service, %(arch)s clients will fail to boot unless explicitly assigned to a service using the create-client command. """ % { 'arch': arch, 'name': sname } print >> sys.stderr, cw(_(_warning)) prompt = _("Are you sure you want to delete this alias? [y/N]: ") if not com.ask_yes_or_no(prompt): raise SystemExit(1) # If there are dependent aliases or clients, then remove these first aliases = config.get_aliased_services(service_name) for dependent in aliases: logging.debug("recursively calling delete_specified_service for %s", dependent) delete_specified_service(dependent, True, True) clients = config.get_clients(service_name).keys() for dependent in clients: logging.debug("calling remove_client for %s", dependent) clientctrl.remove_client(dependent) logging.debug("now deleting service %s", service_name) # remove DHCP bootfile configuration for this service, if set remove_dhcp_configuration(service) # stop the service first (avoid pulling files out from under programs) try: service.delete() except StandardError as err: # Bail out if the service could not be unmounted during the disable, # as it won't be possible to delete necessary files. print >> sys.stderr, _("\nService could not be deleted.") raise SystemExit(err) # if this was the last service, go to maintenance config.check_for_enabled_services()
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 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