[rt-devel] RT 2.0.60 / Data migration

Jesse Vincent jesse at bestpractical.com
Mon Jan 20 15:20:24 EST 2003


RT 2.1.60 now exists. It contains a number of I18N fixes, the requisite
set of bug fixes and and a bunch of enhancements to support....data
migration from RT 2.0.  I'm attaching the prototype data migration tools
here. I'd appreciate it if folks would test out data migration, but I
strongly recommend that nobody attempt to migrate a production RT
instance with them yet.


	Caveats:

	They don't import your Templates. If you've changed them you'll
	need to migrate them by hand.

	They don't get all Scrips correct just yet.

	They're not optimized for large ticket loads.  If you attempt to
	import 20,000 tickets with these tools, you're going to be an
	unhappy camper.  Once we're reasonably confident that the tools
	are importing data correctly, they'll be refactored to handle
	large loads more gracefully.



2.0-export > dumpfile # will create a dump of your running RT2 instance

2to3 dumpfile # will turn a virgin rt3 instance into a clone of your RT2
instance.


	-j


-- 
»|« http://www.bestpractical.com/rt  -- Trouble Ticketing. Free.
-------------- next part --------------
#!/usr/bin/perl -w
# RT is (c) 1996-2001 Jesse Vincent <jesse at fsck.com>

use strict;
use Carp;
use Getopt::Long qw(:config pass_through);
use Data::Dumper;

use lib "/opt/fsck.com-rt2/lib";
use lib "/opt/fsck.com-rt2/etc";

use RT::Interface::CLI qw(CleanEnv LoadConfig DBConnect
  GetCurrentUser GetMessageContent);
use RT::Groups;
use RT::Users;
use RT::Queues;
use RT::ACL;
use RT::Tickets;

#Clean out all the nasties from the environment
CleanEnv();

#Load etc/config.pm and drop privs
LoadConfig();

#Connect to the database and get RT::SystemUser and RT::Nobody loaded
DBConnect();

package RT::Faketix;


use RT::EasySearch;
use RT::Ticket;

use vars qw( @ISA );
@ISA= qw(RT::EasySearch);


sub _Init {
    my $self = shift;
    $self->{'table'} = 'Tickets';
    $self->{'primary_key'} = 'id';
    return ( $self->SUPER::_Init(@_) );
}


sub NewItem {
    RT::Ticket->new(shift->CurrentUser);
}



package main;

my $ds;

my $blank_Group = RT::Group->new($RT::SystemUser);
$blank_Group->_Accessible( 'Foo', 'read' );
my $acc = $blank_Group->{_AccessibleCache};

my $Groups = RT::Groups->new($RT::SystemUser);
$Groups->LimitToReal();

foreach my $Group ( @{ $Groups->ItemsArrayRef } ) {

        my $group;

    foreach my $param ( sort keys %$acc, 'id' ) {
        $group->{$param} = $Group->_Value($param)
          if ( $Group->_Value($param) );
    }
    my $members = $Group->MembersObj();
    foreach my $member ( @{ $members->ItemsArrayRef } ) {
        push @{ $group->{Member} }, $member->UserObj->Id;

    }
        push @{$ds->{'Group'}},$group;
}


my $blank_User = RT::User->new($RT::SystemUser);
$blank_User->_Accessible( 'Foo', 'read' );
$acc = $blank_User->{_AccessibleCache};

my $users = RT::Users->new($RT::SystemUser);
$users->UnLimit();

foreach my $user ( @{ $users->ItemsArrayRef } ) {
        my $user_ds;
    foreach my $param ( sort keys %$acc, 'id' ) {
        $user_ds->{$param} = $user->_Value($param)
          if ( $user->_Value($param) );
    }
    push (@{$ds->{'User'}},$user_ds);
}

my $blank_Queue = RT::Queue->new($RT::SystemUser);
$blank_Queue->_Accessible( 'Foo', 'read' );
$acc = $blank_Queue->{_AccessibleCache};

