Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
5708 dpurdie 1
########################################################################
2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
3
#
4
# Module name   : checkRelease.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Determine package that required for a Release/SBOM that are
10
#                 not in dpkg_archive.
11
#                 
12
#                 Such packages may need to be recovered from S3
13
#
14
# Usage         : See POD at the end of this file
15
#
16
#......................................................................#
17
 
18
require 5.006_001;
19
use strict;
20
use warnings;
21
use JatsEnv;
22
use JatsError;
23
use JatsSystem;
24
use JatsRmApi;
25
use FileUtils;
26
use DBI;
27
use Getopt::Long;
28
use Pod::Usage;                             # required for help support
29
 
30
#
31
#   Config Options
32
#
33
my $VERSION = "1.0.0";                      # Update this
34
my $opt_help = 0;
35
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
36
my $opt_sbom_id;
37
my $opt_rtag_id;
38
my $opt_test = 0;
39
my $opt_patch = 1;
40
my $opt_rootpkg;
41
my $opt_rootpkg_version;
42
 
43
#
44
#   Data Base Interface
45
#
46
my $RM_DB;
47
my $DM_DB;
48
 
49
#
50
#   Global variables
51
#
52
my %os_id_list;                 # os_id in the SBOM
53
my %os_env_list;                # OS Environments
54
my %pv_id;                      # Packages in the SBOM
55
my %Package;                    # Per Package information
56
my %Release;                    # Release information
57
my %Release_pvid;               # Release info
58
my %Pegged;                     # Pegged/SDK packages by pvid - these do not need dependencies                                
59
my @StrayPackages;              # Non-top level packages
60
my @create_list;                # List of files created
61
my $fpref = "sbom";             # Sbom Prefix
62
our $GBE_DPKG;
63
my $sbom_name;
64
my $sbom_branch;
65
my $sbom_project;
66
my $sbom_version;
67
my $rtag_release;
68
my $rtag_project;
69
 
70
#
71
#   Packages to be ignored
72
#
73
my %ignore;
74
my %patch;
75
 
76
 
77
#-------------------------------------------------------------------------------
78
# Function        : Main
79
#
80
# Description     : Main entry point
81
#                   Parse user options
82
#
83
# Inputs          :
84
#
85
# Returns         :
86
#
87
 
88
my $result = GetOptions (
89
                "help:+"            => \$opt_help,              # flag, multiple use allowed
90
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
91
                "verbose:+"         => \$opt_verbose,           # flag
92
                "sbomid|sbom_id=s"  => \$opt_sbom_id,           # string
93
                "rtagid|rtag_id=s"  => \$opt_rtag_id,           # string
94
                "rootpackage=s"     => \$opt_rootpkg,           # String
95
                "ignore=s",         => sub{my ($a,$i) = @_; $ignore{$i} = 0 },
96
                "test!"             => \$opt_test,              #[no]flag
97
                "patch!"            => \$opt_patch,             #[no]flag
98
                );
99
 
100
#
101
#   Process help and manual options
102
#
103
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
104
pod2usage(-verbose => 1)  if ($opt_help == 2 );
105
pod2usage(-verbose => 2)  if ($opt_help > 2);
106
 
107
ErrorConfig( 'name'    => 'ESCROW',
108
             'verbose' => $opt_verbose );
109
 
