3 # Notify users of slices that are about to expire
5 # Mark Huang <mlhuang@cs.princeton.edu>
6 # Copyright (C) 2005 The Trustees of Princeton University
8 # pylint: disable=c0326
12 from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
14 # Load shell with default configuration
15 sys.path.append('/usr/share/plc_api')
16 from PLC.Shell import Shell
20 plc = Shell(globals())
22 PLC_WWW_HOST = plc.config.PLC_WWW_HOST
23 PLC_NAME = plc.config.PLC_NAME
26 slice_url = f"https://{PLC_WWW_HOST}/db/slices/index.php?id="
29 parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
30 parser.add_argument("-s", "--slice", action="append", dest="slices", default=None,
31 help="Slice(s) to check (default: all)")
32 parser.add_argument("-x", "--expires", type=int, default=5,
33 help="Warn if slice expires this many days from now")
34 parser.add_argument("-n", "--dry-run", action="store_true", default=False,
35 help="Dry run, do not actually e-mail users")
36 parser.add_argument("-f", "--force", action="store_true", default=False,
37 help="Force, send e-mail even if slice is not close to expiring")
38 parser.add_argument("-v", "--verbose", action="store_true", default=False,
40 args = parser.parse_args()
42 now = int(time.time())
43 expires = now + (args.expires * 24 * 60 * 60)
46 print("Checking for slices that expire before " + time.ctime(expires))
48 slice_filter = {'peer_id': None}
50 slice_filter['name'] = args.slices
52 # issue one call to GetPersons to gather the sfa_created tag on all persons
53 persons = GetPersons({'peer_id': None}, ['person_id', 'email', 'sfa_created'])
54 persons_by_id = { p['person_id'] : p for p in persons }
56 print("retrieved {} persons".format(len(persons)))
60 ['slice_id', 'name', 'expires', 'description', 'url', 'person_ids'])
62 print("scanning {} slices".format(len(slices)))
65 # See if slice expires before the specified warning date
66 if not args.force and slice['expires'] > expires:
69 # Calculate number of whole days left
70 delta = slice['expires'] - now
71 days = delta // (24 * 60 * 60)
73 days = "less than a day"
79 days = f"{days} day{suffix}"
81 slice_name = slice['name']
82 slice_id = slice['slice_id']
85 The {PLC_NAME} slice {slice_name} will expire in {days}.
88 # Explain that slices must have descriptions and URLs
89 if not slice['description'] or not slice['description'].strip() or \
90 not slice['url'] or not slice['url'].strip():
92 Before you may renew this slice, you must provide a short description
93 of the slice and a link to a project website.
96 # Provide links to renew or delete the slice
98 To update, renew, or delete this slice, visit the URL:
100 {slice_url}{slice_id}
103 # compute set of persons but keep federated users (the ones with sfa_created) out
104 slice_persons = [persons_by_id[id] for id in slice['person_ids']]
105 recipient_emails = [person['email'] for person in slice_persons
106 if not person['sfa_created']]
107 nb_in_slice = len(slice_persons)
108 nb_not_sfa = len(recipient_emails)
110 if not recipient_emails:
112 print(f"""{slice_name} has no recipient
113 ({nb_in_slice} in slice, {nb_not_sfa} not sfa_created)""")
116 log_details = [time.ctime(now), slice_name, time.ctime(slice['expires'])]
117 details = "\t".join(log_details)
118 recipients = ",".join(recipient_emails)
119 log_data = f"{details}\t{recipients}"
121 extras = GetMessages({'message_id': "renew_reminder_addition"})
123 message += extras[0]['template']
126 print(f"-------------------- Found slice to renew {slice_name}")
128 print(f"---- log_data\n{log_data}")
130 NotifyPersons(slice['person_ids'],
131 f"{PLC_NAME}: slice {slice_name} expires in {days}",
135 if __name__ == '__main__':