my $Queues = RT::Queues->new($RT::SystemUser);
$Queues->UnLimit();

foreach my $Queue ( @{ $Queues->ItemsArrayRef } ) {
        my $queue_ds;
    foreach my $param ( sort keys %$acc, 'id' ) {
        $queue_ds->{$param} = $Queue->_Value($param)
          if ( $Queue->_Value($param) );
    }
    my $watchers = $Queue->Watchers();
    my $watchers_ds;
    foreach my $w ( @{ $watchers->ItemsArrayRef } ) {
        my $ds = { Type => $w->Type,
                   Email => $w->Email,
                   Id => $w->Id };

        push (@{$watchers_ds}, $ds);
        }
        $queue_ds->{'Watchers'} = $watchers_ds;
    


    my $blank_KeywordSelect = RT::KeywordSelect->new($RT::SystemUser);
    $blank_KeywordSelect->_Accessible( 'Foo', 'read' );
    my $ksacc = $blank_KeywordSelect->{_AccessibleCache};

    my $ks = $Queue->KeywordSelects();
    foreach my $keysel ( @{ $ks->ItemsArrayRef } ) {
        my $ks_ds;
        foreach my $param ( sort keys %$ksacc, 'id' ) {
            $ks_ds->{$param} = $keysel->_Value($param) if ( $keysel->_Value($param) );
        }
        my $descendents = $keysel->KeywordObj->Descendents;
        foreach my $desc ( keys %{$descendents} ) {
            push @{ $ks_ds->{Value} }, $descendents->{$desc};

        }
        push (@{$queue_ds->{'CustomField'}}, $ks_ds);
    }

    my $ACL = RT::ACL->new($RT::SystemUser);
    $ACL->LimitToQueue( $Queue->Id );

    foreach my $ace ( @{ $ACL->ItemsArrayRef } ) {
        my $right_ds = { PrincipalType => $ace->PrincipalType,
                         PrincipalId => $ace->PrincipalObj->Id,
                         Name => $ace->RightName };
        if ($ace->PrincipalType eq 'Group' && $ace->PrincipalObj->Pseudo) {
                $right_ds->{'Role'} =  $ace->PrincipalObj->Name;
                delete $right_ds->{'PrincipalId'};
                }
        push ( @{ $queue_ds->{'Right'}}, $right_ds);
    }
	my $scrips = RT::Scrips->new($RT::SystemUser);
	$scrips->LimitToQueue($Queue->Id);
	foreach my $scrip (@{$scrips->ItemsArrayRef}) {
                my $scrip_ds = {
                Condition => $scrip->ConditionObj->Name(),
                Template => $scrip->TemplateObj->Name(),
                Action => $scrip->ActionObj->Name(),
                };
                push (@{$queue_ds->{'Scrip'}}, $scrip_ds);
	} 
        push (@{$ds->{'Queue'}}, $queue_ds);

}
my $blank_KeywordSelect = RT::KeywordSelect->new($RT::SystemUser);
$blank_KeywordSelect->_Accessible( 'Foo', 'read' );
my $global_ksacc = $blank_KeywordSelect->{_AccessibleCache};
my $global_ks    = RT::KeywordSelects->new($RT::SystemUser);
$global_ks->LimitToQueue(0);
foreach my $keysel ( @{ $global_ks->ItemsArrayRef } ) {
    foreach my $param ( sort keys %$global_ksacc, 'id' ) {
        $ds->{Global}->{ $keysel->id }->{$param} = $keysel->_Value($param)
          if ( $keysel->_Value($param) );
    }
    my $descendents = $keysel->KeywordObj->Descendents;
    foreach my $desc ( keys %{$descendents} ) {
        push @{ $ds->{Global}->{ $keysel->id }->{Value} },
          $descendents->{$desc};

    }
}

	my $scrips = RT::Scrips->new($RT::SystemUser);
	$scrips->LimitToGlobal();
	foreach my $scrip (@{$scrips->ItemsArrayRef}) {
                my $scrip_ds = {
                Condition => $scrip->ConditionObj->Name(),
                Template => $scrip->TemplateObj->Name(),
                Action => $scrip->ActionObj->Name(),
                };
                push (@{$ds->{'Global'}->{'Scrip'}}, $scrip_ds);

	} 