110
#
111
#   Sanity test
112
#
113
unless ( $opt_rtag_id || $opt_sbom_id || $#ARGV >= 1)
114
{
115
    Error ("Need sbomid and/or rtagid",
116
           "Example: -sbomid=13543, for NZS Phase-1",
117
           "Example: -sbomid=13543 -rtagid=xxxx, for NZS Phase-1, compared against given release",
118
           "Example: -rtagid=2362, for Sydney R1/R2",
119
           "Example: -rtagid=8843 -root=StockholmSBOM",
120
           "Example: PackageName PackageVersion, for extracting a single package",
121
    )
122
}
123
 
124
 
125
Warning ("No sbomid provided. Output based an a Release") unless ( $opt_sbom_id );
126
$fpref = "release" unless ( $opt_sbom_id );
127
 
128
#
129
#   Import essential EnvVars
130
#
131
EnvImport('GBE_DPKG');
132
 
133
if ( $opt_sbom_id )
134
{
135
    #
136
    #   Determines the OS_ID's for the bom
137
    #
138
    getOSIDforBOMID($opt_sbom_id);
139
    getSBOMDetails($opt_sbom_id);
140
 
141
    #
142
    #   Locate packages associated with the base install for each os
143
    #
144
    foreach my $base_env_id ( sort keys %os_env_list )
145
    {
146
        getPackagesforBaseInstall( $base_env_id );
147
    }
148
 
149
    #
150
    #   Determine all the top level packages in the BOM
151
    #
152
    foreach my $os_id ( sort keys %os_id_list )
153
    {
154
        getPackages_by_osid( $os_id );
155
    }
156
 
157
    #
158
    #   For each Top Level Package determine the dependent packages
159
    #
160
    getPkgDetailsForPVIDs (keys %pv_id);
161
    LocateStrays(0);
162
 
163
    #
164
    #   Determine packages in a given Release
165
    #
166
    if ( $opt_rtag_id )
167
    {
168
        getPkgDetailsByRTAG_ID( $opt_rtag_id );
169
    }
170
}
171
elsif ( $opt_rtag_id )
172
{
173
    getPkgDetailsByRTAG_ID( $opt_rtag_id );
174
    if ( $opt_rootpkg )
175
    {
176
        #
177
        #   Base the report on a single package in a release
178
        #   Determine the package
179
        #
180
        Error ("Root Package not found: $opt_rootpkg") unless ( exists $Release{$opt_rootpkg} );
181
        my @root_vers = keys %{$Release{$opt_rootpkg}};
182
        Error ("Multiple versions of Root Package: $opt_rootpkg", @root_vers ) if ( $#root_vers > 0 );
183
        $opt_rootpkg_version = $root_vers[0];
184
        Message("Root Package: $opt_rootpkg, " . $opt_rootpkg_version);
185
 
186
        getPkgDetailsByPV_ID( $Release{$opt_rootpkg}{$opt_rootpkg_version}{pv_id} );
187
    }
188
    else
189
    {
190
        getPkgDetailsForPVIDs (keys %Release_pvid);
191
    }
192
    LocateStrays(1);
193
}
194
elsif ( $#ARGV >= 1 )
195
{
196
    #
197
    #   Locate package and dependents
198
    #   Convert package name into a PVID
199
    #
200
    my $pv_id = getPkgDetailsByName( @ARGV );
201
    Error ("Cannot locate package by name and version: @ARGV")
202
        unless ( $pv_id );
203
 
204
    #
205
    #   Set package as the root package
206
    $opt_rootpkg = $ARGV[0];
207
    $opt_rootpkg_version = $ARGV[1];
208
    getPkgDetailsByPV_ID( $pv_id  );
209
    LocateStrays(2);
210
}
211
else
212
{
213
    Error ("Don't know what to do with common line arguments provided");
214
}
215
 
216
 
217
#
218
#   Remove packages to be ignored
219
#
220
foreach my $pkg ( keys %ignore )
221
{
222
    delete $Package{$pkg};
223
}
224
 
225
##
226
##   Display a list of all packages found so far
227
##
228
#foreach my $name ( sort keys %Package )
229
#{
230
#    foreach my $ver ( sort keys %{$Package{$name}} )
231
#    {
232
#
233
#        my $tag = $Package{$name}{$ver}{vcstag} || '';
234
#
235
#        printf ("%30s %15s %s\n", $name, $ver, $tag );
236
#    }
237
#}
238
 
239
#
240
#   Generate output files
241
#       1) Jats extract commands
242
#       2) Error list
243
my $file;
244
$file = "${fpref}_extract.txt";
245
push @create_list, $file;
246
open (JE, ">$file" ) || Error ("Cannot create $file");
247
 
248
$file = "${fpref}_status.txt";
249
push @create_list, $file;
250
 
251
open (ST, ">$file" ) || Error("Cannot create $file");
252
print ST "Cannot build:\n";
253
 
254
my $missing_count = 0;
255
my $pkg_count = 0;
256
foreach my $name ( sort keys %Package )
257
{
258
    foreach my $ver ( sort keys %{$Package{$name}} )
259
    {
260
       my $pdir = catdir($::GBE_DPKG, $name, $ver);
261
       my $tfile = catfile( $pdir, 'descpkg');
262
       $pkg_count++;
263
 
264
       if (! -d $pdir )
265
       {
266
           Warning("Not in dpkg_archive: $name $ver");
267
           $missing_count++;
268
           next;
269
       }
270
 
271
       if (! $tfile)
272
       {
273
           Warning("Not in dpkg_archive: $name $ver - Bad Form");
274
           $missing_count++;
275
           next;
276
       }
277
    }
278
}
279
 
280
Message("Packages: $pkg_count");
281
Message("Missing: $missing_count");
282
 
283
close (JE);
284
close (ST);
285
 
286
 
287
#
288
#   Display names of files created
289
#
290
foreach my $file ( sort @create_list )
291
{
292
    Message ("Created: $file");
293
}
294
exit;
295
 
296
 
297
#-------------------------------------------------------------------------------
298
# Function        : getSBOMDetails
299
#
300
# Description     : Get some details about the SBOM
301
#                   Used fro descriptive text
302
#
303
# Inputs          : $bom_id             - BOM to process
304
#
305
# Returns         : 
306
#
307
sub getSBOMDetails
308
{
309
    my ($bom_id) = @_;
310
    my $foundDetails = 0;
311
    my (@row);
312
Verbose ("getSBOMDetails");
313
    connectDM(\$DM_DB) unless ($DM_DB);
314
 
315
    my $m_sqlstr = "SELECT distinct dp.PROJ_NAME ,bn.BOM_NAME, br.BRANCH_NAME, bm.BOM_VERSION, bm.BOM_LIFECYCLE" .
316
                   " FROM DEPLOYMENT_MANAGER.BOMS bm, DEPLOYMENT_MANAGER.BOM_NAMES bn, DEPLOYMENT_MANAGER.BRANCHES br, DEPLOYMENT_MANAGER.DM_PROJECTS dp" .
317
                   " WHERE bm.BOM_ID = $bom_id AND bm.BOM_NAME_ID = bn.BOM_NAME_ID AND bm.BRANCH_ID = br.BRANCH_ID AND br.PROJ_ID = dp.PROJ_ID";
318
 
319
    my $sth = $DM_DB->prepare($m_sqlstr);
320
    if ( defined($sth) )
321
    {
322
        if ( $sth->execute( ) )
323
        {
324
            if ( $sth->rows )
325
            {
326
                while ( @row = $sth->fetchrow_array )
327
                {
328
                    $sbom_project   = $row[0];
329
                    $sbom_name      = $row[1];
330
                    $sbom_branch    = $row[2];
331
                    $sbom_version   = $row[3] . '.' . $row[4];
332
                    $foundDetails = 1;
333
                }
334
            }
335
            $sth->finish();
336
        }
337
        else
338
        {
339
            Error("getSBOMDetails:Execute failure", $m_sqlstr );
340
        }
341
    }
342
    else
343
    {
344
        Error("getSBOMDetails:Prepare failure" );
345
    }
346
 
347
    Error("getSBOMDetails:No OS Information Found" ) unless $foundDetails;
348
 
349
}
350
 
351
#-------------------------------------------------------------------------------
352
# Function        : getReleaseDetails
353
#
354
# Description     : Get some details about the Release
355
#                   Used fro descriptive text
356
#
357
# Inputs          : $rtag_id             - RTAG_ID to process
358
#
359
# Returns         : 
360
#
361
sub getReleaseDetails
362
{
363
    my ($rtag_id) = @_;
364
    my $foundDetails = 0;
365
    my (@row);
366
Verbose ("getReleaseDetails");
367
    connectDM(\$DM_DB) unless ($DM_DB);
368
 
369
    my $m_sqlstr = "SELECT distinct rt.RTAG_NAME, pr.PROJ_NAME" .
370
                   " FROM RELEASE_MANAGER.RELEASE_TAGS rt, RELEASE_MANAGER.PROJECTS pr" .
371
                   " WHERE rt.RTAG_ID = $rtag_id AND rt.PROJ_ID = pr.PROJ_ID";
372
 
373
    my $sth = $DM_DB->prepare($m_sqlstr);
374
    if ( defined($sth) )
375
    {
376
        if ( $sth->execute( ) )
377
        {
378
            if ( $sth->rows )
379
            {
380
                while ( @row = $sth->fetchrow_array )
381
                {
382
                    $rtag_release = $row[0];
383
                    $rtag_project = $row[1];
384
                    $foundDetails = 1;
385
                }
386
            }
387
            $sth->finish();
388
        }
389
        else
390
        {
391
            Error("getReleaseDetails:Execute failure", $m_sqlstr );
392
        }
393
    }
394
    else
395
    {
396
        Error("getReleaseDetails:Prepare failure" );
397
    }
398
 
399
    Error("getReleaseDetails:No OS Information Found" ) unless $foundDetails;
400
 
401
}
402
 
403
 
404
 
405
#-------------------------------------------------------------------------------
406
# Function        : getOSIDforBOMID
407
#
408
# Description     : Get all the os_id's associated with a BOMID
409
#                   Also get base_env_id's where they exist
410
#
411
# Inputs          : $bom_id             - BOM to process
412
#
413
# Returns         :
414
#
415
 
416
sub getOSIDforBOMID
417
{
418
    my ($bom_id) = @_;
419
    my $foundDetails = 0;
420
    my (@row);
421
    Verbose ("getOSIDforBOMID");
422
    connectDM(\$DM_DB) unless ($DM_DB);
423
 
424
    my $m_sqlstr = qq{
425
                   SELECT distinct os.OS_ID, os.OS_NAME, nn.NODE_NAME, obe.BASE_ENV_ID 
426
                    FROM DEPLOYMENT_MANAGER.OPERATING_SYSTEMS os,
427
                         DEPLOYMENT_MANAGER.BOM_CONTENTS bc,
428
                         DEPLOYMENT_MANAGER.NETWORK_NODES nn,
429
                         DEPLOYMENT_MANAGER.OS_BASE_ENV obe
430
                    WHERE bc.BOM_ID = $bom_id
431
                      AND bc.NODE_ID = os.NODE_ID
432
                      AND nn.NODE_ID = os.NODE_ID
433
                      AND obe.OS_ID (+) = os.OS_ID
434
                      };
435
    my $sth = $DM_DB->prepare($m_sqlstr);
436
    if ( defined($sth) )
437
    {
438
        if ( $sth->execute( ) )
439
        {
440
            if ( $sth->rows )
441
            {
442
                while ( @row = $sth->fetchrow_array )
443
                {
444
                    Verbose ("OS_ID: ".join (',',@row) );
445
                    $os_id_list{$row[0]}{os_name} = $row[1];
446
                    $os_id_list{$row[0]}{node_name} = $row[2];
447
 
448
                    if ( defined $row[3] )
449
                    {
450
                        $os_env_list{$row[3]}{needed} = 1;
451
                        $os_env_list{$row[3]}{os_id}{$row[0]} = 1;
452
                    }
453
 
454
                    $foundDetails = 1;
455
                }
456
            }
457
            $sth->finish();
458
        }
459
        else
460
        {
461
            Error("getOSIDforBOMID:Execute failure" );
462
        }
463
    }
464
    else
465
    {
466
        Error("getOSIDforBOMID:Prepare failure" );
467
    }
468
 
469
    Error("getOSIDforBOMID:No OS Information Found" ) unless $foundDetails;
470
 
471
}
472
 
473
#-------------------------------------------------------------------------------
474
# Function        : getPackagesforBaseInstall
475
#
476
# Description     : Get all the packages for a given base install
477
#
478
# Inputs          :
479
#
480
# Returns         :
481
#
482
 
483
sub getPackagesforBaseInstall
484
{
485
    my ($base_env_id) = @_;
486
    my $foundDetails = 0;
487
    my (@row);
488
 
489
    connectDM(\$DM_DB) unless ($DM_DB);
490
 
491
    # First get details from pv_id
492
 
493
    my $m_sqlstr = "SELECT DISTINCT bec.PROD_ID, pkg.pkg_name, pv.pkg_version, pkg.pkg_id, pv.pv_id" .
494
                " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv, DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd, DEPLOYMENT_MANAGER.BASE_ENV_CONTENTS bec".
495
                " WHERE bec.BASE_ENV_ID = $base_env_id AND bec.PROD_ID (+)= pv.PV_ID AND pv.pkg_id = pkg.pkg_id";
496
 
497
    my $sth = $DM_DB->prepare($m_sqlstr);
498
    if ( defined($sth) )
499
    {
500
        if ( $sth->execute( ) )
501
        {
502
            if ( $sth->rows )
503
            {
504
                while ( @row = $sth->fetchrow_array )
505
                {
506
                    Verbose ("OS ENV Package($base_env_id}:" . join (',',@row) );
507
 
508
                    my $pv_id =     $row[0];
509
                    my $name =      $row[1]  || 'BadName';
510
                    my $ver =       $row[2]  || 'BadVer';
511
 
512
                    $pv_id{$pv_id}{pkg_name} =$name;
513
                    $pv_id{$pv_id}{pkg_ver} = $ver;
514
                    foreach my $os_id ( keys %{$os_env_list{$base_env_id}{os_id}} )
515
                    {
516
                        $pv_id{$pv_id}{os_id}{$os_id} = 2;
517
                    }
518
                }
519
            }
520
            $sth->finish();
521
        }
522
        else
523
        {
524
            Error ("getPackagesforBaseInstall: Execute error");
525
        }
526
    }
527
    else
528
    {
529
        Error("getPackagesforBaseInstall:Prepare failure" );
530
    }
531
 
532
}
533
 
534
 
535
#-------------------------------------------------------------------------------
536
# Function        : getPackages_by_osid
537
#
538
# Description     : Get all the packages used by a given os_id
539
#
540
# Inputs          :
541
#
542
# Returns         :
543
#
544
 
545
my $count = 0;
546
sub getPackages_by_osid
547
{
548
    my ($os_id) =@_;
549
    my $foundDetails = 0;
550
    my (@row);
551
 
552
    connectDM(\$DM_DB) unless ($DM_DB);
553
 
554
    # First get details from pv_id
555
 
556
    my $m_sqlstr = "SELECT osc.*, pkg.pkg_name, pv.pkg_version, pd.IS_REJECTED, pv.IS_PATCH,pv.IS_OBSOLETE, pkg.pkg_id, pv.pv_id" .
557
                " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv, DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd,".
558
                "(" .
559
                " SELECT osc.seq_num, osc.prod_id".
560
                " FROM DEPLOYMENT_MANAGER.os_contents osc".
561
                " WHERE osc.os_id = $os_id" .
562
                " ) osc" .
563
                " WHERE pd.PROD_ID (+)= pv.PV_ID" .
564
                "   AND pv.pkg_id = pkg.pkg_id" .
565
                "   AND osc.PROD_ID = pv.pv_id" .
566
                " ORDER BY osc.SEQ_NUM desc" ;
567
 
568
    my $sth = $DM_DB->prepare($m_sqlstr);
569
    if ( defined($sth) )
570
    {
571
        if ( $sth->execute( ) )
572
        {
573
            if ( $sth->rows )
574
            {
575
                while ( @row = $sth->fetchrow_array )
576
                {
577
next if ( $opt_test && ++$count > 2 );
578
                    Verbose ("SBOM Package:".join (',',@row) );
579
                    my $pv_id =     $row[8];
580
                    my $name =      $row[2]  || 'BadName';
581
                    my $ver =       $row[3]  || 'BadVer';
582
 
583
                    $pv_id{$pv_id}{pkg_name} =$name;
584
                    $pv_id{$pv_id}{pkg_ver} = $ver;
585
                    $pv_id{$pv_id}{os_id}{$os_id} = 1;
586
                }
587
            }
588
            $sth->finish();
589
        }
590
    }
591
    else
592
    {
593
        Error("getPackages_by_osid:Prepare failure" );
594
    }
595
}
596
 
597
#-------------------------------------------------------------------------------
598
# Function        : getPkgDetailsByPV_ID
599
#
600
# Description     : Populate the Packages structure given a PV_ID
601
#                   Called for each package in the SBOM
602
#
603
# Inputs          : PV_ID           - Package Unique Identifier
604
#
605
# Returns         : Populates Package
606
#
607
sub getPkgDetailsByPV_ID
608
{
609
    my ($PV_ID) = @_;
610
    my $foundDetails = 0;
611
    my (@row);
612
 
613
    connectRM(\$RM_DB) unless ($RM_DB);
614
 
615
    # First get details from pv_id
616
 
617
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION, pv.IS_DEPLOYABLE, pbi.BSA_ID, pbi.BM_ID, PV_DESCRIPTION, release_manager.PK_RMAPI.return_vcs_tag($PV_ID)" .
618
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_BUILD_INFO pbi" .
619
                    " WHERE pv.PV_ID = \'$PV_ID\' AND pv.PKG_ID = pkg.PKG_ID AND pv.PV_ID = pbi.PV_ID (+) ";
620
 
621
    my $sth = $RM_DB->prepare($m_sqlstr);
622
    if ( defined($sth) )
623
    {
624
        if ( $sth->execute( ) )
625
        {
626
            if ( $sth->rows )
627
            {
628
                while ( @row = $sth->fetchrow_array )
629
                {
630
                    my $pv_id       = $row[0];
631
                    my $name        = $row[1];
632
                    my $ver         = $row[2];
633
                    my $deployable  = $row[3];
634
                    my $build_info  = $row[4] || '';
635
                    my $build_mach  = $row[5] || '';
636
                    my $description = $row[6] || '';
637
                    my $vcstag      = $row[7] || '';
638
 
639
                    #
640
                    #   BSA_ID: 1:debug, 2:prod, 3:debug+prod, 4:Java1.4 5: Java 1.5
641
                    #   BM_ID : 1:solaris, 2:win32, 3: linux, 4:generic
642
                    #
643
 
644
 
645
                    #
646
                    #   Does it look like a patch
647
                    #   We may want to ignore it.
648
                    #
649
                    my $patch = "";
650
                    unless ( $opt_patch )
651
                    {
652
                        if ( $ver =~ m~\.p\d+.\w+$~ )
653
                        {
654
                            $patch = "Patch";
655
                            $patch{$name} = 0
656
                                unless (  exists $patch{$name} );
657
                            $patch{$name}++;
658
                        }
659
                    }
660
                    Verbose ("getPkgDetailsByPV_ID: $PV_ID, $name, $ver, $build_mach ,$build_info, $patch");
661
                    next if ( $patch );
662
 
663
 
664
                    if ( exists $ignore{$name} )
665
                    {
666
                        Verbose2( "    Ignoring: $PV_ID, $name, $ver, $build_mach ,$build_info, $patch\n");
667
                        $ignore{$name}++;
668
                        last;
669
                    }
670
 
671
                    $vcstag =~ tr~\\/~/~;
672
 
673
                    $Package{$name}{$ver}{pvid} = $PV_ID;
674
                    $Package{$name}{$ver}{done} = 1;
675
                    $Package{$name}{$ver}{base} = 1;
676
                    $Package{$name}{$ver}{deployable} = 1 if ($deployable);
677
                    $Package{$name}{$ver}{build}{$build_mach} = $build_info if $build_mach;
678
                    $Package{$name}{$ver}{description} = $description;
679
                    $Package{$name}{$ver}{vcstag} = $vcstag;
680
 
681
                    GetDepends( $pv_id, $name, $ver );
682
 
683
                }
684
            }
685
            else
686
            {
687
                Warning ("No Package details for: PVID: $PV_ID");
688
            }
689
            $sth->finish();
690
        }
691
        else
692
        {
693
            Error("getPkgDetailsByPV_ID: Execute failure", $m_sqlstr );
694
        }
695
    }
696
    else
697
    {
698
        Error("Prepare failure" );
699
    }
700
}
701
 
702
#-------------------------------------------------------------------------------
703
# Function        : getPkgDetailsByName
704
#
705
# Description     : Determine the PVID for a given package name and version
706
#
707
# Inputs          : $pname          - Package name
708
#                   $pver           - Package Version
709
#
710
# Returns         : 
711
#
712
 
713
sub getPkgDetailsByName
714
{
715
    my ($pname, $pver) = @_;
716
    my $pv_id;
717
    my (@row);
718
 
719
    connectRM(\$RM_DB) unless ($RM_DB);
720
 
721
    # First get details for a given package version
722
 
723
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION" .
724
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
725
                    " WHERE pkg.PKG_NAME = \'$pname\' AND pv.PKG_VERSION = \'$pver\' AND pv.PKG_ID = pkg.PKG_ID";
726
    my $sth = $RM_DB->prepare($m_sqlstr);
727
    if ( defined($sth) )
728
    {
729
        if ( $sth->execute( ) )
730
        {
731
            if ( $sth->rows )
732
            {
733
                while ( @row = $sth->fetchrow_array )
734
                {
735
                    $pv_id = $row[0];
736
                    my $name = $row[1];
737
                    my $ver = $row[2];
738
                    Verbose( "getPkgDetailsByName :PV_ID= $pv_id");
739
                }
740
            }
741
            $sth->finish();
742
        }
743
    }
744
    else
745
    {
746
        Error("Prepare failure" );
747
    }
748
    return $pv_id;
749
}
750
 
751
#-------------------------------------------------------------------------------
752
# Function        : getPkgDetailsForPVIDs
753
#
754
# Description     : Get all package details by PVID, from a list of PVIDs
755
#
756
# Inputs          : List of PVID's to process
757
#
758
# Returns         : Nothing
759
#
760
sub getPkgDetailsForPVIDs
761
{
762
 
763
    my $count = 0;
764
    foreach my $pv_id ( @_ )
765
    {
766
        next if ( $opt_test && ++$count > 2 );
767
        getPkgDetailsByPV_ID( $pv_id);
768
    }
769
}
770
 
771
#-------------------------------------------------------------------------------
772
# Function        : GetDepends
773
#
774
# Description     : Extract the dependancies for a given package version
775
#                   Ignore pegged and SDK packages
776
#
777
# Inputs          : $pvid
778
#
779
# Returns         :
780
#
781
sub GetDepends
782
{
783
    my ($pv_id, $pname, $pver ) = @_;
784
 
785
    connectRM(\$RM_DB) unless ($RM_DB);
786
    if (exists $Pegged{$pv_id})
787
    {
788
        Verbose("$pname, $pver is pegged");
789
        return;
790
    }
791
 
792
    #
793
    #   Now extract the package dependacies
794
    #
795
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pv.PKG_VERSION, pd.DPV_ID" .
796
                   " FROM RELEASE_MANAGER.PACKAGE_DEPENDENCIES pd, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
797
                   " WHERE pd.PV_ID = \'$pv_id\' AND pd.DPV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
798
    my $sth = $RM_DB->prepare($m_sqlstr);
799
    if ( defined($sth) )
800
    {
801
        if ( $sth->execute( ) )
802
        {
803
            if ( $sth->rows )
804
            {
805
                my %depends;
806
                while ( my @row = $sth->fetchrow_array )
807
                {
808
#print "$pname $pver ===== @row\n";
809
                    my $name = $row[0];
810
                    my $ver = $row[1];
811
 
812
                    Verbose2( "       Depends: $name, $ver");
813
 
814
                    $depends{$name,$ver} = 1;
815
                    $Package{$name}{$ver}{usedby}{$pname,$pver} = 1;
816
 
817
                    unless ( exists $Package{$name}{$ver}{done} )
818
                    {
819
                        my @DATA = ($name, $ver, $row[2]);
820
                        push @StrayPackages, \@DATA;
821
                    }
822
                }
823
                $Package{$pname}{$pver}{depends} = \%depends;
824
            }
825
            $sth->finish();
826
        }
827
    }
828
    else
829
    {
830
        Error("GetDepends:Prepare failure" );
831
    }
832
}
833
 
834
#-------------------------------------------------------------------------------
835
# Function        : getPkgDetailsByRTAG_ID
836
#
837
# Description     : Extract all the packages for a given rtag_id
838
#
839
# Inputs          : RTAG_ID
840
#
841
# Returns         : 
842
#
843
 
844
sub getPkgDetailsByRTAG_ID
845
{
846
    my ($RTAG_ID) = @_;
847
    my $foundDetails = 0;
848
    my (@row);
849
 
850
    connectRM(\$RM_DB);
851
 
852
    # First get details from pv_id
853
 
854
    my $m_sqlstr = "
855
                SELECT pv.PV_ID, 
856
                  pkg.PKG_NAME, 
857
                  pv.PKG_VERSION, 
858
                  rc.SDKTAG_ID, 
859
                  NVL2(peg.pv_id,1,0) as pegged 
860
                FROM RELEASE_MANAGER.RELEASE_CONTENT rc, 
861
                  RELEASE_MANAGER.PACKAGE_VERSIONS pv, 
862
                  RELEASE_MANAGER.PEGGED_VERSIONS peg, 
863
                  RELEASE_MANAGER.PACKAGES pkg 
864
                WHERE rc.RTAG_ID = $RTAG_ID 
865
                 AND rc.PV_ID     = pv.PV_ID 
866
                 AND pv.PKG_ID    = pkg.PKG_ID 
867
                 AND peg.RTAG_ID (+) = rc.RTAG_ID 
868
                 AND peg.PV_ID (+) = rc.pv_id
869
                ";
870
        $m_sqlstr=~ s~\s+~ ~g;
871
 
872
    my $sth = $RM_DB->prepare($m_sqlstr);
873
    if ( defined($sth) )
874
    {
875
        if ( $sth->execute( ) )
876
        {
877
            if ( $sth->rows )
878
            {
879
                while ( @row = $sth->fetchrow_array )
880
                {
881
                    my $pv_id   = $row[0];
882
                    my $name    = $row[1];
883
                    my $ver     = $row[2];
884
                    my $sdk     = $row[3] || 0;
885
                    my $peg     = $row[4];
886
                    Verbose ("getPkgDetailsByRTAG_ID: $RTAG_ID, $name, $ver, $pv_id, $sdk, $peg");
887
 
888
                    $Release{$name}{$ver}{pv_id} = $pv_id;
889
                    $Release_pvid{$pv_id} = 1;
890
                    $Pegged{$pv_id} = 1 if ($sdk | $peg);
891
                }
892
            }
893
            $sth->finish();
894
        }
895
        else
896
        {
897
            Error("Execute failure. getPkgDetailsByRTAG_ID: $m_sqlstr", $sth->errstr() );
898
 
899
        }
900
    }
901
    else
902
    {
903
        Error("getPkgDetailsByRTAG_ID:Prepare failure" );
904
    }
905
}
906
 
907
 
908
#-------------------------------------------------------------------------------
909
# Function        : LocateStrays
910
#
911
# Description     : Locate stray packages
912
#                   These are packages that have not been defined by the
913
#                   top level SBOM. These are not really stray
914
#
915
# Inputs          : $mode           2: No stray tagging
916
#                                   0: Mark all as stray
917
#                                   1: Don't mark packages as stray
918
#                                      if they are in releases hash
919
# Returns         : Nothing
920
#
921
sub LocateStrays
922
{
923
    my ($mode) = @_;
924
    while ( $#StrayPackages >= 0 )
925
    {
926
        my $DATA = pop @StrayPackages;
927
        my $name = $DATA->[0];
928
        my $ver = $DATA->[1];
929
        my $pv_id = $DATA->[2];
930
 
931
        next if ( exists $Package{$name}{$ver}{done} );
932
        getPkgDetailsByPV_ID ( $pv_id );
933
 
934
        next if ( $mode > 1 );
935
        if ( $mode )
936
        {
937
            next if ( exists $Release{$name}{$ver} );
938
        }
939
        $Package{$name}{$ver}{stray} = 1;
940
#print "Stray: $pv_id, $name, $ver\n";
941
    }
942
}
943
 
944
#-------------------------------------------------------------------------------
945
#   Documentation
946
#
947
 
948
=pod
949
 
950
=head1 NAME
951
 
952
checkRelease - Check Release/SBOM packages against dpkg_archive
953
 
954
=head1 SYNOPSIS
955
 
956
  jats escrow [options] [name version]
957
 
958
 Options:
959
    -help              - brief help message
960
    -help -help        - Detailed help message
961
    -man               - Full documentation
962
    -sbomid=xxx        - Specify the SBOM to process
963
    -rtagid=xxx        - Specify the Release to process (Optional)
964
    -rootpackage=xxx   - Specifies a root package. In conjunction with -rtagid.
965
    -ignore=name       - Ignore packages with the specified name
966
    -verbose           - Enable verbose output
967
    -[no]patch         - Ignore/Include patches. Default:Include
968
    -[no]test          - Reduced package scanning for test
969
 
970
=head1 OPTIONS
971
 
972
=over 8
973
 
974
=item B<-help>
975
 
976
Print a brief help message and exits.
977
 
978
=item B<-help -help>
979
 
980
Print a detailed help message with an explanation for each option.
981
 
982
=item B<-man>
983
 
984
Prints the manual page and exits.
985
 
986
=item B<-sbomid=xxx>
987
 
988
This option specifies the SBOM to process. The sbomid must be determined from
989
Deployment Manager.
990
 
991
=item B<-rtagid=xxx>
992
 
993
This option specified an RTAG_ID that must be determined from Release Manager.
994
 
995
This option may be used with or without the B<-sbomid=xxx> option.
996
 
997
With an SBOM_ID this option specifies an RTAG_ID to process in conjunction with the SBOM.
998
The program will determine packages that are in the Release, but not in the
999
SBOM.
1000
 
1001
Without an SBOM_ID, this option will limit the processing to the specified
1002
release. Less information is generated. This form of the generation may be
1003
combined with B<-rootpackage=xxx> to further limit the set of packages
1004
processed.
1005
 
1006
=item B<-rootpackage=xxx>
1007
 
1008
This option can be used in conjunction with B<-rtagid=xxx> to limit the
1009
extraction to named package and all of its dependent packages. The tool will
1010
determine the required version of the package via the specified release.
1011
 
1012
=item B<-ignore=name>
1013
 
1014
All versions of the named package will be ignored. This parameter is options.
1015
It may be used multiple times.
1016
 
1017
=item B<-[no]patch>
1018
 
1019
This option is used ignore patches. If -nopatch is selected, then packages
1020
versions that look like a patch will be added to the ignore list.
1021
 
1022
=item B<-[no]test>
1023
 
1024
This option is used for testing. It will only process the first two OS entries
1025
in the SBOM. This speeds up processing. It does not generate a complete list of
1026
packages.
1027
 
1028
=item B<-verbose>
1029
 
1030
This option will display progress information as the program executes.
1031
 
1032
=back
1033
 
1034
=head1 DESCRIPTION
1035
 
1036
This program is a tool for extracting Escrow build information.
1037
The program has two modes of operation:
1038
 
1039
=over 8
1040
 
1041
=item 1
1042
 
1043
Generation. Generate files describing packages within an SBOM/Release/
1044
Package.
1045
 
1046
=item 2
1047
 
1048
Extraction  Supervise extraction of source trees.
1049
 
1050
=back
1051
 
1052
=head2 Generation Operations
1053
 
1054
This program has several modes of operation. The mode is determined from the
1055
command line arguments provided.
1056
 
1057
=over 8
1058
 
1059
=item   Full Escrow
1060
 
1061
This mode requires an SBOM_ID. If an RTAG_ID is also provided, then additional
1062
information will be generated.
1063
 
1064
=item   Release Escrow
1065
 
1066
If only an RTAG_ID is provided then the processing wil be limited to the
1067
packages involved in creating the specified release.
1068
 
1069
If a 'rootpackage' name is provided, then the processing is limited to
1070
packages that depend on the named package.
1071
 
1072
=item   Single Package
1073
 
1074
If a package name and a package version are specified on the command line,
1075
then the processing will be limited to the specified package and ist dependents.
1076
No release related information will be provided.
1077
 
1078
=back
1079
 
1080
The 'Full Escrow' extract is the complete operation. All others are sub-sets of
1081
this processing. The complete processing is:
1082
 
1083
=over 8
1084
 
1085
=item *
1086
 
1087
Determine all the NODES in the SBOM
1088
 
1089
=item *
1090
 
1091
Determine all the Base Packages for each NODE
1092
 
1093
=item *
1094
 
1095
Determine all the Packages for each NODE
1096
 
1097
=item *
1098
 
1099
Determine all the dependent packages for all packages encountered
1100
 
1101
=item *
1102
 
1103
Generate a list of jats commands to extract the package source
1104
 
1105
=item *
1106
 
1107
Generate a file describing the build order
1108
 
1109
=item *
1110
 
1111
Generate a file describing the packages that cannot be built
1112
 
1113
=item *
1114
 
1115
Generate an HTML file with extensive cross reference information
1116
 
1117
=over 8
1118
 
1119
=item *
1120
 
1121
List of all packages with references into Release Manager
1122
 
1123
=item *
1124
 
1125
List of all packages showing dependent packages
1126
 
1127
=item *
1128
 
1129
List of all packages showing consumer packages
1130
 
1131
=item *
1132
 
1133
List of all packages for which multiple versions are required
1134
 
1135
=item *
1136
 
1137
Details of packages that are not built.
1138
 
1139
=item *
1140
 
1141
Build order
1142
 
1143
=item *
1144
 
1145
Build machines and built types
1146
 
1147
=item *
1148
 
1149
Deployed target nodes, with references into Deployment Manager
1150
 
1151
=back
1152
 
1153
=back
1154
 
1155
This may take some time, as a typical escrow build may contain many hundreds of packages.
1156
 
1157
The program will display a list of files that have been created.
1158
 
1159
=head2 Extraction Operations
1160
 
1161
Given an 'extract' file from a previous run of this program the program will:
1162
 
1163
=over 8
1164
 
1165
=item *
1166
 
1167
Parse the 'extract' file
1168
 
1169
=item *
1170
 
1171
Create subdirectories for each package version within the file. This is done
1172
in such a way that no views are left in place.
1173
 
1174
=item *
1175
 
1176
Create a log file showing packages that could not be extracted.
1177
 
1178
=back
1179
 
1180
=cut
1181