Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#!/usr/local/bin/perl -w
2
 
3
require 5.8.2;
4
use Getopt::Std;
5
use DeployUtils::Logger;
6
 
7
use vars qw ( $opt_l $opt_h $opt_a $opt_A $opt_d $opt_D $opt_y );
8
 
9
getopts('l:haAdDy');
10
 
11
help() if ( defined($opt_h) );
12
help("Must supply nodespec file & new version number as args") if ( !defined($ARGV[0]) || !defined($ARGV[1]) );
13
help("Cant use -a & -A together") if ( defined($opt_a) && defined($opt_A) );
14
help("Cant use -d & -D together") if ( defined($opt_d) && defined($opt_D) );
15
 
16
setLogLevel($opt_l) if ( defined($opt_l) );
17
 
18
my $ver = shift;
19
my $retval;
20
 
21
while ( my $nsfile = shift )
22
{
23
    $retval = pkgmnt::init($ver, $nsfile,
24
                            (defined($opt_d)) ? "NO" : (defined($opt_D)) ? "YES" : "ASK",
25
                            (defined($opt_a)) ? "NO" : (defined($opt_A)) ? "YES" : "ASK",
26
                            (defined($opt_y)) ? 1 : 0 );
27
 
28
    $retval = pkgmnt::getNodeSpecFromDM() if ( $retval );
29
 
30
    if ( $retval )
31
    {
32
        pkgmnt::checkForDeleted();
33
        pkgmnt::checkForNew();
34
        pkgmnt::mergeHashs();
35
        $retval = pkgmnt::updateNodeSpecFile();
36
    }
37
 
38
    LogError("-x", "Unable to process Nodespec file [$nsfile]") if ( ! $retval );
39
}
40
 
41
 
42
 
43
sub help
44
{
45
    my $error = shift;
46
    my $usage = qq(
47
updateNodeSpec.pl [-l N] [-d|-D] [-a|-A] [-y] NewVersion nodespecfile 
48
where
49
    NewVersion   : The new BOM version for the nodespec file.
50
    nodespecfile : Specifies the nodespec file to update.
51
 
52
Options:
53
    -l  : Sets log level 1-5
54
 
55
    -d  : Dont Automatically Delete packages from nodespec file if DM does not have them.
56
    -D  : Do Automatically Delete packages from nodespec file if DM does not have them.
57
        : DEFAULT if neither supplied is to interactively ask for each package.
58
 
59
    -a  : Dont Automatically Add new packages from DM into nodespec file.
60
    -A  : Do Automatically Add new packages from DM into nodespec file.
61
        : DEFAULT if neither supplied is to interactively ask for each package.
62
 
63
    -y  : Automatically answer yes to final Update nodespec file question.
64
    );
65
 
66
    print "$error\n" if ( defined $error );
67
    print $usage;
68
    exit 1;
69
}
70
 
71
 
72
#============================================================================
73
package pkgmnt;
74
 
75
use strict;
76
use DBI;
77
use Data::Dumper;
78
use DeployUtils::Logger;
79
use JatsRmApi;
80
 
81
our ($G_NodeSBOMVersion, $G_NodeName, %G_NodeProcessHash, %G_NodePkgHash, %G_NodeDmInfo);
82
our %newPkgs;
83
our ( @actionlog, $actions );
84
 
85
our $nodeSpecFile;
86
our ( $newVer, $bomver, $lifecycle );
87
our ( $autoDelete, $autoAdd, $autoUpdate );
88
 