my $ACL = RT::ACL->new($RT::SystemUser);
$ACL->LimitToSystem();

foreach my $ace ( @{ $ACL->ItemsArrayRef } ) {
        my $right_ds = { PrincipalType => $ace->PrincipalType,
                         PrincipalId => $ace->PrincipalObj->Id,
                         Name => $ace->RightName };
        if ($ace->PrincipalType eq 'Group' && $ace->PrincipalObj->Pseudo) {
                $right_ds->{'Role'} =  $ace->PrincipalObj->Name;
                delete $right_ds->{'PrincipalId'};
                }

        push (
            @{ $ds->{'Global'}->{'Right'}}, $right_ds);
}

my $blank_Link = RT::Link->new($RT::SystemUser);
$blank_Link->_Accessible( 'Foo', 'read' );
$acc = $blank_Link->{_AccessibleCache};
my $links = RT::Links->new($RT::SystemUser);
$links->UnLimit();
while (my $l = $links->Next) {
        my $link_ds;
            foreach my $param ( sort keys %$acc ) {
                    $link_ds->{$param} = $l->_Value($param)
                              if ( $l->_Value($param) );
                                  }
        push (@{$ds->{'Link'}}, $link_ds);
}

my $tix = RT::Faketix->new($RT::SystemUser);
$tix->Limit( FIELD => 'id', OPERATOR => "!=", VALUE => "0" );
while ( my $t = $tix->Next ) {
        my $tick_ds;
    print STDERR "Exporting ticket " . $t->Id . "\n";
    foreach my $param ( sort keys %{ $t->{_AccessibleCache} }, 'id' ) {
        $tick_ds->{$param} = $t->_Value($param)
          if ( $t->_Value($param) );
    }
    my $watchers = $t->Watchers();
    my $watchers_ds; 
    foreach my $w ( @{ $watchers->ItemsArrayRef } ) {
        my $ds = { Type => $w->Type,
                   Email => $w->Email,
                   Id => $w->Id };

        push (@{$watchers_ds}, $ds);
        }
        $tick_ds->{'Watchers'} = $watchers_ds;
    



    my $selects = $t->QueueObj->KeywordSelects();
    while ( my $ks = $selects->Next ) {
        my $keywords = $t->KeywordsObj( $ks->Id );
        while ( my $key = $keywords->Next ) {

            my $name = $key->KeywordObj->RelativePath( $ks->KeywordObj );
            push ( @{ $tick_ds->{'CustomFields'} ->{ $ks->id } }, $name
            );
        }
    }



my $blank_Transaction = RT::Transaction->new($RT::SystemUser);
$blank_Transaction->_Accessible( 'Foo', 'read' );
my $tracc = $blank_Transaction->{_AccessibleCache};
    my $tr = $t->Transactions;
    while ( my $trans = $tr->Next ) {
        my $trans_ds;
        print STDERR "  Exporting transaction " . $trans->Id . "\n";
        foreach my $tr_param ( sort keys %$tracc, 'id' ) {
            $trans_ds->{$tr_param} = $trans->_Value($tr_param)
              if ( $trans->_Value($tr_param) );
        }
        my $attachments = RT::Attachments->new($RT::SystemUser);
        $attachments->Limit(
            FIELD    => 'TransactionId',
            OPERATOR => "=",
            VALUE    => $trans->Id
        );

        while ( my $att = $attachments->Next ) {
                my $att_ds;
            print STDERR "   Exporting attachment " . $att->Id . "\n";
            foreach my $att_param ( sort keys %{ $att->{_AccessibleCache} } ) {
                $att_ds->{$att_param} = $att->_Value($att_param)
                  if ( $att->_Value($att_param) );
            }
                push (@{$trans_ds->{'Attachment'}}, $att_ds);
        }

        push (@{$tick_ds->{'Transaction'}}, $trans_ds);
    }
        push (@{$ds->{'Ticket'}}, $tick_ds);
}

