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
287 dpurdie 176
FROM deployment_manager.dm_projects dm_,
177
     deployment_manager.branches branches,
178
     deployment_manager.boms boms,
179
     deployment_manager.bom_names bom,
180
     deployment_manager.network_nodes net,
181
     deployment_manager.bom_contents bomcont,
182
     deployment_manager.operating_systems ope,
183
     deployment_manager.os_contents oc,
184
     release_manager.package_versions pv,
185
     release_manager.PACKAGES pkg
227 dpurdie 186
WHERE ( (dm_.proj_id = branches.proj_id) AND (branches.branch_id = boms.branch_id) AND
187
        (bom.bom_name_id = boms.bom_name_id) AND (boms.bom_id = bomcont.bom_id) AND
188
        (net.node_id = bomcont.node_id) AND (net.node_id = ope.node_id) AND
189
        (ope.os_id = oc.os_id) AND (oc.prod_id = pv.pv_id) AND (pv.pkg_id = pkg.pkg_id) AND
190
        (dm_.proj_name = '$G_NodeDmInfo{ProjectName}') AND
191
        (branches.branch_name = '$G_NodeDmInfo{BranchName}') AND
192
        (bom.bom_name = '$G_NodeDmInfo{BomName}') AND
193
        (boms.bom_version = '$bomver') AND
194
        (boms.bom_lifecycle = '$lifecycle') AND
195
        (net.node_name = '$G_NodeDmInfo{NodeName}') AND
196
        (ope.os_name = '$G_NodeDmInfo{OsName}')
197
       )
198
    /;
199
    my ($sth )  = $DM->prepare($m_sqlstr);
200
    my @row;
201
    my $found = 0;
202
 
203
    LogDebug("Executing SQL statement\n$m_sqlstr");
204
    if ( defined($sth) )
205
    {
206
        if ( $sth->execute() )
207
        {
208
            if ( $sth->rows )
209
            {
210
                while ( @row = $sth->fetchrow_array )
211
                {
212
                    # Skip Patches
213
                    if ( !defined($row[5]) || $row[5] !~ /y/i )
214
                    {
215
                        # if extension defined
216
                        if ( defined($row[4]) )
217
                        {
218
                            # remove dot from start of extension
219
                            $row[4] =~ s/^\.//;
220
                            # remove extension from version
221
                            if ( $row[2] =~ /\.$row[4]$/ )
222
                            {
223
                                $row[2] =~ s/\.$row[4]$//;
224
                            }
225
                            else
226
                            {
227
                                LogWarn("Pkg [$row[1]] version [$row[2]] & extension [$row[4]] do not match");
228
                            }
229
                        }
230
                        else
231
                        {
232
                            $row[4] = "";
233
                        }
234
                        $row[3] = "" if ( ! defined($row[3]) );
235
                        chomp $row[3];
236
 
237
                        # if pkg version defined in _Forceversion then we  force the version
238
                        if ( defined($G_NodeDmInfo{_ForceVersion}{$row[1]}) && defined($G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]}))
239
                        {
240
                            LogDebug("Forcing pkg [$row[1]] from version [$row[2]] to [$G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]}]");
241
                            $newPkgs{$row[1]}{PkgVersion}   = $G_NodeDmInfo{_ForceVersion}{$row[1]}{$row[2]};
242
                        }
243
                        else
244
                        {
245
                            $newPkgs{$row[1]}{PkgVersion}   = $row[2];
246
                        }
247
                        $newPkgs{$row[1]}{PkgProjAcronym}   = $row[4];
248
                        $newPkgs{$row[1]}{PkgDesc}          = $row[3];
249
                        $found = 1;
250
                        LogDebug("Found DM Pkg [$row[1]], ver [$row[2]], proj [$row[4]], desc [$row[3]]");
251
                    }
252
                }
253
            }
254
            if ( ! $found )
255
            {
256
                LogError("-x", "Found No Information about node in Deployment Manager");
257
                return 0;
258
            }            
259
            $sth->finish();
260
        }
261
        else