89
sub init
90
{
91
    ( $newVer, $nodeSpecFile, $autoDelete, $autoAdd, $autoUpdate ) = @_;
92
 
93
    LogNorm("");
94
    LogNorm("");
95
    LogNorm("Upgrading NodeSpec file [$nodeSpecFile] to $newVer");
96
 
97
    if ( ! -f $nodeSpecFile )
98
    {
99
        LogError("-x", "Nodespec file [$nodeSpecFile] does not exist");
100
        return 0;
101
    }
102
 
103
    # version must start & end with numbers and contain numbers & '.' in between
104
    if ( $newVer =~ /^[0-9]+[0-9\.]*[0-9]+$/ )
105
    {
106
        # split version number into number sections
107
        my @verNums = split(/\./, "$newVer");
108
        #last section is the lifecycle number so remove from list
109
        $lifecycle = pop(@verNums);
110
        #now join rest of numbers
111
        $bomver = join(".", @verNums);
112
    }
113
    else
114
    {
115
        LogError("-x", "Version number format incorrect, must contain digits & '.' eg (1.2 or 1.1.2)");
116
        return 0;
117
    }
118
 
119
    $autoDelete = uc $autoDelete;
120
    $autoAdd = uc $autoAdd;
121
 
122
    if ( $autoDelete ne "YES" && $autoDelete ne "NO" && $autoDelete ne "ASK" )
123
    {
124
        LogError("-x", "autoDelete flag must be YES, NO or ASK");
125
        return 0;
126
    }
127
    if ( $autoAdd ne "YES" && $autoAdd ne "NO" && $autoAdd ne "ASK" )
128
    {
129
        LogError("-x", "autoAdd flag must be YES, NO or ASK");
130
        return 0;
131
    }
132
 
133
    $Data::Dumper::Purity = 1;
134
    $Data::Dumper::Quotekeys = 0;
135
    $Data::Dumper::Sortkeys = 1;
136
    $Data::Dumper::Indent = 1;
137
 
138
    $G_NodeSBOMVersion = "";
139
    $G_NodeName = "";
140
    %G_NodeProcessHash = ( );
141
    %G_NodePkgHash = ( );
142
    %G_NodeDmInfo = ( );    
143
    %newPkgs = ( );
144
    $#actionlog = -1;
145
    $actions = 0;
146
 
147
    # require the nodespk file to get details
148
    require $nodeSpecFile;
149
 
150
    if ( ! defined($G_NodeDmInfo{ProjectName}) && ! defined($G_NodeDmInfo{BranchName}) &&
151
         ! defined($G_NodeDmInfo{BomName}) && ! defined($G_NodeDmInfo{NodeName}) &&
152
         ! defined($G_NodeDmInfo{OsName}) )
153
    {
154
        LogError("-x", "G_NodeDmInfo hash in nodespec does not have enough info");
155
        return 0;
156
    }
157
 
158
    LogInfo("ProjectName : $G_NodeDmInfo{ProjectName}");
159
    LogInfo("BranchName  : $G_NodeDmInfo{BranchName}");
160
    LogInfo("BomName     : $G_NodeDmInfo{BomName}");
161
    LogInfo("NodeName    : $G_NodeDmInfo{NodeName}");
162
    LogInfo("OsName      : $G_NodeDmInfo{OsName}");
163
 
164
    return 1;
165
}
166
 
167
 
168
 
169
sub getNodeSpecFromDM
170
{
171
    my $DM;
172
    connectDM( \$DM );
173
 
174
    my ($m_sqlstr ) = qq /
175
SELECT oc.prod_id, pkg.pkg_name, pv.pkg_version, pv.pv_description, pv.v_ext, pv.is_patch
176
FROM dm_projects dm_, branches branches, boms boms, bom_names bom, network_nodes net,
177
     bom_contents bomcont, operating_systems ope, os_contents oc,
178
     release_manager.package_versions pv, release_manager.PACKAGES pkg
179
WHERE ( (dm_.proj_id = branches.proj_id) AND (branches.branch_id = boms.branch_id) AND
180
        (bom.bom_name_id = boms.bom_name_id) AND (boms.bom_id = bomcont.bom_id) AND
181
        (net.node_id = bomcont.node_id) AND (net.node_id = ope.node_id) AND
182
        (ope.os_id = oc.os_id) AND (oc.prod_id = pv.pv_id) AND (pv.pkg_id = pkg.pkg_id) AND
183
        (dm_.proj_name = '$G_NodeDmInfo{ProjectName}') AND
184
        (branches.branch_name = '$G_NodeDmInfo{BranchName}') AND
185
        (bom.bom_name = '$G_NodeDmInfo{BomName}') AND
186
        (boms.bom_version = '$bomver') AND
187
        (boms.bom_lifecycle = '$lifecycle') AND
188
        (net.node_name = '$G_NodeDmInfo{NodeName}') AND
189
        (ope.os_name = '$G_NodeDmInfo{OsName}')
190
       )
191
    /;
192
    my ($sth )  = $DM->prepare($m_sqlstr);
193
    my @row;
194
    my $found = 0;
195
 
196
    LogDebug("Executing SQL statement\n$m_sqlstr");
197
    if ( defined($sth) )
198
    {
199
        if ( $sth->execute() )
200
        {
201
            if ( $sth->rows )
202
            {
203
                while ( @row = $sth->fetchrow_array )
204
                {
205
                    # Skip Patches
206
                    if ( !defined($row[5]) || $row[5] !~ /y/i )
207
                    {
208
                        # if extension defined
209
                        if ( defined($row[4]) )
210
                        {
211
                            # remove dot from start of extension
212
                            $row[4] =~ s/^\.//;
213
                            # remove extension from version
214
                            if ( $row[2] =~ /\.$row[4]$/ )
215
                            {
216
                                $row[2] =~ s/\.$row[4]$//;
217
                            }
218
                            else
219
                            {
220
                                LogWarn("Pkg [$row[1]] version [$row[2]] & extension [$row[4]] do not match");
221
                            }
222
                        }
223
                        else
224
                        {
225
                            $row[4] = "";
226
                        }
227
                        $row[3] = "" if ( ! defined($row[3]) );
228
                        chomp $row[3];
229
 
230
                        # if pkg version defined in _Forceversion then we  force the version
231
                        if ( defined($G_NodeDmInfo{_ForceVersion}{$row[1]}) && defined($G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]}))
232
                        {
233
                            LogDebug("Forcing pkg [$row[1]] from version [$row[2]] to [$G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]}]");
234
                            $newPkgs{$row[1]}{PkgVersion}   = $G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]};
235
                        }
236
                        else
237
                        {
238
                            $newPkgs{$row[1]}{PkgVersion}   = $row[2];
239
                        }
240
                        $newPkgs{$row[1]}{PkgProjAcronym}   = $row[4];
241
                        $newPkgs{$row[1]}{PkgDesc}          = $row[3];
242
                        $found = 1;
243
                        LogDebug("Found DM Pkg [$row[1]], ver [$row[2]], proj [$row[4]], desc [$row[3]]");
244
                    }
245
                }
