1 = Resources = 2 3 In imip-agent, resources are a special kind of user that act upon requests 4 to schedule events and that perform such scheduling autonomously, meaning 5 that no human intervention is necessary when such resources receive messages 6 containing invitations. 7 8 By default, the [[../AgentPrograms|agent program]] responsible for resources 9 merely attempts to fit a received event into the resource's schedule. However, 10 in some organisations and environments, it is likely to be the case that other 11 policies are needed to ensure that a resource is not misused, overused or made 12 unnecessarily unavailable. 13 14 The [[../Preferences|preferences]] provide a way of controlling the behaviour 15 of resources, just as with any other kind of user, but certain preferences 16 are central to the configuration of resources. 17 18 <<TableOfContents(2,4)>> 19 20 == Scheduling Functions == 21 22 The [[../Preferences#scheduling_function|scheduling_function]] setting 23 indicates the behaviour of a resource when a valid request to schedule an 24 event has been received. By default, a value equivalent to the following is 25 employed: 26 27 {{{{#!table 28 '''Scheduling Functions''' || '''Decision Process''' 29 == 30 <style="vertical-align: top;"> 31 32 {{{ 33 schedule_in_freebusy 34 }}} 35 36 || 37 38 {{{#!graphviz 39 //format=svg 40 //transform=notugly 41 digraph scheduling_decisions { 42 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 43 edge [tooltip="Scheduling decisions"]; 44 45 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 46 47 subgraph { 48 rank=same; 49 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 50 freebusy [label="Free/busy",shape=folder]; 51 } 52 53 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 54 55 subgraph { 56 rank=same; 57 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 58 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 59 } 60 61 mail -> schedule_in_freebusy -> schedule -> accept; 62 schedule_in_freebusy -> decline [style=dashed]; 63 freebusy -> schedule_in_freebusy; 64 } 65 }}} 66 67 }}}} 68 69 As described above, this merely attempts to schedule an event in the free 70 periods of the resource's schedule. However, no attempt is made to reject the 71 booking of the resource according to the identity of the organiser. 72 73 === Identity Controls === 74 75 Although identity controls may be implemented in the e-mail system, 76 effectively preventing the messages from addresses other than those within 77 an organisation (for example) from being delivered to the resource, it is 78 possible to use scheduling functions to implement such controls instead. 79 80 ==== Same Domain Membership ==== 81 82 For instance, the following combines the default free/busy check with a 83 test that the organiser belongs to the same Internet mail domain (by using 84 the organiser's address): 85 86 {{{{#!table 87 '''Scheduling Functions''' || '''Decision Process''' 88 == 89 <style="vertical-align: top;"> 90 91 {{{ 92 schedule_in_freebusy 93 same_domain_only 94 }}} 95 96 || 97 98 {{{#!graphviz 99 //format=svg 100 //transform=notugly 101 digraph scheduling_decisions { 102 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 103 edge [tooltip="Scheduling decisions"]; 104 105 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 106 107 subgraph { 108 rank=same; 109 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 110 freebusy [label="Free/busy",shape=folder]; 111 } 112 113 same_domain_only [label="Organiser has resource domain?",shape=ellipse,style=filled,fillcolor=gold]; 114 115 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 116 117 subgraph { 118 rank=same; 119 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 120 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 121 } 122 123 mail -> schedule_in_freebusy -> same_domain_only -> schedule -> accept; 124 schedule_in_freebusy -> decline [style=dashed]; 125 same_domain_only -> decline [style=dashed]; 126 freebusy -> schedule_in_freebusy; 127 } 128 }}} 129 130 }}}} 131 132 Note that if the first function is omitted, no check against the resource's 133 schedule will occur, so it is necessary to mention any such function in the 134 list. 135 136 ==== Access Control Lists ==== 137 138 A simple domain-related test may not be sufficient to control access to a 139 resource. Thus, another function is provided to exercise a finer degree of 140 control over event participants. For example: 141 142 {{{{#!table 143 '''Scheduling Functions and Data''' || '''Decision Process''' 144 == 145 <style="vertical-align: top;"> 146 147 {{{ 148 schedule_in_freebusy 149 access_control_list 150 }}} 151 152 Access control list: 153 154 {{{ 155 accept 156 }}} 157 158 || 159 160 {{{#!graphviz 161 //format=svg 162 //transform=notugly 163 digraph scheduling_decisions { 164 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 165 edge [tooltip="Scheduling decisions"]; 166 167 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 168 169 subgraph { 170 rank=same; 171 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 172 freebusy [label="Free/busy",shape=folder]; 173 } 174 175 subgraph { 176 rank=same; 177 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 178 acl [label="acl setting",shape=folder]; 179 } 180 181 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 182 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 183 184 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 185 186 subgraph { 187 rank=same; 188 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 189 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 190 } 191 192 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> end_acl -> schedule -> accept; 193 end_acl -> decline [style=dashed]; 194 schedule_in_freebusy -> decline [style=dashed]; 195 freebusy -> schedule_in_freebusy; 196 acl -> access_control_list; 197 } 198 }}} 199 200 }}}} 201 202 To accompany the scheduling functions, the [[../Preferences#acl|acl]] setting 203 in the resource's preferences must be set, or if a separate file is more 204 appropriate, its full path may be given as an argument to `access_control_list`: 205 206 {{{ 207 schedule_in_freebusy 208 access_control_list /etc/imip-agent/resources.acl 209 }}} 210 211 Within the file provided by the setting or separate file, a list of rules 212 must describe the handling procedure for an event. For example, the following 213 was given in the above example: 214 215 {{{ 216 accept 217 }}} 218 219 This will merely accept all invitations, anyway. However, it may be 220 appropriate to prevent certain users from using resources. For example: 221 222 {{{{#!table 223 '''Scheduling Functions and Data''' || '''Decision Process''' 224 == 225 <style="vertical-align: top;"> 226 227 {{{ 228 schedule_in_freebusy 229 access_control_list 230 }}} 231 232 Access control list: 233 234 {{{ 235 accept 236 decline attendee simon.skunk@example.com 237 }}} 238 239 || 240 241 {{{#!graphviz 242 //format=svg 243 //transform=notugly 244 digraph scheduling_decisions { 245 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 246 edge [tooltip="Scheduling decisions"]; 247 248 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 249 250 subgraph { 251 rank=same; 252 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 253 freebusy [label="Free/busy",shape=folder]; 254 } 255 256 subgraph { 257 rank=same; 258 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 259 acl [label="acl setting",shape=folder]; 260 } 261 262 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 263 decline_attendee [label="Is attendee simon.skunk@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 264 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 265 266 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 267 268 subgraph { 269 rank=same; 270 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 271 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 272 } 273 274 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> decline_attendee -> end_acl -> schedule -> accept; 275 end_acl -> decline [style=dashed]; 276 schedule_in_freebusy -> decline [style=dashed]; 277 freebusy -> schedule_in_freebusy; 278 acl -> access_control_list; 279 } 280 }}} 281 282 }}}} 283 284 This example indicates that by default, invitations will be accepted, but if 285 one of the attendees of an event is `simon.skunk@example.com`, the invitation 286 will be declined. However, it may be the case that this rule should be 287 overridden under certain circumstances. For example: 288 289 {{{{#!table 290 '''Scheduling Functions and Data''' || '''Decision Process''' 291 == 292 <style="vertical-align: top;"> 293 294 {{{ 295 schedule_in_freebusy 296 access_control_list 297 }}} 298 299 Access control list: 300 301 {{{ 302 accept 303 decline attendee simon.skunk@example.com 304 accept organiser paul.boddie@example.com 305 }}} 306 307 || 308 309 {{{#!graphviz 310 //format=svg 311 //transform=notugly 312 digraph scheduling_decisions { 313 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 314 edge [tooltip="Scheduling decisions"]; 315 316 mail [label="Incoming mail",shape=folder,style=filled,fillcolor=cyan]; 317 318 subgraph { 319 rank=same; 320 schedule_in_freebusy [label="Can schedule in free/busy?",shape=ellipse,style=filled,fillcolor=gold]; 321 freebusy [label="Free/busy",shape=folder]; 322 } 323 324 subgraph { 325 rank=same; 326 access_control_list [label="Access control list permits booking?",shape=ellipse,style=filled,fillcolor=gold]; 327 acl [label="acl setting",shape=folder]; 328 } 329 330 accept_default [label="Accept invitation by default",shape=ellipse,style=filled,fillcolor=darkorange]; 331 decline_attendee [label="Is attendee simon.skunk@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 332 accept_organiser [label="Is organiser paul.boddie@example.com?",shape=ellipse,style=filled,fillcolor=darkorange]; 333 end_acl [label="end",shape=ellipse,style=filled,fillcolor=darkorange]; 334 335 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 336 337 subgraph { 338 rank=same; 339 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 340 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 341 } 342 343 mail -> schedule_in_freebusy -> access_control_list -> accept_default -> decline_attendee -> accept_organiser -> end_acl -> schedule -> accept; 344 end_acl -> decline [style=dashed]; 345 schedule_in_freebusy -> decline [style=dashed]; 346 freebusy -> schedule_in_freebusy; 347 acl -> access_control_list; 348 } 349 }}} 350 351 }}}} 352 353 Here, the stated organiser may still arrange a booking of the resource where 354 the previously-mentioned attendee is involved. 355 356 === Quota Controls === 357 358 In contrast to each user's stored information which consolidates information 359 related to that user's own schedule, the quota system consolidates information 360 related to the schedules of one or more resources, thus enabling observations 361 to be made about their collective usage. 362 363 First, consider a resource such as a car where an organiser of an event may be 364 booking the car for travel purposes. A quota prevents the organiser from 365 booking the resource too much and denying other users access to it. 366 367 Now consider a number of separate car resources. An organiser might attempt to 368 get around any individual resource quota by booking a number of different cars. 369 By grouping the resources together, the organiser will exhaust any quota set on 370 the group of resources as they try and make reservations for the different 371 members of the quota group. 372 373 ==== Initialising Quotas ==== 374 375 Within the journal storage area, a quota may be initialised with limits 376 indicating the amount of time that can be occupied by the cumulative total of 377 all events scheduled by an individual user or a group of which they are a 378 member. 379 380 Such limits may be set directly using the `limits` file in a quota directory 381 (described in the [[../FilesystemUsage|filesystem guide]]) or in the 382 `quota_limits` table (described in the [[../DatabaseStore|database guide]]), 383 but a tool is also provided to set such limits. For example: 384 385 {{{ 386 cat <<EOF | set_quota_limits.py 'mailto:resource-car-cadillac@example.com' 387 mailto:vincent.vole@example.com PT10H 388 EOF 389 }}} 390 391 {{{#!wiki tip 392 In the above example, shell syntax is used to indicate a 393 [[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04|here document]] 394 providing a kind of "inline" file that is terminated by the final `EOF`. 395 The contents of this file are piped to the tool with a single argument given 396 indicating the quota involved. 397 398 You could also just invoke the tool and then enter the limit descriptions, 399 ending the input with Ctrl-D or equivalent end-of-file keystroke, or save 400 the descriptions in a file and then use input redirection with the filename. 401 }}} 402 403 The above example indicates that the given user may only reserve 10 hours 404 of events or less time within the given quota (corresponding to a specific 405 resource in the above example). Attempts to schedule more time will be 406 declined. 407 408 To impose a general quota, the special `*` identity can be used: 409 410 {{{ 411 cat <<EOF | set_quota_limits.py 'mailto:resource-car-cadillac@example.com' 412 * PT10H 413 EOF 414 }}} 415 416 Note that this general quota applies to each individual identity and not 417 collectively to all unspecified identities. To impose such a collective 418 quota, a group may be defined for this purpose as described below. 419 420 When a user identity is not listed and no general quota is defined, that 421 particular user will be unable to reserve the resource unless defined as a 422 member of a group listed in the `limits` file, as described below. 423 424 ==== Sharing Quotas Across Users ==== 425 426 When the use of resources is to be shared between users in such a way that 427 groups of users will be sharing a single quota, a `groups` file in a quota 428 directory (or records in the `quota_groups` table) must be defined, mapping 429 each user identity to the group to which they will belong. 430 431 A tool is provided to define groups and is used as follows: 432 433 {{{ 434 cat <<EOF | tools/set_quota_groups.py 'mailto:resource-car-cadillac@example.com' 435 mailto:vincent.vole@example.com developers 436 * others 437 EOF 438 }}} 439 440 Here, otherwise unrecognised organisers are mapped to the `others` group. 441 Thus, all scheduling performed by such organisers will be done in a common 442 journal with this label. 443 444 The process of determining where an organiser's usage of resources is 445 recorded is illustrated by the following example: 446 447 {{{{#!table 448 '''Scheduling Data''' || '''Decision Process''' 449 == 450 <style="vertical-align: top;"> 451 The groups are defined as follows in the `groups` file: 452 453 {{{ 454 mailto:vincent.vole@example.com developers 455 mailto:harvey.horse@example.com developers 456 mailto:paul.boddie@example.com developers 457 mailto:simon.skunk@example.com testers 458 }}} 459 460 The group identity can then be employed in the `limits` file: 461 462 {{{ 463 developers PT10H 464 testers PT20H 465 }}} 466 467 || 468 469 {{{#!graphviz 470 //format=svg 471 //transform=notugly 472 digraph quota_users { 473 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Quota users"]; 474 edge [tooltip="Quota users"]; 475 476 subgraph { 477 rank=same; 478 user1 [label="User is vincent.vole@example.com"]; 479 user2 [label="User is oliver.otter@example.com"]; 480 } 481 482 havegroup [label="Have group for quota?",shape=ellipse,style=filled,fillcolor=gold]; 483 haveuser [label="Have group for user in quota?",shape=ellipse,style=filled,fillcolor=gold]; 484 485 group1 [label="User is vincent.vole@example.com\nGroup is developers"]; 486 group2 [label="User is oliver.otter@example.com"]; 487 488 checkuser1 [label="Have limit for group?",shape=ellipse,style=filled,fillcolor=gold]; 489 checkgeneral1 [label="Have general limit?",shape=ellipse,style=filled,fillcolor=gold]; 490 491 checkuser2 [label="Have limit for user?",shape=ellipse,style=filled,fillcolor=gold]; 492 checkgeneral2 [label="Have general limit?",shape=ellipse,style=filled,fillcolor=gold]; 493 494 accept [label="Quota",shape=folder,style=filled,fillcolor=cyan]; 495 decline [label="No quota",shape=folder,style=filled,fillcolor=cyan]; 496 497 user1 -> havegroup -> haveuser -> group1 -> checkuser1 -> checkgeneral1 -> accept; 498 user2 -> havegroup -> haveuser -> group2 -> checkuser2 -> checkgeneral2 -> decline [style=dashed]; 499 } 500 }}} 501 }}}} 502 503 Where individuals are not assigned to groups, any individual limit will apply 504 to them; otherwise, the general quota applies. Where individuals are assigned 505 to groups, any group limit will apply; otherwise, the general quota applies. 506 507 ==== Individual Resource Quotas ==== 508 509 The trivial case of applying quotas is to give a resource its own quota. This 510 is achieved by not specifying any arguments to the `check_quota` scheduling 511 function or to the `add_to_quota` and `remove_from_quota` functions. 512 513 {{{{#!table 514 '''Scheduling Functions''' || '''Decision Process''' 515 == 516 <style="vertical-align: top;"> 517 518 {{{ 519 check_quota 520 }}} 521 522 || 523 524 {{{#!graphviz 525 //format=svg 526 //transform=notugly 527 digraph scheduling_decisions { 528 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 529 edge [tooltip="Scheduling decisions"]; 530 531 subgraph { 532 rank=same; 533 mail [label="Incoming mail\nfrom vincent.vole@example.com",shape=folder,style=filled,fillcolor=cyan]; 534 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 535 } 536 537 subgraph { 538 rank=same; 539 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 540 quota [label="Quota for resource",shape=folder]; 541 quota_for_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 542 } 543 544 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 545 546 subgraph { 547 rank=same; 548 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 549 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 550 } 551 552 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 553 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 554 555 mail -> check_quota -> schedule -> accept; 556 check_quota -> decline [style=dashed]; 557 schedule -> add_to_quota -> quota; 558 quota -> quota_for_vole -> check_quota; 559 560 cancel -> remove_from_quota -> quota; 561 } 562 }}} 563 564 }}}} 565 566 ==== Common Resource Quotas ==== 567 568 By indicating an argument to the different functions, a common quota can be 569 employed. In the following example, both resources would employ the given 570 function invocations to pool their knowledge about their schedules. 571 572 {{{{#!table 573 '''Scheduling Functions''' || '''Decision Process''' 574 == 575 <style="vertical-align: top;"> 576 577 {{{ 578 check_quota cars 579 }}} 580 581 || 582 583 {{{#!graphviz 584 //format=svg 585 //transform=notugly 586 digraph scheduling_decisions { 587 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 588 edge [tooltip="Scheduling decisions"]; 589 590 subgraph { 591 rank=same; 592 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 593 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 594 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 595 } 596 597 subgraph { 598 rank=same; 599 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 600 quota_cars [label="Quota for cars",shape=folder]; 601 quota_cars_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 602 } 603 604 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 605 606 subgraph { 607 rank=same; 608 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 609 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 610 } 611 612 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 613 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 614 615 mail_cadillac -> check_quota; 616 mail_pontiac -> check_quota -> schedule -> accept; 617 check_quota -> decline [style=dashed]; 618 schedule -> add_to_quota -> quota_cars; 619 quota_cars -> quota_cars_vole -> check_quota; 620 621 cancel -> remove_from_quota -> quota_cars; 622 } 623 }}} 624 625 }}}} 626 627 ==== Collective Scheduling ==== 628 629 Consider two separate resources: both may be reserved at the same time by the 630 same organiser; neither resource would normally decline the reservation on the 631 basis of schedule availability, should the period concerned be free. However, 632 it may be undesirable for one organiser to occupy both resources at the same 633 time. 634 635 Consequently, a mechanism is required to pool the resource schedules in such a 636 way that any reservation performed for one resource at a given point in time 637 prohibits another reservation performed for a related resource at the same 638 point in time by the same user. 639 640 The free/busy records held for a given quota group permit such collective 641 scheduling decisions and are employed as follows: 642 643 {{{{#!table 644 '''Scheduling Functions''' || '''Decision Process''' 645 == 646 <style="vertical-align: top;"> 647 648 {{{ 649 schedule_across_quota cars 650 }}} 651 652 || 653 654 {{{#!graphviz 655 //format=svg 656 //transform=notugly 657 digraph scheduling_decisions { 658 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 659 edge [tooltip="Scheduling decisions"]; 660 661 subgraph { 662 rank=same; 663 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 664 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 665 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 666 } 667 668 subgraph { 669 rank=same; 670 schedule_across_quota [label="Can be scheduled within the quota?",shape=ellipse,style=filled,fillcolor=gold]; 671 quota_cars [label="Quota for cars",shape=folder]; 672 freebusy_cars_vole [label="...recording schedule for\nvincent.vole@example.com",shape=folder]; 673 } 674 675 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 676 677 subgraph { 678 rank=same; 679 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 680 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 681 } 682 683 add_to_quota_freebusy [label="Add to quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 684 remove_from_quota_freebusy [label="Remove from quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 685 686 mail_cadillac -> schedule_across_quota; 687 mail_pontiac -> schedule_across_quota -> schedule -> accept; 688 schedule_across_quota -> decline [style=dashed]; 689 schedule -> add_to_quota_freebusy -> quota_cars -> freebusy_cars_vole; 690 freebusy_cars_vole -> schedule_across_quota; 691 692 cancel -> remove_from_quota_freebusy -> freebusy_cars_vole; 693 } 694 }}} 695 696 }}}} 697 698 ==== Delegating Attendance ==== 699 700 A number of resources may be regarded as interchangeable and can therefore 701 stand in for each other when they are unavailable. The iCalendar specification 702 supports the notion of delegation: the recipient of an event invitation may 703 delegate their attendance to other calendar user, informing that user and the 704 event organiser of this decision. 705 706 To define such delegation relationships, a quota is first selected as the 707 repository of common scheduling information for a group of resources. Then, 708 the members of the group are defined as delegates. This can be done using a 709 tool provided for this purpose. For example: 710 711 {{{ 712 cat <<EOF | tools/set_delegates.py 'cars' 713 mailto:resource-car-cadillac@example.com 714 mailto:resource-car-pontiac@example.com 715 EOF 716 }}} 717 718 Here, two resources are defined that will delegate to each other if they 719 cannot attend an event according to their own schedule. 720 721 {{{{#!table 722 '''Scheduling Functions''' || '''Decision Process''' 723 == 724 <style="vertical-align: top;"> 725 726 {{{ 727 schedule_for_delegate cars 728 }}} 729 730 || 731 732 {{{#!graphviz 733 //format=svg 734 //transform=notugly 735 digraph scheduling_decisions { 736 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 737 edge [tooltip="Scheduling decisions"]; 738 739 subgraph { 740 rank=same; 741 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 742 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 743 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 744 } 745 746 subgraph { 747 rank=same; 748 schedule_for_delegate [label="Can be scheduled or delegated?",shape=ellipse,style=filled,fillcolor=gold]; 749 quota_cars [label="Quota for cars",shape=folder]; 750 freebusy_cars_vole [label="...recording schedule for\nvincent.vole@example.com",shape=folder]; 751 } 752 753 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 754 755 subgraph { 756 rank=same; 757 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 758 delegate [label="Delegate",shape=folder,style=filled,fillcolor=cyan]; 759 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 760 } 761 762 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 763 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 764 765 mail_cadillac -> schedule_for_delegate; 766 mail_pontiac -> schedule_for_delegate -> schedule -> accept; 767 schedule_for_delegate -> delegate [style=dashed]; 768 schedule_for_delegate -> decline [style=dashed]; 769 schedule -> add_to_quota -> quota_cars -> freebusy_cars_vole; 770 freebusy_cars_vole -> schedule_for_delegate; 771 772 cancel -> remove_from_quota -> freebusy_cars_vole; 773 } 774 }}} 775 776 }}}} 777 778 Note that it is generally more useful to have delegation decisions made on the 779 basis of many resources, which is what the journal entries for each quota 780 provides, but also for many organisers attempting to reserve those resources. 781 Although the journal for each quota may be divided up to administer quotas for 782 multiple groups of organisers, for the purposes of delegation - deciding 783 whether a resource is generally available, and deciding which other resource 784 would be available instead - a single group of all organisers is more desirable.