print "sub Data {\n";
print scalar Dumper($ds);
print "}\n1;\n";
#print $xml->XMLout($ds);
-------------- next part --------------
#!/usr/bin/perl -w

package RT;
use strict;

use Data::Dumper;
BEGIN  {$RT::DontCacheSearchBuilderRecords = 1;}
use vars qw($dbh $debug);
$debug = 0;

my $import_users  = 1;
my $import_groups = 1;
my $import_tickets = 1;
use lib ( "/opt/rt3/lib", "" );

use Getopt::Long;

use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);
use RT::Tickets;
use RT::Template;
use RT::CustomFields;
use RT::Principals;

#*RT::Principal::HasRight = sub { 1 };;
#Clean out all the nasties from the environment
CleanEnv();

# Load the config file
RT::LoadConfig();

#Connect to the database and get RT::SystemUser and RT::Nobody loaded
RT::Init();



require shift @ARGV;
my $VAR1 = Data();

my $user_map;
my $group_map;
my $queue_map;
my $cf_map;
my @errors;

foreach my $scrip (@{$VAR1->{'Global'}->{'Scrip'}}) {
        my $so = RT::Scrip->new($RT::SystemUser);
        my $t = $scrip->{'Template'} || undef;
        my $c = $scrip->{'Condition'} || undef;
        my $a = $scrip->{'Action'} || undef;

        $t =~ s/(.)([A-Z])/$1 $2/g;
        $c =~ s/(.)([A-Z])/$1 $2/g;
        $a =~ s/(.)([A-Z])/$1 $2/g;

        $a =~ s/Admin Watchers/AdminCcs/;

        my %params = 
                (Template => $t ,
                    ScripAction =>  $a,
                    ScripCondition => $c,
                    Description => "Imported from RT 2.0");


        $so->Create(%params);

        unless ($so->Id) {
                push @errors, "Could not create scrip: ".Dumper($scrip);
        }


}


if ($import_users) {


        my $users = $VAR1->{'User'};
$RT::Handle->SimpleQuery("DELETE FROM Users where Name='root'"); 

    foreach my $user ( @{$users} ) {

        if ($user->{'Name'} eq 'Nobody') {
                $user_map->{$user->{'id'}} = $RT::Nobody->Id;
                 next; 
        }

        if ($user->{'Name'} eq 'RT_System') {
                $user_map->{$user->{'id'}} = $RT::SystemUser->Id;
                 next; 
        }



        #         import user
        my $user_obj = RT::User->new($RT::SystemUser);
        delete $user->{'Disabled'};
        my $old_id = $user->{'id'};
        delete $user->{'id'};
        $user->{'CryptedPassword'} = $user->{'Password'} unless ($user->{'Password'} =~ '^\*');
        delete $user->{'Password'};
        print "Creating $old_id - " . $user->{'Name'} . "\n";
        $user_obj->Create( %{ $user } );
        my $id = $user_obj->Id();
        die "Failed to create user for" . Dumper $user unless ($id);
        $user_map->{$old_id} = $id;

    }

}

# find all groups
if ($import_groups) {

        my $groups = $VAR1->{'Group'};

    # foreach group
    foreach my $group ( @{$groups} ) {

        #         create group
        my $g = RT::Group->new($RT::SystemUser);
        my $old_id = $group->{'id'};
        delete $group->{'id'};
        my $members = $group->{'Member'};
        delete $group->{'Member'};


        $g->CreateUserDefinedGroup( %{$group} );
        my $id = $g->Id();
        die "Failed to create group for" . Dumper $groups->{$group} unless ($id);
        $group_map->{$old_id} = $id;

        #         import members

        foreach my $member ( @{$members} ) {
                print "Adding $member to ".$g->Id."\n";
            $g->AddMember( $user_map->{ $member}  );
        }
    }
}

