1.1 --- a/README.txt Mon Aug 31 18:09:31 2015 +0200
1.2 +++ b/README.txt Mon Aug 31 23:29:43 2015 +0200
1.3 @@ -58,6 +58,7 @@
1.4 The conf directory contains subdirectories for different systems:
1.5
1.6 apache Apache 2 site configuration for publishing resources
1.7 + cron Cron command scheduling for free/busy updates
1.8 exim Exim 4 routing and transport configuration
1.9 postfix Postfix routing and transport configuration
1.10
1.11 @@ -187,6 +188,23 @@
1.12 dpkg-statoverride --force --update --add \
1.13 cyrus lmtp 750 /var/run/cyrus/socket
1.14
1.15 +Configuring Cron for Free/Busy Updates
1.16 +--------------------------------------
1.17 +
1.18 +The periods occupied by recurring events are not expanded beyond a certain
1.19 +window of time by imip-agent. As a consequence, free/busy collections need to
1.20 +be progressively expanded over time to include periods occupied by such events
1.21 +that were not previously recorded in those collections.
1.22 +
1.23 +The conf/cron/cron.daily/imip-agent file contains commands that update
1.24 +free/busy collections for all known users, and this should be copied to the
1.25 +appropriate destination. For example:
1.26 +
1.27 +cp conf/cron/cron.daily/imip-agent /etc/cron.daily/
1.28 +
1.29 +Where frequency-specific directories are not supported by cron on a system, a
1.30 +crontab entry of the appropriate format is required instead.
1.31 +
1.32 Prerequisites
1.33 -------------
1.34
4.1 --- a/tools/install.sh Mon Aug 31 18:09:31 2015 +0200
4.2 +++ b/tools/install.sh Mon Aug 31 23:29:43 2015 +0200
4.3 @@ -1,9 +1,10 @@
4.4 #!/bin/sh
4.5
4.6 +# Agents and modules.
4.7 +
4.8 AGENTS="imip_person.py imip_person_outgoing.py imip_resource.py"
4.9 MODULES="markup.py imip_store.py vCalendar.py vContent.py vRecurrence.py"
4.10 INSTALL_DIR=/var/lib/imip-agent
4.11 -WEB_INSTALL_DIR=/var/www/imip-agent
4.12
4.13 if [ ! -e "$INSTALL_DIR" ]; then
4.14 mkdir -p "$INSTALL_DIR"
4.15 @@ -28,6 +29,18 @@
4.16 cp imiptools/*.py "$INSTALL_DIR/imiptools/"
4.17 cp imiptools/handlers/*.py "$INSTALL_DIR/imiptools/handlers/"
4.18
4.19 +# Tools
4.20 +
4.21 +if [ ! -e "$INSTALL_DIR/tools" ]; then
4.22 + mkdir -p "$INSTALL_DIR/tools"
4.23 +fi
4.24 +
4.25 +cp tools/make_freebusy.py "$INSTALL_DIR/tools/"
4.26 +
4.27 +# Web manager interface.
4.28 +
4.29 +WEB_INSTALL_DIR=/var/www/imip-agent
4.30 +
4.31 if [ ! -e "$WEB_INSTALL_DIR" ]; then
4.32 mkdir -p "$WEB_INSTALL_DIR"
4.33 fi
5.1 --- a/tools/make_freebusy.py Mon Aug 31 18:09:31 2015 +0200
5.2 +++ b/tools/make_freebusy.py Mon Aug 31 23:29:43 2015 +0200
5.3 @@ -21,7 +21,6 @@
5.4 this program. If not, see <http://www.gnu.org/licenses/>.
5.5 """
5.6
5.7 -from bisect import bisect_left
5.8 from codecs import getwriter
5.9 from imiptools.data import get_window_end, Object
5.10 from imiptools.dates import get_default_timezone, to_utc_datetime
5.11 @@ -30,26 +29,28 @@
5.12 from imip_store import FileStore, FilePublisher
5.13 import sys
5.14
5.15 -# Main program.
5.16 +def make_freebusy(user, participant, store_and_publish, include_needs_action, reset_updated_list, verbose):
5.17
5.18 -if __name__ == "__main__":
5.19 + """
5.20 + Make free/busy details for the records of the given 'user', generating
5.21 + details for 'participant' if not indicated as None; otherwise, generating
5.22 + free/busy details concerning the given user.
5.23
5.24 - # Interpret the command line arguments.
5.25 + If 'store_and_publish' is set, the stored details will be updated;
5.26 + otherwise, the details will be written to standard output.
5.27
5.28 - try:
5.29 - user = sys.argv[1]
5.30 - args = sys.argv[2:]
5.31 - participant = args and args[0] not in ("-n", "-s", "-v", "-r") and args[0] or user
5.32 - store_and_publish = "-s" in args
5.33 - include_needs_action = "-n" in args
5.34 - verbose = "-v" in args
5.35 - reset_updated_list = "-r" in args
5.36 - except IndexError:
5.37 - print >>sys.stderr, """\
5.38 - Need a user and an optional participant (if different from the user),
5.39 - along with the -s option if updating the store and the published details.
5.40 + If 'include_needs_action' is set, details of objects whose participation
5.41 + status is set to "NEEDS-ACTION" for the participant will be included in the
5.42 + details.
5.43 +
5.44 + If 'reset_updated_list' is set, all objects will be inspected for periods;
5.45 + otherwise, only those in the stored free/busy providers file will be
5.46 + inspected.
5.47 +
5.48 + If 'verbose' is set, messages will be written to standard error.
5.49 """
5.50 - sys.exit(1)
5.51 +
5.52 + participant = participant or user
5.53
5.54 preferences = Preferences(user)
5.55 tzid = preferences.get("TZID") or get_default_timezone()
5.56 @@ -110,12 +111,54 @@
5.57 if user == participant:
5.58 store.set_freebusy(user, fb)
5.59 publisher.set_freebusy(user, fb)
5.60 - store.set_freebusy_providers(user, to_utc_datetime(window_end, tzid), [obj for obj in objs if obj.possibly_active_from(window_end, tzid)])
5.61 +
5.62 + # Update the list of objects providing periods on future occasions.
5.63 +
5.64 + store.set_freebusy_providers(user, to_utc_datetime(window_end, tzid),
5.65 + [obj for obj in objs if obj.possibly_active_from(window_end, tzid)])
5.66 else:
5.67 store.set_freebusy_for_other(user, fb, participant)
5.68 +
5.69 + # Alternatively, just write the collection to standard output.
5.70 +
5.71 else:
5.72 f = getwriter("utf-8")(sys.stdout)
5.73 for item in fb:
5.74 print >>f, "\t".join(item.as_tuple(strings_only=True))
5.75
5.76 +# Main program.
5.77 +
5.78 +if __name__ == "__main__":
5.79 +
5.80 + # Interpret the command line arguments.
5.81 +
5.82 + try:
5.83 + user = sys.argv[1]
5.84 + args = sys.argv[2:]
5.85 + participant = args and args[0] not in ("-n", "-s", "-v", "-r") and args[0] or None
5.86 + store_and_publish = "-s" in args
5.87 + include_needs_action = "-n" in args
5.88 + reset_updated_list = "-r" in args
5.89 + verbose = "-v" in args
5.90 +
5.91 + except IndexError:
5.92 + print >>sys.stderr, """\
5.93 +Need a user and an optional participant (if different from the user),
5.94 +along with the -s option if updating the store and the published details.
5.95 +Specify -n to include objects with PARTSTAT of NEEDS-ACTION.
5.96 +Specify -r to inspect all objects, not just those expected to provide details.
5.97 +Specify -v for additional messages on standard error.
5.98 + """
5.99 + sys.exit(1)
5.100 +
5.101 + if user in ("*", "all"):
5.102 + users = FileStore().get_users()
5.103 + else:
5.104 + users = [user]
5.105 +
5.106 + for user in users:
5.107 + if verbose:
5.108 + print >>sys.stderr, user
5.109 + make_freebusy(user, participant, store_and_publish, include_needs_action, reset_updated_list, verbose)
5.110 +
5.111 # vim: tabstop=4 expandtab shiftwidth=4