262
        {
263
            LogError("-x", "Unable to execute SQL statement in DBI");
264
            return 0;
265
        }
266
    }
267
    else
268
    {
269
        LogError("-x", "Unable to prepare SQL statement in DBI");
270
        return 0;
271
    }
272
 
273
    disconnectDM(\$DM);
274
    return 1;
275
}
276
 
277
 
278
sub checkForDeleted
279
{
280
    foreach my $i ( keys %G_NodePkgHash )
281
    {
282
        # if pkg not defined in newPkgs from DM AND its not in the NoDelete List then we ask or process
283
        # that is is pkg is not in DM but it is in NoDelete list then we keep it as if it was
284
        if ( ! defined($newPkgs{$i}) && ! defined($G_NodeDmInfo{_NoDelete}{$i}) )
285
        {
286
            # ask if neither -d or -D set
287
            my $ans = "";
288
            $ans = askYN("Pkg [$i] is not in new list, remove") if ( $autoDelete eq "ASK" );
289
 
290
            # if -d defined or asn = N then we dont delete so just log
291
            if ( $autoDelete eq "NO" || $ans eq "N" )
292
            {
293
                push(@actionlog, "KEEP   Old Pkg [$i]: Version [$G_NodePkgHash{$i}{PkgVersion}] Project [$G_NodePkgHash{$i}{PkgProjAcronym}] from original Nodespec");
294
                # keeping an old package is not a real action, as nothing changes in nodespec
295
            }
296
            # if -D defined or ans = Y then delete
297
            elsif ( $autoDelete eq "YES" || $ans eq "Y" )
298
            {
299
                push(@actionlog, "DELETE Old Pkg [$i]: Version [$G_NodePkgHash{$i}{PkgVersion}] Project [$G_NodePkgHash{$i}{PkgProjAcronym}] from original Nodespec");
300
                delete($G_NodePkgHash{$i});
301
                $actions++;
302
            }
303
        }
304
    }
305
}
306
 
307
 
308
sub checkForNew
309
{
310
    foreach my $i ( keys %newPkgs )
311
    {
312
        if ( ! defined($G_NodePkgHash{$i}) )
313
        {
314
            # if pkg is defined in noAdd list then we just remove, otherwise process as normal
315
            if ( defined($G_NodeDmInfo{_NoAdd}{$i}) )
316
            {
317
                delete($newPkgs{$i});
318
            }
319
            else
320
            {
321
                # ask if neither -d or -D set
322
                my $ans = "";
323
                $ans = askYN("Pkg [$i] has been added, add") if ( $autoAdd eq "ASK" );
324
 
325
                # if -A defined or ans = Y then we add so just log
326
                if ( $autoAdd eq "YES" || $ans eq "Y" )
327
                {
328
                    push(@actionlog, "ADD    New Pkg [$i]: Version [$newPkgs{$i}{PkgVersion}] Project [$newPkgs{$i}{PkgProjAcronym}] from Deployment Manager");
329
                    $actions++;
330
                }
331
                # if -a defined then dont Add (remove from dm list), otherwise ask
332
                elsif ( $autoAdd eq "NO" || $ans eq "N" )
333
                {
334
                    push(@actionlog, "SKIP   New Pkg [$i]: Version [$newPkgs{$i}{PkgVersion}] Project [$newPkgs{$i}{PkgProjAcronym}] from Deployment Manager");
335
                    delete($newPkgs{$i});
336
                    # deleting a new package is not a real action, as nothing changes in nodespec
337
                }
338
            }
339
        }
340
    }
341
}
342
 
343
 