#print scalar Dumper $groups;
#
#
# for global
#
#         import custom fields
#
#         import templates
#
#         import acls

        foreach my $right (@{$VAR1->{'Global'}->{'Right'}}) {
                my $princ = RT::Principal->new($RT::SystemUser);
                my $id;
                if ($right->{'PrincipalType'} eq 'User')  {
                        $id = $user_map->{$right->{'PrincipalId'}};
                } else {
                        $id = $group_map->{$right->{'PrincipalId'}};

                }

                if ($right->{'Role'}) {
                        my $g = RT::Group->new($RT::SystemUser);
                        $g->LoadSystemInternalGroup($right->{'Role'});
                        $id = $g->Id;
                }
                else {
                        $princ->Load($id);
                }
                $princ->Id || die "Couldn't load principal $id to grant them ".$right->{'Name'} . " globally\n". Dumper($right);
                $princ->GrantRight(Object => $RT::System, Right => $right->{'Name'});
        }


        foreach my $cf (@{$VAR1->{'Global'}->{'CustomField'}}) {
                my $type;
                my $cfobj = RT::CustomField->new($RT::SystemUser);
                if ($cf->{'Single'}) {
                        $type = 'SelectSingle';
                } else {
                        $type = 'SelectMultiple';
                }
                $cfobj->Create (Name => $cf->{'Name'}, Type => $type, Queue => '0');
                unless ($cfobj->Id) {
                        die "Couldn't create custom field ".$cf->{'Name'};
                }
                $cf_map->{$cf->{'id'}} = $cfobj->Id;

                foreach my $val (@{$cf->{'Value'}}) {
                        $cfobj->AddValue(Name => $val);
                }
        }

# find all queues in RT 2.0


#
# for each queue

$RT::Handle->SimpleQuery("DELETE FROM Queues where id = 1");

my $queues = $VAR1->{'Queue'};

foreach my $queue ( @{$queues} ) {
        my %temp;
     foreach my $attr qw(id CustomField Watchers Scrip Right) {
        $temp{$attr} = $queue->{$attr};
        delete $queue->{$attr};
        }
    my $queue_obj = RT::Queue->new($RT::SystemUser);
    $queue_obj->Create( %{ $queue } );
    my $id = $queue_obj->Id();
    die "Failed to create queue for" . Dumper $queue unless ($id);
    $queue_map->{$temp{'id'}}       = $id;


        foreach my $watcher (@{$temp{Watchers}}) {
                $queue_obj->AddWatcher($watcher);
        }

       
        foreach my $right (@{$temp{'Right'}}) {
                my $princ = RT::Principal->new($RT::SystemUser);
        my $id;
                if ($right->{'PrincipalType'} eq 'User')  {
                        $id = $user_map->{$right->{'PrincipalId'}};
                } else {
                        $id = $group_map->{$right->{'PrincipalId'}};

                }
                if ($right->{'Role'}) {
                        my $g = RT::Group->new($RT::SystemUser);
                        $g->LoadQueueGroup(Type => $right->{'Role'} ,Queue => $queue_obj->Id);
                        unless ($g->Id) {
                                $g->LoadSystemInternalGroup($right->{'Role'});
                        }
                        $id = $g->Id;
                }
                $princ->Load($id);
                $princ->Id || die "Couldn't load principal $id to grant them ".$right->{'Name'} . " on queue ".$queue_obj->Name."\n".Dumper($right);
                $princ->GrantRight(Object => $queue_obj, Right => $right->{'Name'});
        }
        foreach my $cf (@{$temp{'CustomField'}}) {
                my $type;
                my $cfobj = RT::CustomField->new($RT::SystemUser);
                if ($cf->{'Single'}) {
                        $type = 'SelectSingle';
                } else {
                        $type = 'SelectMultiple';
                }
                $cfobj->Create (Name => $cf->{'Name'}, Type => $type, Queue => $queue_obj->Id);
                unless ($cfobj->Id) {
                        die "Couldn't create custom field ".$cf->{'Name'};
                }
                $cf_map->{$cf->{'id'}} = $cfobj->Id;
                foreach my $val (@{$cf->{'Value'}}) {
                        $cfobj->AddValue(Name => $val);
                }
        }
        foreach my $scrip (@{$temp{'Scrip'}}) {
        $scrip->{'Template'} =~ s/(.)([A-Z])/$1 $2/g;
        $scrip->{'Condition'} =~ s/(.)([A-Z])/$1 $2/g;
        $scrip->{'Action'} =~ s/(.)([A-Z])/$1 $2/g;
        $scrip->{'Action'} =~ s/Admin Watchers/AdminCcs/;
        my $so = RT::Scrip->new($RT::SystemUser);
        $so->Create(Template => $scrip->{'Template'},
                    ScripAction => $scrip->{'Action'},
                    ScripCondition => $scrip->{'Condition'},
                    Description => "Imported from RT 2.0",
                    Queue => $queue_obj->Id );

        unless ($so->Id) {
                push @errors, "Could not create scrip: ".Dumper($scrip);
        }


}


}


