Source : dibs
-Version : 0.99.18
+Version : 0.99.20
Maintainer : taejun ha<taejun.ha@samsung.com>, jiil hyoun <jiil.hyoun@samsung.com>, donghyuk yang <donghyouk.yang@samsung.com>, donghee yang <donghee.yang@samsung.com>, sungmin kim <dev.sungmin.kim@samsung.com
Package : dibs
#end
client.install( option[:pkg], option[:os], option[:t], option[:f] )
when "install-file" then
- client = Client.new( nil, option[:loc], nil )
- client.install_local_pkg( option[:pkg], option[:f] )
+ client = Client.new( option[:url], option[:loc], nil )
+ client.install_local_pkg( option[:pkg], option[:t], option[:f] )
when "uninstall" then
client = Client.new( nil, option[:loc], nil )
client.uninstall( option[:pkg], option[:t] )
end
# upload to ftp server
- FileTransfer.set_logger(@log)
ftp_filepath = nil
for attempt in ATTEMPTS
- ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file)
+ ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file, @log)
if !ftp_filepath.nil? then break;
else @log.info "Server is the #{attempt} upload attempt fails" end
end
req.puts "UPLOADED,#{ftp_filepath}"
elsif cmd == "SUCC" then
@log.info "Client downloaded file successfully"
- FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath)
+ FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath, @log)
@log.info "Cleaned temporary dir on FTP server: #{ftp_filepath}"
break
elsif cmd == "ERROR" then
end
# download from ftp server
- FileTransfer.set_logger(@log)
dst_filepath = nil
for attempt in ATTEMPTS
- dst_filepath = FileTransfer.getfile(ip, port, username, passwd, filepath, dst_file)
+ dst_filepath = FileTransfer.getfile(ip, port, username, passwd, filepath, dst_file, @log)
if not dst_filepath.nil? then break
else "Server is the #{attempt} download attempt fails" end
end
return false
end
- FileTransfer.set_logger(@log)
-
# 1. If "READY" is received, upload src file to FTP server
# After uploading it, send "UPLOADED,ip,file_path,username,passwd"
# 2. If "SUCC" is received, remove the file on FTP server
@log.info "Server is ready to receive file"
ftp_filepath = nil
for attempt in ATTEMPTS
- ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file)
+ ftp_filepath = FileTransfer.putfile(ip, port, username, passwd, src_file, @log)
if !ftp_filepath.nil? then break;
else @log.info "Client is the #{attempt} upload attempt fails" end
end
send "UPLOADED,#{ip},#{port},#{ftp_filepath},#{username},#{passwd}"
elsif line.strip == "SUCC" then
@log.info "Server downloaded file sucessfully"
- FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath)
+ FileTransfer.cleandir(ip, port, username, passwd, ftp_filepath, @log)
@log.info "Client cleaned temporary dir on ftp server: #{ftp_filepath}"
elsif line.strip == "ERROR" then
@log.error "Server failed to download the file. Please check server log"
return false
end
- FileTransfer.set_logger(@log)
-
# 1. If "READY" is received, send "FTP,ip,port,username,passwd"
# 2. if "UPLOADED,ftp_file_path" is received,
# Download the file
end
ftp_filepath = tok[1].strip
@log.info "Server uploaded file sucessfully"
- FileTransfer.set_logger(@log)
dst_filepath = nil
for attempt in ATTEMPTS
- dst_filepath = FileTransfer.getfile(ip, port, username, passwd, ftp_filepath, dst_file)
+ dst_filepath = FileTransfer.getfile(ip, port, username, passwd, ftp_filepath, dst_file, @log)
if not dst_filepath.nil? then break
else "Client is the #{attempt} download attempt fails" end
end
def set_parent_job( parent )
# if parent exists, share build-root
@parent = parent
- @buildroot_dir = "#{@server.path}/jobs/#{@parent.id}/buildroot"
end
# get parent
return []
end
+
+ def get_buildroot()
+ return @buildroot_dir
+ end
+
# set reverse build check job
def set_rev_build_check_job( parent )
thread_main()
# close
- terminate()
+ if not is_sub_job? then
+ terminate()
+ end
}
if sync then
#cancel
def cancel()
+ # cancel all its reverse job
+ for job in @server.jobmgr.reverse_build_jobs
+ if job.get_parent_job() == self and job.cancel_state == "NONE" then
+ job.cancel_state = "INIT"
+ end
+ end
+
# cancel log print
if not @log.nil? then
@log.info( "JOB is canceled by cancel operation !!", Log::LV_USER)
case @status
when "REMOTE_WORKING" then
- client = BuildCommClient.create( @server.ip, @server.port, @log )
+ client = BuildCommClient.create( @remote_server.ip, @remote_server.port, @log )
if not client.nil? then
client.send "CANCEL|#{@remote_id}|#{self.get_project.passwd}"
result1 = client.receive_data()
end
+ # check whether build this job or not
+ # if not build, then return its compat pkgs list
def check_compatable_packages
- compatable_packages = {} # | packag, os_list |
+ compat_pkgs = [] # [ package name, os, local_path ]
+
@pkginfo.get_target_packages(@os).each do |p|
# if package has only os then must build
- if p.os_list.count > 1 then
- compat_found = false
- p.os_list.each do |o|
- #check other package already in package server
- ver_svr = @pkgsvr_client.get_attr_from_pkg( p.package_name, o, "version")
- if not ver_svr.nil? and p.version.eql? ver_svr then
- # get package file name
- if compatable_packages[p.package_name].nil? then
- compatable_packages[p.package_name] = [o]
- else
- compatable_packages[p.package_name].push o
+ if p.os_list.count <= 1 then return [] end
+
+ compat_found = false
+ p.os_list.each do |o|
+ # check parent pkgs first
+ if not @parent.nil? then
+ parent_pkgs = Dir.glob("#{@parent.source_path}/#{p.package_name}_*_*.zip")
+ parent_pkgs.each do |lp|
+ lpname = Utils.get_package_name_from_package_file( lp )
+ lver = Utils.get_version_from_package_file(lp)
+ los = Utils.get_os_from_package_file( lp )
+ if lpname == p.package_name and o == los and lver == p.version then
+ compat_pkgs.push [p.package_name,o,lp]
+ compat_found = true
+ break
end
- compat_found = true
end
end
- if not compat_found then return {} end
- else
- return {}
+ if compat_found then break end
+
+ # check other package already in package server
+ ver_svr = @pkgsvr_client.get_attr_from_pkg( p.package_name, o, "version")
+ if not ver_svr.nil? and p.version.eql? ver_svr then
+ compat_pkgs.push [p.package_name,o,nil]
+ compat_found = true
+ break
+ end
end
+
+ # if there is no compat pkgs for one pkg, then must build
+ if not compat_found then return [] end
end
- return compatable_packages
+
+ return compat_pkgs
end
@log.info( " - FTP Server : #{@server.ftp_addr}" )
else
builder = Builder.create( "JB#{@id}", @pkgserver_url, @log.path,
- "#{@buildroot_dir}/#{@os}", @server.build_cache_dir )
+ "#{@buildroot_dir}", @server.build_cache_dir )
if builder.nil?
@log.error( "Creating job builder failed", Log::LV_USER)
return false
end
#compatable os support
- comp_pkgs = check_compatable_packages
- if comp_pkgs.size > 0 and not @is_rev_build_check_job then
+ compat_ok = true
+ compat_pkgs = check_compatable_packages
+ if compat_pkgs.size > 0 and not @is_rev_build_check_job then
# bring package from server for reverse check
- comp_pkgs.each do |pkg_name,os_list|
- loc = @pkgsvr_client.download(pkg_name, os_list[0], false)
- loc.each do |location|
- ext = File.extname(location)
- base_package_name= File.basename( location, "#{os_list[0]}#{ext}" )
- FileUtils.mv location, "#{@source_path}/#{base_package_name}#{@os}#{ext}"
+ compat_pkgs.each do |p|
+ pkg_name = p[0]; cos = p[1]; local_path = p[2]
+
+ if not local_path.nil? then
+ ext = File.extname(local_path)
+ base_package_name= File.basename(local_path, "#{cos}#{ext}")
+ @log.info( "Copying compatible package:#{local_path}", Log::LV_USER)
+ FileUtils.cp local_path, "#{@source_path}/#{base_package_name}#{@os}#{ext}"
+ else
+ @log.info( "Downloading compatible package:#{pkg_name}(#{cos})", Log::LV_USER)
+ loc = @pkgsvr_client.download(pkg_name, cos, false)
+ if loc.nil? or loc.count != 1 then
+ @log.warn( "Downloading compatible package failed!:#{pkg_name}(#{cos})", Log::LV_USER)
+ compat_ok = false
+ break
+ end
+ ext = File.extname(loc[0])
+ base_package_name= File.basename(loc[0], "#{cos}#{ext}")
+ FileUtils.mv loc[0], "#{@source_path}/#{base_package_name}#{@os}#{ext}"
end
end
else
+ compat_ok = false
+ end
+
+ # if compat check failed
+ if not compat_ok then
# build
if @is_remote_job then
result = builder.build(@project.name, @project.passwd, @source_path, @os,
# calculate empty rooms
# if sub job, his parent should be excluded
local_empty_rooms = @jobmgr.get_number_of_empty_room
- if job.is_sub_job? then
- local_empty_rooms += 1
- end
if local_empty_rooms > 0 and can_build?(job) then
candidates.push self
@log.error( "Job is CANCELED" , Log::LV_USER)
@server.cleaner.clean_afterwards(@id)
else
+ @log.info( "Job is FINISHED successfully!" , Log::LV_USER)
+
# if succeeded, register source info and copy pkginfo.manifest
+ @log.info( "Updating the source info for project \"#{@project.name}\"" , Log::LV_USER)
@project.add_source_info( @pkginfo.get_version(), @git_commit)
@project.copy_package_info( @pkginfo.get_version(),
"#{@source_path}/package/pkginfo.manifest")
# check availabiltiy
if not @server.check_job_availability( self ) then
@log.error( "No servers that are able to build your packages.", Log::LV_USER)
+ @log.error( "Host-OS (#{@os}) is not supported in build server.", Log::LV_USER)
@status = "ERROR"
@server.log.info "Adding the job \"#{@id}\" is canceled"
end
class JobCleanAction < Action
- def initialize( time, job_path, list_file )
+ def initialize( time, job_path, list_file, server )
super(time,0)
@job_path = job_path
@job_id = @job_path.split("/")[-1]
@list_file = list_file
+ @server = server
end
def execute
-
+
+ # Start to clean job
+ @server.log.info "Executing clean action for the job #{@job_id}"
+
# remove directories
if File.exist? "#{@job_path}/buildroot" then
FileUtils.rm_rf "#{@job_path}/buildroot"
job_path = "#{jobs_path}/#{id}"
time = Time.mktime(year.to_i, month.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i)
@server.log.info "Registered clean-action for the job in list : #{id}"
- @handler.register(JobCleanAction.new(time,job_path,@list_file))
+ @handler.register(JobCleanAction.new(time,job_path,@list_file, @server))
# add clean list
clean_list.push id
job_path = "#{jobs_path}/#{id}"
time = Time.now
@server.log.info "Registered clean-action for old job : #{id}"
- @handler.register(JobCleanAction.new(time,job_path,@list_file))
+ @handler.register(JobCleanAction.new(time,job_path,@list_file, @server))
end
end
curr = Time.now
time = Time.now + @server.keep_time
job_path = "#{@server.path}/jobs/#{job_id}"
- @handler.register(JobCleanAction.new(time, job_path, @list_file))
+ @handler.register(JobCleanAction.new(time, job_path, @list_file, @server))
+
+ @server.log.info "Registered delayed clean-action for the job #{job_id}"
end
def clean(job_id)
time = Time.now
job_path = "#{@server.path}/jobs/#{job_id}"
- @handler.register(JobCleanAction.new(time, job_path, @list_file))
+ @handler.register(JobCleanAction.new(time, job_path, @list_file, @server))
+
+ @server.log.info "Registered clean-action for the job #{job_id}"
end
end
BuildCommServer.send( @second_out, msg )
end
rescue
- close()
+ # close second_out
+ @second_out.close
+ @second_out = nil
+
error "Connection closed by remote client"
- if not @parent_job.nil? then
- @parent_job.status="ERROR"
- # terminate job
- @parent_job.terminate
- # exit thread if independent worker thread
- if @parent_job.thread == Thread.current then
- error "Thread wiil be terminated"
- @parent_job.thread=nil
- Thread.exit
- end
+ # cancel parent job
+ if not @parent_job.nil? and @parent_job.cancel_state == "NONE" then
+ @parent_job.cancel_state = "INIT"
end
-
end
end
require "packageServer.rb"
class JobManager
- attr_accessor :max_working_jobs, :jobs, :internal_jobs
+ attr_accessor :max_working_jobs, :jobs, :internal_jobs, :reverse_build_jobs
+ attr_accessor :internal_job_schedule
# initialize
def initialize( parent )
end
@parent.log.info "Checking the job \"#{job.id}\" was finished!"
}
+ @parent.log.info "Job \"#{job.id}\" entered INITIALIZING status"
end
def cancel_job( job)
job.cancel_state = "WORKING"
+ @parent.log.info "Creating thread for canceling the job \"#{job.id}\""
Thread.new {
# thread terminate
if not job.thread.nil? then
#terminate job thread
job.thread.terminate
job.thread = nil
- job.terminate
end
# job cacncel
# cancel finished
job.status = "CANCELED"
+
+ # call terminate process for job
+ job.terminate
}
end
# handle
def handle()
# for cancel jobs
- (@jobs + @internal_jobs + @reverse_build_jobs).select{|j| j.cancel_state == "INIT" }.each do |job|
+ (@jobs + @internal_jobs + @reverse_build_jobs).select {|j| j.cancel_state == "INIT" }.each do |job|
cancel_job( job )
end
# for reverse build jobs
- for job in @reverse_build_jobs
+ job_list = @reverse_build_jobs
+ for job in job_list
# if "ERROR", "FINISHED", "CANCELED" remove it from list
if job.status == "ERROR"
@parent.log.info "Job \"#{job.id}\" is stopped by ERROR"
@reverse_build_jobs.delete job
elsif job.status == "FINISHED"
+ @parent.log.info "Job \"#{job.id}\" is removed by FINISH status"
@reverse_build_jobs.delete job
elsif job.status == "CANCELED"
+ @parent.log.info "Job \"#{job.id}\" is removed by CANCELED status"
@reverse_build_jobs.delete job
end
end
# for internal jobs
- for job in @internal_jobs
+ job_list = @internal_jobs
+ for job in job_list
# if "ERROR", "FINISHED", "CANCELED" remove it from list
if job.status == "ERROR"
@parent.log.info "Job \"#{job.id}\" is stopped by ERROR"
@internal_jobs.delete job
elsif job.status == "FINISHED"
+ @parent.log.info "Job \"#{job.id}\" is removed by FINISH status"
@internal_jobs.delete job
elsif job.status == "CANCELED"
+ @parent.log.info "Job \"#{job.id}\" is removed by CANCELED status"
@internal_jobs.delete job
end
end
# for normal job
- for job in @jobs
+ job_list = @jobs
+ for job in job_list
# if "ERROR", "FINISHED", "CANCELED" remove it from list
if job.status == "ERROR"
@parent.log.info "Job \"#{job.id}\" is stopped by ERROR"
@jobs.delete job
elsif job.status == "FINISHED"
+ @parent.log.info "Job \"#{job.id}\" is removed by FINISH status"
@jobs.delete job
elsif job.status == "CANCELED"
+ @parent.log.info "Job \"#{job.id}\" is removed by CANCELED status"
@jobs.delete job
end
if not selected_job.nil? then return selected_job end
# if no reverse build job exist!
- if not @internal_job_schedule.locked? and @internal_jobs.count > 0 then
- return get_available_job_in_list(@internal_jobs, true)
- else
- return get_available_job_in_list(@jobs, false)
- end
+ @internal_job_schedule.synchronize {
+ # internal job first
+ ret = nil
+ if @internal_jobs.count > 0 then
+ ret = get_available_job_in_list(@internal_jobs, true)
+ end
+
+ # not found, select normal job
+ if ret.nil? then
+ ret = get_available_job_in_list(@jobs, false)
+ end
+
+ return ret
+ }
end
# return "max_working_jobs_cnt - current_working_jobs_cnt"
def get_number_of_empty_room
working_cnt = 0
+ parent_list = []
for job in @jobs + @internal_jobs + @reverse_build_jobs
if job.status == "WORKING" then
working_cnt = working_cnt + 1
end
+
+ # must exclude parent job
+ if not job.get_parent_job().nil? then
+ parent_list.push job.get_parent_job()
+ end
end
- return @max_working_jobs - working_cnt
+ parent_list.uniq!
+
+ return @max_working_jobs - working_cnt + parent_list.count
end
# gather all working jobs and full-build jobs
check_dep_jobs = []
for job in jobs
+ if job.cancel_state != "NONE" then next end
+
if job.status == "WORKING" or job.status == "REMOTE_WORKING" or job.status == "PENDING" then
check_dep_jobs.push job
elsif ( check_dep_wait and job.status == "WAITING") then
# for waiting jobs
for job in jobs
+ if job.cancel_state != "NONE" then next end
if job.status != "WAITING" then next end
# check build dependency against working job
pre_jobs = []
for cjob in check_dep_jobs
if job == cjob then next end
- if (cjob.status == "WORKING" or cjob.status == "REMOTE_WORKING" or cjob.status == "PENDING" ) and
+ # In case that "WORKING/REMOTE_WORKING" job has build dependency on me
+ if (cjob.status == "WORKING" or cjob.status == "REMOTE_WORKING" ) and
+ (job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then
+ pre_jobs.push cjob
+ # In case that "PENDING" job is depends on me (not depended )
+ elsif cjob.status == "PENDING" and (not job.does_depend_on? cjob) and
(job.has_build_dependency?( cjob ) or job.is_compatible_with?( cjob)) then
pre_jobs.push cjob
elsif check_dep_wait and cjob.status == "WAITING" and
end
+ def get_buildroot()
+ return @buildroot_dir
+ end
+
+
+ def get_parent_job()
+ return nil
+ end
+
+
# execute
def execute(sync=false)
@log.info( "Invoking a thread for MULTI-BUILD Job #{@id}", Log::LV_USER)
#terminate
def terminate()
+
# report error
if @status == "ERROR" then
+ # register delayed clean action for sub jobs
+ for job in @sub_jobs
+ @server.cleaner.clean_afterwards(job.id)
+ end
+
+ # register delayed clean action for me
@log.error( "Job is stopped by ERROR" , Log::LV_USER)
@server.cleaner.clean_afterwards(@id)
+
+ elsif @status == "CANCELED" then
+ # register delayed clean action for sub jobs
+ for job in @sub_jobs
+ @server.cleaner.clean_afterwards(job.id)
+ end
+
+ # register delayed clean action for me
+ @log.error( "Job is stopped by CANCEL" , Log::LV_USER)
+ @server.cleaner.clean_afterwards(@id)
+
else
- # clean up
+ # terminate all sub jobs
+ for job in @sub_jobs
+ if not job.log.nil? then job.terminate() end
+ end
+
+ # register direct clean action for me
@server.cleaner.clean(@id)
end
end
# add to internal job
- @server.jobmgr.stop_internal_job_schedule()
- for job in @sub_jobs
- # init finished, add internal_jobs
- @server.jobmgr.add_internal_job(job)
- @log.info( "Added new job \"#{job.get_project().name}\" for #{job.os}! (#{job.id})",
- Log::LV_USER)
- if not @server.job_log_url.empty? then
- @log.info( " * Log URL : #{@server.job_log_url}/#{job.id}/log", Log::LV_USER)
+ @server.jobmgr.internal_job_schedule.synchronize {
+ for job in @sub_jobs
+ # init finished, add internal_jobs
+ @server.jobmgr.add_internal_job(job)
+ @log.info( "Added new job \"#{job.get_project().name}\" for #{job.os}! (#{job.id})",
+ Log::LV_USER)
+ if not @server.job_log_url.empty? then
+ @log.info( " * Log URL : #{@server.job_log_url}/#{job.id}/log", Log::LV_USER)
+ end
end
- end
- @server.jobmgr.resume_internal_job_schedule()
+ }
# show job status changes
all_jobs_finished = false
- error_exist = false
- while not all_jobs_finished and not error_exist
+ stop_status = "FINISHED"
+ while not all_jobs_finished
all_jobs_finished = true
for job in @sub_jobs
-
# check status chanaged, if then print
if job_status_map[ job.id ] != job.status then
- @log.info("Sub-Job \"#{job.get_project().name}\" for #{job.os} has entered \"#{job.status}\" state. (#{job.id})", Log::LV_USER)
+ @log.info(" * Sub-Job \"#{job.get_project().name}(#{job.os})\" has entered \"#{job.status}\" state. (#{job.id})", Log::LV_USER)
job_status_map[ job.id ] = job.status
end
- if job.status != "ERROR" and job.status != "FINISHED" and job.cancel_state == "NONE" then
+ # check all jobs are finished
+ if job.status != "ERROR" and job.status != "FINISHED" and job.status != "CANCELED" then
all_jobs_finished = false
end
- if job.status == "ERROR" then
- error_exist = true
+ # check there is some error or cancel
+ if stop_status == "FINISHED" and
+ (job.status == "ERROR" or job.status == "CANCELED") then
+
+ # cancel all other un-finished jobs
+ @sub_jobs.each do |sub|
+ if sub.status != "ERROR" and sub.status != "FINISHED" and
+ sub.status != "CANCELED" and sub.cancel_state == "NONE" then
+ @log.info(" * Sub-Job \"#{sub.get_project().name}(#{sub.os})\" has entered \"CANCELING\" state. (#{sub.id})", Log::LV_USER)
+ sub.cancel_state = "INIT"
+ end
+ end
+
+ stop_status = job.status
break
end
end
+
+ #
sleep 1
end
- if @cancel_state != "NONE" then
- @status = "CANCELED"
- if not @log.nil? then
- @log.info( "JOB is canceled by cancel operation !!", Log::LV_USER)
- end
- else
- # check error
- if error_exist then
- @sub_jobs.each do |sub|
- if sub.status != "ERROR" and sub.status != "FINISHED" and sub.cancel_state == "NONE" then
- sub.cancel_state = "INIT"
- end
- end
- @status = "ERROR"
- return
- end
-
- # upload
- if not upload() then
- @status = "ERROR"
- return
- end
+ if stop_status == "ERROR" or stop_status == "CANCELED" then
+ @status = stop_status
+ return
+ end
- # INFO. don't change this string
- @log.info( "Job is completed!", Log::LV_USER)
- @status = "FINISHED"
+ # upload
+ if not upload() then
+ @status = "ERROR"
+ return
end
+
+ # INFO. don't change this string
+ @log.info( "Job is completed!", Log::LV_USER)
+ @status = "FINISHED"
end
return @project
end
+
+ def get_buildroot()
+ return @buildroot_dir
+ end
+
+ def get_parent_job()
+ return nil
+ end
+
# execute
def execute(sync=false)
@log.info( "Invoking a thread for REGISTER Job #{@id}", Log::LV_USER)
if client.send("BUILD|GIT|#{project_name}|#{project_passwd}|#{os}|NO|YES|#{rev}|#{commit}|#{pkg_list}") then
result = client.read_lines do |l|
# check build result
- if l.include? "Job is stopped by ERROR" then
+ if l.include? "Job is stopped by ERROR" or
+ l.include? "Error:" then
result = false
break
end
# if job on resolve process, its unresolved project
#of pending ancestor must be excluded.
- if not job.pending_ancestor.nil? then
+ if job.type == "BUILD" and not job.pending_ancestor.nil? then
found = false
job.pending_ancestor.rev_fail_projects.each { |fp|
f_prj = fp[0]
f_os = fp[1]
- if rev_prj == f_prj and rev_os == os then
+ if rev_prj == f_prj and rev_os == f_os then
found = true
break
end
end
# for all reverse job
- for new_job in rev_build_jobs
+ for rev_job in rev_build_jobs
# add to job manager
- job.server.jobmgr.add_reverse_build_job(new_job)
- log.info( " * Added new job for reverse-build ... #{rev_prj.name}(#{rev_os}) (#{new_job.id})", Log::LV_USER)
+ job.server.jobmgr.add_reverse_build_job(rev_job)
+ log.info( " * Added new job for reverse-build ... \
+ #{rev_job.get_project().name}(#{rev_job.os}) (#{rev_job.id})", Log::LV_USER)
end
# wait for job finish
failure_list.push [ rev_prj, rev_os ]
end
+ # if "exist on error" cancel all other jobs
if exit_on_error then
- # cancel all other jobs
cancel_other_jobs = true
+ for j in rev_build_jobs
+ if j.status != "ERROR" and j.status != "FINISHED" and
+ j.status != "CANCELED" and j.cancel_state == "NONE" then
- # exit
+ j.cancel_state = "INIT"
+ end
+ end
break
end
when "FINISHED"
success_list.push rev_job
end
else
- if exit_on_error and cancel_other_jobs then
- rev_job.cancel_state = "INIT"
- else
- rev_build_finished = false
- end
+ rev_build_finished = false
end
end
sleep 1
end
+ # clean up all reverse build jobs
+ for rev_job in rev_build_jobs
+ if rev_job.status == "ERROR" or rev_job.status == "CANCELED" then
+ rev_job.server.cleaner.clean_afterwards(rev_job.id)
+ else
+ rev_job.server.cleaner.clean(rev_job.id)
+ end
+ end
+
return failure_list
end
if os_list.nil? or os_list.empty? then
raise "Unsupported OS name is used!"
end
+
+ # check project type
+ if prj.type == "BINARY" then
+ BuildCommServer.send_begin(req)
+ req.puts "Can't build about Binary type package."
+ BuildCommServer.send_end(req)
+ raise "Can't build about Binary type package."
+ end
# create new job
for os in os_list
#puts "Received QUERY JOB"
# gather all jobs to show
- job_list = @parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs
+ job_list = @parent_server.jobmgr.jobs + @parent_server.jobmgr.internal_jobs + @parent_server.jobmgr.reverse_build_jobs
# send the status
BuildCommServer.send_begin(req)
else
for l in local_dep_pkgs
@log.info( "Installing local pacakge...#{l}", Log::LV_USER)
- cl.install_local_pkg(l,false)
+ cl.install_local_pkg(l,true,false)
end
end
end
# write pkginfo.manifest
def write_pkginfo_files(pkginfo,os,src_path)
- # get category
+ # get category
os_category = Utils.get_os_category( os )
for pkg in pkginfo.packages
next
end
- # install script files
- copy_post_install_script(pkg,os,src_path);
- copy_post_remove_script(pkg,os,src_path);
+ # install/remove script files
+ if not copy_post_install_script(pkg,os,src_path) then return false end
+ if not copy_post_remove_script(pkg,os,src_path) then return false end
# write manifest file
install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os}"
# if there is no intall directory, error
if not File.exist? install_dir then
install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
-
+
if not File.exist? install_dir then
@log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
@log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
# copy post-install script
def copy_post_install_script(pkg,os,src_path)
-
+
tar = nil
+ src = nil
- # get category
- os_category = Utils.get_os_category( os )
+ # get category
+ os_category_list = []
+ pkg.os_list.each do |cos|
+ os_category_list.push Utils.get_os_category(cos)
+ end
- if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{os}"
- src = "#{src_path}/package/#{pkg.package_name}.install.#{os}"
- else
- if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{os_category}"
- src = "#{src_path}/package/#{pkg.package_name}.install.#{os_category}"
- else
- src = nil
+ # check compatable os
+ (pkg.os_list + os_category_list).uniq.each do |cos|
+ if File.exist? "#{src_path}/package/#{pkg.package_name}.install.#{cos}" then
+ if src.nil? then
+ src = "#{src_path}/package/#{pkg.package_name}.install.#{cos}"
+ else
+ @log.error( "compatable package can have only one install script\n but you have another availabe install scripts", Log::LV_USER)
+ @log.error( " * package/#{File.basename src}", Log::LV_USER)
+ @log.error( " * package/#{pkg.package_name}.install.#{cos}", Log::LV_USER)
+ return false
+ end
end
end
# if there is no intall directory, error
if not File.exist? install_dir then
+ os_category = Utils.get_os_category( os )
install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
-
+
if not File.exist? install_dir then
@log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
@log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
tar = "#{install_dir}/install.BAT"
else
puts "Unknown OS: #{os} "
- return
+ return true
end
FileUtils.cp(src, tar)
- end
-
- return
+ end
+
+ return true
end
# copy post-remove script
def copy_post_remove_script(pkg,os,src_path)
-
+
tar = nil
+ src = nil
- # get category
- os_category = Utils.get_os_category( os )
+ # get category
+ os_category_list = []
+ pkg.os_list.each do |cos|
+ os_category_list.push Utils.get_os_category(cos)
+ end
- if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{os}"
- src = "#{src_path}/package/#{pkg.package_name}.remove.#{os}"
- else
- if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{os_category}"
- src = "#{src_path}/package/#{pkg.package_name}.remove.#{os_category}"
- else
- src = nil
+ # check compatable os
+ (pkg.os_list + os_category_list).uniq.each do |cos|
+ if File.exist? "#{src_path}/package/#{pkg.package_name}.remove.#{cos}" then
+ if src.nil? then
+ src = "#{src_path}/package/#{pkg.package_name}.remove.#{cos}"
+ else
+ @log.error( "compatable package can have only one remove script but you have another availabe remove scripts", Log::LV_USER)
+ @log.error( " * package/#{File.basename src}", Log::LV_USER)
+ @log.error( " * package/#{pkg.package_name}.remove.#{cos}", Log::LV_USER)
+ return false
+ end
end
end
# if there is no intall directory, error
if not File.exist? install_dir then
+ os_category = Utils.get_os_category( os )
install_dir = "#{src_path}/package/#{pkg.package_name}.package.#{os_category}"
-
+
if not File.exist? install_dir then
@log.error( "Following directory must be created before writing pkginfo.manifest", Log::LV_USER)
@log.error( " * package/#{pkg.package_name}.package.#{os}", Log::LV_USER)
tar = "#{install_dir}/remove.BAT"
else
puts "Unknown OS: #{os} "
- return
+ return true
end
FileUtils.cp(src, tar)
- end
+ end
+ return true
end
end
end
- # sleep 1 min
- sleep 5
+ # sleep 10 sec
+ sleep 10
end
end
class FileTransfer
- @@log = nil
-
- def FileTransfer.set_logger(logger)
- @@log = logger
- end
-
- def FileTransfer.putfile(ip, port, username, passwd, bpath)
+ def FileTransfer.putfile(ip, port, username, passwd, bpath, logger)
filename = File.basename(bpath)
uniqdir = Utils.create_uniq_name
ftp_filepath = File.join(uniqdir, filename)
else
ftp.connect(ip, port)
end
- @@log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ logger.info "[FTP log] Connected FTP server (#{ip}:#{port})"
ftp.login(username, passwd)
ftp.binary = true
ftp.mkdir(uniqdir)
ftp.chdir(uniqdir)
ftp.put(bpath)
- @@log.info "[FTP log] Put a file"
- @@log.info "[FTP log] from \"#{bpath}\" to \"#{ftp_filepath}\""
+ logger.info "[FTP log] Put a file"
+ logger.info "[FTP log] from \"#{bpath}\" to \"#{ftp_filepath}\""
files = ftp.list(filename)
if files.empty? then
- @@log.error "[FTP log] Failed to upload file (#{filename} does not exist)"
+ logger.error "[FTP log] Failed to upload file (#{filename} does not exist)"
return nil
end
ftp.quit
- @@log.info "[FTP log] Disconnected FTP server"
+ logger.info "[FTP log] Disconnected FTP server"
rescue => e
- @@log.error "[FTP log] Exception"
- @@log.error e.message
- @@log.error e.backtrace.inspect
+ logger.error "[FTP log] Exception"
+ logger.error e.message
+ logger.error e.backtrace.inspect
return nil
end
return ftp_filepath
end
- def FileTransfer.getfile(ip, port, username, passwd, bpath, target)
+ def FileTransfer.getfile(ip, port, username, passwd, bpath, target, logger)
dirname = File.dirname(bpath)
filename = File.basename(bpath)
else
ftp.connect(ip, port)
end
- @@log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ logger.info "[FTP log] Connected FTP server (#{ip}:#{port})"
ftp.login(username, passwd)
ftp.binary = true
ftp.chdir(dirname)
ftp.get(filename, dst_file)
- @@log.info "[FTP log] Get a file"
- @@log.info "[FTP log] from \"#{bpath}\" to \"#{dst_file}\""
+ logger.info "[FTP log] Get a file"
+ logger.info "[FTP log] from \"#{bpath}\" to \"#{dst_file}\""
ftp.quit
- @@log.info "[FTP log] Disconnected FTP server"
+ logger.info "[FTP log] Disconnected FTP server"
rescue => e
- @@log.error "[FTP log] Exception"
- @@log.error e.message
- @@log.error e.backtrace.inspect
+ logger.error "[FTP log] Exception"
+ logger.error e.message
+ logger.error e.backtrace.inspect
return nil
end
if not File.exist? dst_file then
- @@log.error "[FTP log] Failed to download file (#{dst_file} does not exist)"
+ logger.error "[FTP log] Failed to download file (#{dst_file} does not exist)"
return nil
end
return bpath
end
- def FileTransfer.cleandir(ip, port, username, passwd, path)
+ def FileTransfer.cleandir(ip, port, username, passwd, path, logger)
dirname = File.dirname(path)
begin
else
ftp.connect(ip, port)
end
- @@log.info "[FTP log] Connected FTP server (#{ip}:#{port})"
+ logger.info "[FTP log] Connected FTP server (#{ip}:#{port})"
ftp.login(username, passwd)
old_dir = ftp.pwd
ftp.chdir(dirname)
end
ftp.chdir(old_dir)
ftp.rmdir(dirname)
- @@log.info "[FTP log] Clean dir (#{dirname})"
+ logger.info "[FTP log] Clean dir (#{dirname})"
ftp.quit
- @@log.info "[FTP log] Disconnected FTP server"
+ logger.info "[FTP log] Disconnected FTP server"
rescue => e
- @@log.error "[FTP log] Exception"
- @@log.error e.message
- @@log.error e.backtrace.inspect
+ logger.error "[FTP log] Exception"
+ logger.error e.message
+ logger.error e.backtrace.inspect
return nil
end
require "Version"
require "net/ftp"
$update_mutex = Mutex.new
+$update_os_mutex = Mutex.new
+$install_pkg_mutex = Mutex.new
class Client
# constant
DEFAULT_SERVER_ADDR = "http://172.21.17.55/dibs/unstable"
OS_INFO_FILE = "os_info"
- attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log, :support_os_list, :config_dist_path
+ attr_accessor :server_addr, :location, :pkg_hash_os, :is_server_remote, :installed_pkg_hash_loc, :archive_pkg_list, :all_dep_list, :log, :support_os_list, :config_dist_path, :download_path
public
# initialize
@all_dep_list = []
@is_server_remote = Utils.is_url_remote(server_addr)
@support_os_list = []
- @config_dist_path = CONFIG_PATH + "/" + get_distribution
+ @config_dist_path = CONFIG_PATH + "/" + get_flat_serveraddr
+ @download_path = @config_dist_path + "/downloads"
# create directory
if not File.exist? @config_dist_path then FileUtils.mkdir_p "#{@config_dist_path}" end
+ if not File.exist? @download_path then FileUtils.mkdir_p "#{@download_path}" end
# chop server address, if end with "/"
if server_addr.strip.end_with? "/" then server_addr = server_addr.chop end
@log = logger
end
- FileInstaller.set_logger(@log)
- FileDownLoader.set_logger(@log)
- FileTransfer.set_logger(@log)
-
# read installed pkg list, and create hash
if not File.exist? @location then FileUtils.mkdir_p "#{@location}" end
create_installed_pkg_hash()
end
else dependent_pkg_list = [pkg_name] end
- surl = nil
- addr_arr = @server_addr.split('/')
- if addr_arr[-2].eql? "snapshots" then
+ surl = @server_addr
+ if is_snapshot_url then
surl = @server_addr + "/../.."
- else
- surl = @server_addr
- end
+ end
# download files
file_local_path = []
dependent_pkg_list.each do |p|
+ pkg_name = get_attr_from_pkg(p, os, "name")
pkg_path = get_attr_from_pkg(p, os, "path")
pkg_ver = get_attr_from_pkg(p, os, "version")
+ pkg_checksum = get_attr_from_pkg(p, os, "checksum")
+ pkg_size = get_attr_from_pkg(p, os, "size")
if pkg_path.nil? or pkg_ver.nil? then
@log.error "\"#{p}\" package does not exist in package server. If it exist in package server, then try \"pkg-cli update\""
return nil
end
url = surl + pkg_path
filename = pkg_path.split('/')[-1]
- if not FileDownLoader.download(url, @location) then
+
+ cached_filepath = nil
+ if Utils.is_linux_like_os( Utils::HOST_OS ) then
+ cached_filepath = get_cached_filepath(filename, pkg_checksum, pkg_size, os)
+ if not cached_filepath.nil? then url = cached_filepath end
+ end
+
+ if not FileDownLoader.download(url, @location, @log) then
@log.error "Failed download #{pkg_name} [#{pkg_ver}]"
return nil
end
file_path = File.join(@location, filename)
file_local_path.push(file_path)
+
+ if Utils.is_linux_like_os( Utils::HOST_OS ) then
+ if cached_filepath.nil? then
+ remove_downloaded_pkgs(pkg_name)
+ FileUtils.cp(file_path, @download_path)
+ end
+ end
+
@log.info "Downloaded \"#{p} [#{pkg_ver}]\" package file.. OK"
- #@log.info " [path : #{file_path}]"
end
if trace then
@log.info " [path : #{file_local_path.join(", ")}]"
return file_local_path
- end
-
- public
- # download source package
- def download_source(pkg_name, os)
+ end
- # get source file path
- src_path = get_attr_from_pkg(pkg_name, os, "src_path")
- if src_path.nil? or src_path.empty? then
- @log.error "#{pkg_name} package does not have source"
- return nil
- end
- file_url = nil
+ private
+ def remove_downloaded_pkgs(pkg_name)
+ pkg_file_prefix = "#{@download_path}/#{pkg_name}_*"
+ pkg_files = Dir.glob(pkg_file_prefix)
- addr_arr = @server_addr.split('/')
- if addr_arr[-2].eql? "snapshots" then
- surl = @server_addr + "/../.." + src_path
- else
- surl = @server_addr + src_path
- end
+ if not pkg_files.nil? then
+ Utils.execute_shell("rm -f #{pkg_file_prefix}")
+ end
+ end
- # download file
- filename = src_path.split('/')[-1]
- if not FileDownLoader.download(surl, @location) then
- @log.error "Failed download #{pkg_name} source"
- return nil
- end
- file_local_path = File.join(@location, filename)
- @log.info "Downloaded source of #{pkg_name} package.. OK"
- @log.info " [path : #{file_local_path}]"
+ private
+ def get_cached_filepath(pkg_filename, pkg_checksum, pkg_size, os)
+
+ cached_filepath = "#{@download_path}/#{pkg_filename}"
+ if File.exist? cached_filepath then
+ checksum = `sha256sum #{cached_filepath}`.split(" ")[0]
+ size = `du -b #{cached_filepath}`.split[0].strip
+ if checksum.eql? pkg_checksum and size.eql? pkg_size then
+ return cached_filepath
+ end
+ end
+ return nil
+ end
- return file_local_path
- end
-
public
# download dependent source
def download_dep_source(file_name)
else
file_url = @server_addr + "/source/#{file_name}"
end
- if not FileDownLoader.download(file_url, @location) then
+ if not FileDownLoader.download(file_url, @location, @log) then
@log.error "Failed download #{file_name}"
return nil
end
path = Utils::HOME + "/tmp/#{uniq_name}"
if not File.exist? path then FileUtils.mkdir_p "#{path}" end
begin
- if not FileInstaller.extract_a_file(pkg_path, manifest_file, path) then
+ if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then
@log.error "The \"pkginfo.manifest\" file does not exist in \"#{pkg_path}\""
return false
end
manifest_path = File.join(path, manifest_file)
pkg = Parser.read_single_pkginfo_from manifest_path
- FileUtils.rm_f(manifest_path)
+ if File.exists? manifest_path then FileUtils.rm_f(manifest_path) end
FileUtils.remove_dir(path, true)
rescue Interrupt
@log.error "Client: Interrupted.."
- FileUtils.rm_f(manifest_path)
FileUtils.remove_dir(path, true)
- @log.info "Removed #{manifest_path}"
@log.info "Removed #{path}"
raise Interrupt
rescue RuntimeError => e
@log.error( e.message, Log::LV_USER)
- FileUtils.rm_f(manifest_path)
FileUtils.remove_dir(path, true)
- @log.info "Removed #{mainfest_path}"
@log.info "Removed #{path}"
return false
end
else dist = File.basename(server) end
return dist
- end
+ end
+
+ private
+ def get_flat_serveraddr()
+ server = @server_addr
+ if server.nil? or server.empty? then
+ @log.error "Server addr is nil"
+ return nil
+ end
+
+ server = server.delete ".:/@"
+ return server
+ end
public
# install package
# install all install dependency packages
def install(pkg_name, os, trace, force)
+ ret = true
+ $install_pkg_mutex.synchronize {
+ ret = install_internal( pkg_name, os, trace, force )
+ }
+
+ return ret
+ end
+
+
+ private
+ def install_internal(pkg_name, os, trace, force)
+
if trace.nil? then trace = true end
if force.nil? then force = false end
@log.error "#{pkg_name} package does not exist in remote package list"
return false
end
+
compare_result = compare_version_with_installed_pkg(pkg_name, pkg_ver)
if not force then
- case compare_result
- when -1 then
- @log.warn "\"#{pkg_name}\" package version is bigger then remote package version"
- return true
- when 0 then
- @log.warn "\"#{pkg_name}\" package version is same with remote package version"
- return true
- when 1, 2 then
- end
- end
-
- # if enable trace, create all dependent package list
- if trace then
- dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force)
- if dependent_pkg_list.nil? then
- @log.error "Failed to get dependency for \"#{pkg_name}\" package"
- return false
- end
- else
- dependent_pkg_list = [pkg_name]
- end
-
- # TODO: need to compare dependent package version
- # install packages including dependent packages
- dependent_pkg_list.each do |pkg|
- if not install_pkg(pkg, os, force) then
- @log.error "#{pkg} does not exist"
- return false
- end
- add_pkg_info(pkg, os)
- end
-
- # write installed package information to file
- write_pkg_hash_to_file(nil)
+ case compare_result
+ when -1 then
+ @log.warn "\"#{pkg_name}\" package version is bigger then remote package version"
+ return true
+ when 0 then
+ @log.warn "\"#{pkg_name}\" package version is same with remote package version"
+ return true
+ when 1, 2 then
+ end
+ end
+
+ # if enable trace, create all dependent package list
+ if trace then
+ dependent_pkg_list = get_install_dependent_packages(pkg_name, os, true, force)
+ if dependent_pkg_list.nil? then
+ @log.error "Failed to get dependency for \"#{pkg_name}\" package"
+ return false
+ end
+ else
+ dependent_pkg_list = [pkg_name]
+ end
+
+ # TODO: need to compare dependent package version
+ # install packages including dependent packages
+ dependent_pkg_list.each do |pkg|
+ if not install_pkg(pkg, os, force) then
+ @log.error "#{pkg} does not exist"
+ return false
+ end
+ add_pkg_info(pkg, os)
+ end
+
+ # write installed package information to file
+ write_pkg_hash_to_file(nil)
if trace then
@log.info "Installed \"#{pkg_name} [#{pkg_ver}]\" package with all dependent packages.. OK"
else
@log.info "Install only \"#{pkg_name} [#{pkg_ver}]\" package.. OK"
end
+
return true
end
+
public
# install local package (ignore dependent packages)
- def install_local_pkg(pkg_path, force)
+ def install_local_pkg(pkg_path, trace, force)
+
+ ret = true
+ $install_pkg_mutex.synchronize {
+ ret = install_local_pkg_internal(pkg_path, trace, force)
+ }
+
+ return ret
+ end
+
+
+ private
+ def install_local_pkg_internal(pkg_path, trace, force)
file_name = File.basename(pkg_path)
pkg_name = file_name.split('_')[0]
uniq_name = Utils.create_uniq_name
path = Utils::HOME + "/tmp/#{uniq_name}"
- if not File.exist? path then FileUtils.mkdir_p "#{path}" end
+ if not File.exist? path then FileUtils.mkdir_p "#{path}" end
begin
- if not FileInstaller.extract_a_file(pkg_path, manifest_file, path) then
+ if not FileInstaller.extract_a_file(pkg_path, manifest_file, path, @log) then
@log.error "pkginfo.manifest file does not exist in #{pkg_path}"
return false
end
manifest_path = File.join(path, manifest_file)
pkg = Parser.read_single_pkginfo_from manifest_path
new_pkg_ver = pkg.version
- FileUtils.rm_f(manifest_path)
FileUtils.remove_dir(path, true)
rescue Interrupt
@log.error "Client: Interrupted.."
- FileUtils.rm_f(manifest_path)
FileUtils.remove_dir(path, true)
- @log.info "Removed #{mainfest_path}"
@log.info "Removed #{path}"
raise Interrupt
rescue RuntimeError => e
@log.error( e.message, Log::LV_USER)
- FileUtils.rm_f(manifest_path)
- FileUtils.remove_dir(path, true)
- @log.info "Removed #{mainfest_path}"
+ FileUtils.remove_dir(path, true)
@log.info "Removed #{path}"
return false
end
- compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
- if not force then
- case compare_result
- when -1 then
- @log.warn "\"#{pkg_name}\" package version is bigger then remote package version.."
- return true
- when 0 then
- @log.warn "\"#{pkg_name}\" package version is same with remote package version.."
- return true
- when 1, 2 then
- end
- end
+ compare_result = compare_version_with_installed_pkg(pkg_name, new_pkg_ver)
+ if not force then
+ case compare_result
+ when -1 then
+ @log.warn "installed \"#{pkg_name}\" package version is bigger.."
+ return true
+ when 0 then
+ @log.warn "\"#{pkg_name}\" package version is same with installed package version.."
+ return true
+ when 1, 2 then
+ end
+ end
+
+ if check_installed_pkg(pkg_name) then
+ uninstall(pkg_name, false)
+ end
- if check_installed_pkg(pkg_name) then
- uninstall(pkg_name, false)
- end
+ if trace then
+ install_dep_pkgs = pkg.install_dep_list
+ new_pkg_os = pkg.os
+ install_dep_pkgs.each do |pkg|
+ if not install_internal(pkg.package_name, new_pkg_os, true, false) then
+ @log.warn "#{pkg} package is not installed"
+ end
+ end
+ end
- # install package
- ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location)
+ # install package
+ ret = FileInstaller.install(pkg_name, pkg_path, "binary", @location, @log)
- add_local_pkg_info(pkg_name)
- write_pkg_hash_to_file(nil)
+ add_local_pkg_info(pkg_name)
+ write_pkg_hash_to_file(nil)
@log.info "Installed \"#{pkg_path} [#{new_pkg_ver}]\" file.. OK"
return true
end
+
public
# upgrade package
def upgrade(os, trace)
end
end
- if not install(p, os, trace, false) then
+ if not install_internal(p, os, trace, false) then
@log.error "Failed to install \"#{p}\" package.."
return false
end
pkg_list.each do |p|
if not check_installed_pkg(p) then next end
- if not FileInstaller.uninstall(p, type, @location) then
+ if not FileInstaller.uninstall(p, type, @location, @log) then
@log.error "Failed uninstall \"#{pkg_name}\" package"
return false
end
if File.exist? @location then FileUtils.rm_rf(@location) end
FileUtils.mkdir_p(@location)
#@pkg_hash_os.clear
- #@installed_pkg_hash_loc.clear
+ @installed_pkg_hash_loc.clear
#@archive_pkg_list.clear
@log.info "Cleaned \"#{@location}\" path.. OK"
end
if pkg_hash.nil? then return false end
pkg = pkg_hash[pkg_name]
if pkg.nil? then
- @log.warn "There is no \"#{pkg_name}\" remote package information in list"
+ #@log.warn "There is no \"#{pkg_name}\" remote package information in list"
return false
end
if pkg.nil? then return nil end
case attr
+ when "name" then return pkg.package_name
when "path" then return pkg.path
when "source" then return pkg.source
when "version" then return pkg.version
when "build_dep_list" then return pkg.build_dep_list
when "install_dep_list" then return pkg.install_dep_list
when "attribute" then return pkg.attribute
+ when "checksum" then return pkg.checksum
+ when "size" then return pkg.size
+
end
end
end
# install package
- ret = FileInstaller.install(pkg_name, file_local_path, type, @location)
- FileUtils.rm_f(file_local_path)
+ ret = FileInstaller.install(pkg_name, file_local_path, type, @location, @log)
FileUtils.remove_dir(tmppath, true)
rescue Interrupt
@log.error "Client: Interrupted.."
- FileUtils.rm_f(file_local_path)
FileUtils.remove_dir(tmppath, true)
- @log.info "Removed #{file_local_path}"
@log.info "Removed #{tmppath}"
raise Interrupt
end
return nil
end
- @log.info "Added information for \"#{pkg_name}\" package.. OK"
+ @log.info "Read information for \"#{pkg_name}\" package.. OK"
return pkg
end
private
def get_remote_pkg_os_list()
- file_url = @server_addr + "/" + OS_INFO_FILE
- if(is_server_remote) then
- FileDownLoader.download(file_url, @config_dist_path)
- File.open( "#{@config_dist_path}/#{OS_INFO_FILE}", "r" ) do |f|
- f.each_line do |l|
- @support_os_list.push l.strip
- end
- end
- else
- if File.exist?(file_url) then
- File.open(file_url) do |f|
+ file_url = @server_addr + "/" + OS_INFO_FILE
+ if is_snapshot_url then
+ file_url = @server_addr + "/../../" + OS_INFO_FILE
+ end
+
+ $update_os_mutex.synchronize {
+ if(is_server_remote) then
+ FileDownLoader.download(file_url, @config_dist_path, @log)
+ File.open( "#{@config_dist_path}/#{OS_INFO_FILE}", "r" ) do |f|
f.each_line do |l|
@support_os_list.push l.strip
end
end
+ else
+ if File.exist?(file_url) then
+ File.open(file_url) do |f|
+ f.each_line do |l|
+ @support_os_list.push l.strip
+ end
+ end
+ end
end
- end
+ }
end
+ # get the lastest snapshot
+ # from_server : if true, update from server
+ def get_lastest_snapshot(from_server)
+ ssinfo_file = "snapshot.info"
+ file_url = @server_addr + "/" + ssinfo_file
+ if from_server then
+ if not FileDownLoader.download(file_url, @config_dist_path, @log) then
+ @log.warn "Server does not have \"#{ssinfo_file}\" file. This error can be ignored."
+ return nil
+ end
+ else
+ FileUtils.cp(file_url, @config_dist_path)
+ end
+
+ file_path = File.join(@config_dist_path, ssinfo_file)
+ contents = File.open(file_path, "r").read
+
+ _list = contents.split("\n\n")
+ if _list.nil? or _list == "" or _list.empty? then return nil end
+ list = _list[-1].split("\n")
+ if list.nil? or list == "" or list.empty? then return nil end
+ _path = list[-1].split(":")
+ if _path.nil? or _path == "" or _path.length != 2 then return nil end
+ path = _path[1].strip
+ if path == nil or path == "" then return nil end
+
+ return path
+ end
+
+ # if url includes snapshot infomation, retuen true
+ def is_snapshot_url()
+ addr_arr = @server_addr.split('/')
+ if addr_arr[-2].eql? "snapshots" then
+ return true
+ else
+ return false
+ end
+ end
+
# from_server : if true, update from server
def create_remote_pkg_hash(from_server)
+
+ snapshot_path = ""
+
+ if not is_snapshot_url then
+ snapshot_path = get_lastest_snapshot(from_server)
+ @log.info "The lastest snapshot : #{snapshot_path}"
+ if snapshot_path.nil? then
+ @log.warn "Failed to get the lastest package list"
+ snapshot_path = ""
+ end
+ end
+
for os in @support_os_list
filename = PKG_LIST_FILE_PREFIX + os
- file_url = @server_addr + "/" + filename
+ file_url = @server_addr + snapshot_path + "/" + filename
local_file_path = File.join(@config_dist_path, filename)
if from_server then
- if not FileDownLoader.download(file_url, @config_dist_path) then
+ if not FileDownLoader.download(file_url, @config_dist_path, @log) then
return false
end
else
end
filename = "archive_pkg_list"
- file_url = @server_addr + "/" + filename
+ file_url = @server_addr + snapshot_path + "/" + filename
if from_server then
- if not FileDownLoader.download(file_url, @config_dist_path) then
+ if not FileDownLoader.download(file_url, @config_dist_path, @log) then
@log.warn "Server does not have \"#{filename}\" file. This error can be ignored."
end
else
when "install-file" then
if options[:pkg].nil? or options[:pkg].empty? then
- raise ArgumentError, "Usage: pkg-cli install-lpkg -P <package file> [-l <location>] [--force]"
+ raise ArgumentError, "Usage: pkg-cli install-lpkg -P <package file> [-l <location>] [-u <package server url>] [--trace] [--force]"
end
when "uninstall" then
+ "\t" + "pkg-cli clean [-l <location>] [--force]" + "\n" \
+ "\t" + "pkg-cli download -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace]" + "\n" \
+ "\t" + "pkg-cli install -P <package name> [-o <os>] [-l <location>] [-u <package server url>] [--trace] [--force]" + "\n" \
- + "\t" + "pkg-cli install-file -P <package file> [-l <location>] [--force]" + "\n" \
+ + "\t" + "pkg-cli install-file -P <package file> [-l <location>] [-u <package server url>] [--trace] [--force]" + "\n" \
+ "\t" + "pkg-cli uninstall -P <package name> [-l <location>] [--trace]" + "\n" \
+ "\t" + "pkg-cli upgrade [-l <location>] [-o <os>] [-u <package server url>] [--trace]" + "\n" \
+ "\t" + "pkg-cli check-upgrade [-l <location>] [-o <os>] [-u <package server url>]" + "\n" \
def get_package_from_file(file_path)
tmp_dir = @location + "/" + Utils.create_uniq_name
- FileInstaller.set_logger(@log)
-
#if file extension is .zip then check pkginfo.manifest
if File.extname(file_path).eql? ".zip" then
FileUtils.mkdir tmp_dir
- ret = FileInstaller.extract_a_file(file_path, "pkginfo.manifest", tmp_dir)
+ ret = FileInstaller.extract_a_file(file_path, "pkginfo.manifest", tmp_dir, @log)
else
return nil
end
class FileDownLoader
- @@log = nil
-
- def FileDownLoader.set_logger(logger)
- @@log = logger
- end
-
- def FileDownLoader.download(url, path)
+ def FileDownLoader.download(url, path, logger)
ret = false
if not File.directory? path then
- @@log.error "\"#{path}\" does not exist"
+ logger.error "\"#{path}\" does not exist"
return ret
- end
-
+ end
+
is_remote = Utils.is_url_remote(url)
filename = url.split('/')[-1]
fullpath = File.join(path, filename)
if is_remote then
- ret = Utils.execute_shell_with_log( "wget #{url} -O #{fullpath} -nv", @@log )
+ ret = Utils.execute_shell_with_log( "wget #{url} -O #{fullpath} -nv", logger )
else
if not File.exist? url then
- @@log.error "\"#{url}\" file does not exist"
+ logger.error "\"#{url}\" file does not exist"
return false
else
ret = system "cp #{url} #{fullpath}"
CONFIG_PATH = "#{PackageServerConfig::CONFIG_ROOT}/client"
PACKAGE_INFO_DIR = ".info"
- @@log = nil
-
- def FileInstaller.set_logger(logger)
- @@log = logger
- end
-
- def FileInstaller.install(package_name, package_file_path, type, target_path)
+ def FileInstaller.install(package_name, package_file_path, type, target_path, logger)
if not File.exist? package_file_path then
- @@log.error "\"#{package_file_path}\" file does not exist."
+ logger.error "\"#{package_file_path}\" file does not exist."
return false
end
begin
log = log + "##### extract file : #{package_file_path} #####\n"
- log = log + extract_file(package_name, package_file_path, path, target_path)
+ log = log + extract_file(package_name, package_file_path, path, target_path, logger)
move_dir(package_name, path, target_path)
log = log + "##### execute install script #####\n"
- log = log + execute_install_script(package_name, path, target_path)
+ log = log + execute_install_script(package_name, path, target_path, logger)
log = log + "##### move remove script #####\n"
move_remove_script(package_name, path, target_path)
log = log + "##### remove temporary dir : #{path} #####\n"
Utils.execute_shell("rm -rf #{path}")
rescue Interrupt
- @@log.error "FileInstaller: Interrupted.."
+ logger.error "FileInstaller: Interrupted.."
Utils.execute_shell("rm -rf #{path}")
- @@log.info "Removed #{path}"
+ logger.info "Removed #{path}"
raise Interrupt
end
end
- def FileInstaller.execute_install_script(package_name, path, target_path)
+ def FileInstaller.execute_install_script(package_name, path, target_path, logger)
script_file_prefix = "#{path}/install.*"
script_file = Dir.glob(script_file_prefix)[0]
log = ""
if not script_file.nil? then
- @@log.info "Execute \"#{script_file}\" file"
+ logger.info "Execute \"#{script_file}\" file"
if Utils.is_windows_like_os( Utils::HOST_OS ) then
cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
else
return log
end
- def FileInstaller.execute_remove_script(package_name, target_path)
+ def FileInstaller.execute_remove_script(package_name, target_path, logger)
info_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
if not File.directory? info_path then
return false
log = ""
if not script_file.nil? then
- @@log.info "Execute \"#{script_file}\" file"
+ logger.info "Execute \"#{script_file}\" file"
if Utils.is_windows_like_os( Utils::HOST_OS ) then
cmd = "set INSTALLED_PATH=\"#{target_path}\"& #{script_file}"
else
end
end
- def FileInstaller.remove_pkg_files(package_name, target_path)
+ def FileInstaller.remove_pkg_files(package_name, target_path, logger)
list_path = target_path + "/#{PACKAGE_INFO_DIR}/#{package_name}"
if not File.directory? list_path then
begin
Dir.rmdir(file_path)
rescue SystemCallError
- @@log.warn "\"#{file_path}\" directory is not empty"
+ logger.warn "\"#{file_path}\" directory is not empty"
end
else directories.push(file_path) end
elsif File.file? file_path then FileUtils.rm_f(file_path)
elsif File.symlink? file_path then File.unlink file_path
# if files are already removed by remove script,
- else @@log.warn "\"#{file_path}\" does not exist" end
+ else logger.warn "\"#{file_path}\" does not exist" end
end
end
directories.reverse.each do |path|
+ if not File.directory? path then next end
entries = Dir.entries(path)
if entries.include? "." then entries.delete(".") end
if entries.include? ".." then entries.delete("..") end
begin
Dir.rmdir(path)
rescue SystemCallError
- @@log.warn "\"#{file_path}\" directory is not empty"
+ logger.warn "\"#{file_path}\" directory is not empty"
end
else next end
end
return true
end
- def FileInstaller.uninstall(package_name, type, target_path)
+ def FileInstaller.uninstall(package_name, type, target_path, logger)
case type
when "binary" then
- execute_remove_script(package_name, target_path)
- remove_pkg_files(package_name, target_path)
+ execute_remove_script(package_name, target_path, logger)
+ remove_pkg_files(package_name, target_path, logger)
when "source" then
end
FileUtils.cp "#{source_path}/pkginfo.manifest", config_path
end
- def FileInstaller.extract_file(package_name, package_file_path, path, target_path)
+ def FileInstaller.extract_file(package_name, package_file_path, path, target_path, logger)
dirname = File.dirname(package_file_path)
filename = File.basename(package_file_path)
ext = File.extname(filename)
show_file_list_command = "tar -tf #{_package_file_path}"
extract_file_list_command = "tar xf \"#{_package_file_path}\" -C \"#{_path}\""
else
- @@log.error "\"#{filename}\" is not supported."
+ logger.error "\"#{filename}\" is not supported."
return nil
end
log = `#{extract_file_list_command}`
end
- @@log.info "Extracted \"#{filename}\" file.. OK"
+ logger.info "Extracted \"#{filename}\" file.. OK"
if log.nil? then log = "" end
return log
end
- def FileInstaller.extract_a_file(package_file_path, target_file, path)
+ def FileInstaller.extract_a_file(package_file_path, target_file, path, logger)
dirname = File.dirname(package_file_path)
filename = File.basename(package_file_path)
ext = File.extname(filename)
end
if File.exist? target_file_path then
- @@log.info "Extracted \"#{target_file}\" file.."
+ logger.info "Extracted \"#{target_file}\" file.."
return true
else
- @@log.warn "Failed to extracted \"#{target_file}\" file.."
+ logger.warn "Failed to extracted \"#{target_file}\" file.."
return false
end
end