344
sub mergeHashs
345
{
346
    my $str;
347
    my $updated;
348
    foreach my $i ( keys %newPkgs )
349
    {
350
        if ( defined($G_NodePkgHash{$i}) )
351
        {
352
            $str = "UPDATE Pkg [$i]: ";
353
            $updated = 0;
354
            if ( $newPkgs{$i}{PkgVersion} ne $G_NodePkgHash{$i}{PkgVersion} )
355
            {
356
                $str .= "Version [$G_NodePkgHash{$i}{PkgVersion}]=>[$newPkgs{$i}{PkgVersion}] ";
357
                $updated = 1;
358
                $G_NodePkgHash{$i}{PkgVersion} = $newPkgs{$i}{PkgVersion};
359
            }
360
 
361
            if ( ($newPkgs{$i}{PkgProjAcronym} || '') ne ($G_NodePkgHash{$i}{PkgProjAcronym} || '') )
362
            {
363
                $str .= "Project [$G_NodePkgHash{$i}{PkgProjAcronym}]=>[$newPkgs{$i}{PkgProjAcronym}] ";
364
                $updated = 1;
365
                if ( $newPkgs{$i}{PkgProjAcronym} )
366
                {
367
                    $G_NodePkgHash{$i}{PkgProjAcronym} = $newPkgs{$i}{PkgProjAcronym};
368
                }
369
                else
370
                {
371
                    delete $G_NodePkgHash{$i}{PkgProjAcronym};
372
                }
373
            }
374
 
375
            if ( $newPkgs{$i}{PkgDesc} ne $G_NodePkgHash{$i}{PkgDesc} )
376
            {
377
                $str .= "Description [$G_NodePkgHash{$i}{PkgDesc}]=>[$newPkgs{$i}{PkgDesc}] ";
378
                $updated = 1;
379
                $G_NodePkgHash{$i}{PkgDesc} = $newPkgs{$i}{PkgDesc};
380
            }
381
            if ( $updated )
382
            {
383
                push(@actionlog, $str);
384
                $actions++;
385
            }
386
        }
387
        else
388
        {
389
            $G_NodePkgHash{$i}{PkgVersion} = $newPkgs{$i}{PkgVersion};
390
            $G_NodePkgHash{$i}{PkgProjAcronym} = $newPkgs{$i}{PkgProjAcronym};
391
            $G_NodePkgHash{$i}{PkgDesc} = $newPkgs{$i}{PkgDesc};
392
            $G_NodePkgHash{$i}{ERGPkgFlag} = "T";
393
            $G_NodePkgHash{$i}{CheckVersionFlag} = "T";
394
            # no need to log as its already done
395
        }
396
    }
397
}
398
 
399
 
400
 