#
#         import watchers
#
#         import templates
#
#         import acls
#
#         import scrips
#
#Find all links


#
# for each ticke

if ($import_tickets) {

foreach my $ticket ( @{$VAR1->{'Ticket'}}) {
        my %temp;
    print "Importing ticket ".$ticket->{'id'} ."\n";

    my $tick_object = RT::Ticket->new($RT::SystemUser);

    $ticket->{'Status'} = 'deleted' if ( $ticket->{'Status'} eq 'dead' );

    $ticket->{'Queue'} = $queue_map->{ $ticket->{'Queue'} };
    $ticket->{'Owner'} = $user_map->{ $ticket->{'Owner'} };

    $ticket->{'Creator'}       = $user_map->{ $ticket->{'Creator'} };
    $ticket->{'LastUpdatedBy'} = $user_map->{ $ticket->{'LastUpdatedBy'} };

    $ticket->{'_RecordTransaction'} = 0;
     foreach my $attr qw(Watchers Transaction CustomFields) {
        $temp{$attr} = $ticket->{$attr};
        delete $ticket->{$attr};
     }

    foreach my $watcher ( @{$temp{'Watchers'}} ) {
        my $val;
            $val = $watcher->{'Email'};
        push ( @{ $ticket->{ $watcher->{'Type'} }}, $val );

    }

    foreach my $cf (keys %{$temp{'CustomFields'}}) {
                my $cfid = $cf_map->{$cf};
                $ticket->{'CustomField-'.$cfid} = $temp{'CustomFields'}->{$cf};

        } 

    $tick_object->Create( %{$ticket} );

    unless ( $tick_object->Id == $ticket->{id} ) {
        die "Couldn't create ticket $ticket " . Dumper( $ticket);
    }


    #         import ticket keywords


    #import ticket transactions
    foreach my $t ( @{$temp{Transaction}} ) {

        print "            transaction ".$t->{'id'} ."\n";
        $t->{'ActivateScrips'} = 0;
        if ( $t->{'Type'} eq 'Status' ) {
            if ( $t->{'NewValue'} eq 'dead' ) {
                $t->{'NewValue'} = 'deleted';
            }

            if ( $t->{'OldValue'} eq 'dead' ) {
                $t->{'OldValue'} = 'deleted';
            }

        }
        if ( $t->{'Type'} =~ /^AddWatcher$/ ) {
            my $u = RT::User->new($RT::SystemUser);
            $u->Load( $t->{'NewValue'} );
            unless ( $u->Id ) {
                $u->LoadByEmail( $t->{'NewValue'} );
            }
            unless ( $u->Id ) {

                my $new_user = RT::User->new($RT::SystemUser);

                my ( $Val, $Message ) = $new_user->Create(
                               Name         => $t->{'NewValue'},
                               EmailAddress => $t->{'NewValue'},
                               RealName     => $t->{'NewValue'},
                               Privileged   => 0,
                               Comments => 'Autocreated when added as a watcher'
                );
                unless ($Val) {
                    $RT::Logger->error( "Failed to create user "
                                        . $t->{'NewValue'} . ": "
                                        . $Message );

                    # Deal with the race condition of two account creations at once
                    $new_user->LoadByEmail( $t->{'NewValue'} );
                }
                $u->Load( $new_user->PrincipalId );
            }
            $t->{'NewValue'} = $u->Id;
        }

        if ( $t->{'Type'} =~ /^DelWatcher$/ ) {
            my $u = RT::User->new($RT::SystemUser);
            $u->Load( $t->{'OldValue'} );
            unless ( $u->Id ) {
                $u->LoadByEmail( $t->{'OldValue'} );
            }
            unless ( $u->Id ) {

                my $new_user = RT::User->new($RT::SystemUser);

                my ( $Val, $Message ) = $new_user->Create(
                               Name         => $t->{'OldValue'},
                               EmailAddress => $t->{'OldValue'},
                               RealName     => $t->{'OldValue'},
                               Privileged   => 0,
                               Comments => 'Autocreated when added as a watcher'
                );
                unless ($Val) {
                    $RT::Logger->error( "Failed to create user "
                                        . $t->{'OldValue'} . ": "
                                        . $Message );

                    # Deal with the race condition of two account creations at once
                    $new_user->LoadByEmail( $t->{'OldValue'} );
                }
                $u->Load( $new_user->PrincipalId );
            }
            $t->{'OldValue'} = $u->Id;
        }

        if ( $t->{'Type'} =~ /^(Force|Give|Take|Untake)$/ ) {
            $t->{'OldValue'} = $user_map->{ $t->{OldValue} };
            $t->{'NewValue'} = $user_map->{ $t->{NewValue} };
        }

        my $trans_obj = RT::Transaction->new($RT::SystemUser);
        $t->{'Creator'} = $user_map->{ $t->{'Creator'} };
         my $attach = $t->{'Attachment'};
        delete $t->{'Attachment'};

        $trans_obj->Create( %{ $t } );
        unless ( $trans_obj->Id == $t->{'id'} ) {
            die "Couldn't create trans  ".$t->{'id'}." " . Dumper( $t);
        }

        foreach my $a (@{$attach}) {
                my $att = RT::Attachment->new($RT::SystemUser);
                $att->Import(%{$a});
                print "               attachment ".$att->Id ."\n";
                unless( $att->Id) {
            die "Couldn't create attachment $a " . Dumper( $a);

                }
        }
    }


}
}

foreach my $link (@{$VAR1->{'Link'}}) {
        my $l = RT::Link->new($RT::SystemUser);

        $link->{'Base'} =~ s#/(.*?)/ticket/#/ticket/#;
        $link->{'Target'} =~ s#/(.*?)/ticket/#/ticket/#;



        my ($val, $msg) = $l->Create(Type=> $link->{'Type'},
        Target => ($link->{'LocalTarget'} || $link->{'Target'}),
        Base => ($link->{'LocalBase'} || $link->{'Base'})
);
        unless ($l->Id ) {
                if ($link->{'LocalBase'} != $link->{'LocalTarget'}) {
                push (@errors,  "Couldn't create link  ".$msg.Dumper($link));
                }
        }
}

print join("\n", at errors);


More information about the Rt-devel mailing list