Change-Id: I077ab48c4d2aae7295fec49cef279ba45ce53981
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/2919
Reviewed-by: Divya Thaluru <dthaluru@vmware.com>
Tested-by: gerrit-photon <photon-checkins@vmware.com>
... | ... |
@@ -63,6 +63,18 @@ else |
63 | 63 |
PHOTON_RPMCHECK_FLAGS := |
64 | 64 |
endif |
65 | 65 |
|
66 |
+ifeq ($(BUILDDEPS),true) |
|
67 |
+PUBLISH_BUILD_DEPENDENCIES := -bd True |
|
68 |
+else |
|
69 |
+PUBLISH_BUILD_DEPENDENCIES := |
|
70 |
+endif |
|
71 |
+ |
|
72 |
+ifdef WEIGHTS |
|
73 |
+PACKAGE_WEIGHTS_PATH = -pw $(WEIGHTS) |
|
74 |
+else |
|
75 |
+PACKAGE_WEIGHTS_PATH = |
|
76 |
+endif |
|
77 |
+ |
|
66 | 78 |
TOOLS_BIN := $(SRCROOT)/tools/bin |
67 | 79 |
CONTAIN := $(TOOLS_BIN)/contain |
68 | 80 |
VIXDISKUTIL := $(TOOLS_BIN)/vixdiskutil |
... | ... |
@@ -111,6 +123,8 @@ packages-micro: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SOUR |
111 | 111 |
-n $(PHOTON_BUILD_NUMBER) \ |
112 | 112 |
-v $(PHOTON_RELEASE_VERSION) \ |
113 | 113 |
$(PHOTON_RPMCHECK_FLAGS) \ |
114 |
+ $(PUBLISH_BUILD_DEPENDENCIES) \ |
|
115 |
+ $(PACKAGE_WEIGHTS_PATH) \ |
|
114 | 116 |
-t ${THREADS} |
115 | 117 |
|
116 | 118 |
live-iso: check-tools $(PHOTON_STAGE) $(PHOTON_PACKAGES_MINIMAL) |
... | ... |
@@ -145,6 +159,8 @@ packages-minimal: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SO |
145 | 145 |
-n $(PHOTON_BUILD_NUMBER) \ |
146 | 146 |
-v $(PHOTON_RELEASE_VERSION) \ |
147 | 147 |
$(PHOTON_RPMCHECK_FLAGS) \ |
148 |
+ $(PUBLISH_BUILD_DEPENDENCIES) \ |
|
149 |
+ $(PACKAGE_WEIGHTS_PATH) \ |
|
148 | 150 |
-t ${THREADS} |
149 | 151 |
|
150 | 152 |
iso: check-tools $(PHOTON_STAGE) $(PHOTON_PACKAGES) |
... | ... |
@@ -228,6 +244,8 @@ packages: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $(PHOTON_PUBLISH_R |
228 | 228 |
-w $(PHOTON_STAGE)/pkg_info.json \ |
229 | 229 |
-g $(PHOTON_DATA_DIR)/pkg_build_options.json \ |
230 | 230 |
$(PHOTON_RPMCHECK_FLAGS) \ |
231 |
+ $(PUBLISH_BUILD_DEPENDENCIES) \ |
|
232 |
+ $(PACKAGE_WEIGHTS_PATH) \ |
|
231 | 233 |
-t ${THREADS} |
232 | 234 |
|
233 | 235 |
updated-packages: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SOURCES) $(CONTAIN) generate-dep-lists |
... | ... |
@@ -247,6 +265,8 @@ updated-packages: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $(PHOTON_P |
247 | 247 |
-v $(PHOTON_RELEASE_VERSION) \ |
248 | 248 |
-k $(PHOTON_INPUT_RPMS_DIR) \ |
249 | 249 |
$(PHOTON_RPMCHECK_FLAGS) \ |
250 |
+ $(PUBLISH_BUILD_DEPENDENCIES) \ |
|
251 |
+ $(PACKAGE_WEIGHTS_PATH) \ |
|
250 | 252 |
-t ${THREADS} |
251 | 253 |
|
252 | 254 |
tool-chain-stage1: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SOURCES) $(CONTAIN) generate-dep-lists |
... | ... |
@@ -1,7 +1,9 @@ |
1 |
+import json |
|
1 | 2 |
import ThreadPool |
2 | 3 |
from constants import constants |
3 | 4 |
from Logger import Logger |
4 |
-import threading |
|
5 |
+import threading |
|
6 |
+from Queue import PriorityQueue |
|
5 | 7 |
|
6 | 8 |
class Scheduler(object): |
7 | 9 |
|
... | ... |
@@ -10,8 +12,13 @@ class Scheduler(object): |
10 | 10 |
listOfPackagesToBuild=[] |
11 | 11 |
listOfPackagesCurrentlyBuilding=[] |
12 | 12 |
sortedList=[] |
13 |
- listOfPackagesNextToBuild=[] |
|
13 |
+ listOfPackagesNextToBuild=PriorityQueue() |
|
14 | 14 |
listOfFailedPackages=[] |
15 |
+ alldependencyGraph = {} |
|
16 |
+ dependencyGraph = {} |
|
17 |
+ priorityMap = {} |
|
18 |
+ pkgWeights={} |
|
19 |
+ isPriorityScheduler=1 |
|
15 | 20 |
logger=None |
16 | 21 |
event=None |
17 | 22 |
stopScheduling=False |
... | ... |
@@ -23,7 +30,109 @@ class Scheduler(object): |
23 | 23 |
@staticmethod |
24 | 24 |
def setLog(logName,logPath): |
25 | 25 |
Scheduler.logger = Logger.getLogger(logName, logPath) |
26 |
- |
|
26 |
+ |
|
27 |
+ @staticmethod |
|
28 |
+ def getBuildRequiredPackages(package): |
|
29 |
+ listRequiredRPMPackages = [] |
|
30 |
+ listRequiredRPMPackages.extend(constants.specData.getBuildRequiresForPackage(package)) |
|
31 |
+ |
|
32 |
+ listRequiredPackages = [] |
|
33 |
+ |
|
34 |
+ for pkg in listRequiredRPMPackages: |
|
35 |
+ basePkg = constants.specData.getSpecName(pkg) |
|
36 |
+ if basePkg not in listRequiredPackages: |
|
37 |
+ listRequiredPackages.append(basePkg) |
|
38 |
+ |
|
39 |
+ return listRequiredPackages |
|
40 |
+ |
|
41 |
+ |
|
42 |
+ @staticmethod |
|
43 |
+ def getDependencies(package, parentPackage, k): |
|
44 |
+ |
|
45 |
+ for node in Scheduler.alldependencyGraph[package].keys(): |
|
46 |
+ Scheduler.getDependencies(node, package, k) |
|
47 |
+ |
|
48 |
+ if parentPackage == None: |
|
49 |
+ return |
|
50 |
+ else: |
|
51 |
+ for node in Scheduler.alldependencyGraph[package].keys(): |
|
52 |
+ try: |
|
53 |
+ Scheduler.alldependencyGraph[parentPackage][node] = max( |
|
54 |
+ Scheduler.alldependencyGraph[parentPackage][node], |
|
55 |
+ Scheduler.alldependencyGraph[package][node] * k) |
|
56 |
+ except KeyError: |
|
57 |
+ Scheduler.alldependencyGraph[parentPackage][node] = \ |
|
58 |
+ Scheduler.alldependencyGraph[package][node] * k |
|
59 |
+ |
|
60 |
+ @staticmethod |
|
61 |
+ def makeGraph(): |
|
62 |
+ k = 3 |
|
63 |
+ for package in Scheduler.sortedList: |
|
64 |
+ for child_pkg in Scheduler.dependencyGraph[package].keys(): |
|
65 |
+ Scheduler.getDependencies(child_pkg, package, k) |
|
66 |
+ for node in Scheduler.alldependencyGraph[child_pkg].keys(): |
|
67 |
+ try: |
|
68 |
+ Scheduler.dependencyGraph[package][node] = max( |
|
69 |
+ Scheduler.dependencyGraph[package][node], |
|
70 |
+ Scheduler.alldependencyGraph[child_pkg][node] * k) |
|
71 |
+ except KeyError: |
|
72 |
+ Scheduler.dependencyGraph[package][node] = \ |
|
73 |
+ Scheduler.alldependencyGraph[child_pkg][node] * k |
|
74 |
+ if constants.publishBuildDependencies: |
|
75 |
+ dependencyLists = {} |
|
76 |
+ for package in Scheduler.dependencyGraph.keys(): |
|
77 |
+ dependencyLists[package] = [] |
|
78 |
+ for dependency in Scheduler.dependencyGraph[package].keys(): |
|
79 |
+ dependencyLists[package].append(dependency) |
|
80 |
+ graphfile = open(str(constants.logPath) + "/BuildDependencies.json", 'w') |
|
81 |
+ graphfile.write(json.dumps(dependencyLists, sort_keys=True, indent=4)) |
|
82 |
+ graphfile.close() |
|
83 |
+ |
|
84 |
+ @staticmethod |
|
85 |
+ def parseWeights(): |
|
86 |
+ Scheduler.pkgWeights.clear() |
|
87 |
+ weightFile = open(constants.packageWeightsPath, 'r') |
|
88 |
+ Scheduler.pkgWeights = json.load(weightFile) |
|
89 |
+ weightFile.close() |
|
90 |
+ |
|
91 |
+ @staticmethod |
|
92 |
+ def getWeight(package): |
|
93 |
+ try: |
|
94 |
+ return float(Scheduler.pkgWeights[package]) |
|
95 |
+ except KeyError: |
|
96 |
+ return 0 |
|
97 |
+ |
|
98 |
+ |
|
99 |
+ |
|
100 |
+ @staticmethod |
|
101 |
+ def setPriorities(): |
|
102 |
+ if constants.packageWeightsPath == None: |
|
103 |
+ Scheduler.logger.info("Priority Scheduler disabled") |
|
104 |
+ Scheduler.isPriorityScheduler = 0 |
|
105 |
+ else: |
|
106 |
+ Scheduler.parseWeights() |
|
107 |
+ |
|
108 |
+ for package in Scheduler.sortedList: |
|
109 |
+ Scheduler.dependencyGraph[package] = {} |
|
110 |
+ Scheduler.alldependencyGraph[package] = {} |
|
111 |
+ for child_package in Scheduler.getBuildRequiredPackages(package): |
|
112 |
+ Scheduler.dependencyGraph[package][child_package] = 1 |
|
113 |
+ for child_package in Scheduler.getRequiredPackages(package): |
|
114 |
+ Scheduler.alldependencyGraph[package][child_package] = 1 |
|
115 |
+ Scheduler.makeGraph() |
|
116 |
+ for package in Scheduler.sortedList: |
|
117 |
+ try: |
|
118 |
+ Scheduler.priorityMap[package] = Scheduler.getWeight(package) |
|
119 |
+ except KeyError: |
|
120 |
+ Scheduler.priorityMap[package] = 0 |
|
121 |
+ for child_pkg in Scheduler.dependencyGraph[package].keys(): |
|
122 |
+ Scheduler.priorityMap[child_pkg] = Scheduler.priorityMap[child_pkg] \ |
|
123 |
+ + (Scheduler.dependencyGraph[package][child_pkg] |
|
124 |
+ * (Scheduler.getWeight(package))) |
|
125 |
+ Scheduler.logger.info("set Priorities: Priority of all packages") |
|
126 |
+ Scheduler.logger.info(Scheduler.priorityMap) |
|
127 |
+ |
|
128 |
+ |
|
27 | 129 |
@staticmethod |
28 | 130 |
def setParams(sortedList,listOfAlreadyBuiltPackages): |
29 | 131 |
Scheduler.sortedList=sortedList |
... | ... |
@@ -34,6 +143,7 @@ class Scheduler(object): |
34 | 34 |
Scheduler.listOfPackagesCurrentlyBuilding=[] |
35 | 35 |
Scheduler.listOfPackagesNextToBuild=[] |
36 | 36 |
Scheduler.listOfFailedPackages=[] |
37 |
+ Scheduler.setPriorities() |
|
37 | 38 |
|
38 | 39 |
@staticmethod |
39 | 40 |
def getRequiredPackages(package): |
... | ... |
@@ -52,7 +162,7 @@ class Scheduler(object): |
52 | 52 |
|
53 | 53 |
@staticmethod |
54 | 54 |
def __getListNextPackagesReadyToBuild(): |
55 |
- listOfPackagesNextToBuild=[] |
|
55 |
+ listOfPackagesNextToBuild=PriorityQueue() |
|
56 | 56 |
Scheduler.logger.info("Checking for next possible packages to build") |
57 | 57 |
for pkg in Scheduler.listOfPackagesToBuild: |
58 | 58 |
if pkg in Scheduler.listOfPackagesCurrentlyBuilding: |
... | ... |
@@ -67,37 +177,49 @@ class Scheduler(object): |
67 | 67 |
Scheduler.logger.info(reqPkg+" is not available. So we cannot build "+ pkg +" at this moment.") |
68 | 68 |
break |
69 | 69 |
if canBuild: |
70 |
- listOfPackagesNextToBuild.append(pkg) |
|
70 |
+ listOfPackagesNextToBuild.put((-Scheduler.priorityMap[pkg], pkg)) |
|
71 | 71 |
Scheduler.logger.info("Adding "+ pkg +" to the schedule list") |
72 | 72 |
return listOfPackagesNextToBuild |
73 |
- |
|
73 |
+ |
|
74 | 74 |
@staticmethod |
75 | 75 |
def getNextPackageToBuild(): |
76 | 76 |
Scheduler.logger.info("Waiting to acquire scheduler lock") |
77 | 77 |
Scheduler.lock.acquire() |
78 |
- |
|
78 |
+ |
|
79 | 79 |
if Scheduler.stopScheduling: |
80 | 80 |
Scheduler.logger.info("Released scheduler lock") |
81 | 81 |
Scheduler.lock.release() |
82 | 82 |
return None |
83 |
- |
|
83 |
+ |
|
84 | 84 |
if len(Scheduler.listOfPackagesToBuild) == 0: |
85 | 85 |
if Scheduler.event is not None: |
86 | 86 |
Scheduler.event.set() |
87 |
- |
|
88 |
- if len(Scheduler.listOfPackagesNextToBuild) == 0: |
|
89 |
- listOfPackagesNextToBuild=Scheduler.__getListNextPackagesReadyToBuild() |
|
90 |
- Scheduler.listOfPackagesNextToBuild=listOfPackagesNextToBuild |
|
91 |
- |
|
92 |
- if len(Scheduler.listOfPackagesNextToBuild) == 0: |
|
87 |
+ |
|
88 |
+ try: |
|
89 |
+ if Scheduler.listOfPackagesNextToBuild.qsize() == 0: |
|
90 |
+ listOfPackagesNextToBuild = Scheduler.__getListNextPackagesReadyToBuild() |
|
91 |
+ Scheduler.listOfPackagesNextToBuild = listOfPackagesNextToBuild |
|
92 |
+ except: |
|
93 |
+ if len(Scheduler.listOfPackagesNextToBuild) == 0: |
|
94 |
+ listOfPackagesNextToBuild = Scheduler.__getListNextPackagesReadyToBuild() |
|
95 |
+ Scheduler.listOfPackagesNextToBuild = listOfPackagesNextToBuild |
|
96 |
+ |
|
97 |
+ if Scheduler.listOfPackagesNextToBuild.qsize() == 0: |
|
93 | 98 |
Scheduler.logger.info("Released scheduler lock") |
94 | 99 |
Scheduler.lock.release() |
95 | 100 |
return None |
96 |
- |
|
97 |
- package=Scheduler.listOfPackagesNextToBuild.pop(0) |
|
98 |
- |
|
99 |
- if len(Scheduler.listOfPackagesNextToBuild) > 0: |
|
100 |
- ThreadPool.ThreadPool.activateWorkerThreads(len(Scheduler.listOfPackagesNextToBuild)) |
|
101 |
+ |
|
102 |
+ packageTup=Scheduler.listOfPackagesNextToBuild.get() |
|
103 |
+ |
|
104 |
+ if packageTup[0] == 0 and Scheduler.isPriorityScheduler == 1: |
|
105 |
+ listOfPackagesNextToBuild = Scheduler.__getListNextPackagesReadyToBuild() |
|
106 |
+ Scheduler.listOfPackagesNextToBuild = listOfPackagesNextToBuild |
|
107 |
+ packageTup = Scheduler.listOfPackagesNextToBuild.get() |
|
108 |
+ |
|
109 |
+ package = packageTup[1] |
|
110 |
+ Scheduler.logger.info("PackagesNextToBuild " + str(packageTup)) |
|
111 |
+ if Scheduler.listOfPackagesNextToBuild.qsize() > 0: |
|
112 |
+ ThreadPool.ThreadPool.activateWorkerThreads(Scheduler.listOfPackagesNextToBuild.qsize()) |
|
101 | 113 |
Scheduler.logger.info("Released scheduler lock") |
102 | 114 |
Scheduler.lock.release() |
103 | 115 |
Scheduler.listOfPackagesCurrentlyBuilding.append(package) |
... | ... |
@@ -130,5 +252,4 @@ class Scheduler(object): |
130 | 130 |
if len(Scheduler.listOfFailedPackages) != 0: |
131 | 131 |
return True |
132 | 132 |
return False |
133 |
- |
|
134 |
- |
|
135 | 133 |
\ No newline at end of file |
134 |
+ |
... | ... |
@@ -38,7 +38,8 @@ def main(): |
38 | 38 |
parser.add_argument("-w", "--pkginfo-file", dest="pkgInfoFile", default="../../stage/pkg_info.json") |
39 | 39 |
parser.add_argument("-g", "--pkg-build-option-file", dest="pkgBuildOptionFile", default="../../common/data/pkg_build_options.json") |
40 | 40 |
parser.add_argument("-q", "--rpmcheck-stop-on-error", dest="rpmCheckStopOnError", default=False, action ="store_true") |
41 |
- |
|
41 |
+ parser.add_argument("-bd", "--publish-build-dependencies", dest="publishBuildDependencies", default=False) |
|
42 |
+ parser.add_argument("-pw", "--package-weights-path", dest="packageWeightsPath", default=None) |
|
42 | 43 |
parser.add_argument("-y", "--generate-pkg-yaml-files", dest="generatePkgYamlFiles", default=False, action ="store_true") |
43 | 44 |
parser.add_argument("-j", "--pkg-yaml-dir-path", dest="pkgYamlDirPath", default="../../stage/") |
44 | 45 |
parser.add_argument("-f", "--pkg-blacklist-file", dest="pkgBlacklistFile", default=None) |
... | ... |
@@ -49,7 +50,6 @@ def main(): |
49 | 49 |
cmdUtils.runCommandInShell("mkdir -p "+options.logPath) |
50 | 50 |
|
51 | 51 |
logger=Logger.getLogger(options.logPath+"/Main") |
52 |
- |
|
53 | 52 |
errorFlag=False |
54 | 53 |
package = None |
55 | 54 |
pkgInfoJsonFile = options.pkgInfoFile |
... | ... |
@@ -84,6 +84,10 @@ def main(): |
84 | 84 |
logger.error("Given input RPMS Path is not a directory:"+options.inputRPMSPath) |
85 | 85 |
errorFlag = True |
86 | 86 |
|
87 |
+ if options.packageWeightsPath is not None and not os.path.isfile(options.packageWeightsPath): |
|
88 |
+ logger.error("Given input Weights file is not a file:"+options.packageWeightsPath) |
|
89 |
+ errorFlag = True |
|
90 |
+ |
|
87 | 91 |
if options.generatePkgYamlFiles: |
88 | 92 |
if options.pkgBlacklistFile is not None and options.pkgBlacklistFile != "" and not os.path.isfile(options.pkgBlacklistFile): |
89 | 93 |
logger.error("Given package blacklist file is not valid:"+options.pkgBlacklistFile) |
... | ... |
@@ -152,7 +156,6 @@ def main(): |
152 | 152 |
# print stacktrace |
153 | 153 |
traceback.print_exc() |
154 | 154 |
sys.exit(1) |
155 |
- |
|
156 | 155 |
sys.exit(0) |
157 | 156 |
|
158 | 157 |
def buildPackagesList(csvFilename): |
... | ... |
@@ -20,7 +20,8 @@ class constants(object): |
20 | 20 |
rpmCheck=False |
21 | 21 |
sourceRpmPath="" |
22 | 22 |
noDepsPackageList=["texinfo","bzip2","gettext","nspr","xz","bison","go"] |
23 |
- |
|
23 |
+ publishBuildDependencies=False |
|
24 |
+ packageWeightsPath=None |
|
24 | 25 |
# These packages will be built in first order as build-core-toolchain stage |
25 | 26 |
listCoreToolChainPackages=[ |
26 | 27 |
"filesystem", |
... | ... |
@@ -328,6 +329,8 @@ class constants(object): |
328 | 328 |
constants.testForceRPMS=[] |
329 | 329 |
constants.rpmCheck = options.rpmCheck |
330 | 330 |
constants.rpmCheckStopOnError = options.rpmCheckStopOnError |
331 |
+ constants.publishBuildDependencies=options.publishBuildDependencies |
|
332 |
+ constants.packageWeightsPath=options.packageWeightsPath |
|
331 | 333 |
if constants.rpmCheck: |
332 | 334 |
constants.testLogger=Logger.getLogger("MakeCheckTest",constants.logPath) |
333 | 335 |
|