246
            }
247
            if ( ! $found )
248
            {
249
                LogError("-x", "Found No Information about node in Deployment Manager");
250
                return 0;
251
            }            
252
            $sth->finish();
253
        }
254
        else
255
        {
256
            LogError("-x", "Unable to execute SQL statement in DBI");
257
            return 0;
258
        }
259
    }
260
    else
261
    {
262
        LogError("-x", "Unable to prepare SQL statement in DBI");
263
        return 0;
264
    }
265
 
266
    disconnectDM(\$DM);
267
    return 1;
268
}
269
 
270
 
271
sub checkForDeleted
272
{
273
    foreach my $i ( keys %G_NodePkgHash )
274
    {
275
        # if pkg not defined in newPkgs from DM AND its not in the NoDelete List then we ask or process
276
        # that is is pkg is not in DM but it is in NoDelete list then we keep it as if it was
277
        if ( ! defined($newPkgs{$i}) && ! defined($G_NodeDmInfo{_NoDelete}{$i}) )
278
        {
279
            # ask if neither -d or -D set
280
            my $ans = "";
281
            $ans = askYN("Pkg [$i] is not in new list, remove") if ( $autoDelete eq "ASK" );
282
 
283
            # if -d defined or asn = N then we dont delete so just log
284
            if ( $autoDelete eq "NO" || $ans eq "N" )
285
            {
286
                push(@actionlog, "KEEP   Old Pkg [$i]: Version [$G_NodePkgHash{$i}{PkgVersion}] Project [$G_NodePkgHash{$i}{PkgProjAcronym}] from original Nodespec");
287
                # keeping an old package is not a real action, as nothing changes in nodespec
288
            }
289
            # if -D defined or ans = Y then delete
290
            elsif ( $autoDelete eq "YES" || $ans eq "Y" )
291
            {
292
                push(@actionlog, "DELETE Old Pkg [$i]: Version [$G_NodePkgHash{$i}{PkgVersion}] Project [$G_NodePkgHash{$i}{PkgProjAcronym}] from original Nodespec");
293
                delete($G_NodePkgHash{$i});
294
                $actions++;
295
            }
296
        }
297
    }
298
}
299
 
300
 
301
sub checkForNew
302
{
303
    foreach my $i ( keys %newPkgs )
304
    {
305
        if ( ! defined($G_NodePkgHash{$i}) )
306
        {
307
            # if pkg is defined in noAdd list then we just remove, otherwise process as normal
308
            if ( defined($G_NodeDmInfo{_NoAdd}{$i}) )
309
            {
310
                delete($newPkgs{$i});
311
            }
312
            else
313
            {
314
                # ask if neither -d or -D set
315
                my $ans = "";
316
                $ans = askYN("Pkg [$i] has been added, add") if ( $autoAdd eq "ASK" );
317
 
318
                # if -A defined or ans = Y then we add so just log
319
                if ( $autoAdd eq "YES" || $ans eq "Y" )
320
                {
321
                    push(@actionlog, "ADD    New Pkg [$i]: Version [$newPkgs{$i}{PkgVersion}] Project [$newPkgs{$i}{PkgProjAcronym}] from Deployment Manager");
322
                    $actions++;
323
                }
324
                # if -a defined then dont Add (remove from dm list), otherwise ask
325
                elsif ( $autoAdd eq "NO" || $ans eq "N" )
326
                {
327
                    push(@actionlog, "SKIP   New Pkg [$i]: Version [$newPkgs{$i}{PkgVersion}] Project [$newPkgs{$i}{PkgProjAcronym}] from Deployment Manager");
328
                    delete($newPkgs{$i});
329
                    # deleting a new package is not a real action, as nothing changes in nodespec
330
                }
331
            }
332
        }
333
    }
334
}
335
 
