--- /dev/null
+# Any configuration directives you include here will override
+# RT's default configuration file, RT_Config.pm
+
+#Site Configurations
+
+#Name of the site
+Set($rtname, 'PLC_NAME');
+
+#Site's Organization
+Set($Organization , 'PLC_RT_HOSTNAME');
+
+#Main email address for contacting the Support Team
+Set($CorrespondAddress , 'support@PLC_RT_HOSTNAME');
+
+#Default destination email address for replies
+Set($CommentAddress , 'root@PLC_RT_HOSTNAME');
+
+#System administrator mail address
+Set($OwnerEmail , 'root@PLC_RT_HOSTNAME');
+
+#Maximum attachment size
+Set($MaxAttachmentSize , 10000000);
+
+#Database configurations
+
+#Type of database: Postgresql
+Set($DatabaseType , 'Pg'); # e.g. Pg or mysql
+
+#The name of the database user (inside the database)
+Set($DatabaseUser , 'RT_DB_USER');
+
+#Password the DatabaseUser should use to access the database
+Set($DatabasePassword , 'RT_DB_PASSWORD');
+
+#The name of the RT's database on your database server
+Set($DatabaseName , 'RT_DB_NAME');
+
+#Database host
+Set($DatabaseHost , 'localhost');
+
+#RT's Database host
+Set($DatabaseRTHost , 'localhost');
+
+#Webserver paramters
+
+#Web path, such as https://rt.domain/web_path
+Set($WebPath , "/rt3"); # e.g. Set($WebPath , "");
+
+#URL
+Set($WebBaseURL , "https://PLC_RT_HOSTNAME"); # Set($WebBaseURL , "http://rt.PLC_RT_HOSTNAME");
+
+#Adding plugins
+#Set(@Plugins,qw(RT::FM));
+
+#Tuning Up the RT Config
+
+#Log File
+Set($LogToFile , 'debug');
+Set($LogDir, '/var/log/rt3/');
+#rt_debug.log should be created and set to the correct owner(apache ownerand group)/permissions (-rw-r--r--)Set($LogToFileNamed , "rt_debug.log");
+
+#Notify requestor: True (1)
+Set($NotifyActor, 1);
+
+#Send a copy to RT owner: True
+Set($LoopsToRTOwner , 1);
+
+# Try to figure out CC watchers
+Set($ParseNewMessageForTicketCcs , 1);
+
+# pattern to self-identify to avoid loops to itself.
+Set($RTAddressRegexp , '^(support|monitor|legal|security)@PLC_RT_HOSTNAME$');
+
+Set($WebImagesURL , $WebPath . "/NoAuth/images/"); # need this for below
+Set($LogoURL, "/misc/logo.gif");
+Set($LogoLinkURL, 'http://PLC_WWW_HOSTNAME');
+Set($LogoImageURL, "http://PLC_RT_HOSTNAME/misc/logo.gif");
+Set($LogoAltText, "PLC_NAME");
+
+1;
--- /dev/null
+#!/usr/bin/perl -w
+#
+# rtadduser: Batch add local users to RT based on a csv file named users_data.csv located # in the same directory
+# Mohamed El Erian <mohamed.elerian@britishcouncil.org.eg,melerian@gmail.com>
+# Partly based on script provided by David Maze <dmaze@cag.lcs.mit.edu>
+# File format is username,realname,email_address,organization,address1,city,country
+# $Id$
+#
+
+use lib "/usr/lib";
+use strict;
+use English;
+use RT::Interface::CLI qw(CleanEnv);
+use RT::User;
+
+CleanEnv();
+RT::LoadConfig();
+RT::Init();
+my @raw_data;
+my $bc_user = '';
+my $username = '';
+my $realname = '';
+my $email_address = '';
+my $organization = '';
+my $address1 = '';
+my $city = '';
+my $country = '';
+my $priv = 0;
+
+if ( $ARGV[0] =~ /priv/ )
+{
+ shift @ARGV;
+ $priv = 1;
+}
+
+open(USERS_DATA, $ARGV[0]) || die("Could not open file!");
+@raw_data=<USERS_DATA>;
+close(USERS_DATA);
+foreach $bc_user (@raw_data)
+{
+ chop($bc_user);
+ ($email_address,$realname,$organization)=split(/\,/,$bc_user);
+
+ my $UserObj = new RT::User(RT::SystemUser);
+ # print "adding user: $email_address\n";
+ $UserObj->Create(Name => $email_address,
+ RealName => $realname,
+ EmailAddress => $email_address,
+ Password => 'tpdemo2009',
+ Organization => $organization,
+ Privileged => $priv);
+ #Address1 => $address1,
+ #City => $city,
+ #Country => country,
+}
+
+
--- /dev/null
+
+@ACL = (
+ { GroupDomain => 'SystemInternal',
+ GroupType => 'Everyone',
+ Right => 'CreateTicket', },
+
+ { GroupDomain => 'SystemInternal',
+ GroupType => 'Everyone',
+ Right => 'ReplyToTicket', },
+
+ { GroupDomain => 'RT::System-Role',
+ GroupType => 'AdminCc',
+ Right => 'WatchAsAdminCc', },
+
+ { GroupDomain => 'RT::System-Role',
+ GroupType => 'Cc',
+ Right => 'ReplyToTicket', },
+
+ { GroupDomain => 'RT::System-Role',
+ GroupType => 'Cc',
+ Right => 'Watch', },
+
+ { GroupDomain => 'RT::System-Role',
+ GroupType => 'Owner',
+ Right => 'ReplyToTicket', },
+
+ { GroupDomain => 'RT::System-Role',
+ GroupType => 'Owner',
+ Right => 'ModifyTicket', },
+);
+
+@Scrips = (
+ { ScripCondition => 'On Create',
+ ScripAction => 'AutoReply To Requestors',
+ Template => 'AutoReply' },
+ { ScripCondition => 'On Correspond',
+ ScripAction => 'Notify Requestors, Ccs and AdminCcs',
+ Template => 'PlanetLab Correspond with CC in body', },
+ { ScripCondition => 'On Create',
+ ScripAction => 'Notify AdminCcs',
+ Template => 'PlanetLab Create with CC in body', },
+);
+
+@Templates = (
+ { Queue => '0',
+ Name => 'Autoreply', # loc
+ Description => 'Default Autoresponse template', # loc
+ Content => 'Subject: AutoReply: {$Ticket->Subject}
+
+Hello,
+
+Thank you very much for reporting this.
+
+This message was automatically generated in response to the
+creation of a trouble ticket regarding:
+
+ "{$Ticket->Subject()}"
+
+There is no need to reply to this message right now. Your ticket has been
+assigned an ID of [{$rtname} #{$Ticket->id()}].
+
+Please include the string:
+
+ [{$rtname} #{$Ticket->id}]
+
+in the subject line of all future correspondence about this issue. To do so,
+you may reply to this message.
+
+Thank you,
+{$Ticket->QueueObj->CorrespondAddress()}
+
+-------------------------------------------------------------------------
+{$Transaction->Content()}
+'
+ },
+ {
+ Queue => '0',
+ Name => 'PlanetLab Correspond with CC in body',
+ Description => 'Message with the recipients in the header', # loc
+ Content => 'RT-Attach-Message: yes
+
+Email Recipients (see http://PLC_RT_HOSTNAME/support )
+ Owner: {$Ticket->OwnerObj->Name}
+ Requestor: {$Ticket->RequestorAddresses}
+{ if ($acc=$Ticket->AdminCcAddresses) { " Ticket Ccs: " . $acc } }
+
+==================================================
+
+{$Transaction->Content()}
+'
+ },
+ {
+ Queue => '0',
+ Name => 'PlanetLab Create with CC in body',
+ Description => 'Create with CC in body', # loc
+ Content => 'RT-Attach-Message: yes
+
+Email Recipients (see http://PLC_RT_HOSTNAME/support )
+ Owner: {$Ticket->OwnerObj->Name}
+ Requestor: {$Ticket->RequestorAddresses}
+{ if ($acc=$Ticket->AdminCcAddresses) { " Ticket Ccs: " . $acc } }
+
+==================================================
+
+{$Transaction->CreatedAsString}: Request {$Ticket->id} was acted upon.
+Transaction: {$Transaction->Description}
+
+Subject: {$Transaction->Subject || $Ticket->Subject || "(No subject given)"}
+
+{$Transaction->Content()}
+'
+ },
+);
+
+@Queues = (
+ { Name => 'monitor',
+ Description => 'Queue for monitor',
+ CorrespondAddress => 'monitor@PLC_RT_HOSTNAME',
+ CommentAddress => '', },
+
+ { Name => 'security',
+ Description => 'Queue for security issues',
+ CorrespondAddress => 'security@PLC_RT_HOSTNAME',
+ CommentAddress => '', },
+
+ { Name => 'legal',
+ Description => 'Queue for legal issues',
+ CorrespondAddress => 'legal@PLC_RT_HOSTNAME',
+ CommentAddress => '', },
+)
--- /dev/null
+#!/bin/bash
+
+MDIR=/usr/share/monitor
+source $MDIR/monitorconfig.sh
+${MONITOR_SCRIPT_ROOT}/plcquery.py --type person --withsitename --byrole admin \
+ --format="%(email)s,%(first_name)s %(last_name)s,%(name)s" \
+ | ${MONITOR_SCRIPT_ROOT}/rt3/adduserstort.pl priv -
--- /dev/null
+# Initial data for a fresh RT3 Installation.
+
+@Users = (
+ { Name => 'Nobody',
+ RealName => 'Nobody in particular',
+ Comments => 'Do not delete or modify this user. It is integral '
+ . 'to RT\'s internal data structures',
+ Privileged => '0', },
+
+ { Name => 'root',
+ Gecos => 'root',
+ RealName => 'RT Admin',
+ Password => 'password',
+ EmailAddress => "root\@localhost",
+ Comments => 'SuperUser',
+ Privileged => '1', } );
+
+@Groups = (
+ { Name => '',
+ Type => 'Everyone', # loc
+ Domain => 'SystemInternal',
+ Instance => '',
+ Description => 'Pseudogroup for internal use', # loc
+ },
+ { Type => 'Privileged', # loc
+ Domain => 'SystemInternal',
+ Instance => '',
+ Name => '',
+ Description => 'Pseudogroup for internal use', # loc
+ },
+ { Name => '',
+ Type => 'Unprivileged', # loc
+ Domain => 'SystemInternal',
+ Instance => '',
+ Description => 'Pseudogroup for internal use', # loc
+ },
+ { Name => '',
+ Type => 'Owner', # loc
+ Domain => 'RT::System-Role',
+ Instance => '',
+ Description => 'SystemRolegroup for internal use', # loc
+ },
+ { Name => '',
+ Type => 'Requestor', # loc
+ Domain => 'RT::System-Role',
+ Instance => '',
+ Description => 'SystemRolegroup for internal use', # loc
+ },
+ { Name => '',
+ Type => 'Cc', # loc
+ Domain => 'RT::System-Role',
+ Instance => '',
+ Description => 'SystemRolegroup for internal use', # loc
+ },
+ { Name => '',
+ Type => 'AdminCc', # loc
+ Domain => 'RT::System-Role',
+ Instance => '',
+ Description => 'Pseudogroup for internal use', # loc
+ }, );
+
+@Queues = ({ Name => 'support',
+ Description => 'Support',
+ CorrespondAddress => 'support@PLC_RT_HOSTNAME',
+ CommentAddress => '', },
+
+ { Name => '___Approvals',
+ Description => 'A system-internal queue for the approvals system',
+ Disabled => 2, } );
+
+@ScripActions = (
+
+ { Name => 'Autoreply To Requestors', # loc
+ Description =>
+'Always sends a message to the requestors independent of message sender' , # loc
+ ExecModule => 'Autoreply',
+ Argument => 'Requestor' },
+ { Name => 'Notify Requestors', # loc
+ Description => 'Sends a message to the requestors', # loc
+ ExecModule => 'Notify',
+ Argument => 'Requestor' },
+ { Name => 'Notify Owner as Comment', # loc
+ Description => 'Sends mail to the owner', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'Owner' },
+ { Name => 'Notify Owner', # loc
+ Description => 'Sends mail to the owner', # loc
+ ExecModule => 'Notify',
+ Argument => 'Owner' },
+ { Name => 'Notify Ccs as Comment', # loc
+ Description => 'Sends mail to the Ccs as a comment', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'Cc' },
+ { Name => 'Notify Ccs', # loc
+ Description => 'Sends mail to the Ccs', # loc
+ ExecModule => 'Notify',
+ Argument => 'Cc' },
+ { Name => 'Notify AdminCcs as Comment', # loc
+ Description => 'Sends mail to the administrative Ccs as a comment', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'AdminCc' },
+ { Name => 'Notify AdminCcs', # loc
+ Description => 'Sends mail to the administrative Ccs', # loc
+ ExecModule => 'Notify',
+ Argument => 'AdminCc' },
+
+ { Name => 'Notify Requestors and Ccs as Comment', # loc
+ Description => 'Send mail to requestors and Ccs as a comment', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'Requestor,Cc' },
+
+ { Name => 'Notify Requestors and Ccs', # loc
+ Description => 'Send mail to requestors and Ccs', # loc
+ ExecModule => 'Notify',
+ Argument => 'Requestor,Cc' },
+
+ { Name => 'Notify Requestors, Ccs and AdminCcs as Comment', # loc
+ Description => 'Send mail to all watchers as a "comment"', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'All' },
+ { Name => 'Notify Requestors, Ccs and AdminCcs', # loc
+ Description => 'Send mail to all watchers', # loc
+ ExecModule => 'Notify',
+ Argument => 'All' },
+ { Name => 'Notify Other Recipients as Comment', # loc
+ Description => 'Sends mail to explicitly listed Ccs and Bccs', # loc
+ ExecModule => 'NotifyAsComment',
+ Argument => 'OtherRecipients' },
+ { Name => 'Notify Other Recipients', # loc
+ Description => 'Sends mail to explicitly listed Ccs and Bccs', # loc
+ ExecModule => 'Notify',
+ Argument => 'OtherRecipients' },
+ { Name => 'User Defined', # loc
+ Description => 'Perform a user-defined action', # loc
+ ExecModule => 'UserDefined', },
+ { Name => 'Create Tickets', # loc
+ Description =>
+ 'Create new tickets based on this scrip\'s template', # loc
+ ExecModule => 'CreateTickets', },
+ { Name => 'Open Tickets',
+ Description => 'Open tickets on correspondence', # loc
+ ExecModule => 'AutoOpen' },
+);
+
+@ScripConditions = (
+ { Name => 'On Create', # loc
+ Description => 'When a ticket is created', # loc
+ ApplicableTransTypes => 'Create',
+ ExecModule => 'AnyTransaction', },
+
+ { Name => 'On Transaction', # loc
+ Description => 'When anything happens', # loc
+ ApplicableTransTypes => 'Any',
+ ExecModule => 'AnyTransaction', },
+ {
+
+ Name => 'On Correspond', # loc
+ Description => 'Whenever correspondence comes in', # loc
+ ApplicableTransTypes => 'Correspond',
+ ExecModule => 'AnyTransaction', },
+
+ {
+
+ Name => 'On Comment', # loc
+ Description => 'Whenever comments come in', # loc
+ ApplicableTransTypes => 'Comment',
+ ExecModule => 'AnyTransaction' },
+ {
+
+ Name => 'On Status Change', # loc
+ Description => 'Whenever a ticket\'s status changes', # loc
+ ApplicableTransTypes => 'Status',
+ ExecModule => 'AnyTransaction',
+
+ },
+ {
+
+ Name => 'On Priority Change', # loc
+ Description => 'Whenever a ticket\'s priority changes', # loc
+ ApplicableTransTypes => 'Set',
+ ExecModule => 'PriorityChange',
+ },
+ {
+
+ Name => 'On Owner Change', # loc
+ Description => 'Whenever a ticket\'s owner changes', # loc
+ ApplicableTransTypes => 'Any',
+ ExecModule => 'OwnerChange',
+
+ },
+ {
+
+ Name => 'On Queue Change', # loc
+ Description => 'Whenever a ticket\'s queue changes', # loc
+ ApplicableTransTypes => 'Set',
+ ExecModule => 'QueueChange',
+
+ },
+ { Name => 'On Resolve', # loc
+ Description => 'Whenever a ticket is resolved', # loc
+ ApplicableTransTypes => 'Status',
+ ExecModule => 'StatusChange',
+ Argument => 'resolved'
+
+ },
+
+ { Name => 'User Defined', # loc
+ Description => 'Whenever a user-defined condition occurs', # loc
+ ApplicableTransTypes => 'Any',
+ ExecModule => 'UserDefined'
+
+ },
+
+);
+
+@Templates = (
+ { Queue => '0',
+ Name => 'Blank', # loc
+ Description => 'A blank template', # loc
+ Content => '', },
+
+ { Queue => '0',
+ Name => 'Transaction', # loc
+ Description => 'Default transaction template', # loc
+ Content => 'RT-Attach-Message: yes
+
+
+{$Transaction->CreatedAsString}: Request {$Ticket->id} was acted upon.
+Transaction: {$Transaction->Description}
+ Queue: {$Ticket->QueueObj->Name}
+ Subject: {$Transaction->Subject || $Ticket->Subject || "(No subject given)"}
+ Owner: {$Ticket->OwnerObj->Name}
+ Requestors: {$Ticket->RequestorAddresses}
+ Status: {$Ticket->Status}
+ Ticket <URL: {$RT::WebURL}Ticket/Display.html?id={$Ticket->id} >
+
+
+{$Transaction->Content()}
+'
+ },
+
+ {
+
+ Queue => '0',
+ Name => 'Admin Correspondence', # loc
+ Description => 'Default admin correspondence template', # loc
+ Content => 'RT-Attach-Message: yes
+
+
+<URL: {$RT::WebURL}Ticket/Display.html?id={$Ticket->id} >
+
+{$Transaction->Content()}
+'
+ },
+
+ { Queue => '0',
+ Name => 'Correspondence', # loc
+ Description => 'Default correspondence template', # loc
+ Content => 'RT-Attach-Message: yes
+
+{$Transaction->Content()}
+'
+ },
+
+ { Queue => '0',
+ Name => 'Admin Comment', # loc
+ Description => 'Default admin comment template', # loc
+ Content =>
+'Subject: [Comment] {my $s=($Transaction->Subject||$Ticket->Subject); $s =~ s/\\[Comment\\]//g; $comment =~ s/^Re//i; $s;}
+
+
+{$RT::WebURL}Ticket/Display.html?id={$Ticket->id}
+This is a comment. It is not sent to the Requestor(s):
+
+{$Transaction->Content()}
+'
+ },
+
+ { Queue => '0',
+ Name => 'Status Change', # loc
+ Description => 'Ticket status changed', # loc
+ Content => 'Subject: Status Changed to: {$Transaction->NewValue}
+
+
+{$RT::WebURL}Ticket/Display.html?id={$Ticket->id}
+
+{$Transaction->Content()}
+'
+ },
+
+ {
+
+ Queue => '0',
+ Name => 'Resolved', # loc
+ Description => 'Ticket Resolved', # loc
+ Content => 'Subject: Resolved: {$Ticket->Subject}
+
+According to our records, your request has been resolved. If you have any
+further questions or concerns, please respond to this message.
+'
+ },
+ { Queue => '___Approvals',
+ Name => "New Pending Approval", # loc
+ Description =>
+ "Notify Owners and AdminCcs of new items pending their approval", # loc
+ Content => 'Subject: New Pending Approval: {$Ticket->Subject}
+
+Greetings,
+
+There is a new item pending your approval: "{$Ticket->Subject()}",
+a summary of which appears below.
+
+Please visit {$RT::WebURL}Approvals/Display.html?id={$Ticket->id}
+to approve or reject this ticket, or {$RT::WebURL}Approvals/ to
+batch-process all your pending approvals.
+
+-------------------------------------------------------------------------
+{$Transaction->Content()}
+'
+ },
+ { Queue => '___Approvals',
+ Name => "Approval Passed", # loc
+ Description =>
+ "Notify Owner of their ticket has been approved by some approver", # loc
+ Content => 'Subject: Ticket Approved: {$Ticket->Subject}
+
+Greetings,
+
+Your ticket has been approved by { eval { $Approval->OwnerObj->Name } }.
+Other approvals may be pending.
+'
+ },
+ { Queue => '___Approvals',
+ Name => "All Approvals Passed", # loc
+ Description =>
+ "Notify Owner of their ticket has been approved by all approvers", # loc
+ Content => 'Subject: Ticket Approved: {$Ticket->Subject}
+
+Greetings,
+
+Your ticket has been approved. Its Owner may now start to act on it.
+'
+ },
+ { Queue => '___Approvals',
+ Name => "Approval Rejected", # loc
+ Description =>
+ "Notify Owner of their rejected ticket", # loc
+ Content => 'Subject: Ticket Rejected: {$Ticket->Subject}
+
+Greetings,
+
+Your ticket has been rejected by { eval { $Approval->OwnerObj->Name } }.
+'
+ },
+);
+# }}}
+
+@Scrips = (
+ { ScripCondition => 'On Correspond',
+ ScripAction => 'Open Tickets',
+ Template => 'Blank' },
+ { ScripCondition => 'On Owner Change',
+ ScripAction => 'Notify Owner',
+ Template => 'Transaction' },
+ { ScripCondition => 'On Correspond',
+ ScripAction => 'Notify Other Recipients',
+ Template => 'Correspondence' },
+
+ { Description => "When an approval ticket is created, notify the Owner and AdminCc of the item awaiting their approval", # loc
+ Queue => '___Approvals',
+ ScripCondition => 'User Defined',
+ CustomIsApplicableCode => q[
+ $self->TicketObj->Type eq 'approval' and
+ $self->TransactionObj->Field eq 'Status' and
+ $self->TransactionObj->NewValue eq 'open' and
+ eval { $T::Approving = ($self->TicketObj->AllDependedOnBy( Type => 'ticket' ))[0] }
+ ],
+ ScripAction => 'Notify Owner',
+ Template => 'New Pending Approval' },
+ { Description => "If an approval is rejected, reject the original and delete pending approvals", # loc
+ Queue => '___Approvals',
+ ScripCondition => 'On Status Change',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => q[
+# ------------------------------------------------------------------- #
+return(0) unless ( lc($self->TransactionObj->NewValue) eq "rejected" or
+ lc($self->TransactionObj->NewValue) eq "deleted" );
+
+my $rejected = 0;
+my $links = $self->TicketObj->DependedOnBy;
+foreach my $link (@{ $links->ItemsArrayRef }) {
+ my $obj = $link->BaseObj;
+ if ($obj->QueueObj->IsActiveStatus($obj->Status)) {
+ if ($obj->Type eq 'ticket') {
+ $obj->Comment(
+ Content => $self->loc("Your request was rejected."),
+ );
+ $obj->SetStatus(
+ Status => 'rejected',
+ Force => 1,
+ );
+
+ $T::Approval = $self->TicketObj; # so we can access it inside templates
+ $self->{TicketObj} = $obj; # we want the original id in the token line
+ $rejected = 1;
+ }
+ else {
+ $obj->SetStatus(
+ Status => 'deleted',
+ Force => 1,
+ );
+ }
+ }
+}
+
+$links = $self->TicketObj->DependsOn;
+foreach my $link (@{ $links->ItemsArrayRef }) {
+ my $obj = $link->TargetObj;
+ if ($obj->QueueObj->IsActiveStatus($obj->Status)) {
+ $obj->SetStatus(
+ Status => 'deleted',
+ Force => 1,
+ );
+ }
+}
+
+# Now magically turn myself into a Requestor Notify object...
+require RT::Action::Notify; bless($self, 'RT::Action::Notify');
+$self->{Argument} = 'Requestor'; $self->Prepare;
+
+return $rejected;
+# ------------------------------------------------------------------- #
+ ],
+ CustomCommitCode => '"never needed"',
+ Template => 'Approval Rejected', },
+ { Description => "When a ticket has been approved by any approver, add correspondence to the original ticket", # loc
+ Queue => '___Approvals',
+ ScripCondition => 'On Resolve',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => q[
+# ------------------------------------------------------------------- #
+return(0) unless ($self->TicketObj->Type eq 'approval');
+
+my $note;
+my $t = $self->TicketObj->Transactions;
+while (my $o = $t->Next) {
+ $note .= $o->Content . "\n" if $o->ContentObj
+ and $o->Content !~ /Default Approval/;
+}
+
+foreach my $obj ($self->TicketObj->AllDependedOnBy( Type => 'ticket' )) {
+ $obj->Comment(
+ Content => $self->loc( "Your request has been approved by [_1]. Other approvals may still be pending.", # loc
+ $self->TransactionObj->CreatorObj->Name,
+ ) . "\n" . $self->loc( "Approver's notes: [_1]", # loc
+ $note
+ ),
+ );
+ $T::Approval = $self->TicketObj; # so we can access it inside templates
+ $self->{TicketObj} = $obj; # we want the original id in the token line
+}
+
+# Now magically turn myself into a Requestor Notify object...
+require RT::Action::Notify; bless($self, 'RT::Action::Notify');
+$self->{Argument} = 'Requestor'; $self->Prepare;
+
+return 1;
+# ------------------------------------------------------------------- #
+ ],
+ CustomCommitCode => '"never needed"',
+ Template => 'Approval Passed' },
+ { Description => "When a ticket has been approved by all approvers, add correspondence to the original ticket", # loc
+ Queue => '___Approvals',
+ ScripCondition => 'On Resolve',
+ ScripAction => 'User Defined',
+ CustomPrepareCode => q[
+# ------------------------------------------------------------------- #
+# Find all the tickets that depend on this (that this is approving)
+
+my $Ticket = $self->TicketObj;
+my @TOP = $Ticket->AllDependedOnBy( Type => 'ticket' );
+my $links = $Ticket->DependedOnBy;
+my $passed = 0;
+
+while (my $link = $links->Next) {
+ my $obj = $link->BaseObj;
+ next if ($obj->HasUnresolvedDependencies( Type => 'approval' ));
+
+ if ($obj->Type eq 'ticket') {
+ $obj->Comment(
+ Content => $self->loc("Your request has been approved."),
+ );
+ $T::Approval = $Ticket; # so we can access it inside templates
+ $self->{TicketObj} = $obj; # we want the original id in the token line
+ $passed = 1;
+ }
+ elsif ($obj->Type eq 'approval') {
+ $obj->SetStatus( Status => 'open', Force => 1 );
+ }
+ elsif ($RT::UseCodeTickets and $obj->Type eq 'code') {
+ my $code = $obj->Transactions->First->Content;
+ my $rv;
+
+ foreach my $TOP (@TOP) {
+ local $@;
+ $rv++ if eval $code;
+ $RT::Logger->error("Cannot eval code: $@") if $@;
+ }
+
+ if ($rv or !@TOP) {
+ $obj->SetStatus( Status => 'resolved', Force => 1,);
+ }
+ else {
+ $obj->SetStatus( Status => 'rejected', Force => 1,);
+ }
+ }
+}
+
+# Now magically turn myself into a Requestor Notify object...
+require RT::Action::Notify; bless($self, 'RT::Action::Notify');
+$self->{Argument} = 'Requestor'; $self->Prepare;
+
+return 0; # ignore $passed;
+# ------------------------------------------------------------------- #
+ ],
+ CustomCommitCode => '"never needed"',
+ Template => 'All Approvals Passed', },
+
+);
+
+@ACL = (
+ { UserId => 'Nobody', # - principalId
+ Right => 'OwnTicket', },
+
+ { UserId => 'root', # - principalid
+ Right => 'SuperUser', },
+
+
+);
+
+# Predefined searches
+
+@Attributes = (
+ { Name => 'Search - My Tickets',
+ Description => '[_1] highest priority tickets I own', # loc
+ Content =>
+ { Format => "'<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__id__</a>/TITLE:#', '<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__Subject__</a>/TITLE:Subject', Priority, QueueName, ExtendedStatus",
+ Query => " Owner = '__CurrentUser__' AND ( Status = 'new' OR Status = 'open')",
+ OrderBy => 'Priority',
+ Order => 'DESC' },
+ },
+ { Name => 'Search - Unowned Tickets',
+ Description => '[_1] newest unowned tickets', # loc
+ Content =>
+# 'Take' #loc
+ { Format => "'<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__id__</a>/TITLE:#', '<a href=\"__WebPath__/Ticket/Display.html?id=__id__\">__Subject__</a>/TITLE:Subject', QueueName, ExtendedStatus, CreatedRelative, '<A HREF=\"__WebPath__/Ticket/Display.html?Action=Take&id=__id__\">__loc(Take)__</a>/TITLE: ' ",
+ Query => " Owner = 'Nobody' AND ( Status = 'new' OR Status = 'open')",
+ OrderBy => 'Created',
+ Order => 'DESC' },
+ },
+ { Name => 'HomepageSettings',
+ Description => 'HomepageSettings',
+ Content =>
+ { 'body' => # loc
+ [ { type => 'system', name => 'My Tickets' },
+ { type => 'system', name => 'Unowned Tickets' },
+ { type => 'component', name => 'QuickCreate'},
+ ],
+ 'summary' => # loc
+ [
+ { type => 'component', name => 'MyReminders' },
+ { type => 'component', name => 'Quicksearch' },
+ { type => 'component', name => 'RefreshHomepage' },
+ ]
+ },
+}
+);
--- /dev/null
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# <jesse@bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/copyleft/gpl.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+ <div id="logo">
+ <a href="<%$RT::LogoLinkURL%>"><img src="<%$RT::LogoImageURL%>" alt="<% loc($RT::LogoAltText) %>" /></a>
+% if ($show_name) {
+ <div class="rtname"><% loc("RT for [_1]", $RT::rtname) %></div>
+% }
+ </div>
+<%args>
+ $show_name => 1
+</%args>
--- /dev/null
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC
+%# <jesse@bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/copyleft/gpl.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+ <table width="100%" class="ticket-summary">
+ <tr>
+ <td valign="top" width="50%" class="boxcontainer">
+ <&| /Widgets/TitleBox, title => loc('The Basics'),
+ title_href =>"$RT::WebPath/Ticket/Modify.html?id=".$Ticket->Id,
+ class => 'ticket-info-basics' &>
+ <& /Ticket/Elements/ShowBasics, Ticket => $Ticket &>
+ </&>
+
+% if ($Ticket->QueueObj->TicketCustomFields->First) {
+ <&| /Widgets/TitleBox, title => loc('Custom Fields'),
+ title_href =>"$RT::WebPath/Ticket/Modify.html?id=".$Ticket->Id,
+ class => 'ticket-info-cfs' &>
+ <& /Ticket/Elements/ShowCustomFields, Ticket => $Ticket &>
+ </&>
+% }
+ <&| /Widgets/TitleBox, title => loc('People'),
+ title_href =>"$RT::WebPath/Ticket/ModifyPeople.html?id=".$Ticket->Id,
+ class => 'ticket-info-people' &>
+ <& /Ticket/Elements/ShowPeople, Ticket => $Ticket &>
+ </&>
+
+ <& /Ticket/Elements/ShowAttachments, Ticket => $Ticket, Attachments => $Attachments &>
+ <br />
+ <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &>
+
+ <& /Elements/Callback, %ARGS, _CallbackName => 'LeftColumn' &>
+ </td>
+ <td valign="top" width="50%" class="boxcontainer">
+ <&| /Widgets/TitleBox, title => loc("Dates"),
+ title_href =>"$RT::WebPath/Ticket/ModifyDates.html?id=".$Ticket->Id,
+ class => 'ticket-info-dates' &>
+ <& /Ticket/Elements/ShowDates, Ticket => $Ticket &>
+ </&>
+
+ <&| /Widgets/TitleBox, title => loc('Links'),
+ title_href => "$RT::WebPath/Ticket/ModifyLinks.html?id=".$Ticket->Id,
+ class => 'ticket-info-links' &>
+ <& /Elements/ShowLinks, Ticket => $Ticket &>
+ </&>
+ <& /Elements/Callback, %ARGS, _CallbackName => 'RightColumn' &>
+
+ </td>
+ </tr>
+ </table>
+<%ARGS>
+$Ticket => undef
+$Attachments => undef
+</%ARGS>
+
+
+
+
--- /dev/null
+#!/bin/bash
+#
+# priority: 850
+#
+# Manage settings for the RT installtion
+#
+# Stephen Soltesz <soltesz@cs.princeton.edu>
+# Copyright (C) 2008 The Trustees of Princeton University
+#
+# $Id$
+#
+
+# Source function library and configuration
+. /etc/plc.d/functions
+. /etc/planetlab/plc_config
+local_config=/etc/planetlab/configs/site.xml
+
+PLCRTPATH=/usr/share/plcrt
+
+# Be verbose
+set -x
+
+# Default locations
+PGDATA=/var/lib/pgsql/data
+postgresql_conf=$PGDATA/postgresql.conf
+pghba_conf=$PGDATA/pg_hba.conf
+
+# Export so that we do not have to specify -p to psql invocations
+export PGPORT=$PLC_DB_PORT
+
+
+RT3_DB_USER="rt3user"
+RT3_DB_NAME="rt3"
+
+WROTE_PG_CONFIG=
+
+if [ -z "$PLC_RT_IP" ] ; then
+ PLC_RT_IP=$( gethostbyname $PLC_RT_HOST )
+fi
+
+# NOTE: code duplicated from monitor.functions to allow package to be separate
+# from it.
+function check_pg_hba ()
+{
+ NAME=$1
+ USER=$2
+ #### SETUP ACCESS to this user and database
+ mkdir -p $PGDATA/pg_hba.conf.d
+ CONF=$PGDATA/pg_hba.conf.d/${NAME}.conf
+ if [ ! -f $CONF ] ; then
+ echo "host $NAME $USER 127.0.0.1/32 password" > $CONF
+ echo "host $NAME $USER $PLC_MONITOR_IP/32 password" >> $CONF
+
+ WROTE_PG_CONFIG="true"
+ fi
+}
+
+# TODO: make values re-configurable... this may be an issue with RT's db, though.
+function update_config ()
+{
+ pattern=$1
+ with=$2
+ file=$3
+ sed -i -e "s/$pattern/$with/g" $file
+}
+
+function check_rt_siteconfig ()
+{
+ tmp_siteconfig=$(mktemp)
+ tmp_initialdata=$(mktemp)
+
+ # TODO: need a better approach for this.
+ for f in $PLCRTPATH/conf.d/*.pl ; do
+ update_config PLC_RT_HOSTNAME $PLC_RT_HOST $f
+ done
+
+ # if the templates are newer than the actual config, then replace them.
+ if [ $PLCRTPATH/RT_SiteConfig.pm -nt /etc/rt3/RT_SiteConfig.pm ] ;
+ then
+ # copy templates
+ cp -f $PLCRTPATH/RT_SiteConfig.pm $tmp_siteconfig
+ cp -f $PLCRTPATH/initialdata $tmp_initialdata
+
+ # setup RT_SiteConfig.pm
+ update_config PLC_NAME "$PLC_NAME" $tmp_siteconfig
+ update_config PLC_RT_HOSTNAME $PLC_RT_HOST $tmp_siteconfig
+ update_config PLC_WWW_HOSTNAME $PLC_WWW_HOST $tmp_siteconfig
+
+ update_config RT_DB_NAME $RT3_DB_NAME $tmp_siteconfig
+ update_config RT_DB_USER $RT3_DB_USER $tmp_siteconfig
+ update_config RT_DB_PASSWORD $PLC_MONITOR_DBPASSWORD $tmp_siteconfig
+
+ # setup initialdata
+ update_config PLC_RT_HOSTNAME $PLC_RT_HOST $tmp_initialdata
+
+ # copy to live configuration
+ cp -f $tmp_siteconfig /etc/rt3/RT_SiteConfig.pm
+ cp -f $tmp_initialdata /etc/rt3/initialdata
+ chmod 644 /etc/rt3/RT_SiteConfig.pm
+ chmod 644 /etc/rt3/initialdata
+
+ rm -f $tmp_siteconfig
+ rm -f $tmp_initialdata
+ fi
+}
+
+function check_rt_custom ()
+{
+ rsync -qv -az $PLCRTPATH/local/html /usr/share/rt3
+}
+
+function check_rt_pghba ()
+{
+ NAME=$RT3_DB_NAME
+ USER=$RT3_DB_USER
+ CONF=$PGDATA/pg_hba.conf.d/${NAME}.conf
+ PATTERN="host all postgres 127.0.0.1/32 trust"
+
+ if ! grep -q "$PATTERN" $CONF ; then
+ #### SETUP ACCESS from postgres user to run init for the first time.
+ echo "$PATTERN" >> $CONF
+ WROTE_PG_CONFIG="true"
+ fi
+
+}
+
+function check_rt_aliases ()
+{
+
+ if ! grep -q "rt-mailgate --queue support" /etc/aliases ;
+ then
+ sed -i -e "s/^support.*postmaster//g" /etc/aliases
+ sed -i -e "s/^security.*root//g" /etc/aliases
+ cat <<EOF >> /etc/aliases
+# added by RT init scripts for default queues.
+support: "|/usr/sbin/rt-mailgate --queue support --action correspond --url http://localhost/rt3/"
+monitor: "|/usr/sbin/rt-mailgate --queue monitor --action correspond --url http://localhost/rt3/"
+security: "|/usr/sbin/rt-mailgate --queue security --action correspond --url http://localhost/rt3/"
+legal: "|/usr/sbin/rt-mailgate --queue legal --action correspond --url http://localhost/rt3/"
+EOF
+ /usr/bin/newaliases
+ fi
+
+}
+
+function check_rt_init ()
+{
+ if [ ! -f /etc/rt3/setup.finished ] ; then
+ /usr/sbin/rt-setup-database --action init --dba postgres
+ for f in $PLCRTPATH/conf.d/*.pl ; do
+ /usr/sbin/rt-setup-database --action insert --dba postgres --datafile $f
+ done
+
+ # run initial setup scripts (run only once, or for the first time)
+ if [ -d $PLCRTPATH/setup.d ] ; then
+ for f in $PLCRTPATH/setup.d/*.{pl,py,sh} ; do
+ $f
+ done
+ fi
+
+ touch /etc/rt3/setup.finished
+
+ fi
+}
+
+check_rt_sendmail ()
+{
+ tmp_sendmailmc=$(mktemp)
+
+ # if the templates is newer than the processed config, then update it
+ if grep -q "Addr=127.0.0.1," /etc/mail/sendmail.mc ;
+ then
+ # copy templates
+ cp -f /etc/mail/sendmail.mc $tmp_sendmailmc
+
+ # setup initialdata
+ update_config "Addr=127.0.0.1," "" $tmp_sendmailmc
+
+ # copy to live configuration
+ cp -f $tmp_sendmailmc /etc/mail/sendmail.mc
+ rm -f $tmp_sendmailmc
+
+ # edit /etc/mail/access to add local IP
+ if ! grep "$PLC_RT_IP" /etc/mail/access ; then
+ echo "$PLC_RT_IP RELAY" >> /etc/mail/access
+ makemap hash /etc/mail/access.db < /etc/mail/access
+ fi
+ if [ ! -f /etc/smrsh/rt-mailgate ] ; then
+ ln -s /usr/sbin/rt-mailgate /etc/smrsh/rt-mailgate
+ fi
+ if ! grep "$PLC_RT_HOST" /etc/mail/local-host-names ; then
+ # edit /etc/mail/local-host-names
+ echo "$PLC_RT_HOST" >> /etc/mail/local-host-names
+ fi
+ m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
+ service sendmail restart
+ fi
+
+
+}
+
+if [ "$PLC_RT_ENABLED" != "1" ] ; then
+ exit 0
+fi
+
+case "$1" in
+ start)
+ MESSAGE=$"Bootstrap RT (please wait...)"
+ dialog "$MESSAGE"
+
+ check_pg_hba $RT3_DB_NAME $RT3_DB_USER
+ #check_user_and_db $RT3_DB_NAME $RT3_DB_USER
+ check_rt_siteconfig
+ check_rt_pghba
+ if [ -n "$WROTE_PG_CONFIG" ] ; then
+ # NOTE: restart db to enable access by users granted above.
+ service plc restart postgresql
+ MESSAGE=$"Bootstrap RT 2 (please wait...)"
+ dialog "$MESSAGE"
+ fi
+ check_rt_aliases
+ check_rt_init
+ check_rt_sendmail
+ check_rt_custom # todo: restart httpd if needed.
+
+ result "$MESSAGE"
+ ;;
+
+
+ delete)
+ MESSAGE=$"Deleting databases..."
+ dialog "$MESSAGE"
+
+ service plc stop httpd
+
+ dropdb -U postgres $RT3_DB_NAME
+ dropuser -U postgres $RT3_DB_USER
+ rm -f /etc/rt3/RT_SiteConfig.pm
+ rm -f /etc/rt3/initialdata
+ PATTERN="host all postgres 127.0.0.1/32 trust"
+ sed -i -e "s|$PATTERN||g" $PGDATA/pg_hba.conf.d/${RT3_DB_NAME}.conf
+
+ sed -i -e "s/.*mailgate.*//g" /etc/aliases
+ rm -f /etc/rt3/setup.finished
+
+ sed -i -e "s/Port=smtp, Name=MTA/Port=smtp,Addr=127.0.0.1, Name=MTA/g" /etc/mail/sendmail.mc
+ service plc start httpd
+
+ result "$MESSAGE"
+ ;;
+
+ stop)
+ MESSAGE=$"Stopping RT"
+ dialog "$MESSAGE"
+
+ # TODO: is there anything to stop?
+
+ result "$MESSAGE"
+ ;;
+esac
+
+exit $ERRORS
--- /dev/null
+#
+# $Id$
+#
+
+%define url $URL: svn+ssh://svn.planet-lab.org/svn/PLCRT/trunk/plcrt.spec $
+
+%define name plcrt
+%define version 1.0
+%define taglevel 1
+
+%define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+
+Name: %{name}
+Version: %{version}
+Release: %{release}
+License: GPL
+Group: Applications/System
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+
+Vendor: PlanetLab
+Packager: PlanetLab Central <support@planet-lab.org>
+Distribution: PlanetLab %{plrelease}
+URL: %(echo %{url} | cut -d ' ' -f 2)
+
+Summary: PLCRT account initialization for the root image.
+Group: Applications/System
+
+%description
+PLCRT is a collection of configuration scripts for configuring RT.
+By default RT does not come with all the settings needed for a standard PLC,
+or PlanetLab in particular.
+
+%package
+Summary: PLCRT Setup scripts for RT3
+Group: Applications/System
+
+Requires: python
+Requires: perl
+Requires: rt3
+Requires: myplc
+
+
+%prep
+%setup -q
+
+%install
+
+install -d $RPM_BUILD_ROOT/%{_datadir}/%{name}
+install -D -m 755 plcrt.init $RPM_BUILD_ROOT/%{_sysconfdir}/plc.d/plcrt
+
+echo " * Installing core scripts"
+rsync -a ./ $RPM_BUILD_ROOT/%{_datadir}/%{name}/
+
+echo " * Installing cron scripts"
+install -D -m 644 rt.cron $RPM_BUILD_ROOT/%{_sysconfdir}/cron.d/rt.cron
+
+chmod 755 $RPM_BUILD_ROOT/%{_datadir}/%{name}/adduserstort.pl
+chmod 755 $RPM_BUILD_ROOT/%{_datadir}/%{name}/rtcron.d/*.sh
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%config /etc/rt3/RT_SiteConfig.pm
+#%config /etc/plcrt.conf
+%{_datadir}/%{name}
+%{_sysconfdir}/plc.d/plcrt
+%{_sysconfdir}/cron.d/rt.cron
+
+%post
+if grep 'pam_loginuid.so' /etc/pam.d/crond ; then
+ sed -i -e 's/^session required pam_loginuid.so/#session required pam_loginuid.so/g' /etc/pam.d/crond
+fi
+
+if ! grep '<category id="plc_rt">' /etc/planetlab/default_config.xml ; then
+ sed -i 's|<category id="plc_net">| <category id="plc_rt">\n <name>RT Configuration</name>\n <description>RT</description>\n <variablelist>\n <variable id="enabled" type="boolean">\n <name>Enabled</name>\n <value>false</value>\n <description>Enable on this machine.</description>\n </variable>\n <variable id="host" type="hostname">\n <name>Hostname</name>\n <value>localhost.localdomain</value>\n <description>The fully qualified hostname.</description>\n </variable>\n <variable id="ip" type="ip">\n <name>IP Address</name>\n <value/>\n <description>The IP address of the RT server.</description>\n </variable>\n </variablelist>\n </category>\n <category id="plc_net">|' /etc/planetlab/default_config.xml
+fi
+
+plc-config --save /etc/planetlab/default_config.xml \
+ --category plc_rt --variable enabled --value true
+
+%changelog
+* Thu Jun 26 2009 Stephen Soltesz <soltesz@cs.princeton.edu> - PLCRT-1.0-1
+- initial addition.
--- /dev/null
+SHELL=/bin/bash
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/share/plcrt
+HOME=/usr/share/plcrt
+
+01 * * * * root rtcron.sh
+
--- /dev/null
+#!/bin/bash
+
+D=/usr/share/plcrt/
+for f in $D/cron.d/*.sh ; do
+ bash -c "$f"
+done