401
sub updateNodeSpecFile
402
{
403
    my ( $buffer, $line );
404
    LogNorm("--------------------------------------------------------------------");
405
 
406
    if ( $G_NodeSBOMVersion eq $newVer && $actions == 0 )
407
    {
408
        LogNorm("NO ACTIONS will be performed on the nodespec file [$nodeSpecFile]");
409
        LogNorm("--------------------------------------------------------------------");
410
    }
411
    else
412
    {
413
        LogNorm("The Following actions will be performed on the nodespec file [$nodeSpecFile]");
414
        LogNorm("UPDATE BOM version from $G_NodeSBOMVersion to $newVer");
415
        foreach my $i ( sort @actionlog )
416
        {
417
            LogNorm($i);
418
        }
419
        LogNorm("--------------------------------------------------------------------");
420
        if ( $autoUpdate || askYN("Update nodespec file as described ") eq "Y" )
421
        {
422
            # read all comment lines up to first comment line
423
            if ( ! open(NODESPEC, "<$nodeSpecFile") )
424
            {
425
                LogError("-x", "Unable to open Node Spec File to update");
426
                return 0;
427
            }
428
            do
429
            {
430
                $line = <NODESPEC>;
431
                $line =~ s/\r\n/\n/;
432
                $buffer .= $line if ( $line =~ /^#/ );
433
            }
434
            while ( $line =~ /^#/ );
435
            close NODESPEC;
436
 
437
            # now lets update the file
438
            if ( ! open(NODESPEC, ">$nodeSpecFile") ) 
439
            {
440
                LogError("-x", "Unable to open Node Spec File to update");
441
                return 0;
442
            }
443
            binmode(NODESPEC);
444
 
445
            print NODESPEC "$buffer\n";
446
 
447
            # Dumper prints hashes as references ie $hash = { .... };
448
            # Where the original nodespec files were real hashes ie %hash = ( .... );
449
            # So we dump hashes to buffer and replace the first line with real hash & (
450
            # and replace last line }; with );
451
 
452
            $buffer = Data::Dumper->Dump([ \%G_NodeDmInfo ], [ "pkgmnt::G_NodeDmInfo" ]);
453
            $buffer =~ s/^\$(pkgmnt::G_NodeDmInfo *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
454
            print NODESPEC "$buffer\n";
455
 
456
            print NODESPEC Data::Dumper->Dump([ $newVer ], [ "pkgmnt::G_NodeSBOMVersion" ]) . "\n";
457
 
458
            print NODESPEC Data::Dumper->Dump([ $G_NodeName ], [ "pkgmnt::G_NodeName" ]) . "\n";
459
 
460
            $buffer = Data::Dumper->Dump([ \%G_NodeProcessHash], [ "pkgmnt::G_NodeProcessHash" ]);
461
            $buffer =~ s/^\$(pkgmnt::G_NodeProcessHash *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
462
            print NODESPEC "$buffer\n";
463
 
464
            $buffer = Data::Dumper->Dump([ \%G_NodePkgHash ], [ "pkgmnt::G_NodePkgHash" ]);
465
            $buffer =~ s/^\$(pkgmnt::G_NodePkgHash *= *)\{(.*)\}(.*)$/\%$1\($2\)$3/ms;
466
            print NODESPEC "$buffer\n1;\n";
467
 
468
            close NODESPEC;
469
 
470
            LogNorm("Updated nodespec file $nodeSpecFile");
471
        }
472
    }
473
    return 1;
474
}
475
 
476
 
477
 
478
sub askYN
479
{
480
    use Term::ReadKey;
481
    my $msg = shift;
482
    $msg .= " [ynq] ? ";
483
    my $ch = "";
484
    my $rMode = 0;
485
    while ( $ch ne "Y" && $ch ne "N" )
486
    {
487
        LogNorm("-n", $msg);
488
        #$ch = uc HotKey::readkey();
489
        eval { ReadMode('cbreak'); $rMode = 1 }; # do in eval because it barfs on cygwin term
490
        $ch = uc ReadKey(0);
491
        eval { ReadMode('normal') };
492
        chomp $ch;
493
        if ( $rMode )
494
        {
495
            print "\n";
496
        }
497
        else
498
        {
499
            # if not rMode then a CR needs to be entered so lets remove it.
500
            my $a = <STDIN>;
501
        }
502
        LogError("Quitting application") if ( $ch eq "Q" );
503
    }
504
    return $ch;
505
}
506
 
507
 
508
1;
509
 
510
 
511
#============================================================================
512
# HotKey.pm
513
#package HotKey;
514
 
515
#use strict;
516
#use POSIX qw(:termios_h);
517
#my ($term, $oterm, $echo, $noecho, $fd_stdin);
518
 
519
#BEGIN {
520
#$fd_stdin = fileno(STDIN);
521
#$term     = POSIX::Termios->new();
522
#$term->getattr($fd_stdin);
523
#$oterm     = $term->getlflag();
524
 
525
#$echo     = ECHO | ECHOK | ICANON;
526
#$noecho   = $oterm & ~$echo;
527
#}
528
 
529
#sub cbreak {
530
#    $term->setlflag($noecho);  # ok, so i don't want echo either
531
#    $term->setcc(VTIME, 1);
532
#    $term->setattr($fd_stdin, TCSANOW);
533
#}
534
 
535
#sub cooked {
536
#    $term->setlflag($oterm);
537
#    $term->setcc(VTIME, 0);
538
#   $term->setattr($fd_stdin, TCSANOW);
539
#}
540
 
541
#sub readkey {
542
#    my $key = '';
543
#    cbreak();
544
#    sysread(STDIN, $key, 1);
545
#    cooked();
546
#    return $key;
547
#}
548
 
549
#END { cooked() }
550
#1;