[Title] support distribution lock
authorjiil.hyoun <jiil.hyoun@samsung.com>
Thu, 29 Nov 2012 07:36:04 +0000 (16:36 +0900)
committerjiil.hyoun <jiil.hyoun@samsung.com>
Thu, 29 Nov 2012 07:36:04 +0000 (16:36 +0900)
[Type] Feature
[Module] Toolchain /
[Priority] Major
[Jira#]
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

Change-Id: Ib42d5e0a35666eaca50815592ee1d11004126d59

src/build_server/BinaryUploadProject.rb
src/build_server/CommonProject.rb
src/build_server/DistributionManager.rb
src/build_server/GitBuildProject.rb
src/build_server/JobManager.rb
src/build_server/ProjectManager.rb
src/build_server/SocketJobRequestListener.rb

index f913446d2eff8a4fbb1e9f75d5b26bbc8424b54d..e101c480a8d6212810f3bb56318557aa7506fe0a 100644 (file)
@@ -161,6 +161,8 @@ class BinaryUploadProject < CommonProject
 
                if is_new then
                        db.do "INSERT INTO project_bins VALUES (#{@prj_id},'#{@pkg_name}')"
+                       db.do "INSERT INTO group_project_accesses 
+                               VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','UNLOCK')"
                else
                        db.do "UPDATE project_bins SET pkg_name='#{@pkg_name}' WHERE project_id=#{@prj_id})"
                end
index 61eb39fba042e5bbf2ad2896f4861741dea2ec20..efdba9338588897f9debb9f4ea05ed44632adcab 100644 (file)
@@ -165,7 +165,6 @@ class CommonProject
                return @prj_id
        end
 
-
        def self.create_table(db, inc, post_fix) 
                db.do "CREATE TABLE projects ( 
                        id INTEGER PRIMARY KEY #{inc}, 
@@ -333,7 +332,7 @@ class CommonProject
        end
 
 
-       public 
+       public
        def self.get_project_row(name, dist_name, db)
                row = db.select_one("SELECT * FROM distributions WHERE name='#{dist_name}'")
                dist_id = row['id']
@@ -341,8 +340,17 @@ class CommonProject
                return row
        end
 
+       public
+       def self.get_project_from_pkg_name_row(pkg_name, dist_name, db)
+               return db.select_one("SELECT projects.id,projects.distribution_id,projects.name,projects.ptype,projects.password 
+                                                        FROM distributions,projects,project_bins
+                                                        WHERE distributions.name='#{dist_name}' and
+                                                        distributions.id = projects.distribution_id and
+                                                        projects.id = project_bins.project_id and
+                                                        project_bins.pkg_name = '#{pkg_name}'")
+       end
 
-       public 
+       public
        def self.get_all_project_rows(db)
                result = []
                rows = db.select_all("SELECT projects.name,distributions.name as dist_name,projects.ptype 
index fb70c656dcc178f21e2013cde8cef00e654aa8c7..5862f8877a0328a6c2b34bcff7ef2bbef1358861 100644 (file)
@@ -36,9 +36,10 @@ require "RegisterPackageJob.rb"
 require "packageServer.rb"
 
 class PackageDistribution
-       attr_accessor :name, :pkgsvr_url, :pkgsvr_ip, :pkgsvr_port, :status, :description
+       attr_accessor :name, :pkgsvr_url, :pkgsvr_ip, :pkgsvr_port, :status, :description, :id
 
        def initialize( name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, status )
+               @id = -1
                @name = name
                @pkgsvr_url = pkgsvr_url
                @pkgsvr_ip = pkgsvr_ip
@@ -48,24 +49,20 @@ class PackageDistribution
        end
 
 
-       def self.create_table(db, inc, post_fix) 
+       def self.create_table(db, inc, post_fix)
                db.do "CREATE TABLE distributions ( 
                        id INTEGER PRIMARY KEY #{inc}, 
                        name VARCHAR(32) NOT NULL UNIQUE, 
                        pkgsvr_url VARCHAR(256), 
                        pkgsvr_addr VARCHAR(64), 
-                       status VARCHAR(32) NOT NULL DEFAULT 'OPEN', 
+                       status VARCHAR(32) NOT NULL DEFAULT 'OPEN',
                        description VARCHAR(256) ) #{post_fix}"
        end
 
-       
+
        def self.load(name, db)
                row = db.select_one("SELECT * FROM distributions WHERE name='#{name}'")
-               if not row.nil? then
-                       return load_row(row)
-               end
-
-               return nil
+               return ( row.nil? ) ? nil : load_row(row)
        end
 
 
@@ -78,23 +75,14 @@ class PackageDistribution
 
 
        def self.load_all(db)
-               result = []
                rows = db.select_all("SELECT * FROM distributions")
-               rows.each do |row|
-                       result.push load_row(row)
-               end
-
-               return result
+               return rows.map{|x| load_row(x)}
        end
 
 
        def self.load_first(db)
                row = db.select_one("SELECT * FROM distributions")
-               if not row.nil? then
-                       return load_row(row)
-               end
-
-               return nil
+               return ( row.nil? ) ? nil : load_row(row)
        end
 
 
@@ -103,7 +91,8 @@ class PackageDistribution
                pkgsvr_port = row['pkgsvr_addr'].split(":")[1].to_i
                new_obj = new(row['name'], row['pkgsvr_url'], pkgsvr_ip, pkgsvr_port, row['status'])
                new_obj.description = row['description']
-       
+               new_obj.id = row['id']
+
                return new_obj
        end
 
@@ -112,7 +101,7 @@ class PackageDistribution
                dist_addr = @pkgsvr_ip + ":" + @pkgsvr_port.to_s
                row = db.select_one("SELECT * FROM distributions WHERE name='#{@name}'")
                if row.nil? then
-                       db.do "INSERT INTO distributions(name, pkgsvr_url, pkgsvr_addr, status, description) VALUES ('#{@name}','#{@pkgsvr_url}','#{dist_addr}','#{@status}', '#{@description}')"
+                       db.do "INSERT INTO distributions(name, pkgsvr_url, pkgsvr_addr, status, description) VALUES ('#{@name}','#{@pkgsvr_url}','#{dist_addr}','#{@status}','#{@description}')"
                else
                        db.do "UPDATE distributions SET pkgsvr_url='#{@pkgsvr_url}', pkgsvr_addr='#{dist_addr}', status='#{@status}', description='#{@description}' WHERE name='#{@name}'"
                end
@@ -121,11 +110,7 @@ class PackageDistribution
 
        def self.get_distribution_id(db, dist_name)
                row = db.select_one("SELECT * FROM distributions WHERE name='#{dist_name}'")
-               if row.nil? then 
-                       return "NULL"
-               else
-                       return row['id']
-               end
+               return ( row.nil? ) ? "NULL" : row['id']
        end
 end
 
@@ -141,21 +126,13 @@ class DistributionManager
        # get default distribution
        def get_default_distribution_name()
                dist = get_first_distribution()
-               if not dist.nil? then 
-                       return dist.name
-               else
-                       return nil
-               end
+               return ( dist.nil? ) ? nil : dist.name
        end
 
 
        def get_default_pkgsvr_url()
                dist = get_first_distribution()
-               if not dist.nil? then 
-                       return dist.pkgsvr_url
-               else
-                       return ""
-               end
+               return ( dist.nil? ) ? "" : dist.pkgsvr_url
        end
 
 
@@ -165,7 +142,6 @@ class DistributionManager
                @server.get_db_connection() do |db|
                        return get_distribution_internal(name, db)
                end
-
                return nil
        end
 
@@ -186,7 +162,6 @@ class DistributionManager
                        new_dist = PackageDistribution.new(name, pkgsvr_url, pkgsvr_ip, pkgsvr_port, "OPEN")
                        new_dist.save(db)
                end
-               
                @server.log.info "Added a new distribution \"#{name}\""
                return true
        end
@@ -234,16 +209,16 @@ class DistributionManager
                        dist = get_distribution_internal(name, db)
                        if dist.nil? then return false end
 
-                       dist.status = value ? "LOCKED" : "OPEN"
+                       dist.status = (value)? "LOCKED" : "OPEN"
                        dist.save(db)
                end
-               if result then 
-                       if value then   
+               if result then
+                       if value then
                                @server.log.info "The distribution \"#{name}\" is locked!"
                        else
                                @server.log.info "The distribution \"#{name}\" is unlocked!"
                        end
-               end     
+               end
 
                return result
        end
index 2063dab9cd5143dc7f7aa396c3c085b27981ef79..be75aab4b99ab2f1e3fca50b017d72c9ad18d316 100644 (file)
@@ -137,6 +137,8 @@ class GitBuildProject < CommonProject
 
                if is_new then
                        db.do "INSERT INTO project_gits VALUES (#{@prj_id},'#{@repository}','#{@branch}')"
+                       db.do "INSERT INTO group_project_accesses 
+                               VALUES ( (SELECT groups.id FROM groups WHERE groups.name = 'admin'),'#{@prj_id}','UNLOCK')"
                else
                        db.do "UPDATE project_gits SET git_repos='#{@repository}',git_branch='#{@branch}' WHERE project_id=#{@prj_id})"
                end
index 37147c2a9fb4a802a535c1f6a4ed31a3e4fe5f7b..b03213f25e33b83585368f3c83c0715398ee3638 100644 (file)
@@ -102,6 +102,16 @@ class JobManager
                return new_idx
        end
 
+       def is_user_accessable(job,user_id)
+               result = nil
+               @server.get_db_connection() do |db|
+                       result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses
+                                       WHERE user_groups.group_id = group_project_accesses.group_id and
+                                       group_project_accesses.project_id = #{job.get_project.get_project_id} and
+                                       user_groups.user_id = #{user_id}"
+               end
+               return (not result.nil?)
+       end
 
        def create_new_register_job( file_path, dist_name )
                return RegisterPackageJob.new( file_path, nil, @server, nil, dist_name )
index 25a498e1142f788cfb0e74be72cf145f2f1e3f30..2a4e9e082c21bcc9ea1e558ea1c035f9a0084407 100644 (file)
@@ -170,6 +170,32 @@ class ProjectManager
                return result
        end
 
+       public
+       def get_project_accessable(project_name, dist_name, user_id)
+               prj = get_project(project_name, dist_name)
+               result = nil
+               @server.get_db_connection() do |db|
+                       result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses 
+                                                       WHERE user_groups.user_id = #{user_id} and 
+                                                       user_groups.group_id = group_project_accesses.group_id and
+                                                       group_project_accesses.project_id = #{prj.get_project_id} and
+                                                       group_project_accesses.build = 'UNLOCK'"
+               end
+               return (not result.nil?)
+       end
+
+       def get_project_pkg_name_accessable(pkg_name, dist_name, user_id)
+               result = nil
+               prj = get_project_from_package_name(pkg_name, dist_name)
+               @server.get_db_connection() do |db|
+                       result = db.select_one "SELECT user_groups.group_id FROM user_groups,group_project_accesses 
+                                                       WHERE user_groups.user_id = #{user_id} and 
+                                                       user_groups.group_id = group_project_accesses.group_id and
+                                                       group_project_accesses.project_id = #{prj.get_project_id} and
+                                                       group_project_accesses.build = 'UNLOCK'"
+               end
+               return (not result.nil?)
+       end
 
        # create new job for project
        # if cannot create, return nil
@@ -250,16 +276,9 @@ class ProjectManager
 
 
        def get_project_from_package_name(pkg_name, dist_name)
-               get_all_projects().each do |prj|
-                       if prj.type != "BINARY" then next end
-                       # check project's distribution
-                       if prj.dist_name != dist_name then next end
-                       # check project provide target package
-                       if prj.pkg_name == pkg_name then
-                               return prj
-                       end
+               @server.get_db_connection() do |db|
+                       return get_project_from_pkg_name_internal(pkg_name,dist_name,db)
                end
-
                return nil
        end
 
@@ -335,4 +354,9 @@ class ProjectManager
                end
        end
 
+       private
+       def get_project_from_pkg_name_internal(pkg_name, dist_name, db)
+               row = CommonProject.get_project_from_pkg_name_row(pkg_name, dist_name, db)
+               return ( row.nil? ) ? nil : BinaryUploadProject.load(row[:name], dist_name, @server, db)
+       end
 end
index ada54f8e12c1421200092861c5cff89ce5394dc4..81fef09dedc8b8909e1ddb1da3f785299bcee7ff 100644 (file)
@@ -171,7 +171,6 @@ class SocketJobRequestListener
 
        end
 
-
        # "BUILD"
        def handle_cmd_build( line, req )
                tok = line.split("|").map { |x| x.strip }
@@ -231,6 +230,7 @@ class SocketJobRequestListener
                        raise "No user information!"
                end
 
+
                # multi build job
                if project_name_list.count > 1 or os_list.count > 1 then
                        new_job_list = []
@@ -239,6 +239,13 @@ class SocketJobRequestListener
                                if not passwd_list[i].nil? then passwd = passwd_list[i]
                                else passwd = passwd_list[0] end
                                check_build_project(pname,passwd,dist_name,req)
+                               if not check_project_user_id(pname,dist_name,user_id) then
+                                       BuildCommServer.send_begin(req)
+                                       req.puts "Error: \"#{user_email}\" can't access \"#{pname}\" project!"
+                                       req.puts "You are not in project control group"
+                                       BuildCommServer.send_end(req)
+                                       raise "#{user_email} can't accesse #{pname} project!"
+                               end
                                os_list.each do |os|
                                        new_job = create_new_job( pname, os, dist_name )
                                        if new_job.nil? then
@@ -285,6 +292,13 @@ class SocketJobRequestListener
                        os = os_list[0]
 
                        check_build_project(pname,passwd,dist_name,req)
+                       if not check_project_user_id(pname,dist_name,user_id) then
+                               BuildCommServer.send_begin(req)
+                               req.puts "Error: \"#{user_email}\" can't access \"#{pname}\" project!"
+                               req.puts "You are not in project control group"
+                               BuildCommServer.send_end(req)
+                               raise "#{user_email} can't accesse #{pname} project!"
+                       end
                        new_job = create_new_job( pname, os, dist_name )
                        if new_job.nil? then
                                raise "\"#{pname}\" does not support #{os} in #{dist_name}"
@@ -360,6 +374,7 @@ class SocketJobRequestListener
                case tok[1]
                        # RESOLVE|GIT|project_name|passwd|os|async|dist_name|user_email|verbose
                when "GIT"
+
                        # parse
                        project_name=tok[2]
                        passwd=tok[3]
@@ -395,24 +410,33 @@ class SocketJobRequestListener
                        end
                        os = os_list[0]
 
-                       # create new job
-                       new_job = create_new_job( project_name, os, dist_name )
-                       if new_job.nil? then
-                               raise "Creating build job failed : #{project_name}, #{os}"
-                       end
-                       @log.info "Received a request for resolving this project : #{project_name}, #{os}"
-
                        # check user email
                        user_id = @parent_server.check_user_id_from_email( user_email )
-                       if user_id != -1 then
-                               new_job.user_id = user_id
-                       else
+                       if user_id == -1 then
                                BuildCommServer.send_begin(req)
                                req.puts "Error: Cannot find the user with \"#{user_email}\"!"
                                BuildCommServer.send_end(req)
                                raise "No user information!"
                        end
 
+                       # check user accessable
+                       if not check_project_user_id(project_name,dist_name,user_id) then
+                               BuildCommServer.send_begin(req)
+                               req.puts "Error: \"#{user_email}\" can't access \"#{project_name}\" project!"
+                               req.puts "You are not in project control group"
+                               BuildCommServer.send_end(req)
+                               raise "#{user_email} can't accesse #{project_name} project!"
+                       end
+
+                       # create new job
+                       new_job = create_new_job( project_name, os, dist_name )
+                       if new_job.nil? then
+                               raise "Creating build job failed : #{project_name}, #{os}"
+                       end
+                       @log.info "Received a request for resolving this project : #{project_name}, #{os}"
+
+                       new_job.user_id = user_id
+
                        # resolve
                        new_job.set_resolve_flag()
 
@@ -589,6 +613,13 @@ class SocketJobRequestListener
                else
                        if cancel_job.cancel_state == "NONE" then
                                # check passwd
+                               if not @parent_server.jobmgr.is_user_accessable(cancel_job,user_id) then
+                                       BuildCommServer.send_begin(req)
+                                       req.puts "Error: \"#{tok[3]}\" can't access \"#{cancel_job.get_project.name}\" project!"
+                                       req.puts "You are not in project control group"
+                                       BuildCommServer.send_end(req)
+                                       raise "#{tok[3]} can't accesse #{cancel_job.get_project.name} project!"
+                               end
                                if cancel_job.type == "MULTIBUILD" then
                                        cancel_job.get_sub_jobs().select{|x| x.cancel_state == "NONE" }.each do |sub|
                                                if not check_project_password( sub.get_project, tok[2], req) then
@@ -677,7 +708,7 @@ class SocketJobRequestListener
                end
 
                # check distribution
-               if not check_distribution(dist_name, req) then
+               if not check_distribution(dist_name, req, true) then
                        raise "The distribution error!!"
                end
 
@@ -760,6 +791,23 @@ class SocketJobRequestListener
                                raise "No project is defined for this binary : #{filename}!"
                        end
 
+                       # check user email
+                       user_id = @parent_server.check_user_id_from_email( user_email )
+                       if user_id == -1 then
+                               BuildCommServer.send_begin(req)
+                               req.puts "Error: Cannot find the user with \"#{user_email}\"!"
+                               BuildCommServer.send_end(req)
+                               raise "No user information!"
+                       end
+
+                       if not check_project_pkg_name_user_id(filename, dist_name, user_id) then
+                               BuildCommServer.send_begin(req)
+                               req.puts "Error: \"#{user_email}\" can't regist \"#{filename}\"!"
+                               req.puts "You are not in project control group"
+                               BuildCommServer.send_end(req)
+                               raise "#{user_email} can't regist #{filename}!"
+                       end
+
                        # check passwd
                        if not check_project_password(prj, passwd, req) then
                                raise "Project's password is not matched!!"
@@ -772,14 +820,6 @@ class SocketJobRequestListener
                                raise "Creating build job failed : #{prj.name}, #{filename}"
                        end
 
-                       # check user email
-                       user_id = @parent_server.check_user_id_from_email( user_email )
-                       if user_id == -1 then
-                               BuildCommServer.send_begin(req)
-                               req.puts "Error: Cannot find the user with \"#{user_email}\"!"
-                               BuildCommServer.send_end(req)
-                               raise "No user information!"
-                       end
                        new_job.user_id = user_id
 
                        # create logger and set
@@ -854,6 +894,10 @@ class SocketJobRequestListener
        end
 
 
+       private
+       def check_project_user_id(project_name, dist_name, user_id)
+               return @parent_server.prjmgr.get_project_accessable(project_name, dist_name, user_id)
+       end
 
        private
        def check_project_exist(project_name, dist_name, req)
@@ -869,6 +913,14 @@ class SocketJobRequestListener
                return prj
        end
 
+       private
+       def check_project_pkg_name_user_id(file_name, dist_name, user_id)
+               # get package name
+               new_name = file_name.sub(/(.*)_(.*)_(.*)\.zip/,'\1,\2,\3')
+               pkg_name = new_name.split(",")[0]
+               return @parent_server.prjmgr.get_project_pkg_name_accessable(pkg_name, dist_name, user_id)
+       end
+
        private
        def check_project_for_package_file_name(filename, dist_name, req)
                # get package name
@@ -887,7 +939,6 @@ class SocketJobRequestListener
                return prj
        end
 
-
        private
        def check_project_password(prj, passwd, req)
 
@@ -904,14 +955,13 @@ class SocketJobRequestListener
 
 
        private
-       def check_distribution(dist_name, req)
+       def check_distribution(dist_name, req, only_exist = false)
                dist = @parent_server.distmgr.get_distribution(dist_name)
                if dist.nil? then
                        BuildCommServer.send_begin(req)
                        req.puts "Error: The distribution \"#{dist_name}\" does not exist!"
                        BuildCommServer.send_end(req)
-                       return false
-               elsif dist.status != "OPEN" then
+               elsif dist.status != "OPEN" and not only_exist then
                        BuildCommServer.send_begin(req)
                        req.puts "Error: The distribution \"#{dist_name}\" is locked!"
                        BuildCommServer.send_end(req)
@@ -952,19 +1002,17 @@ class SocketJobRequestListener
                                                result.push svr_os
                                        end
                                end
+                       elsif @parent_server.supported_os_list.include?(os) then
+                               result.push os
                        else
-                               if not @parent_server.supported_os_list.include?(os) then
-                                       BuildCommServer.send_begin(req)
-                                       req.puts "Error: Unsupported OS name \"#{os}\" is used!"
-                                       req.puts "Error: Check the following supported OS list. "
-                                       @parent_server.supported_os_list.each do |os_name|
-                                               req.puts " * #{os_name}"
-                                       end
-                                       BuildCommServer.send_end(req)
-                                       return nil
-                               else
-                                       result.push os
+                               BuildCommServer.send_begin(req)
+                               req.puts "Error: Unsupported OS name \"#{os}\" is used!"
+                               req.puts "Error: Check the following supported OS list. "
+                               @parent_server.supported_os_list.each do |os_name|
+                                       req.puts " * #{os_name}"
                                end
+                               BuildCommServer.send_end(req)
+                               return nil
                        end
                end