Class: VCSConnectorRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/vcseif/vcs_connector_runner.rb

Constant Summary collapse

EXISTENCE_PROCLAMATION =
%{
************************************************************************************************************

     Rally VCSConnector starting at: %s  with pid: %s
           curdir: %s
          command: %s

************************************************************************************************************
}
STD_TS_FMT =
'%Y-%m-%d %H:%M:%S Z'
DEFAULT_ORIGIN_TIME =
(DateTime.now - 3).to_time

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ VCSConnectorRunner

Returns a new instance of VCSConnectorRunner.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/vcseif/vcs_connector_runner.rb', line 39

def initialize(config)
    """
        An instance of this class is instantiated with a Hash containing the 
        specifics of a configuration to direct the execution.  Some rudimentary 
        validation of the configuration is done, via use of an instance of a
        Konfabulator, with any detected problem noted and a ConfigurationError is 
        raised in that eventuality.
        Once those items are taken care of, the instance obtains an instance of a
        an AuxiliaryClassLoader instance and an instance of a VCSConnector.
        The AuxiliaryClassLoader is delegated the task of pulling in any Extension classes.
        These instances are then provided to the VCSConnector instance.
        This instance then runs the operate_service method that directs the VCSConnector 
        instance to obtain unrecorded changesets from the target VCS and reflect them in 
        the Rally server.
    """
    @logfile_name  = "%s/logs/%s.log" % [ENV['VCS_APP_ROOT'], config['ConfigName']]
    @lockfile_name = '%s/%s.LOCK'     % [ENV['VCS_APP_ROOT'], config['ConfigName']]
    @log = RallyLogger.new(@logfile_name)
    VCSEIF_Exceptions::logAllExceptions(true, @log)
    @config    = config
    @preview   = false
    @connector = nil
    @extension = {}
    @time_file = nil
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



18
19
20
# File 'lib/vcseif/vcs_connector_runner.rb', line 18

def config
  @config
end

#connectorObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def connector
  @connector
end

#extensionObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def extension
  @extension
end

#lockfile_nameObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def lockfile_name
  @lockfile_name
end

#logObject (readonly)

Returns the value of attribute log.



18
19
20
# File 'lib/vcseif/vcs_connector_runner.rb', line 18

def log
  @log
end

#logfile_nameObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def logfile_name
  @logfile_name
end

#previewObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def preview
  @preview
end

#time_fileObject (readonly)

the following declarations are necessary for testing, otherwise nothing accesses them except the instance



21
22
23
# File 'lib/vcseif/vcs_connector_runner.rb', line 21

def time_file
  @time_file
end

Instance Method Details

#acquireLockObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/vcseif/vcs_connector_runner.rb', line 74

def acquireLock
    """
        Check for conditions to proceed based on lock file absence/presence status.
        Acquisition of the lock is a green-light to proceed.
        Failure to acquire the lock prevents any further operation.
    """
    if LockFile.exists?(@lockfile_name)
        @log.warning("A %s file exists" % @lockfile_name)
        locker = LockFile.current_lock_holder(@lockfile_name)
        if not LockFile.locker_is_running?(@lockfile_name, locker)
            message =  "A prior connector process (%s) did not clean up "
            message << "the lock file on termination, proceeding with this run"
            @log.warn(message % locker)
        else
            @log.error("Another connector process [%s] is still running, unable to proceed" % locker)
            problem = "Simultaneous processes for this connector are prohibited"
            boomex = VCSEIF_Exceptions::UnrecoverableException.new(problem)
            raise boomex, problem
        end
    end

    LockFile.create_lock(@lockfile_name)
    return true
end

#buildTimeFileName(config_name) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/vcseif/vcs_connector_runner.rb', line 208

def buildTimeFileName(config_name)
    tf_name = "%s/time.file" % ENV['VCS_APP_ROOT']
    if not config_name.empty?
        tf_name = "%s/%s_time.file" % [ENV['VCS_APP_ROOT'], config_name]
    end
    return tf_name
end

#calc_last_commit_time(changesets, default) ⇒ Object



198
199
200
201
202
203
204
205
206
# File 'lib/vcseif/vcs_connector_runner.rb', line 198

def calc_last_commit_time(changesets, default)
  return default if changesets.nil? || changesets.empty?
  last = changesets.first # default
  last = changesets[-2] if changesets.length >= 2
  #the last commit we get is a timestamp value from Rally which is already in Zulu with milliseconds
  calctime = DateTime.parse(last["CommitTimestamp"]).to_time
  @log.debug("Calculated timefile value of #{calctime}")
  calctime
end

#inflateConfiguration(config) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/vcseif/vcs_connector_runner.rb', line 239

def inflateConfiguration(config)
    """
        Given a Hash with config info, obtain and return a Konfabulator instance
        that incorporates that config information into a form that provides an easy to
        use interface to access the configuration specification elements.
    """
    begin
        konfig = Konfabulator.new(config, @log)
    rescue VCSEIF_Exceptions::ConfigurationError => ex
        # info for this will have already been logged or blurted
        raise
    rescue VCSEIF_Exceptions::NonFatalConfigurationError => ex
        # info for this will have already been logged or blurted
        raise
    rescue Exception => ex
        raise StandardError, ex.message
    end

    svc_conf = konfig.topLevel('Services')
    @preview = false
    @preview = true if svc_conf and svc_conf['Preview'] == true
    @log.info('Preview mode in effect') if @preview
    @log_level = 'Info'
    ll = svc_conf['LogLevel'] || nil
    ll = ll.downcase.sub(/^(.)/) {$1.capitalize} unless ll.nil? # title case the result
    if ['Fatal', 'Error', 'Warn', 'Info', 'Debug'].include?(ll)
        @log_level = ll
        @log.set_level(@log_level)
        @log.info("LogLevel set to '%s'" % @log_level)
    #else
    #   bad LogLevel specified, do nothing, we've already defaulted to Info level
    end

    # TODO: enable this when a well-defined need for it has been established
    #if svc_conf.contains('PostBatchExtension')
    #    pba_class_name = svc_conf.get('PostBatchExtension')
    #    pba_class = ExtensionLoader.getExtension(pba_class_name)
    #    @extension['PostBatch'] = pba_class.new()
    #end

    return konfig
end

#proclaim_existenceObject



65
66
67
68
69
70
71
72
# File 'lib/vcseif/vcs_connector_runner.rb', line 65

def proclaim_existence
    proc = ProcTable.target_process($$) # $$ is the Ruby shorthand for Process.pid
    start_time = Time.now.utc.strftime(STD_TS_FMT)
    cmd_elements = proc.cmdline.split()
    cmd_elements[0] = File.basename(cmd_elements.first)
    proc.cmdline = cmd_elements.join(" ")
    @log.write(EXISTENCE_PROCLAMATION % [start_time, proc.pid, Dir.pwd, proc.cmdline])
end

#releaseLockObject



99
100
101
# File 'lib/vcseif/vcs_connector_runner.rb', line 99

def releaseLock
    LockFile.destroy_lock(@lockfile_name)
end

#runObject



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/vcseif/vcs_connector_runner.rb', line 105

def run
    proclaim_existence()
    own_lock = false
    own_lock = acquireLock()

    begin
        operateService()
    rescue Exception => ex
        raise
    ensure
        begin
            releaseLock() if own_lock
        rescue Exception => ex
            problem = "ERROR: unable to remove lock file '%s', %s" % [@lockfile_name, ex.message]
            shux = VCSEIF_Exceptions::OperationalError.new(problem)
            raise shux, problem
        end
    end

end