From: Stephen Soltesz Date: Fri, 26 Jun 2009 21:30:15 +0000 (+0000) Subject: initial import of PLCRT; package separately from monitor-rt X-Git-Tag: PLCRT-1.0-0~4 X-Git-Url: http://git.onelab.eu/?p=plcrt.git;a=commitdiff_plain;h=27c2ea9bbeb04156550fdf5138010d625306dc87 initial import of PLCRT; package separately from monitor-rt --- 27c2ea9bbeb04156550fdf5138010d625306dc87 diff --git a/RT_SiteConfig.pm b/RT_SiteConfig.pm new file mode 100644 index 0000000..5c2f530 --- /dev/null +++ b/RT_SiteConfig.pm @@ -0,0 +1,80 @@ +# 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; diff --git a/adduserstort.pl b/adduserstort.pl new file mode 100755 index 0000000..a826499 --- /dev/null +++ b/adduserstort.pl @@ -0,0 +1,57 @@ +#!/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 +# Partly based on script provided by David Maze +# 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=; +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, +} + + diff --git a/conf.d/planetlab.pl b/conf.d/planetlab.pl new file mode 100644 index 0000000..6026845 --- /dev/null +++ b/conf.d/planetlab.pl @@ -0,0 +1,130 @@ + +@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 => '', }, +) diff --git a/cron.d/syncadmins.sh b/cron.d/syncadmins.sh new file mode 100755 index 0000000..f27243d --- /dev/null +++ b/cron.d/syncadmins.sh @@ -0,0 +1,7 @@ +#!/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 - diff --git a/initialdata b/initialdata new file mode 100644 index 0000000..d1a3255 --- /dev/null +++ b/initialdata @@ -0,0 +1,577 @@ +# 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 id} > + + +{$Transaction->Content()} +' + }, + + { + + Queue => '0', + Name => 'Admin Correspondence', # loc + Description => 'Default admin correspondence template', # loc + Content => 'RT-Attach-Message: yes + + +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 => "'__id__/TITLE:#', '__Subject__/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 => "'__id__/TITLE:#', '__Subject__/TITLE:Subject', QueueName, ExtendedStatus, CreatedRelative, '__loc(Take)__/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' }, + ] + }, +} +); diff --git a/local/html/Elements/Logo b/local/html/Elements/Logo new file mode 100644 index 0000000..5bb6c11 --- /dev/null +++ b/local/html/Elements/Logo @@ -0,0 +1,56 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +%# +%# +%# (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 }}} + +<%args> + $show_name => 1 + diff --git a/local/html/Ticket/Elements/ShowSummary b/local/html/Ticket/Elements/ShowSummary new file mode 100644 index 0000000..9847577 --- /dev/null +++ b/local/html/Ticket/Elements/ShowSummary @@ -0,0 +1,100 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC +%# +%# +%# (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 }}} + + + + + +
+ <&| /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 &> +
+ <& /Ticket/Elements/ShowRequestor, Ticket => $Ticket &> + + <& /Elements/Callback, %ARGS, _CallbackName => 'LeftColumn' &> +
+ <&| /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' &> + +
+<%ARGS> +$Ticket => undef +$Attachments => undef + + + + + diff --git a/plcrt.init b/plcrt.init new file mode 100644 index 0000000..96aa8f3 --- /dev/null +++ b/plcrt.init @@ -0,0 +1,262 @@ +#!/bin/bash +# +# priority: 850 +# +# Manage settings for the RT installtion +# +# Stephen Soltesz +# 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 <> /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 diff --git a/plcrt.spec b/plcrt.spec new file mode 100644 index 0000000..65dbbf8 --- /dev/null +++ b/plcrt.spec @@ -0,0 +1,85 @@ +# +# $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 +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 '' /etc/planetlab/default_config.xml ; then + sed -i 's|| \n RT Configuration\n RT\n \n \n Enabled\n false\n Enable on this machine.\n \n \n Hostname\n localhost.localdomain\n The fully qualified hostname.\n \n \n IP Address\n \n The IP address of the RT server.\n \n \n \n |' /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 - PLCRT-1.0-1 +- initial addition. diff --git a/rt.cron b/rt.cron new file mode 100644 index 0000000..f194581 --- /dev/null +++ b/rt.cron @@ -0,0 +1,6 @@ +SHELL=/bin/bash +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/share/plcrt +HOME=/usr/share/plcrt + +01 * * * * root rtcron.sh + diff --git a/rtcron.sh b/rtcron.sh new file mode 100755 index 0000000..6cd578f --- /dev/null +++ b/rtcron.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +D=/usr/share/plcrt/ +for f in $D/cron.d/*.sh ; do + bash -c "$f" +done