336
 
337
sub mergeHashs
338
{
339
    my $str;
340
    my $updated;
341
    foreach my $i ( keys %newPkgs )
342
    {
343
        if ( defined($G_NodePkgHash{$i}) )
344
        {
345
            $str = "UPDATE Pkg [$i]: ";
346
            $updated = 0;
347
            if ( $newPkgs{$i}{PkgVersion} ne $G_NodePkgHash{$i}{PkgVersion} )
348
            {
349
                $str .= "Version [$G_NodePkgHash{$i}{PkgVersion}]=>[$newPkgs{$i}{PkgVersion}] ";
350
                $updated = 1;
351
                $G_NodePkgHash{$i}{PkgVersion} = $newPkgs{$i}{PkgVersion};
352
            }
353
 
354
            if ( ($newPkgs{$i}{PkgProjAcronym} || '') ne ($G_NodePkgHash{$i}{PkgProjAcronym} || '') )
355
            {
356
                $str .= "Project [$G_NodePkgHash{$i}{PkgProjAcronym}]=>[$newPkgs{$i}{PkgProjAcronym}] ";
357
                $updated = 1;
358
                if ( $newPkgs{$i}{PkgProjAcronym} )
359
                {
360
                    $G_NodePkgHash{$i}{PkgProjAcronym} = $newPkgs{$i}{PkgProjAcronym};
361
                }
362
                else
363
                {
364
                    delete $G_NodePkgHash{$i}{PkgProjAcronym};
365
                }
366
            }
367
 
368
            if ( $newPkgs{$i}{PkgDesc} ne $G_NodePkgHash{$i}{PkgDesc} )
369
            {
370
                $str .= "Description [$G_NodePkgHash{$i}{PkgDesc}]=>[$newPkgs{$i}{PkgDesc}] ";
371
                $updated = 1;
372
                $G_NodePkgHash{$i}{PkgDesc} = $newPkgs{$i}{PkgDesc};
373
            }
374
            if ( $updated )
375
            {
376
                push(@actionlog, $str);
377
                $actions++;
378
            }
379
        }
380
        else
381
        {
382
            $G_NodePkgHash{$i}{PkgVersion} = $newPkgs{$i}{PkgVersion};
383
            $G_NodePkgHash{$i}{PkgProjAcronym} = $newPkgs{$i}{PkgProjAcronym};
384
            $G_NodePkgHash{$i}{PkgDesc} = $newPkgs{$i}{PkgDesc};
385
            $G_NodePkgHash{$i}{ERGPkgFlag} = "T";
386
            $G_NodePkgHash{$i}{CheckVersionFlag} = "T";
387
            # no need to log as its already done
388
        }
389
    }
390
}
391
 
392
 
393
 
