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 set_quota_limit.py 'mailto:resource-car-cadillac@example.com' \ 387 'mailto:vincent.vole@example.com' PT10H 388 }}} 389 390 This indicates that the given user may only reserve 10 hours of events or less 391 within the given quota (corresponding to a specific resource in the above 392 example). Attempts to schedule more time will be declined. 393 394 To impose a general quota, the special `*` identity can be used: 395 396 {{{ 397 set_quota_limit.py 'mailto:resource-car-cadillac@example.com' \ 398 '*' PT10H 399 }}} 400 401 When a user identity is not listed and no general quota is defined, that 402 particular user will be unable to reserve the resource unless defined as a 403 member of a group listed in the `limits` file, as described below. 404 405 ==== Sharing Quotas Across Users ==== 406 407 When the use of resources is to be shared between users in such a way that 408 groups of users will be sharing a single quota, the `groups` file in the 409 quota directory must be defined, mapping each user identity to the group to 410 which they will belong. For example: 411 412 {{{{#!table 413 '''Scheduling Data''' || '''Decision Process''' 414 == 415 <style="vertical-align: top;"> 416 The groups are defined as follows in the `groups` file: 417 418 {{{ 419 mailto:vincent.vole@example.com developers 420 mailto:harvey.horse@example.com developers 421 mailto:paul.boddie@example.com developers 422 mailto:simon.skunk@example.com testers 423 }}} 424 425 The group identity can then be employed in the `limits` file: 426 427 {{{ 428 developers PT10H 429 testers PT20H 430 }}} 431 432 || 433 434 {{{#!graphviz 435 //format=svg 436 //transform=notugly 437 digraph quota_users { 438 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Quota users"]; 439 edge [tooltip="Quota users"]; 440 441 subgraph { 442 rank=same; 443 user1 [label="User is vincent.vole@example.com"]; 444 user2 [label="User is oliver.otter@example.com"]; 445 } 446 447 havegroup [label="Have group for quota?",shape=ellipse,style=filled,fillcolor=gold]; 448 haveuser [label="Have group for user in quota?",shape=ellipse,style=filled,fillcolor=gold]; 449 450 group1 [label="User is vincent.vole@example.com\nGroup is developers"]; 451 group2 [label="User is oliver.otter@example.com"]; 452 453 checkuser1 [label="Have limit for group?",shape=ellipse,style=filled,fillcolor=gold]; 454 checkgeneral1 [label="Have general limit?",shape=ellipse,style=filled,fillcolor=gold]; 455 456 checkuser2 [label="Have limit for user?",shape=ellipse,style=filled,fillcolor=gold]; 457 checkgeneral2 [label="Have general limit?",shape=ellipse,style=filled,fillcolor=gold]; 458 459 accept [label="Quota",shape=folder,style=filled,fillcolor=cyan]; 460 decline [label="No quota",shape=folder,style=filled,fillcolor=cyan]; 461 462 user1 -> havegroup -> haveuser -> group1 -> checkuser1 -> checkgeneral1 -> accept; 463 user2 -> havegroup -> haveuser -> group2 -> checkuser2 -> checkgeneral2 -> decline [style=dashed]; 464 } 465 }}} 466 }}}} 467 468 Where individuals are not assigned to groups, any individual limit will apply 469 to them; otherwise, the general quota applies. Where individuals are assigned 470 to groups, any group limit will apply; otherwise, the general quota applies. 471 472 ==== Individual Resource Quotas ==== 473 474 The trivial case of applying quotas is to give a resource its own quota. This 475 is achieved by not specifying any arguments to the `check_quota` scheduling 476 function or to the `add_to_quota` and `remove_from_quota` functions. 477 478 {{{{#!table 479 '''Scheduling Functions''' || '''Decision Process''' 480 == 481 <style="vertical-align: top;"> 482 483 {{{ 484 check_quota 485 }}} 486 487 || 488 489 {{{#!graphviz 490 //format=svg 491 //transform=notugly 492 digraph scheduling_decisions { 493 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 494 edge [tooltip="Scheduling decisions"]; 495 496 subgraph { 497 rank=same; 498 mail [label="Incoming mail\nfrom vincent.vole@example.com",shape=folder,style=filled,fillcolor=cyan]; 499 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 500 } 501 502 subgraph { 503 rank=same; 504 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 505 quota [label="Quota for resource",shape=folder]; 506 quota_for_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 507 } 508 509 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 510 511 subgraph { 512 rank=same; 513 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 514 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 515 } 516 517 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 518 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 519 520 mail -> check_quota -> schedule -> accept; 521 check_quota -> decline [style=dashed]; 522 schedule -> add_to_quota -> quota; 523 quota -> quota_for_vole -> check_quota; 524 525 cancel -> remove_from_quota -> quota; 526 } 527 }}} 528 529 }}}} 530 531 ==== Common Resource Quotas ==== 532 533 By indicating an argument to the different functions, a common quota can be 534 employed. In the following example, both resources would employ the given 535 function invocations to pool their knowledge about their schedules. 536 537 {{{{#!table 538 '''Scheduling Functions''' || '''Decision Process''' 539 == 540 <style="vertical-align: top;"> 541 542 {{{ 543 check_quota cars 544 }}} 545 546 || 547 548 {{{#!graphviz 549 //format=svg 550 //transform=notugly 551 digraph scheduling_decisions { 552 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 553 edge [tooltip="Scheduling decisions"]; 554 555 subgraph { 556 rank=same; 557 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 558 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 559 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 560 } 561 562 subgraph { 563 rank=same; 564 check_quota [label="Is allowed by quota?",shape=ellipse,style=filled,fillcolor=gold]; 565 quota_cars [label="Quota for cars",shape=folder]; 566 quota_cars_vole [label="...applying to\nvincent.vole@example.com",shape=folder]; 567 } 568 569 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 570 571 subgraph { 572 rank=same; 573 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 574 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 575 } 576 577 add_to_quota [label="Add to quota",shape=ellipse,style=filled,fillcolor=darkorange]; 578 remove_from_quota [label="Remove from quota",shape=ellipse,style=filled,fillcolor=darkorange]; 579 580 mail_cadillac -> check_quota; 581 mail_pontiac -> check_quota -> schedule -> accept; 582 check_quota -> decline [style=dashed]; 583 schedule -> add_to_quota -> quota_cars; 584 quota_cars -> quota_cars_vole -> check_quota; 585 586 cancel -> remove_from_quota -> quota_cars; 587 } 588 }}} 589 590 }}}} 591 592 ==== Collective Scheduling ==== 593 594 Consider two separate resources: both may be reserved at the same time by the 595 same organiser; neither resource would normally decline the reservation on the 596 basis of schedule availability, should the period concerned be free. However, 597 it may be undesirable for one organiser to occupy both resources at the same 598 time. 599 600 Consequently, a mechanism is required to pool the resource schedules in such a 601 way that any reservation performed for one resource at a given point in time 602 prohibits another reservation performed for a related resource at the same 603 point in time by the same user. 604 605 The free/busy records held for a given quota group permit such collective 606 scheduling decisions and are employed as follows: 607 608 {{{{#!table 609 '''Scheduling Functions''' || '''Decision Process''' 610 == 611 <style="vertical-align: top;"> 612 613 {{{ 614 schedule_across_quota cars 615 }}} 616 617 || 618 619 {{{#!graphviz 620 //format=svg 621 //transform=notugly 622 digraph scheduling_decisions { 623 node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Scheduling decisions"]; 624 edge [tooltip="Scheduling decisions"]; 625 626 subgraph { 627 rank=same; 628 mail_cadillac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-cadillac@example.com",shape=folder,style=filled,fillcolor=cyan]; 629 mail_pontiac [label="Incoming mail\nfrom vincent.vole@example.com\nto resource-car-pontiac@example.com",shape=folder,style=filled,fillcolor=cyan]; 630 cancel [label="Incoming cancellation",shape=folder,style=filled,fillcolor=cyan]; 631 } 632 633 subgraph { 634 rank=same; 635 schedule_across_quota [label="Can be scheduled within the quota?",shape=ellipse,style=filled,fillcolor=gold]; 636 quota_cars [label="Quota for cars",shape=folder]; 637 freebusy_cars_vole [label="...recording schedule for\nvincent.vole@example.com",shape=folder]; 638 } 639 640 schedule [label="Schedule event for resource",shape=ellipse,style=filled,fillcolor=gold]; 641 642 subgraph { 643 rank=same; 644 accept [label="Accept",shape=folder,style=filled,fillcolor=cyan]; 645 decline [label="Decline",shape=folder,style=filled,fillcolor=cyan]; 646 } 647 648 add_to_quota_freebusy [label="Add to quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 649 remove_from_quota_freebusy [label="Remove from quota free/busy",shape=ellipse,style=filled,fillcolor=darkorange]; 650 651 mail_cadillac -> schedule_across_quota; 652 mail_pontiac -> schedule_across_quota -> schedule -> accept; 653 schedule_across_quota -> decline [style=dashed]; 654 schedule -> add_to_quota_freebusy -> quota_cars -> freebusy_cars_vole; 655 freebusy_cars_vole -> schedule_across_quota; 656 657 cancel -> remove_from_quota_freebusy -> freebusy_cars_vole; 658 } 659 }}} 660 661 }}}}