Creating
Reuseable Perl Scripts
Using
An OO Model
Of
The ClearCase Region
Author: Leslie D.
Paul
Many companies create ClearCase Perl
Scripts to expand and enhance the core functionality of the ClearCase
system. Scripts can be created to
generate reports, perform administrative functions, update ClearCase
attributes, and deploy releases. The
development and maintenance of these scripts can consume hundreds of hours. For example, scripts that contain hard coded
lists of VOB names can not be reused in another Region without editing the
script.
This paper presents an approach to
designing Perl Scripts for reuse across regions and platforms. The design approach is to create an OO Model
of the ClearCase Region defined in a module, and then to build Perl Scripts on
top of the Region Object (module).
The reader should be familiar with Perl
Programming, OO Modeling and ClearCase.
For OO Perl Programming, the reader is referred to the online Perl
documentation (execute perldoc perltoot at the command line) and to the
O’Reilly (Panther) book entitled “Advanced Perl Programming” by Sriram
Srinivasan and to Damian Conway’s book “Object Oriented Perl”.
For those not familiar with
Object Oriented Perl Programming, here are some of the key benefits and
terminology.
Data is encapsulated and
protected within objects. The object’s data is known as attribute values. The object’s subroutines that control access
to the attributes are called methods. An object has the following:
·
Identity or name
·
Attributes
·
Methods
A class is a formal specification for creating instances of
objects. The class defines the allowed
attributes names and the methods that are used within an object to access or
update attribute values. Classes within
Perl are defined in a separate text file called a module. A class is a Perl
module that follows some simple rules (see ‘perldoc perlobj’ for more details).
The encapsulation of data within an object is one of the key benefits
of OO programming. Many programs can
share the same object, but the data within the object cannot be accessed
directly. Instead of using global
variables, OO programs rely on an Object to be the single point of control for
attribute values.
A OO model could be created for ClearCase. Here one:
A region is composed of
vobs. Each vob can have many views
associated with it. A Vob consists of
Elements. A Element has one or more branches
(assumes a main branch). A branch consists
of one or more versions.
Since the objective of this
paper is to show a reuseable design approach – only the ‘region’ and ‘vob’
classes are considered here. Using just
the Region and Vob classes, the approach to creating reuseable Perl scripts can
be illustrated. We’ll start by defining
what a region is.
Careful thought should be given to the
task of defining a Region. The tools and
design approach presented here works best when Region(s) are clearly
defined. The design and organization of
a corporate network is closely tried to the concept of Region. Corporate networks involve three essential
structural components: Domains(s),
Organization Units (OU), and Site(s).
A domain is a logical grouping of
computers for administrative and security purposes. A domain is a logical grouping that is not
necessarily based on the physical location of computers. Hence, a domain can hold computers located in
multiple sites, or buildings, or just a single campus. For geographical dispersed computers, a WAN
or LAN is used to provide network connectivity.
A single domain can be sub-divided into
Organization Units. A company with a
single domain may have separate Organization Units or Divisions for Marketing,
Sales, Research, Manufacturing and Distribution. Each Division may use a WAN/LAN for
interconnecting multiple sites.
A ClearCase region is a conceptual
subset of the hosts of a single network domain based on a logical
grouping. A region could be an entire
domain. A region could be defined for
each Organization Unit within a domain.
A region could be defined for each site within an Organization Unit or
Division. In fact, a region could be
defined for a single computer used by a single group.
Splitting a large Region (one with many
VOBs) into two or more Regions will make the Region class execute faster –
since a region’s data is cached when the Region Class is loaded by a Perl
Script.
A Region is a logical subset of a local
area network where all hosts refer to all VOB and View storage areas through
the same network pathnames. All hosts
in a region will use the same global pathnames when referring to shared
resources.
All ClearCase servers must reside in a
region that is defined at the time of ClearCase installation.
To identify the region a server belongs
to, execute:
Ø
cleartool hostinfo -long
Client:
Product: ClearCase 5.0
Operating
System : SunOS 5.6 Generic
Registry
host: Chicago_sun50
Registry
region: credit_unix_region
License
host: Chicago_sun51
It’s possible to list all Regions
defined in the ClearCase Registry using the command:
Ø
cleartool lsregion
credit_unix_region
market_unix_region
To identify the region on a Unix host:
Ø
cat /var/adm/atria/rgy/rgy_region.conf
credit_unix_region
To identify the region on a Windows
host, open up the Registry tab of the ClearCase program in Control Panel.
A VOB is a ClearCase repository
associated with a single Region. A VOB
cannot span more than one region. By
running a long listing of a VOB, you can display the region associated with a
VOB:
Ø
cleartool lsvob –long /vobs/credit
Tag: /vobs/credit
Global path: \\chicago_sun51\vobstore\credit.vbs
Server host: Chicago_sun51
Access:
public
Mount options:
Region:
credit_unix_region
…
By knowing the region associated with a
server, you also know the set of available VOBs. To list all VOBs for a given region:
Ø
cleartool lsvob –region
credit_unix_region
/vobs/credit
The following diagram
illustrates the layered approach to the design of reuseable Perl scripts:
A Perl script can be designed
so that it is completely reuseable between sites. The reuseable Perl script uses one or more
instances of Objects created from a Perl Class.
The Perl Classes are mostly reuseable.
However, at the time the class library is installed, some minor editing
may be required. For example, the
location of the Configuration Files has to be added to Class.
The Region Class reads a
configuration file, region.conf, that contains data for all known regions. Hence, the region.conf file is site specific.
In addition, the Perl scripts
and modules presented here, use the Log::Log4perl class module available from
CPAN. The Log4perl class provides an OO
log management system. The Log4perl
class is designed after the popular Log4j class. All Perl scripts and objects presented here
will be available at the www.cpan.org web
site (search for ClearCase::Region).
A region consists of zero or
more VOBs. This composition can be
represented by the UML diagram:
This Rose model will be used
to illustrate a reuseable Perl Script Design approach.
An OO model of the ClearCase
Region is dependent on the network configuration, the ClearCase installation
and policies. However, the specific
network configuration and attributes (like region names) can be loaded into the
Region class using a text file. This
text file, called Region.cfg, will be read by the Region class when the class
is first loaded by a calling program.
As an example, let’s consider
a simple ClearCase network configuration.
In this scenario, a region contains one or more VOBs. Development projects also use one or more
VOBs, and all VOBs are within the same region.
Also, development projects never shared the same VOB. Hence, development projects form a
‘subregion’. Within each VOB, a simple
branch per release policy is used.
Here is a sample Region.cfg
for this scenario:
#*****************************************************************
# Region.cfg
#*****************************************************************
# This is the
configuration file that defines ClearCase region(s)
#*****************************************************************
#
# This file is read by
the Region.pm module. For each region,
the
# values are read and
loaded into a hash with the following keys:
# subregion,
description, vobs, vobdir. All of these
values must
# be defined in this
file.
#
# The file may contain
the configuration information for multiple
# regions. Configuration information for each region
must start
# with
['region_name']. All text starting with
a '#' character up
# to the end-of-line
are comments.
#
# NOTE 1: The keys (subregion, description, vobs,
vobdir)
# must be defined in this file in
lower case and listed
# in order for every record.
#
# NOTE 2: A Blank Line must terminate the subregion
record (of
# keys: subregion, description, vobs,
vobdir).
#
# NOTE 3: The subregion key must be the first entry
listed for
# each record and uniquely defines a
project within a
# region.
#
# NOTE 4: All string values must be quoted with
single quotes '.
#
# NOTE 5: All array values must be specified between
brackets
# (i.e. []).
#
#*****************************************************************
['market_unix_region']
subregion 'ma' # subregion id for a
project
description 'Market
Analysis' # project description
vobs [ 'current', 'futures' ] # array of all vobs
vobdir '/vobs'
subregion 'tr' # subregion id for a
project
description
'International trades' # project
description
vobs [ 'trades' ] # array of all vobs
vobdir '/vobs'
['credit_unix_region']
subregion 'cr' # subregion id for a
project
description
'Credit' # project
description
vobs [ 'credit' ] # array of all vobs
vobdir '/vobs'
The
Region.cfg file contains the ‘rules’ for entering the data. The Region class calls a simple ‘parser’ that
reads and parses the Region.cfg file when the class is first loaded. The parser is contained in a helper class,
Region_Cfg_Parser.pm, whose only purpose is to create a hash object for the
Region class. The
ClearCase::Region_Cfg_Parser->new() method reads the region.cfg files,
parses it, and returns a hash reference.
So, for ‘market_unix_region’, the new() method returns a hash reference
for a hash with two keys: ‘ma’ and
‘tr’. The associated values of these
keys are the subregion records (stored in another hash reference).
The
Region_Cfg_Parser module locates the Region.cfg configuration file by searching
all the directories in the @INC array.
When ClearCase::Region is downloaded from CPAN, the ‘default’
configuration file listed above is installed among with the modules. The Region.cfg file should be modified to
reflect your company’s ClearCase configuration.
The
Region_Cfg_Parser uses the name-value pairs in the Region.cfg configuration
file for creating the internal hash structure.
This makes it easy to add an attribute.
For example, by adding the line:
Registry_server ‘Chicago_sun66’
after
each vobdir line, the new attribute becomes part of the region hash – without
any changes to the parser. This can be
represented as:
Of
course, a new accessor method would have to added to Region.pm for this new
attribute.
Also,
the Region class checks to see what ClearCase Region it is operating
under. Under Unix, the Region class
opens the file ‘/var/adm/atria/rgy/rgy_region.conf” to obtain the region name. Under MS-Windows, the Region class opens
Registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Atria\ClearCase\CurrentVersion\InteropRegion
to
determine the ClearCase region.
So,
a program that uses Region class data for in the ‘market_unix_region’ sees that
only the VOB names “current”, “futures”, and “trades” are valid. The same program operating in the
‘credit_unix_region’ sees that only the VOB name ‘credit’ is valid.
The
Region constructor, new(), is used to create the Region object. Actually, the new() constructor creates a
‘subregion’ object having been passed a valid subregion name. So, how do we determine what subregion names
are valid in any given region? For
interactive Perl scripts, you can invoke the new() constructor as:
$region = Region->new(undef);
If
the new() constructor get an undef value for the subregion name, it will
provide a list of all valid subregion names and prompt the user to choose
one. Here’s an example of passing
‘undef’ to the new constructor in the market_unix_region:
Did
not get subregion for project. Must ask...
Please
select project:
1) International trades uses trades with project
id = "tr"
2) Market Analysis uses current futures with
project id = "ma"
Enter
1, 2, ... 2): 1
Another
approach to getting a valid subregion name is to first obtain a list of all
valid subregion names (for the region your operating in), and then use the
Getopt::long Perl Module to allow the user to ‘pass’ the choice on the command
line.
use Getopt::Long;
Then
the program can obtain a list of valid subregion names:
my(%options ) = (); #
command line parameters
my($i ) = 0;
my($subregion ) =
"";
my($subregion_name )
= undef;
my(@subregions ) =
Region->subregions();
my(@subregion_flags )
= ();
Then
set up the options hash (that is used by getoptions):
$i = 0;
foreach $subregion (@subregions) {
$subregion_flags[$i] =
0;
$options{$subregion} =
\$subregion_flags[$i];
$i++;
}
and
then call getoptions:
$retval = GetOptions(%options);
if ($retval == 0) {
$logger->error("Error
in parameter specification.\n");
exit
1;
}
If
the calling program has set one of the subregion options on the command line,
then the %options hash will have the corresponding member of the subregion_flag
array set. Of course, if an invalid
subregion name is passed on the command line, the GetOptions program will now
respond with an error – based on the list of valid subregion names obtained
from the Region class.
The
$subregion_name was initialized as ‘undef’.
If the user passed the subregion name as a command line option (like –tr
or –ma), then this can be determined using:
#
# Determine if the subregion was set
on the command line
#
$i = 0;
foreach $bno (@subregion_flags) {
$sum += $bno;
if ( $bno > 0 ) {
$subregion_name
= $subregions[$i];
}
$i++;
}
Next,
we check that no more than one option was passed on the command line:
#
# Determine if more than one
subregion was set on command line
#
if ($sum > 1) {
$logger->error("only
one region option can be specified.\n");
exit 1;
}
If
two or more options were passed on the command line (e.g. both –tr and –ma are
passed), then the Region new constructor fails will an error message. Calling ‘new’:
$region = Region->new($subregion_name);
will
create one subregion object. If no subregion is selected on the command line,
$subregion_name is undefined and the Region class will ‘prompt’ for one (see
the Region_test program example below).
The
Class method, subregions(), can be used to retrieve a list of all the
subregions in a region. To retrieve all
the Vob names in the current region, the following Perl code fragment could be
used:
my(@subregions) = Region->subregions();
foreach $subregion (@subregions) {
@vobs
= Region->vobs($subregion);
$logger->info("\nFor
subregion name \'$subregion\' all vobs are: @vobs\n");
}
This code was used in the
‘Region_test’ script that will be available on CPAN, along with the Region.pm
class module. When the Region_test
script is execute in the ‘market_unix_region’, it produces the following on in
my MS Command Prompt Window:
> perl Region_test
Current region is
market_unix_region
The subregions are tr ma
For subregion name 'tr' all
vobs are: trades
For subregion name 'tr' the
VOB directory is: /vobs
For subregion name 'ma' all
vobs are: current futures
For subregion name 'ma' the
VOB directory is: /vobs
Got tr : 0
Got ma : 0
Did not get subregion for
project. Must ask...
Please select project:
1)
International trades uses trades with project id = "tr"
2)
Market Analysis uses current futures with project id = "ma"
Enter 1, 2, ... 2): 1
Created Region object for tr
>
The sample program, main_cos
(available from CPAN) demonstrates the use of the Region class. The main_cos program is used to identify any
checked out revisions on the trunk (or main branch). The main_cos program expects to be passed one
subregion name on the command line:
main_cos –tr # OR
main_cos –cr
However, if the subregion
name option is omitted, the Region Class will prompt:
Please select project:
1) International trades uses trades with project
id = "tr"
2) Market Analysis uses current futures with
project id = "ma"
Enter
1, 2, ... 2): 1
So, the main_cos script can
be reused in different regions and subregions because the Region class
encapsulates the relevant data. The
main_cos script uses the variable ${vobdir) = Region->vobdir() to define the
VOB storage directory location for all VOBs.
The Region.pm class module
and all the associated sample scripts referenced in this paper are available
from CPAN. The Region module is not a
‘generic’ class that can be applied to every site, so some customization will
be required. The Region module assumes
that a branch per release version control policy is being used and hence,
contains methods that are most useful when using branch per release
management. Nevertheless, the Region
class is a great starting point for building reuseable objects within your
company – and then layering (or building) reuseable Perl scripts on top.
Include the line:
use ClearCase::Region;
in Perl scripts that will be
using the Region.pm module. This module
must either be installed in one of @INC directories, or specified in one of the
$PERL5LIB directories.
The Region.pm class module
and the associated sample scripts (Region_test, co_backup and main_cos) all use
the Log::Log4perl Class. Log::Log4perl
is freely available from CPAN and SourceForge (http://log4perl.sourceforge.net). The Log::Log4perl module requires the
Log::Dispatch bundle as well. If you
don’t have Log::Log4perl, use the CPAN module or PPM to upgrade your Perl
environment prior to using these programs.
The following Rose model is an OO model of the ClearCase VOB:
The sample script, Vob_test
can be used to test the Vob object.
Running Vob_test produces:
>perl Vob_test
All known vobs: trades
current futures
Did not get flag for vob.
Must ask...
Please select vob:
1)
trades
2)
current
3)
futures
Enter 1, 2, ... 3): 3
You have chosen futures. Is this CORRECT?(y/n): y
You answered Y
Selected vob is futures
Vob subregion via class
method is ma
Vob subregion via object
method is ma
src_dir is "source"
lib_dirs is
"lib,class"
relnums is
"1,2,3,4,5,6"
active is
"0,0,0,1,1,1"
active releases: "4 5
6"
Like the Region Class, the
Vob class also uses a help class, Vob_Cfg_Parser.pm, for the task of parsing
the Vob.cfg file. Here is the Vob.cfg
file that is being used here:
#*****************************************************************
# Vob.cfg
#*****************************************************************
# This is the configuration
file that defines ClearCase vob(s)
#*****************************************************************
#
# This file is read by the
Vob.pm module. For each region, the
# values are read and loaded
into a hash with the following keys:
# vob, src_dir, lib_dirs,
relnums, active. All of these values
must
# be defined in this file for
each [region subregion] section.
#
# The file may contain the
configuration information for multiple
# vobs. All configuration information for all vob
located in a
# subregion must start with
[region subregion] section header. All
# text starting with a '#'
character up to the end-of-line are
# comments.
#
# NOTE 1: The keys (vob, src_dir, lib_dirs, relnums,
active)
# must be defined in this file in
lower case and listed
# in order for every record.
#
# NOTE 2: A Blank Line must terminate the vob record
(of keys:
# vob, src_dir, lib_dirs, relnums, active).
#
# NOTE 3: The 'vob' key must be the first entry
listed for each
# record.
#
# NOTE 4: The first number identified in the relnums
array musts
# be the trunk.
#
# NOTE 5: The active releases array uses a '1' to
identify
# releases that are active. There must be a one-to-one
# correspondence between the relnums
array and the
# active array.
#
# NOTE 6: All string values must be quoted with
single quotes '.
#
# NOTE 7: All array values must be specified between
brackets
# (i.e. []).
#
#*****************************************************************
[market_unix_region ma]
vob 'current'
src_dir 'servlet/source'
lib_dirs ['servlet/lib', 'servlet/class']
relnums [
1, 2, 3, 4, 5, 6 ] # all release
numbers
active [
0, 0, 0, 1, 1, 1 ] # array of active
releases
vob 'futures'
src_dir 'source'
lib_dirs ['lib', 'class']
relnums [
1, 2, 3, 4, 5, 6 ] # all release
numbers
active [
0, 0, 0, 1, 1, 1 ] # array of active
releases
[market_unix_region tr]
vob 'trades'
src_dir 'src'
lib_dirs ['bin']
relnums [
1, 2, 3 ] # all release
numbers
active [
1, 1, 1 ] # array of active releases
[credit_unix_region cr]
vob 'credit'
src_dir 'src'
lib_dirs ['bin']
relnums [
2, 3, 4, 5 ] # all release
numbers
active [
1, 1, 1, 1 ] # array of active
releases
The rules for setting up the Vob.cfg
file are defined in the comments. Adding
an additional attribute is easy. For
example, the Group Id for each Vob could be added with the line:
group_id ‘bankofamerica’
after the ‘active’ line for
each Vob record. The
ClearCase::Vob_Cfg_Parser->new() method will then add the key, group_id, to
the hash reference to class Vob, as shown here:
Of course, the Vob.pm class
would have to be modified to include an accessor method as well.
The sample program, co_backup
(available from CPAN), demonstrates the use of both the Region class and the
Vob class to create a reuseable Perl script. The co_backup Perl script creates
a compress cpio backup of all checked out files in all dynamic views. Hence, the co_backup script can be used to
back up files that are being worked on by developers (in dynamic views) –
without having to back up the entire view.
In addition, this script only
cares about the ‘active’ releases (or views).
The co_backup script uses the Vob object to determine which releases
(branches) are active for a VOB. The
co_backup script assumes that all developer’s views follow a naming convention “<login>_<subregion>_<relno>”. Then by starting in the /view directory, all
developer’s views can be listed using:
cleartool lsview –short ‘*_${subregion}_${relno}’
Of course, if your company
has a different naming convention, then this line will need to change. The co_backup script will start the
developer’s view (if required). The list
of active releases is used to determine which developer’s views to back
up. So, for the “market_unix_region”
listed above, only the developer’s views:
‘*_tr_1’
‘*_tr_2’
‘*_tr_3’
‘*_ma_4’
‘*_ma_5’
‘*_ma_6’
will be backed up (provided
there is some checked out files). When
the co_backup program is executed on the ClearCase server in the
credit_unix_region, the developer’s views:
‘*_cr_2’
‘*_cr_3’
‘*_cr_4’
‘*_cr_5’
will be backed up. Hence, the co_backup script is reuseable in
different regions. If the co_backup
script encounters an error, like a bad view, it logs the error message to:
$HOME/logs/${subregion}${relno}.${vob}.backup.log
using the class
Log::Log4perl.
A Perl script can be designed
so that it is completely reuseable between sites. The reuseable Perl script uses one or more
instances of Objects created from a Perl Classes. The Perl Classes are mostly reuseable. For the co_backup script, this can be
represented as:
The design of the Perl
Classes depends on the network topology, defined Regions, defined subregions or
projects and the version control policy being used. This paper presented a simple network
configuration using a ‘branch per release’ version control policy is illustrate
the design of ClearCase classes for Region and Vob.
Using the Region and Vob
classes, many Perl scripts can be created that are reuseable between sites,
platforms and even companies. The sample
scripts provided with this paper can be used to start building your own
reuseable Perl Scripts.