394
sub updateNodeSpecFile
395
{
396
    my ( $buffer, $line );
397
    LogNorm("--------------------------------------------------------------------");
398
 
399
    if ( $G_NodeSBOMVersion eq $newVer && $actions == 0 )
400
    {
401
        LogNorm("NO ACTIONS will be performed on the nodespec file [$nodeSpecFile]");
402
        LogNorm("--------------------------------------------------------------------");
403
    }
404
    else
405
    {
406
        LogNorm("The Following actions will be performed on the nodespec file [$nodeSpecFile]");
407
        LogNorm("UPDATE BOM version from $G_NodeSBOMVersion to $newVer");
408
        foreach my $i ( sort @actionlog )
409
        {
410
            LogNorm($i);
411
        }
412
        LogNorm("--------------------------------------------------------------------");
413
        if ( $autoUpdate || askYN("Update nodespec file as described ") eq "Y" )
414
        {
415
            # read all comment lines up to first comment line
416
            if ( ! open(NODESPEC, "<$nodeSpecFile") )
417
            {
418
                LogError("-x", "Unable to open Node Spec File to update");
419
                return 0;
420
            }
421
            do
422
            {
423
                $line = <NODESPEC>;
424
                $line =~ s/\r\n/\n/;
425
                $buffer .= $line if ( $line =~ /^#/ );
426
            }
427
            while ( $line =~ /^#/ );
428
            close NODESPEC;
429
 
430
            # now lets update the file
431
            if ( ! open(NODESPEC, ">$nodeSpecFile") ) 
432
            {
433
                LogError("-x", "Unable to open Node Spec File to update");
434
                return 0;
435
            }
436
            binmode(NODESPEC);
437
 
438
            print NODESPEC "$buffer\n";
439
 
440
            # Dumper prints hashes as references ie $hash = { .... };
441
            # Where the original nodespec files were real hashes ie %hash = ( .... );
442
            # So we dump hashes to buffer and replace the first line with real hash & (
443
            # and replace last line }; with );
444
 
445
            $buffer = Data::Dumper->Dump([ \%G_NodeDmInfo ], [ "pkgmnt::G_NodeDmInfo" ]);
446
            $buffer =~ s/^\$(pkgmnt::G_NodeDmInfo *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
447
            print NODESPEC "$buffer\n";
448
 
449
            print NODESPEC Data::Dumper->Dump([ $newVer ], [ "pkgmnt::G_NodeSBOMVersion" ]) . "\n";
450
 
451
            print NODESPEC Data::Dumper->Dump([ $G_NodeName ], [ "pkgmnt::G_NodeName" ]) . "\n";
452
 
453
            $buffer = Data::Dumper->Dump([ \%G_NodeProcessHash], [ "pkgmnt::G_NodeProcessHash" ]);
454
            $buffer =~ s/^\$(pkgmnt::G_NodeProcessHash *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
455
            print NODESPEC "$buffer\n";
456
 
457
            $buffer = Data::Dumper->Dump([ \%G_NodePkgHash ], [ "pkgmnt::G_NodePkgHash" ]);
458
            $buffer =~ s/^\$(pkgmnt::G_NodePkgHash *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
459
            print NODESPEC "$buffer\n1;\n";
460
 
461
            close NODESPEC;
462
 
463
            LogNorm("Updated nodespec file $nodeSpecFile");
464
        }
465
    }
466
    return 1;
467
}
468
 
469
 
470
 
471
sub askYN
472
{
473
    use Term::ReadKey;
474
    my $msg = shift;
475
    $msg .= " [ynq] ? ";
476
    my $ch = "";
477
    my $rMode = 0;
478
    while ( $ch ne "Y" && $ch ne "N" )
479
    {
480
        LogNorm("-n", $msg);
481
        #$ch = uc HotKey::readkey();
482
        eval { ReadMode('cbreak'); $rMode = 1 }; # do in eval because it barfs on cygwin term
483
        $ch = uc ReadKey(0);
484
        eval { ReadMode('normal') };
485
        chomp $ch;
486
        if ( $rMode )
487
        {
488
            print "\n";
489
        }
490
        else
491
        {
492
            # if not rMode then a CR needs to be entered so lets remove it.
493
            my $a = <STDIN>;
494
        }
495
        LogError("Quitting application") if ( $ch eq "Q" );
496
    }
497
    return $ch;
498
}
499
 
500
 
501
1;
502
 
503
 
504
#============================================================================
505
# HotKey.pm
506
#package HotKey;
507
 
508
#use strict;
509
#use POSIX qw(:termios_h);
510
#my ($term, $oterm, $echo, $noecho, $fd_stdin);
511
 
512
#BEGIN {
513
#$fd_stdin = fileno(STDIN);
514
#$term     = POSIX::Termios->new();
515
#$term->getattr($fd_stdin);
516
#$oterm     = $term->getlflag();
517
 
518
#$echo     = ECHO | ECHOK | ICANON;
519
#$noecho   = $oterm & ~$echo;
520
#}
521
 
522
#sub cbreak {
523
#    $term->setlflag($noecho);  # ok, so i don't want echo either
524
#    $term->setcc(VTIME, 1);
525
#    $term->setattr($fd_stdin, TCSANOW);
526
#}
527
 
528
#sub cooked {
529
#    $term->setlflag($oterm);
530
#    $term->setcc(VTIME, 0);
531
#   $term->setattr($fd_stdin, TCSANOW);
532
#}
533
 
534
#sub readkey {
535
#    my $key = '';
536
#    cbreak();
537
#    sysread(STDIN, $key, 1);
538
#    cooked();
539
#    return $key;
540
#}
541
 
542
#END { cooked() }
543
#1;