def test_retrieve_timestamp(self, mock_read_timestamp): """Test for the filestamp retrieval.""" mock_read_timestamp.return_value = None self.assertEqual(convert_to_unix_timestamp(DEFAULT_TIMESTAMP), retrieve_timestamp_with_default("f")[0]) read_ts = "203412130101" mock_read_timestamp.return_value = read_ts start_ts = "20140102" default_ts = "20150103" self.assertEqual( convert_to_unix_timestamp(start_ts), retrieve_timestamp_with_default("f", start_timestamp=start_ts)[0]) self.assertEqual( convert_to_unix_timestamp(read_ts), retrieve_timestamp_with_default("f", default_timestamp=default_ts)[0]) self.assertEqual( utc, retrieve_timestamp_with_default( "f", default_timestamp="20140102")[1].tzinfo) mock_read_timestamp.return_value = None self.assertEqual( convert_to_unix_timestamp(default_ts), retrieve_timestamp_with_default("f", default_timestamp=default_ts)[0])
def test_retrieve_timestamp(self, mock_read_timestamp): """Test for the filestamp retrieval.""" mock_read_timestamp.return_value = None self.assertEqual(convert_to_unix_timestamp(DEFAULT_TIMESTAMP), retrieve_timestamp_with_default("f")[0]) read_ts = "203412130101" mock_read_timestamp.return_value = read_ts start_ts = "20140102" default_ts = "20150103" self.assertEqual(convert_to_unix_timestamp(start_ts), retrieve_timestamp_with_default("f", start_timestamp=start_ts)[0]) self.assertEqual(convert_to_unix_timestamp(read_ts), retrieve_timestamp_with_default("f", default_timestamp=default_ts)[0]) self.assertEqual(utc, retrieve_timestamp_with_default("f", default_timestamp="20140102")[1].tzinfo) mock_read_timestamp.return_value = None self.assertEqual(convert_to_unix_timestamp(default_ts), retrieve_timestamp_with_default("f", default_timestamp=default_ts)[0])
def make_time(self): """ Get start time (from commandline or cache), return current time """ try: (start_timestamp, current_time) = retrieve_timestamp_with_default( getattr(self.options, TIMESTAMP_FILE_OPTION), start_timestamp=self.options.start_timestamp, default_timestamp=DEFAULT_TIMESTAMP, delta= -MAX_RTT, # make the default delta explicit, current_time = now - MAX_RTT seconds ) except Exception as err: self.critical_exception("Failed to retrieve timestamp", err) logging.info("Using start timestamp %s", start_timestamp) logging.info("Using current time %s", current_time) self.start_timestamp = start_timestamp self.current_time = current_time
def main(): """ Main script. The usual. """ options = { "nagios-check-interval-threshold": NAGIOS_CHECK_INTERVAL_THRESHOLD, "access_token": ("OAuth2 token to access the account page REST API", None, "store", None), "account_page_url": ( "URL of the account page where we can find the REST API", str, "store", "https://apivsc.ugent.be/django", ), 'host_institute': ('Name of the institute where this script is being run', str, 'store', GENT), "clusters": ( "Cluster(s) (comma-separated) to sync for. " "Overrides <host_institute>_SLURM_COMPUTE_CLUSTERS that are in production.", "strlist", "store", [], ), 'start_timestamp': ('Timestamp to start the sync from', str, 'store', None), 'cluster_classes': ('Classes of clusters that should be synced, comma-separated', "strlist", 'store', [PRODUCTION, PILOT]) } opts = ExtendedSimpleOption(options) stats = {} (last_timestamp, start_time) = retrieve_timestamp_with_default( SYNC_TIMESTAMP_FILENAME, start_timestamp=opts.options.start_timestamp) logging.info("Using timestamp %s", last_timestamp) logging.info("Using startime %s", start_time) try: client = AccountpageClient(token=opts.options.access_token, url=opts.options.account_page_url + "/api/") host_institute = opts.options.host_institute slurm_account_info = get_slurm_acct_info(SyncTypes.accounts) slurm_user_info = get_slurm_acct_info(SyncTypes.users) logging.debug("%d accounts found", len(slurm_account_info)) logging.debug("%d users found", len(slurm_user_info)) if opts.options.clusters: clusters = opts.options.clusters else: clusters = [ cs for p in opts.options.cluster_classes for cs in VSC_SLURM_CLUSTERS[host_institute][p] ] sacctmgr_commands = [] # All users belong to a VO, so fetching the VOs is necessary/ account_page_vos = [ mkVo(v) for v in client.vo.institute[opts.options.host_institute].get()[1] ] # make sure the institutes and the default accounts (VOs) are there for each cluster institute_vos = dict([ (v.vsc_id, v) for v in account_page_vos if v.vsc_id in INSTITUTE_VOS_BY_INSTITUTE[host_institute].values() ]) sacctmgr_commands += slurm_institute_accounts(slurm_account_info, clusters, host_institute, institute_vos) # The VOs do not track active state of users, so we need to fetch all accounts as well active_accounts = set( [a["vsc_id"] for a in client.account.get()[1] if a["isactive"]]) # dictionary mapping the VO vsc_id on a tuple with the VO members and the VO itself account_page_members = dict([(vo.vsc_id, (set(vo.members), vo)) for vo in account_page_vos]) # process all regular VOs sacctmgr_commands += slurm_vo_accounts(account_page_vos, slurm_account_info, clusters, host_institute) # process VO members sacctmgr_commands += slurm_user_accounts(account_page_members, active_accounts, slurm_user_info, clusters, opts.options.dry_run) logging.info("Executing %d commands", len(sacctmgr_commands)) if opts.options.dry_run: print("Commands to be executed:\n") print("\n".join([" ".join(c) for c in sacctmgr_commands])) else: execute_commands(sacctmgr_commands) if not opts.options.dry_run: (_, ldap_timestamp) = convert_timestamp(start_time) write_timestamp(SYNC_TIMESTAMP_FILENAME, ldap_timestamp) opts.epilogue("Accounts synced to slurm", stats) else: logging.info("Dry run done") except Exception as err: logging.exception("critical exception caught: %s", err) opts.critical("Script failed in a horrible way") sys.exit(NAGIOS_EXIT_CRITICAL)
def main(): options = { 'nagios-check-interval-threshold': NAGIOS_CHECK_INTERVAL_THRESHOLD, 'start-timestamp': ("The timestamp form which to start, otherwise use the cached value", None, "store", None), 'access_token': ('OAuth2 token identifying the user with the accountpage', None, 'store', None), 'account_page_url': ('url for the account page', None, 'store', None), 'start_timestamp': ('Timestamp to start the sync from', str, 'store', None), } # get access_token from conf file ExtendedSimpleOption.CONFIGFILES_INIT = ['/etc/account_page.conf'] opts = ExtendedSimpleOption(options) stats = {} # Creating this here because this is a singleton class _ = LdapQuery(VscConfiguration(VSC_CONF_DEFAULT_FILENAME)) (last_timestamp, start_time) = retrieve_timestamp_with_default( SYNC_TIMESTAMP_FILENAME, start_timestamp=opts.options.start_timestamp) logging.info("Using timestamp %s", last_timestamp) logging.info("Using startime %s", start_time) try: parent_pid = os.fork() logging.info("Forked.") except OSError: logging.exception("Could not fork") parent_pid = 1 except Exception: logging.exception("Oops") parent_pid = 1 if parent_pid == 0: try: global logger logger = fancylogger.getLogger(NAGIOS_HEADER) # drop privileges in the child try: apache_uid = pwd.getpwnam('apache').pw_uid apache_gid = grp.getgrnam('apache').gr_gid os.setgroups([]) os.setgid(apache_gid) os.setuid(apache_uid) logging.info("Now running as %s" % (os.geteuid(), )) except OSError: logger.raiseException("Could not drop privileges") client = AccountpageClient(token=opts.options.access_token, url=opts.options.account_page_url + '/api/') syncer = LdapSyncer(client) last = last_timestamp altered_accounts = syncer.sync_altered_accounts( last, opts.options.dry_run) logging.debug("Altered accounts: %s", altered_accounts) altered_groups = syncer.sync_altered_groups( last, opts.options.dry_run) logging.debug("Altered groups: %s" % altered_groups) if not altered_accounts[ERROR] \ and not altered_groups[ERROR]: logging.info("Child process exiting correctly") sys.exit(0) else: logging.info("Child process exiting with status -1") logging.warning("Error occured in %s" % ([ "%s: %s\n" % (k, v) for (k, v) in [ ("altered accounts", altered_accounts[ERROR]), ("altered groups", altered_groups[ERROR]), ] ])) sys.exit(-1) except Exception: logging.exception("Child caught an exception") sys.exit(-1) else: # parent (_, result) = os.waitpid(parent_pid, 0) logging.info("Child exited with exit code %d" % (result, )) if not result and not opts.options.dry_run: (_, ldap_timestamp) = convert_timestamp(start_time) write_timestamp(SYNC_TIMESTAMP_FILENAME, ldap_timestamp) opts.epilogue("Synchronised LDAP users to the Django DB", stats) else: sys.exit(NAGIOS_EXIT_CRITICAL)
def main(): """ Main script. - build the filter - fetches the users - process the users - write the new timestamp if everything went OK - write the nagios check file """ options = { 'nagios-check-interval-threshold': NAGIOS_CHECK_INTERVAL_THRESHOLD, 'storage': ('storage systems on which to deploy users and vos', None, 'extend', []), 'user': ('process users', None, 'store_true', False), 'vo': ('process vos', None, 'store_true', False), 'access_token': ('OAuth2 token to access the account page REST API', None, 'store', None), 'account_page_url': ('URL of the account page where we can find the REST API', None, 'store', None), 'host_institute': ('Name of the institute where this script is being run', str, 'store', GENT), 'start_timestamp': ('Timestamp to start the sync from', str, 'store', None), } opts = ExtendedSimpleOption(options) stats = {} (last_timestamp, start_time) = retrieve_timestamp_with_default( SYNC_TIMESTAMP_FILENAME, start_timestamp=opts.options.start_timestamp) logging.info("Using timestamp %s", last_timestamp) logging.info("Using startime %s", start_time) try: client = AccountpageClient(token=opts.options.access_token, url=opts.options.account_page_url + "/api/") institute = opts.options.host_institute (users_ok, users_fail) = ([], []) (quota_ok, quota_fail) = ([], []) if opts.options.user: changed_accounts = client.account.institute[institute].modified[ last_timestamp].get()[1] logging.info( "Found %d %s accounts that have changed in the accountpage since %s" % (len(changed_accounts), institute, last_timestamp)) accounts = nub([u['vsc_id'] for u in changed_accounts]) for storage_name in opts.options.storage: (users_ok, users_fail) = process_users(opts.options, accounts, storage_name, client, institute) stats["%s_users_sync" % (storage_name, )] = len(users_ok) stats["%s_users_sync_fail" % (storage_name, )] = len(users_fail) stats["%s_users_sync_fail_warning" % (storage_name, )] = STORAGE_USERS_LIMIT_WARNING stats["%s_users_sync_fail_critical" % (storage_name, )] = STORAGE_USERS_LIMIT_CRITICAL for storage_name in opts.options.storage: storage_changed_quota = [ mkVscUserSizeQuota(q) for q in client.quota.user. storage[storage_name].modified[last_timestamp].get()[1] ] storage_changed_quota = [ q for q in storage_changed_quota if q.fileset.startswith('vsc') ] logging.info( "Found %d accounts that have changed quota on storage %s in the accountpage since %s", len(storage_changed_quota), storage_name, last_timestamp) (quota_ok, quota_fail) = process_users_quota( opts.options, storage_changed_quota, storage_name, client, institute) stats["%s_quota_sync" % (storage_name, )] = len(quota_ok) stats["%s_quota_sync_fail" % (storage_name, )] = len(quota_fail) stats["%s_quota_sync_fail_warning" % (storage_name, )] = STORAGE_QUOTA_LIMIT_WARNING stats["%s_quota_sync_fail_critical" % (storage_name, )] = STORAGE_QUOTA_LIMIT_CRITICAL (vos_ok, vos_fail) = ([], []) if opts.options.vo: changed_vos = client.vo.institute[institute].modified[ last_timestamp].get()[1] changed_vo_quota = client.quota.vo.modified[last_timestamp].get( )[1] vos = sorted( set([v['vsc_id'] for v in changed_vos] + [v['virtual_organisation'] for v in changed_vo_quota])) logging.info( "Found %d %s VOs that have changed in the accountpage since %s" % (len(changed_vos), institute, last_timestamp)) logging.info( "Found %d %s VOs that have changed quota in the accountpage since %s" % (len(changed_vo_quota), institute, last_timestamp)) logging.debug("Found the following {institute} VOs: {vos}".format( institute=institute, vos=vos)) for storage_name in opts.options.storage: (vos_ok, vos_fail) = process_vos(opts.options, vos, storage_name, client, last_timestamp, institute) stats["%s_vos_sync" % (storage_name, )] = len(vos_ok) stats["%s_vos_sync_fail" % (storage_name, )] = len(vos_fail) stats["%s_vos_sync_fail_warning" % (storage_name, )] = STORAGE_VO_LIMIT_WARNING stats["%s_vos_sync_fail_critical" % (storage_name, )] = STORAGE_VO_LIMIT_CRITICAL if not (users_fail or quota_fail or vos_fail) and not opts.options.dry_run: (_, ldap_timestamp) = convert_timestamp(start_time) write_timestamp(SYNC_TIMESTAMP_FILENAME, ldap_timestamp) except Exception as err: logger.exception("critical exception caught: %s" % (err)) opts.critical("Script failed in a horrible way") sys.exit(NAGIOS_EXIT_CRITICAL) opts.epilogue("%s users and VOs synchronised" % institute, stats)