Browse code

BuildContainer based build system.

Make docker-build optional.

Merge testing code & Use docker exec instead of exec_run for returnVal

Squashing commits to merge.
Original Authors: Vinay Kularni (kulkarniv@vmware.com) & Rui Gu (ruig@vmware.com)

Change-Id: I727505f670874af96a6af468f7d417b0293a3f93
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3671
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Rui Gu <ruig@vmware.com>

sharathjg authored on 2017/08/30 09:15:21
Showing 14 changed files
... ...
@@ -225,10 +225,11 @@ who-needs:
225 225
 	@cd $(PHOTON_SPECDEPS_DIR) && \
226 226
 		$(PHOTON_SPECDEPS) -s $(PHOTON_SPECS_DIR) -i who-needs -p $(pkg)
227 227
 
228
-packages: check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SOURCES) $(CONTAIN) generate-dep-lists
228
+packages: check-docker-py check-tools $(PHOTON_STAGE) $(PHOTON_PUBLISH_XRPMS) $(PHOTON_PUBLISH_RPMS) $(PHOTON_SOURCES) $(CONTAIN) generate-dep-lists
229 229
 	@echo "Building all RPMS..."
230 230
 	@cd $(PHOTON_PKG_BUILDER_DIR) && \
231 231
         $(PHOTON_PACKAGE_BUILDER) \
232
+                -bt $(PHOTON_BUILD_TYPE) \
232 233
                 -s $(PHOTON_SPECS_DIR) \
233 234
                 -r $(PHOTON_RPMS_DIR) \
234 235
                 -a $(PHOTON_SRPMS_DIR) \
... ...
@@ -483,6 +484,9 @@ check-tools: check-bison check-g++ check-gawk check-createrepo check-texinfo che
483 483
 check-docker:
484 484
 	@command -v docker >/dev/null 2>&1 || { echo "Package docker not installed. Aborting." >&2; exit 1; }
485 485
 
486
+check-docker-py:
487
+	tdnf install -y docker docker-py --refresh && systemctl daemon-reload && systemctl start docker
488
+
486 489
 check-bison:
487 490
 	@command -v bison >/dev/null 2>&1 || { echo "Package bison not installed. Aborting." >&2; exit 1; }
488 491
 
... ...
@@ -526,6 +530,7 @@ check: packages
526 526
 	@echo "Testing all RPMS ..."
527 527
 	@cd $(PHOTON_PKG_BUILDER_DIR) && \
528 528
         $(PHOTON_PACKAGE_BUILDER) \
529
+                -bt $(PHOTON_BUILD_TYPE) \
529 530
                 -s $(PHOTON_SPECS_DIR) \
530 531
                 -r $(PHOTON_RPMS_DIR) \
531 532
                 -a $(PHOTON_SRPMS_DIR) \
... ...
@@ -533,7 +538,7 @@ check: packages
533 533
                 -b $(PHOTON_CHROOT_PATH) \
534 534
                 -l $(PHOTON_LOGS_DIR) \
535 535
                 -p $(PHOTON_PUBLISH_RPMS_DIR) \
536
-		-e $(PHOTON_PUBLISH_XRPMS_DIR) \
536
+                -e $(PHOTON_PUBLISH_XRPMS_DIR) \
537 537
                 -c $(PHOTON_PULLSOURCES_CONFIG) \
538 538
                 -d $(PHOTON_DIST_TAG) \
539 539
                 -n $(PHOTON_BUILD_NUMBER) \
... ...
@@ -549,13 +554,14 @@ check: packages
549 549
 	@echo "Building package $(PKG_NAME) ..."
550 550
 	@cd $(PHOTON_PKG_BUILDER_DIR) && \
551 551
         $(PHOTON_PACKAGE_BUILDER) -i $(PKG_NAME)\
552
+                              -bt $(PHOTON_BUILD_TYPE) \
552 553
                               -b $(PHOTON_CHROOT_PATH) \
553 554
                               -s $(PHOTON_SPECS_DIR) \
554 555
                               -r $(PHOTON_RPMS_DIR) \
555 556
                               -a $(PHOTON_SRPMS_DIR) \
556 557
                               -x $(PHOTON_SRCS_DIR) \
557 558
                               -p $(PHOTON_PUBLISH_RPMS_DIR) \
558
-			      -e $(PHOTON_PUBLISH_XRPMS_DIR) \
559
+                              -e $(PHOTON_PUBLISH_XRPMS_DIR) \
559 560
                               -c $(PHOTON_PULLSOURCES_CONFIG) \
560 561
                               -d $(PHOTON_DIST_TAG) \
561 562
                               -n $(PHOTON_BUILD_NUMBER) \
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:        Security client
2 2
 Name:           nss
3 3
 Version:        3.31
4
-Release:        2%{?dist}
4
+Release:        3%{?dist}
5 5
 License:        MPLv2.0
6 6
 URL:            http://ftp.mozilla.org/pub/security/nss/releases/NSS_3_31_RTM/src/%{name}-%{version}.tar.gz
7 7
 Group:          Applications/System
... ...
@@ -27,6 +27,7 @@ Requires:       nss-libs = %{version}-%{release}
27 27
 %package devel
28 28
 Summary: Development Libraries for Network Security Services
29 29
 Group: Development/Libraries
30
+Requires: nspr-devel
30 31
 Requires: nss = %{version}-%{release}
31 32
 %description devel
32 33
 Header files for doing development with Network Security Services.
... ...
@@ -96,6 +97,8 @@ sudo -u test ./all.sh && userdel test -r -f
96 96
 %{_libdir}/libsoftokn3.so
97 97
 
98 98
 %changelog
99
+*   Fri Jul 07 2017 Vinay Kulkarni <kulkarniv@vmware.com> 3.31-3
100
+-   Fix buildrequires.
99 101
 *   Thu Jun 29 2017 Xiaolin Li <xiaolinl@vmware.com> 3.31-2
100 102
 -   Fix check.
101 103
 *   Tue Jun 20 2017 Xiaolin Li <xiaolinl@vmware.com> 3.31-1
... ...
@@ -18,6 +18,7 @@ VAGRANT_BUILD=vagrant
18 18
 SRCROOT := $(realpath $(SRCROOT))
19 19
 MAKEROOT := $(realpath $(MAKEROOT))
20 20
 
21
+PHOTON_BUILD_TYPE?=chroot
21 22
 PHOTON_STAGE?=$(SRCROOT)/stage
22 23
 PHOTON_LOGS_DIR=$(PHOTON_STAGE)/LOGS
23 24
 PHOTON_RPMS_DIR=$(PHOTON_STAGE)/RPMS
24 25
new file mode 100644
... ...
@@ -0,0 +1,222 @@
0
+from PackageUtils import PackageUtils
1
+from Logger import Logger
2
+from ToolChainUtils import ToolChainUtils
3
+from CommandUtils import CommandUtils
4
+import os.path
5
+import sys
6
+from constants import constants
7
+import shutil
8
+import docker
9
+
10
+class BuildContainer(object):
11
+
12
+    def __init__(self, mapPackageToCycles, listAvailableCyclicPackages, listBuildOptionPackages, pkgBuildOptionFile, logName=None, logPath=None):
13
+        if logName is None:
14
+            logName = "BuildContainer"
15
+        if logPath is None:
16
+            logPath = constants.logPath
17
+        self.logName = logName
18
+        self.logPath = logPath
19
+        self.logger = Logger.getLogger(logName, logPath, True)
20
+        self.buildContainerImage = "photon_build_container:latest"
21
+        self.dockerClient = docker.from_env(version="auto")
22
+        self.mapPackageToCycles = mapPackageToCycles
23
+        self.listAvailableCyclicPackages = listAvailableCyclicPackages
24
+        self.listNodepsPackages = ["glibc","gmp","zlib","file","binutils","mpfr","mpc","gcc","ncurses","util-linux","groff","perl","texinfo","rpm","openssl","openssl-devel","go"]
25
+        self.listBuildOptionPackages = listBuildOptionPackages
26
+        self.pkgBuildOptionFile = pkgBuildOptionFile
27
+
28
+    def prepareBuildContainer(self, containerTaskName, packageName, isToolChainPackage=False):
29
+        containerID = None
30
+        mountVols = {
31
+                        constants.prevPublishRPMRepo: {'bind': '/publishrpms', 'mode': 'ro'},
32
+                        constants.prevPublishXRPMRepo: {'bind': '/publishxrpms', 'mode': 'ro'},
33
+                        constants.rpmPath: {'bind': constants.topDirPath + "/RPMS", 'mode': 'rw'},
34
+                        constants.sourceRpmPath: {'bind': constants.topDirPath + "/SRPMS", 'mode': 'rw'},
35
+                        constants.logPath + "/" + self.logName: {'bind': constants.topDirPath + "/LOGS", 'mode': 'rw'},
36
+                    }
37
+
38
+        containerName = containerTaskName
39
+        containerName = containerName.replace("+", "p")
40
+        try:
41
+            oldContainerID = self.dockerClient.containers.get(containerName)
42
+            if oldContainerID is not None:
43
+                oldContainerID.remove(force=True)
44
+        except docker.errors.NotFound:
45
+            sys.exc_clear()
46
+
47
+        try:
48
+            self.logger.info("BuildContainer-prepareBuildContainer: Starting build container: " + containerName)
49
+            #TODO: Is init=True equivalent of --sig-proxy?
50
+            containerID = self.dockerClient.containers.run(self.buildContainerImage,
51
+                                                           detach=True,
52
+                                                           name=containerName,
53
+                                                           network_mode="host",
54
+                                                           volumes=mountVols,
55
+                                                           command="/bin/bash -l -c /wait.sh")
56
+            self.logger.debug("Started Photon build container for task " + containerTaskName
57
+                               + " ID: " + containerID.short_id)
58
+            if not containerID:
59
+                raise Exception("Unable to start Photon build container for task " + containerTaskName)
60
+        except Exception as e:
61
+            self.logger.debug("Unable to start Photon build container for task " + containerTaskName)
62
+            raise e
63
+        return containerID
64
+
65
+    def findPackageNameFromRPMFile(self, rpmfile):
66
+        rpmfile = os.path.basename(rpmfile)
67
+        releaseindex = rpmfile.rfind("-")
68
+        if releaseindex == -1:
69
+            self.logger.error("Invalid rpm file:" + rpmfile)
70
+            return None
71
+        versionindex=rpmfile[0:releaseindex].rfind("-")
72
+        if versionindex == -1:
73
+            self.logger.error("Invalid rpm file:" + rpmfile)
74
+            return None
75
+        packageName = rpmfile[0:versionindex]
76
+        return packageName
77
+
78
+    def findInstalledPackages(self, containerID):
79
+        pkgUtils = PackageUtils(self.logName, self.logPath)
80
+        listInstalledRPMs = pkgUtils.findInstalledRPMPackagesInContainer(containerID)
81
+        listInstalledPackages = []
82
+        for installedRPM in listInstalledRPMs:
83
+            packageName = self.findPackageNameFromRPMFile(installedRPM)
84
+            if packageName is not None:
85
+                listInstalledPackages.append(packageName)
86
+        return listInstalledPackages, listInstalledRPMs
87
+
88
+    def buildPackageThreadAPI(self, package, outputMap, threadName,):
89
+        try:
90
+            self.buildPackage(package)
91
+            outputMap[threadName] = True
92
+        except Exception as e:
93
+            self.logger.error(e)
94
+            outputMap[threadName] = False
95
+
96
+    def checkIfPackageIsAlreadyBuilt(self, package):
97
+        basePkg = constants.specData.getSpecName(package)
98
+        listRPMPackages = constants.specData.getRPMPackages(basePkg)
99
+        packageIsAlreadyBuilt = True
100
+        pkgUtils = PackageUtils(self.logName,self.logPath)
101
+        for pkg in listRPMPackages:
102
+            if pkgUtils.findRPMFileForGivenPackage(pkg) is None:
103
+                packageIsAlreadyBuilt = False
104
+                break
105
+        return packageIsAlreadyBuilt
106
+
107
+    def buildPackage(self, package):
108
+        #do not build if RPM is already built
109
+        #test only if the package is in the testForceRPMS with rpmCheck
110
+        #build only if the package is not in the testForceRPMS with rpmCheck
111
+        if self.checkIfPackageIsAlreadyBuilt(package):
112
+            if not constants.rpmCheck:
113
+                self.logger.info("Skipping building the package:"+package)
114
+                return
115
+            elif constants.rpmCheck and package not in constants.testForceRPMS:
116
+                self.logger.info("Skipping testing the package:"+package)
117
+                return
118
+
119
+        #should initialize a logger based on package name
120
+        containerTaskName = "build-" + package
121
+        containerID = None
122
+        isToolChainPackage = False
123
+        if package in constants.listToolChainPackages:
124
+            isToolChainPackage = True
125
+        destLogPath = constants.logPath + "/build-"+package
126
+        try:
127
+            containerID = self.prepareBuildContainer(containerTaskName, package, isToolChainPackage)
128
+            if not os.path.isdir(destLogPath):
129
+                cmdUtils = CommandUtils()
130
+                cmdUtils.runCommandInShell("mkdir -p "+destLogPath)
131
+
132
+            tcUtils = ToolChainUtils(self.logName, self.logPath)
133
+            if package in constants.perPackageToolChain:
134
+                self.logger.debug(constants.perPackageToolChain[package])
135
+                tcUtils.installCustomToolChainRPMSinContainer(containerID, constants.perPackageToolChain[package], package);
136
+
137
+            listInstalledPackages, listInstalledRPMs = self.findInstalledPackages(containerID)
138
+            self.logger.info(listInstalledPackages)
139
+            listDependentPackages = self.findBuildTimeRequiredPackages(package)
140
+            if constants.rpmCheck and package in constants.testForceRPMS:
141
+                listDependentPackages.extend(self.findBuildTimeCheckRequiredPackages(package))
142
+                testPackages=set(constants.listMakeCheckRPMPkgtoInstall)-set(listInstalledPackages)-set([package])
143
+                listDependentPackages.extend(testPackages)
144
+                listDependentPackages=list(set(listDependentPackages))
145
+
146
+            pkgUtils = PackageUtils(self.logName,self.logPath)
147
+            if len(listDependentPackages) != 0:
148
+                self.logger.info("BuildContainer-buildPackage: Installing dependent packages..")
149
+                self.logger.info(listDependentPackages)
150
+                for pkg in listDependentPackages:
151
+                    self.installPackage(pkgUtils, pkg, containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
152
+                # Special case sqlite due to package renamed from sqlite-autoconf to sqlite
153
+                if "sqlite" in listInstalledPackages or "sqlite-devel" in listInstalledPackages or "sqlite-libs" in listInstalledPackages:
154
+                    if "sqlite" not in listInstalledPackages:
155
+                        self.installPackage(pkgUtils, "sqlite", containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
156
+                    if "sqlite-devel" not in listInstalledPackages:
157
+                        self.installPackage(pkgUtils, "sqlite-devel", containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
158
+                    if "sqlite-libs" not in listInstalledPackages:
159
+                        self.installPackage(pkgUtils, "sqlite-libs", containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
160
+                pkgUtils.installRPMSInAOneShotInContainer(containerID, destLogPath)
161
+
162
+            pkgUtils.adjustGCCSpecsInContainer(package, containerID, destLogPath)
163
+
164
+            pkgUtils.buildRPMSForGivenPackageInContainer(
165
+                                               package,
166
+                                               containerID,
167
+                                               self.listBuildOptionPackages,
168
+                                               self.pkgBuildOptionFile,
169
+                                               destLogPath)
170
+            self.logger.info("BuildContainer-buildPackage: Successfully built the package: " + package)
171
+        except Exception as e:
172
+            self.logger.error("Failed while building package:" + package)
173
+            if containerID is not None:
174
+                self.logger.debug("Container " + containerID.short_id + " retained for debugging.")
175
+            logFileName = os.path.join(destLogPath, package + ".log")
176
+            fileLog = os.popen('tail -n 20 ' + logFileName).read()
177
+            self.logger.debug(fileLog)
178
+            raise e
179
+
180
+        # Remove the container
181
+        if containerID is not None:
182
+            containerID.remove(force=True)
183
+
184
+    def findRunTimeRequiredRPMPackages(self, rpmPackage):
185
+        listRequiredPackages = constants.specData.getRequiresForPackage(rpmPackage)
186
+        return listRequiredPackages
187
+
188
+    def findBuildTimeRequiredPackages(self, package):
189
+        listRequiredPackages = constants.specData.getBuildRequiresForPackage(package)
190
+        return listRequiredPackages
191
+
192
+    def findBuildTimeCheckRequiredPackages(self,package):
193
+        listRequiredPackages=constants.specData.getCheckBuildRequiresForPackage(package)
194
+        return listRequiredPackages
195
+
196
+    def installPackage(self, pkgUtils, package, containerID, destLogPath, listInstalledPackages, listInstalledRPMs):
197
+        latestRPM = os.path.basename(pkgUtils.findRPMFileForGivenPackage(package)).replace(".rpm", "")
198
+        if package in listInstalledPackages and latestRPM in listInstalledRPMs:
199
+            return
200
+        self.installDependentRunTimePackages(pkgUtils, package, containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
201
+        noDeps = False
202
+        if self.mapPackageToCycles.has_key(package):
203
+            noDeps = True
204
+        if package in self.listNodepsPackages:
205
+            noDeps = True
206
+        if package in constants.noDepsPackageList:
207
+            noDeps = True
208
+        pkgUtils.prepRPMforInstallInContainer(package, containerID, noDeps, destLogPath)
209
+        listInstalledPackages.append(package)
210
+        listInstalledRPMs.append(latestRPM)
211
+
212
+    def installDependentRunTimePackages(self, pkgUtils, package, containerID, destLogPath, listInstalledPackages, listInstalledRPMs):
213
+        listRunTimeDependentPackages = self.findRunTimeRequiredRPMPackages(package)
214
+        if len(listRunTimeDependentPackages) != 0:
215
+            for pkg in listRunTimeDependentPackages:
216
+                if self.mapPackageToCycles.has_key(pkg) and pkg not in self.listAvailableCyclicPackages:
217
+                    continue
218
+                latestPkgRPM = os.path.basename(pkgUtils.findRPMFileForGivenPackage(pkg)).replace(".rpm", "")
219
+                if pkg in listInstalledPackages and latestPkgRPM in listInstalledRPMs:
220
+                    continue
221
+                self.installPackage(pkgUtils, pkg, containerID, destLogPath, listInstalledPackages, listInstalledRPMs)
0 222
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+# Photon Base Build Container
1
+
2
+FROM scratch
3
+MAINTAINER kulkarniv@vmware.com
4
+
5
+ADD tcroot.tar.gz /
6
+ADD wait.sh /
7
+ADD adjust-gcc-specs.sh /tmp/
8
+
9
+CMD ["/usr/bin/bash", "--login"]
... ...
@@ -3,12 +3,14 @@ import os
3 3
 
4 4
 class Logger(object):
5 5
     @staticmethod
6
-    def getLogger (mymodule, logpath=None):
6
+    def getLogger (mymodule, logpath=None, resetFile=False):
7 7
         logfile=mymodule+".log"
8 8
         if logpath is not None:
9 9
             if not os.path.isdir(logpath):
10 10
                 os.makedirs(logpath)
11 11
             logfile=logpath+"/"+logfile
12
+        if resetFile:
13
+            open(logfile, 'w').close()
12 14
         logger=logging.getLogger(mymodule)
13 15
         if len(logger.handlers) == 0:
14 16
             #creating file handler
... ...
@@ -2,7 +2,10 @@ from PackageBuildDataGenerator import PackageBuildDataGenerator
2 2
 from Logger import Logger
3 3
 import threading
4 4
 from constants import constants
5
+import docker
5 6
 import os
7
+from ChrootUtils import ChrootUtils
8
+from CommandUtils import CommandUtils
6 9
 from PackageUtils import PackageUtils
7 10
 from ToolChainUtils import ToolChainUtils
8 11
 from Scheduler import Scheduler
... ...
@@ -18,6 +21,7 @@ class PackageManager(object):
18 18
         self.logName=logName
19 19
         self.logPath=logPath
20 20
         self.logger=Logger.getLogger(logName,logPath)
21
+        self.dockerClient = docker.from_env(version="auto")
21 22
         self.mapCyclesToPackageList={}
22 23
         self.mapPackageToCycle={}
23 24
         self.sortedPackageList=[]
... ...
@@ -28,6 +32,7 @@ class PackageManager(object):
28 28
         self.listAvailableCyclicPackages=[]
29 29
         self.listBuildOptionPackages=[]
30 30
         self.pkgBuildOptionFile=""
31
+        self.pkgBuildType="chroot"
31 32
 
32 33
     def readPackageBuildData(self, listPackages):
33 34
         try:
... ...
@@ -116,25 +121,37 @@ class PackageManager(object):
116 116
         return True
117 117
 
118 118
     def buildToolChain(self):
119
+        pkgCount = 0
119 120
         try:
120 121
             tUtils=ToolChainUtils()
121
-            tUtils.buildCoreToolChainPackages(self.listBuildOptionPackages, self.pkgBuildOptionFile)
122
+            pkgCount = tUtils.buildCoreToolChainPackages(self.listBuildOptionPackages, self.pkgBuildOptionFile)
122 123
         except Exception as e:
123 124
             self.logger.error("Unable to build tool chain")
124 125
             self.logger.error(e)
125 126
             raise e
127
+        return pkgCount
126 128
 
127 129
     def buildToolChainPackages(self, listBuildOptionPackages, pkgBuildOptionFile, buildThreads):
128
-        self.buildToolChain()
130
+        pkgCount = self.buildToolChain()
131
+        if self.pkgBuildType == "container":
132
+            # Stage 1 build container
133
+            #TODO image name constants.buildContainerImageName
134
+            if pkgCount > 0 or not self.dockerClient.images.list("photon_build_container:latest"):
135
+                self.createBuildContainer()
129 136
         self.buildGivenPackages(constants.listToolChainPackages, buildThreads)
137
+        if self.pkgBuildType == "container":
138
+            # Stage 2 build container
139
+            #TODO: rebuild container only if anything in listToolChainPackages was built
140
+            self.createBuildContainer()
130 141
 
131 142
     def buildTestPackages(self, listBuildOptionPackages, pkgBuildOptionFile, buildThreads):
132 143
         self.buildToolChain()
133 144
         self.buildGivenPackages(constants.listMakeCheckRPMPkgtoInstall, buildThreads)
134 145
 
135
-    def buildPackages(self,listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads):
146
+    def buildPackages(self,listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads, pkgBuildType):
136 147
         self.listBuildOptionPackages = listBuildOptionPackages
137 148
         self.pkgBuildOptionFile = pkgBuildOptionFile
149
+        self.pkgBuildType = pkgBuildType
138 150
         if constants.rpmCheck:
139 151
             constants.rpmCheck=False
140 152
             self.buildToolChainPackages(listBuildOptionPackages, pkgBuildOptionFile, buildThreads)
... ...
@@ -153,6 +170,7 @@ class PackageManager(object):
153 153
         ThreadPool.pkgBuildOptionFile=self.pkgBuildOptionFile
154 154
         ThreadPool.logger=self.logger
155 155
         ThreadPool.statusEvent=statusEvent
156
+        ThreadPool.pkgBuildType=self.pkgBuildType
156 157
 
157 158
     def initializeScheduler(self,statusEvent):
158 159
         Scheduler.setLog(self.logName, self.logPath)
... ...
@@ -210,3 +228,50 @@ class PackageManager(object):
210 210
 
211 211
         self.logger.info("Terminated")
212 212
 
213
+    def createBuildContainer(self):
214
+        self.logger.info("Generating photon build container..")
215
+        try:
216
+            #TODO image name constants.buildContainerImageName
217
+            self.dockerClient.images.remove("photon_build_container:latest", force=True)
218
+        except Exception as e:
219
+            #TODO - better handling
220
+            self.logger.debug("Photon build container image not found.")
221
+
222
+        # Create toolchain chroot and install toolchain RPMs
223
+        chrootID=None
224
+        try:
225
+            #TODO: constants.tcrootname
226
+            chrUtils = ChrootUtils("toolchain-chroot", self.logPath)
227
+            returnVal, chrootID = chrUtils.createChroot("toolchain-chroot")
228
+            self.logger.debug("Created tool-chain chroot: " + chrootID)
229
+            if not returnVal:
230
+                raise Exception("Unable to prepare tool-chain chroot")
231
+            tcUtils = ToolChainUtils("toolchain-chroot", self.logPath)
232
+            tcUtils.installToolChainRPMS(chrootID, "dummy")
233
+        except Exception as e:
234
+            if chrootID is not None:
235
+                self.logger.debug("Deleting chroot: " + chrootID)
236
+                chrUtils.destroyChroot(chrootID)
237
+            raise e
238
+        self.logger.info("VDBG-PU-createBuildContainer: chrootID: " + chrootID)
239
+
240
+        # Create photon build container using toolchain chroot
241
+        #TODO: Coalesce logging
242
+        cmdUtils = CommandUtils()
243
+        cmd = "./umount-build-root.sh " + chrootID
244
+        cmdUtils.runCommandInShell(cmd, self.logPath + "/toolchain-chroot1.log")
245
+        cmd = "cd " + chrootID + " && tar -czvf ../tcroot.tar.gz ."
246
+        cmdUtils.runCommandInShell(cmd, self.logPath + "/toolchain-chroot2.log")
247
+        cmd = "mv " + chrootID + "/../tcroot.tar.gz ."
248
+        cmdUtils.runCommandInShell(cmd, self.logPath + "/toolchain-chroot3.log")
249
+        #TODO: Container name, docker file name from constants.
250
+        self.dockerClient.images.build(tag="photon_build_container:latest",
251
+                                       path=".",
252
+                                       rm=True,
253
+                                       dockerfile="Dockerfile.photon_build_container")
254
+
255
+        # Cleanup
256
+        cmd = "rm -f ./tcroot.tar.gz"
257
+        cmdUtils.runCommandInShell(cmd, self.logPath + "/toolchain-chroot4.log")
258
+        chrUtils.destroyChroot(chrootID)
259
+        self.logger.info("Photon build container successfully created.")
... ...
@@ -28,14 +28,16 @@ class PackageUtils(object):
28 28
         self.rpmbuildBuildallOption = "-ba --clean"
29 29
         self.rpmbuildNocheckOption = "--nocheck"
30 30
         self.rpmbuildCheckOption ="-bi --clean"
31
-        self.rpmbuildDistOption = '--define \\\"dist %s\\\"' % constants.dist
32 31
         self.queryRpmPackageOptions = "-qa"
33 32
         self.forceRpmPackageOptions = "--force"
33
+        self.replaceRpmPackageOptions = "--replacepkgs"
34 34
         self.adjustGCCSpecScript="adjust-gcc-specs.sh"
35 35
         self.rpmFilesToInstallInAOneShot=""
36 36
         self.packagesToInstallInAOneShot=""
37 37
         self.noDepsRPMFilesToInstallInAOneShot=""
38 38
         self.noDepsPackagesToInstallInAOneShot=""
39
+        self.rpmFilesToReInstallInAOneShot=""
40
+        self.noDepsRPMFilesToReInstallInAOneShot=""
39 41
 
40 42
     def getRPMArch(self,rpmName):
41 43
         arch=""
... ...
@@ -105,32 +107,35 @@ class PackageUtils(object):
105 105
                 self.logger.error("Unable to install rpms")
106 106
                 raise Exception("RPM installation failed")
107 107
 
108
-
109
-    def copySourcesTobuildroot(self,listSourceFiles,package,destDir):
108
+    def verifyShaAndGetSourcePath(self, source, package):
110 109
         cmdUtils = CommandUtils()
111
-        for source in listSourceFiles:
112
-            # Fetch/verify sources if sha1 not None.
113
-            sha1 = constants.specData.getSHA1(package, source)
114
-            if sha1 is not None:
115
-                PullSources.get(source, sha1, constants.sourcePath, constants.pullsourcesConfig, self.logger)
116
-
117
-            sourcePath = cmdUtils.findFile(source,constants.sourcePath)
110
+        # Fetch/verify sources if sha1 not None.
111
+        sha1 = constants.specData.getSHA1(package, source)
112
+        if sha1 is not None:
113
+            PullSources.get(source, sha1, constants.sourcePath, constants.pullsourcesConfig, self.logger)
114
+
115
+        sourcePath = cmdUtils.findFile(source,constants.sourcePath)
116
+        if sourcePath is None or len(sourcePath) == 0:
117
+            sourcePath = cmdUtils.findFile(source,constants.specPath)
118 118
             if sourcePath is None or len(sourcePath) == 0:
119
-                sourcePath = cmdUtils.findFile(source,constants.specPath)
120
-                if sourcePath is None or len(sourcePath) == 0:
121
-                    if sha1 is None:
122
-                        self.logger.error("No sha1 found or missing source for "+source)
123
-                        raise Exception("No sha1 found or missing source for "+source)
124
-                    else:
125
-                        self.logger.error("Missing source: "+source+". Cannot find sources for package: "+package)
126
-                        raise Exception("Missing source")
127
-            else:
128 119
                 if sha1 is None:
129
-                    self.logger.error("No sha1 found for "+source)
130
-                    raise Exception("No sha1 found")
131
-            if len(sourcePath) > 1:
132
-                self.logger.error("Multiple sources found for source:"+source+"\n"+ ",".join(sourcePath) +"\nUnable to determine one.")
133
-                raise Exception("Multiple sources found")
120
+                    self.logger.error("No sha1 found or missing source for "+source)
121
+                    raise Exception("No sha1 found or missing source for "+source)
122
+                else:
123
+                    self.logger.error("Missing source: "+source+". Cannot find sources for package: "+package)
124
+                    raise Exception("Missing source")
125
+        else:
126
+            if sha1 is None:
127
+                self.logger.error("No sha1 found for "+source)
128
+                raise Exception("No sha1 found")
129
+        if len(sourcePath) > 1:
130
+            self.logger.error("Multiple sources found for source:"+source+"\n"+ ",".join(sourcePath) +"\nUnable to determine one.")
131
+            raise Exception("Multiple sources found")
132
+        return sourcePath
133
+
134
+    def copySourcesTobuildroot(self,listSourceFiles,package,destDir):
135
+        for source in listSourceFiles:
136
+            sourcePath = self.verifyShaAndGetSourcePath(source, package)
134 137
             self.logger.info("Copying... Source path :" + source + " Source filename: " + sourcePath[0])
135 138
             shutil.copy2(sourcePath[0], destDir)
136 139
 
... ...
@@ -145,6 +150,24 @@ class PackageUtils(object):
145 145
                 else:
146 146
                     shutil.copytree(source, destDir)
147 147
 
148
+    def getAdditionalBuildFiles(self, package, pkgBuildOptionFile):
149
+        listAdditionalFiles = []
150
+        macros = []
151
+        jsonData = open(pkgBuildOptionFile)
152
+        pkg_build_option_json = json.load(jsonData, object_pairs_hook=collections.OrderedDict)
153
+        jsonData.close()
154
+        pkgs_sorted = pkg_build_option_json.items()
155
+        for pkg in pkgs_sorted:
156
+            p = str(pkg[0].encode('utf-8'))
157
+            if p == package:
158
+                filelist = pkg[1]["files"]
159
+                for f in filelist:
160
+                    listAdditionalFiles.append(f)
161
+                macrolist = pkg[1]["macros"]
162
+                for macro in macrolist:
163
+                    macros.append(str(macro.encode('utf-8')))
164
+        return listAdditionalFiles, macros
165
+
148 166
     def buildRPMSForGivenPackage(self,package,chrootID,listBuildOptionPackages,pkgBuildOptionFile,destLogPath=None):
149 167
         self.logger.info("Building rpm's for package:"+package)
150 168
 
... ...
@@ -164,23 +187,9 @@ class PackageUtils(object):
164 164
         self.copySourcesTobuildroot(listSourcesFiles,package,chrootSourcePath)
165 165
         self.copySourcesTobuildroot(listPatchFiles,package,chrootSourcePath)
166 166
 
167
-        listAdditionalFiles = []
168 167
         macros = []
169 168
         if package in listBuildOptionPackages:
170
-            jsonData = open(pkgBuildOptionFile)
171
-            pkg_build_option_json = json.load(jsonData, object_pairs_hook=collections.OrderedDict)
172
-            jsonData.close()
173
-            pkgs_sorted = pkg_build_option_json.items()
174
-            for pkg in pkgs_sorted:
175
-                p = str(pkg[0].encode('utf-8'))
176
-                if p == package:
177
-                    filelist = pkg[1]["files"]
178
-                    for f in filelist:
179
-                        listAdditionalFiles.append(f)
180
-                    macrolist = pkg[1]["macros"]
181
-                    for macro in macrolist:
182
-                        macros.append(str(macro.encode('utf-8')))
183
-
169
+            listAdditionalFiles, macros = self.getAdditionalBuildFiles(package, pkgBuildOptionFile)
184 170
             self.copyAdditionalBuildFiles(listAdditionalFiles,chrootID)
185 171
 
186 172
         #Adding rpm macros
... ...
@@ -216,7 +225,8 @@ class PackageUtils(object):
216 216
 
217 217
     def buildRPM(self,specFile,logFile,chrootCmd,package,macros):
218 218
 
219
-        rpmBuildcmd=self.rpmbuildBinary+" "+self.rpmbuildBuildallOption+" "+self.rpmbuildDistOption
219
+        rpmbuildDistOption = '--define \\\"dist %s\\\"' % constants.dist
220
+        rpmBuildcmd=self.rpmbuildBinary+" "+self.rpmbuildBuildallOption+" "+rpmbuildDistOption
220 221
 
221 222
         if constants.rpmCheck and package in constants.testForceRPMS:
222 223
             self.logger.info("#"*(68+2*len(package)))
... ...
@@ -347,3 +357,297 @@ class PackageUtils(object):
347 347
 
348 348
         self.logger.error("Failed while adjusting gcc specs")
349 349
         raise Exception("Failed while adjusting gcc specs")
350
+
351
+    def copySourcesToContainer(self, listSourceFiles, package, containerID, destDir):
352
+        cmdUtils = CommandUtils()
353
+        for source in listSourceFiles:
354
+            sourcePath = self.verifyShaAndGetSourcePath(source, package)
355
+            self.logger.info("Copying source file: " + sourcePath[0])
356
+            copyCmd = "docker cp " + sourcePath[0] + " " + containerID.short_id + ":" + destDir
357
+            cmdUtils.runCommandInShell(copyCmd)
358
+
359
+    def copyAdditionalBuildFilesToContainer(self, listAdditionalFiles, containerID):
360
+        cmdUtils = CommandUtils()
361
+        #self.logger.debug("VDBG-PU-copyAdditionalBuildFilesToContainer id: " +containerID.short_id)
362
+        #self.logger.debug(listAdditionalFiles)
363
+        for additionalFile in listAdditionalFiles:
364
+            source = additionalFile["src"].encode('utf-8')
365
+            destDir = additionalFile["dst"].encode('utf-8')
366
+            destPath = containerID.short_id + ":" + destDir
367
+            #TODO: exit status of exec_run
368
+            containerID.exec_run("mkdir -p " + destDir)
369
+            if os.path.exists(source):
370
+                copyCmd = "docker cp " + source
371
+                if os.path.isfile(source):
372
+                    self.logger.info("Copying addl source file: " + source)
373
+                    copyCmd += " " + destPath
374
+                else:
375
+                    self.logger.info("Copying addl source file tree: " + source)
376
+                    copyCmd +=  "/. " + destPath
377
+                #TODO: cmd error code
378
+                cmdUtils.runCommandInShell(copyCmd)
379
+
380
+    def getRPMPathInContainer(self, rpmFile, containerID):
381
+        rpmName = os.path.basename(rpmFile)
382
+        #TODO: Container path from constants
383
+        if "PUBLISHRPMS" in rpmFile:
384
+            rpmPath = "/publishrpms/"
385
+        elif "PUBLISHXRPMS" in rpmFile:
386
+            rpmPath = "/publishxrpms/"
387
+        else:
388
+            rpmPath = constants.topDirPath + "/RPMS/"
389
+        if "noarch" in rpmFile:
390
+            rpmPath += "noarch/"
391
+        else:
392
+            rpmPath += "x86_64/"
393
+        rpmPath += rpmName
394
+        return rpmPath
395
+
396
+    def prepRPMforInstallInContainer(self, package, containerID, noDeps=False, destLogPath=None):
397
+        rpmfile = self.findRPMFileForGivenPackage(package)
398
+        if rpmfile is None:
399
+            self.logger.error("No rpm file found for package: " + package)
400
+            raise Exception("Missing rpm file")
401
+
402
+        rpmDestFile = self.getRPMPathInContainer(rpmfile, containerID)
403
+        if noDeps:
404
+            self.noDepsRPMFilesToInstallInAOneShot += " " + rpmDestFile
405
+            self.noDepsPackagesToInstallInAOneShot += " " + package
406
+            if package in constants.listReInstallPackages:
407
+                self.noDepsRPMFilesToReInstallInAOneShot += " " + rpmDestFile
408
+        else:
409
+            self.rpmFilesToInstallInAOneShot += " " + rpmDestFile
410
+            self.packagesToInstallInAOneShot += " " + package
411
+            if package in constants.listReInstallPackages:
412
+                self.rmpFilesToReInstallInAOneShot += " " + rpmDestFile
413
+
414
+    def installRPMSInAOneShotInContainer(self, containerID, destLogPath):
415
+        rpmInstallcmd = self.rpmBinary + " " + self.installRPMPackageOptions + " " + self.forceRpmPackageOptions
416
+
417
+        if self.noDepsRPMFilesToInstallInAOneShot != "":
418
+            self.logger.info("PackageUtils-installRPMSInAOneShotInContainer: Installing nodeps rpms: " + \
419
+                             self.noDepsPackagesToInstallInAOneShot)
420
+            logFile = destLogPath + "/install_rpms_nodeps.log"
421
+            cmd = rpmInstallcmd + " " + self.nodepsRPMPackageOptions + " " + self.noDepsRPMFilesToInstallInAOneShot
422
+            cmd = "/bin/bash -l -c '" + cmd + "'"
423
+            #self.logger.debug("VDBG-PU-installRPMSInAOneShotInContainer: Install nodeps cmd: " + cmd)
424
+            #TODO: Error code from exec_run
425
+            installLog = containerID.exec_run(cmd)
426
+            if not installLog:
427
+                self.logger.error("Unable to install nodeps rpms")
428
+                raise Exception("nodeps RPM installation failed")
429
+            logfile = open(logFile, 'w')
430
+            logfile.write(installLog)
431
+            logfile.close()
432
+
433
+            if self.noDepsRPMFilesToReInstallInAOneShot != "":
434
+                cmd = rpmInstallcmd + " " + self.nodepsRPMPackageOptions + " " + self.forceRpmPackageOptions + " " + self.noDepsRPMFilesToReInstallInAOneShot
435
+                cmd = "/bin/bash -l -c '" + cmd + "'"
436
+                #self.logger.debug("VDBG-PU-installRPMSInAOneShotInContainer: ReInstall nodeps cmd: " + cmd)
437
+                #TODO: Error code from exec_run
438
+                installLog = containerID.exec_run(cmd)
439
+                if not installLog:
440
+                    self.logger.error("Unable to re-install nodeps rpms")
441
+                    raise Exception("nodeps RPM re-installation failed")
442
+                logfile = open(logFile, 'a')
443
+                logfile.write(installLog)
444
+                logfile.close()
445
+
446
+        if self.rpmFilesToInstallInAOneShot != "":
447
+            self.logger.info("PackageUtils-installRPMSInAOneShotInContainer: Installing rpms: " + \
448
+                             self.packagesToInstallInAOneShot)
449
+            logFile = destLogPath + "/install_rpms.log"
450
+            cmd = rpmInstallcmd + " " + self.rpmFilesToInstallInAOneShot
451
+            cmd = "/bin/bash -l -c '" + cmd + "'"
452
+            #self.logger.debug("VDBG-PU-installRPMSInAOneShotInContainer: Install cmd: " + cmd)
453
+            #TODO: Error code from exec_run
454
+            installLog = containerID.exec_run(cmd)
455
+            if not installLog:
456
+                self.logger.error("Unable to install rpms")
457
+                raise Exception("RPM installation failed")
458
+            logfile = open(logFile, 'w')
459
+            logfile.write(installLog)
460
+            logfile.close()
461
+
462
+            if self.rpmFilesToReInstallInAOneShot != "":
463
+                cmd = rpmInstallcmd + " " + self.forceRpmPackageOptions + " " + self.rpmFilesToReInstallInAOneShot
464
+                cmd = "/bin/bash -l -c '" + cmd + "'"
465
+                #self.logger.debug("VDBG-PU-installRPMSInAOneShotInContainer: ReInstall cmd: " + cmd)
466
+                #TODO: Error code from exec_run
467
+                installLog = containerID.exec_run(cmd)
468
+                if not installLog:
469
+                    self.logger.error("Unable to re-install rpms")
470
+                    raise Exception("RPM re-installation failed")
471
+                logfile = open(logFile, 'a')
472
+                logfile.write(installLog)
473
+                logfile.close()
474
+
475
+    def findInstalledRPMPackagesInContainer(self, containerID):
476
+        cmd = self.rpmBinary + " " + self.queryRpmPackageOptions
477
+        cmd = "/bin/bash -l -c '" + cmd + "'"
478
+        #TODO: Error code from exec_run
479
+        result = containerID.exec_run(cmd)
480
+        if result is not None:
481
+            return result.split()
482
+        return result
483
+
484
+    def adjustGCCSpecsInContainer(self, package, containerID, logPath):
485
+        opt = " " + constants.specData.getSecurityHardeningOption(package)
486
+        adjustCmd = "/tmp/" + self.adjustGCCSpecScript + opt
487
+        adjustCmd = "/bin/bash -l -c '" + adjustCmd + "'"
488
+        logFile = logPath + "/adjustGCCSpecScript.log"
489
+
490
+        #TODO: Error code from exec_run
491
+        scriptLog = containerID.exec_run(adjustCmd)
492
+        if scriptLog:
493
+            logfile = open(logFile, 'w')
494
+            logfile.write(scriptLog)
495
+            logfile.close()
496
+            return
497
+
498
+        self.logger.debug(containerID.exec_run("ls -la /tmp/" + self.adjustGCCSpecScript))
499
+        self.logger.debug(containerID.exec_run("lsof /tmp/" + self.adjustGCCSpecScript))
500
+        self.logger.debug(containerID.exec_run("ps ax"))
501
+        self.logger.error("Failed while adjusting gcc specs")
502
+        raise Exception("Failed while adjusting gcc specs")
503
+
504
+    def buildRPMSForGivenPackageInContainer(self, package, containerID, listBuildOptionPackages,
505
+                                            pkgBuildOptionFile, destLogPath=None):
506
+        self.logger.info("Building rpm's for package " + package + " in container " + containerID.short_id)
507
+
508
+        listSourcesFiles = constants.specData.getSources(package)
509
+        listPatchFiles = constants.specData.getPatches(package)
510
+        specFile = constants.specData.getSpecFile(package)
511
+        specName = constants.specData.getSpecName(package) + ".spec"
512
+        sourcePath = constants.topDirPath + "/SOURCES/"
513
+        specPath = constants.topDirPath + "/SPECS/"
514
+        rpmLogFile = constants.topDirPath + "/LOGS/" + package + ".log"
515
+        destLogFile = destLogPath + "/" + package + ".log"
516
+        cmdUtils = CommandUtils()
517
+
518
+        #TODO: mount it in, don't copy
519
+        cpSpecCmd = "docker cp " + specFile + " " + containerID.short_id \
520
+                        + ":" + specPath + specName
521
+        returnVal = cmdUtils.runCommandInShell(cpSpecCmd)
522
+        if not returnVal:
523
+            self.logger.error("Error copying source SPEC file to container")
524
+            raise Exception("Failed copying source SPEC to container")
525
+
526
+# FIXME: some sources are located in SPECS/.. how to mount?
527
+#        if os.geteuid()==0:
528
+        #TODO: mount it in, don't copy
529
+        macros = []
530
+        self.copySourcesToContainer(listSourcesFiles, package, containerID, sourcePath)
531
+        #TODO: mount it in, don't copy
532
+        self.copySourcesToContainer(listPatchFiles, package, containerID, sourcePath)
533
+        if package in listBuildOptionPackages:
534
+            listAdditionalFiles, macros = self.getAdditionalBuildFiles(package, pkgBuildOptionFile)
535
+            self.copyAdditionalBuildFilesToContainer(listAdditionalFiles, containerID)
536
+
537
+        # Add rpm macros
538
+        listRPMMacros = constants.specData.getRPMMacros()
539
+        for macroName in listRPMMacros.keys():
540
+            macros.append(macroName + " " + listRPMMacros[macroName])
541
+
542
+        # Build RPMs
543
+        listRPMFiles=[]
544
+        listSRPMFiles=[]
545
+        try:
546
+            listRPMFiles, listSRPMFiles = self.buildRPMinContainer(
547
+                                                    specPath + specName,
548
+                                                    rpmLogFile,
549
+                                                    destLogFile,
550
+                                                    containerID,
551
+                                                    package,
552
+                                                    macros)
553
+        except Exception as e:
554
+            self.logger.error("Failed while building rpm: " + package)
555
+            raise e
556
+        self.logger.info("RPM build is successful")
557
+
558
+        # Verify RPM and SRPM files exist as success criteria
559
+        for rpmFile in listRPMFiles:
560
+            rpmName = os.path.basename(rpmFile)
561
+            rpmDestDir = self.getRPMDestDir(rpmName, constants.rpmPath)
562
+            rpmDestFile = rpmDestDir + "/" + rpmName
563
+            if not os.path.isfile(rpmDestFile):
564
+                self.logger.error("Could not find RPM file: " + rpmDestFile)
565
+                raise Exception("Built RPM file not found.")
566
+
567
+        for srpmFile in listSRPMFiles:
568
+            srpmName = os.path.basename(srpmFile)
569
+            srpmDestDir = self.getRPMDestDir(os.path.basename(srpmFile), constants.sourceRpmPath)
570
+            srpmDestFile = srpmDestDir + "/" + srpmName
571
+            if not os.path.isfile(srpmDestFile):
572
+                self.logger.error("Could not find RPM file: " + srpmDestFile)
573
+                raise Exception("Built SRPM file not found.")
574
+
575
+    def buildRPMinContainer(self, specFile, rpmLogFile, destLogFile, containerID, package, macros):
576
+
577
+        rpmbuildDistOption = '--define \"dist %s\"' % constants.dist
578
+        rpmBuildCmd = self.rpmbuildBinary + " " + self.rpmbuildBuildallOption \
579
+                          + " " + rpmbuildDistOption
580
+
581
+        if constants.rpmCheck and package in constants.testForceRPMS:
582
+            self.logger.info("#"*(68+2*len(package)))
583
+            if not constants.specData.isCheckAvailable(package):
584
+                self.logger.info("####### "+package+" MakeCheck is not available. Skipping MakeCheck TEST for "+package+ " #######")
585
+                rpmBuildCmd=self.rpmbuildBinary+" --clean"
586
+            else:
587
+                self.logger.info("####### "+package+" MakeCheck is available. Running MakeCheck TEST for "+package+ " #######")
588
+                rpmBuildCmd=self.rpmbuildBinary+" "+self.rpmbuildCheckOption
589
+            self.logger.info("#"*(68+2*len(package)))
590
+        else:
591
+           rpmBuildCmd+=" "+self.rpmbuildNocheckOption
592
+
593
+        for macro in macros:
594
+            rpmBuildCmd += ' --define \"%s\"' % macro
595
+        rpmBuildCmd += " " + specFile
596
+        rpmBuildCmd = "/bin/bash -l -c '" + rpmBuildCmd + " > " + rpmLogFile + " 2>&1'"
597
+        rpmBuildCmd = "docker exec " + str(containerID.short_id) + " " + rpmBuildCmd
598
+
599
+        cmdUtils = CommandUtils()
600
+        self.logger.info("Building rpm for package: " + package)
601
+        #TODO: Show running log of rpmbuildcmd
602
+        #TODO: Get exit status of rpmBuildCmd
603
+        #containerID.exec_run(rpmBuildCmd)
604
+        returnVal = cmdUtils.runCommandInShell(rpmBuildCmd)
605
+
606
+        if not os.path.isfile(destLogFile):
607
+            self.logger.error("RPM build not file not found. Building rpm failed for: " + specFile)
608
+            raise Exception("RPM Build failed")
609
+
610
+        if constants.rpmCheck and package in constants.testForceRPMS:
611
+            if not constants.specData.isCheckAvailable(package):
612
+                constants.testLogger.info(package+" : N/A")
613
+            elif returnVal:
614
+                constants.testLogger.info(package+" : PASS")
615
+            else:
616
+                constants.testLogger.error(package+" : FAIL" )
617
+
618
+        if constants.rpmCheck:
619
+            if not returnVal and constants.rpmCheckStopOnError:
620
+                self.logger.error("Checking rpm is failed "+specFile)
621
+                raise Exception("RPM check failed")
622
+        else:
623
+            if not returnVal:
624
+                self.logger.error("Building rpm is failed "+specFile)
625
+                raise Exception("RPM build failed")
626
+
627
+        #Extracting rpms created from log file
628
+        listRPMFiles=[]
629
+        listSRPMFiles=[]
630
+        logfile = open(destLogFile, 'r')
631
+        rpmBuildLogLines = logfile.readlines()
632
+        logfile.close()
633
+        for i in range(0, len(rpmBuildLogLines)):
634
+            if re.search("^Wrote:", rpmBuildLogLines[i]):
635
+                listcontents = rpmBuildLogLines[i].split()
636
+                if (len(listcontents) == 2) and listcontents[1].strip()[-4:] == ".rpm" and listcontents[1].find("/RPMS/") != -1:
637
+                    listRPMFiles.append(listcontents[1])
638
+                if (len(listcontents) == 2) and listcontents[1].strip()[-8:] == ".src.rpm" and listcontents[1].find("/SRPMS/") != -1:
639
+                    listSRPMFiles.append(listcontents[1])
640
+        #if not listRPMFiles:
641
+        #    self.logger.error("Building rpm failed for " + specFile)
642
+        #    raise Exception("RPM Build failed")
643
+        return listRPMFiles, listSRPMFiles
... ...
@@ -9,6 +9,7 @@ class ThreadPool(object):
9 9
     listAvailableCyclicPackages=[]
10 10
     listBuildOptionPackages=[]
11 11
     pkgBuildOptionFile=""
12
+    pkgBuildType="chroot"
12 13
     logger=None
13 14
     statusEvent=None
14 15
     
... ...
@@ -36,7 +37,8 @@ class ThreadPool(object):
36 36
                 ThreadPool.listAvailableCyclicPackages,
37 37
                 ThreadPool.logger,
38 38
                 ThreadPool.listBuildOptionPackages,
39
-                ThreadPool.pkgBuildOptionFile)
39
+                ThreadPool.pkgBuildOptionFile,
40
+                ThreadPool.pkgBuildType)
40 41
         ThreadPool.mapWorkerThreads[workerThreadName]=workerThread
41 42
    
42 43
     @staticmethod
... ...
@@ -76,6 +76,7 @@ class ToolChainUtils(object):
76 76
     def buildCoreToolChainPackages(self, listBuildOptionPackages, pkgBuildOptionFile):
77 77
         self.logger.info("Building core tool chain packages.....")
78 78
         chrootID=None
79
+        pkgCount = 0
79 80
         try:
80 81
             pkgUtils=PackageUtils(self.logName,self.logPath)
81 82
             for package in constants.listCoreToolChainPackages:
... ...
@@ -95,6 +96,7 @@ class ToolChainUtils(object):
95 95
                 self.installToolChainRPMS(chrootID, package)
96 96
                 pkgUtils.adjustGCCSpecs(package, chrootID, destLogPath)
97 97
                 pkgUtils.buildRPMSForGivenPackage(package, chrootID, listBuildOptionPackages, pkgBuildOptionFile, destLogPath)
98
+                pkgCount += 1
98 99
                 chrUtils.destroyChroot(chrootID)
99 100
                 chrootID=None
100 101
             self.logger.info("Successfully built toolchain")
... ...
@@ -105,7 +107,8 @@ class ToolChainUtils(object):
105 105
             # print stacktrace
106 106
             traceback.print_exc()
107 107
             raise e
108
-
108
+        return pkgCount
109
+                
109 110
     def installToolChainRPMS(self,chrootID, packageName):
110 111
         cmdUtils = CommandUtils()
111 112
         self.prepareBuildRoot(chrootID)
... ...
@@ -175,3 +178,74 @@ class ToolChainUtils(object):
175 175
             self.logger.error("Installing tool chain  failed")
176 176
             raise Exception("RPM installation failed")
177 177
         self.logger.info("Successfully installed all Tool Chain X RPMS")
178
+
179
+    def installToolChainRPMSinContainer(self, containerID):
180
+        self.logger.info("Installing tool-chain RPMS in container: " + containerID.short_id)
181
+        rpmFiles = ""
182
+        packages = ""
183
+        pkgUtils = PackageUtils(self.logName, self.logPath)
184
+        for package in constants.listToolChainRPMPkgsToInstall:
185
+            rpmFile = pkgUtils.findRPMFileForGivenPackage(package)
186
+            if rpmFile is None:
187
+                # sqlite-autoconf package was renamed, but it still published as sqlite-autoconf
188
+                if package == "sqlite":
189
+                    package = "sqlite-autoconf"
190
+                rpmFile = self.findRPMFileInGivenLocation(package, constants.prevPublishRPMRepo)
191
+                if rpmFile is None:
192
+                    if package in constants.listOfRPMsProvidedAfterBuild:
193
+                        self.logger.info("No old version of " + package + " exists, skip until the new version is built")
194
+                        continue
195
+                    self.logger.error("Unable to find rpm " + package + " in current and previous versions")
196
+                    raise Exception("Input Error")
197
+            if rpmFile.find("stage/PUBLISHRPMS"):
198
+                rpmFile = rpmFile.replace(constants.prevPublishRPMRepo, "/publishrpms")
199
+            if rpmFile.find("stage/PUBLISHXRPMS"):
200
+                rpmFile = rpmFile.replace(constants.prevPublishXRPMRepo, "/publishxrpms")
201
+            if rpmFile.find("stage/RPMS"):
202
+                rpmFile = rpmFile.replace(constants.rpmPath, constants.topDirPath + "/RPMS")
203
+            rpmFiles += " " + rpmFile
204
+            packages += " " + package
205
+
206
+        self.logger.debug("Installing tool-chain rpms: " + packages)
207
+
208
+        cmd = "/usr/bin/bash -l -c '/usr/bin/rpm -Uvh --force --nodeps " + rpmFiles + "'"
209
+        self.logger.info("VDBG-TCU-installToolChainRPMSinContainer: Installing rpms cmd: " + cmd)
210
+        tcInstallLog = containerID.exec_run(cmd)
211
+        # TODO: Find a way to collect exit status of the command that was run.
212
+        if not tcInstallLog:
213
+            self.logger.error("Installing tool chain in container failed")
214
+            raise Exception("RPM installation in container failed")
215
+        self.logger.info(tcInstallLog)
216
+        self.logger.info("Successfully installed default tool-chain RPMS in container: " + containerID.short_id)
217
+
218
+    def installCustomToolChainRPMSinContainer(self, containerID, listOfToolChainPkgs, packageName):
219
+        self.logger.info("Installing package specific tool chain RPMs for " + packageName)
220
+        rpmFiles = ""
221
+        packages = ""
222
+        for package in listOfToolChainPkgs:
223
+            if "openjre8" in packageName or "openjdk8" in packageName:
224
+                rpmFile=self.findRPMFileInGivenLocation(package, constants.prevPublishXRPMRepo)
225
+            else:
226
+                rpmFile=self.findRPMFileInGivenLocation(package, constants.prevPublishRPMRepo)
227
+            if rpmFile is None:
228
+                self.logger.error("Unable to find rpm " + package + " in current and previous versions")
229
+                raise Exception("Input Error")
230
+            if rpmFile.find("stage/PUBLISHRPMS"):
231
+                rpmFile = rpmFile.replace(constants.prevPublishRPMRepo, "/publishrpms")
232
+            if rpmFile.find("stage/PUBLISHXRPMS"):
233
+                rpmFile = rpmFile.replace(constants.prevPublishXRPMRepo, "/publishxrpms")
234
+            if rpmFile.find("stage/RPMS"):
235
+                rpmFile = rpmFile.replace(constants.rpmPath, constants.topDirPath + "/RPMS")
236
+            rpmFiles += " " + rpmFile
237
+            packages += " " + package
238
+
239
+        self.logger.debug("Installing rpms: " + packages)
240
+        cmd = "rpm -Uvh --nodeps --force " + rpmFiles
241
+        self.logger.debug("VDBG-TCU-installCustomToolChainRPMSinContainer: Installing rpms cmd: " + cmd)
242
+        tcInstallLog = containerID.exec_run(cmd)
243
+        # TODO: Find a way to collect exit status of the command that was run.
244
+        if not tcInstallLog:
245
+            self.logger.error("Installing tool chain in container failed")
246
+            raise Exception("RPM installation in container failed")
247
+        self.logger.info(tcInstallLog)
248
+        self.logger.info("Successfully installed all tool-chain XRPMS in container: " + containerID.short_id)
... ...
@@ -1,11 +1,12 @@
1
+from BuildContainer import BuildContainer
1 2
 from PackageBuilder import PackageBuilder
2 3
 import threading
3 4
 import Scheduler
4 5
 import ThreadPool
5
- 
6
+
6 7
 class WorkerThread(threading.Thread):
7
-    
8
-    def __init__(self,event,name,mapPackageToCycle,listAvailableCyclicPackages,logger,listBuildOptionPackages,pkgBuildOptionFile):
8
+
9
+    def __init__(self,event,name,mapPackageToCycle,listAvailableCyclicPackages,logger,listBuildOptionPackages,pkgBuildOptionFile,pkgBuildType):
9 10
         threading.Thread.__init__(self)
10 11
         self.statusEvent=event
11 12
         self.name=name
... ...
@@ -14,7 +15,8 @@ class WorkerThread(threading.Thread):
14 14
         self.logger=logger
15 15
         self.listBuildOptionPackages=listBuildOptionPackages
16 16
         self.pkgBuildOptionFile=pkgBuildOptionFile
17
-        
17
+        self.pkgBuildType=pkgBuildType
18
+
18 19
     def run(self):
19 20
         buildThreadFailed=False
20 21
         ThreadPool.ThreadPool.makeWorkerThreadActive(self.name)
... ...
@@ -25,7 +27,10 @@ class WorkerThread(threading.Thread):
25 25
             if pkg is None:
26 26
                 break
27 27
             self.logger.info("Thread "+self.name+" is building package:"+ pkg)
28
-            pkgBuilder = PackageBuilder(self.mapPackageToCycle,self.listAvailableCyclicPackages,self.listBuildOptionPackages,self.pkgBuildOptionFile,"build-"+pkg)
28
+            if self.pkgBuildType == "chroot":
29
+                pkgBuilder = PackageBuilder(self.mapPackageToCycle,self.listAvailableCyclicPackages,self.listBuildOptionPackages,self.pkgBuildOptionFile,"build-"+pkg)
30
+            elif self.pkgBuildType == "container":
31
+                pkgBuilder = BuildContainer(self.mapPackageToCycle,self.listAvailableCyclicPackages,self.listBuildOptionPackages,self.pkgBuildOptionFile,"build-"+pkg)
29 32
             t = threading.Thread(target=pkgBuilder.buildPackageThreadAPI,args=(pkg,outputMap,pkg))
30 33
             t.start()
31 34
             t.join()
... ...
@@ -36,9 +41,9 @@ class WorkerThread(threading.Thread):
36 36
                 break
37 37
             self.logger.info("Thread "+self.name+" finished building package:" + pkg)
38 38
             Scheduler.Scheduler.notifyPackageBuildCompleted(pkg)
39
-        
39
+
40 40
         if buildThreadFailed:
41 41
             self.statusEvent.set()
42
-        
42
+
43 43
         ThreadPool.ThreadPool.makeWorkerThreadInActive(self.name)
44 44
         self.logger.info("Thread "+self.name +" is going to rest")
... ...
@@ -43,6 +43,7 @@ def main():
43 43
     parser.add_argument("-y",  "--generate-pkg-yaml-files",  dest="generatePkgYamlFiles",  default=False, action ="store_true")
44 44
     parser.add_argument("-j",  "--pkg-yaml-dir-path",  dest="pkgYamlDirPath",  default="../../stage/")
45 45
     parser.add_argument("-f",  "--pkg-blacklist-file",  dest="pkgBlacklistFile",  default=None)
46
+    parser.add_argument("-bt", "--build-type",  dest="pkgBuildType",  default="chroot")
46 47
     parser.add_argument("PackageName", nargs='?')
47 48
     options = parser.parse_args()
48 49
     cmdUtils=CommandUtils()
... ...
@@ -147,9 +148,9 @@ def main():
147 147
             pkgManager = PackageManager()
148 148
             pkgManager.buildToolChainPackages(options.buildThreads)
149 149
         elif options.installPackage:
150
-            buildAPackage(package, listBuildOptionPackages, options.pkgBuildOptionFile, options.buildThreads)
150
+            buildAPackage(package, listBuildOptionPackages, options.pkgBuildOptionFile, options.buildThreads, options.pkgBuildType)
151 151
         else:
152
-            buildPackagesForAllSpecs(listBuildOptionPackages, options.pkgBuildOptionFile, logger, options.buildThreads, pkgInfoJsonFile)
152
+            buildPackagesForAllSpecs(listBuildOptionPackages, options.pkgBuildOptionFile, logger, options.buildThreads, pkgInfoJsonFile, options.pkgBuildType)
153 153
     except Exception as e:
154 154
         logger.error("Caught an exception")
155 155
         logger.error(str(e))
... ...
@@ -285,15 +286,15 @@ def buildSRPMList(srpmPath, yamlDir, blackListPkgs, logger, singleFile=True):
285 285
         yamlFile.close()
286 286
     logger.info("Generated srpm yaml files for all packages")
287 287
 
288
-def buildAPackage(package, listBuildOptionPackages, pkgBuildOptionFile, buildThreads):
288
+def buildAPackage(package, listBuildOptionPackages, pkgBuildOptionFile, buildThreads, pkgBuildType):
289 289
     listPackages=[]
290 290
     listPackages.append(package)
291 291
     pkgManager = PackageManager()
292 292
     if constants.rpmCheck:
293 293
         constants.setTestForceRPMS(listPackages[:])
294
-    pkgManager.buildPackages(listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads)
294
+    pkgManager.buildPackages(listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads, pkgBuildType)
295 295
 
296
-def buildPackagesForAllSpecs(listBuildOptionPackages, pkgBuildOptionFile, logger, buildThreads, pkgInfoJsonFile):
296
+def buildPackagesForAllSpecs(listBuildOptionPackages, pkgBuildOptionFile, logger, buildThreads, pkgInfoJsonFile, pkgBuildType):
297 297
     listPackages = constants.specData.getListPackages()
298 298
 
299 299
     logger.info("List of packages to build:")
... ...
@@ -301,7 +302,7 @@ def buildPackagesForAllSpecs(listBuildOptionPackages, pkgBuildOptionFile, logger
301 301
     if constants.rpmCheck:
302 302
         constants.setTestForceRPMS(listPackages[:])
303 303
     pkgManager = PackageManager()
304
-    pkgManager.buildPackages(listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads)
304
+    pkgManager.buildPackages(listPackages, listBuildOptionPackages, pkgBuildOptionFile, buildThreads, pkgBuildType)
305 305
 
306 306
     #Generating package info file which is required by installer
307 307
     logger.info("Writing Package info to the file:"+pkgInfoJsonFile)
... ...
@@ -19,9 +19,22 @@ class constants(object):
19 19
     inputRPMSPath=""
20 20
     rpmCheck=False
21 21
     sourceRpmPath=""
22
-    noDepsPackageList=["texinfo","bzip2","gettext","nspr","xz","bison","go"]
23 22
     publishBuildDependencies=False
24 23
     packageWeightsPath=None
24
+
25
+    noDepsPackageList=[
26
+        "texinfo",
27
+        "bzip2",
28
+        "bzip2-libs",
29
+        "gettext",
30
+        "nspr",
31
+        "xz",
32
+        "bison",
33
+        "go",
34
+        "sqlite",
35
+        "sqlite-devel",
36
+        "sqlite-libs"]
37
+
25 38
     # These packages will be built in first order as build-core-toolchain stage
26 39
     listCoreToolChainPackages=[
27 40
         "filesystem",
... ...
@@ -80,6 +93,7 @@ class constants(object):
80 80
         "lua",
81 81
         "popt",
82 82
         "nspr",
83
+        "nspr-devel",
83 84
         "sqlite",
84 85
         "nss",
85 86
         "elfutils",
... ...
@@ -92,6 +106,7 @@ class constants(object):
92 92
         "autoconf",
93 93
         "automake",
94 94
         "openssl",
95
+        "openssl-devel",
95 96
         "python2",
96 97
         "libdb",
97 98
         "rpm",
... ...
@@ -310,6 +325,9 @@ class constants(object):
310 310
         "gnupg",
311 311
         "ncurses-terminfo" ]
312 312
 
313
+    listReInstallPackages=[
314
+        "go"]
315
+
313 316
     @staticmethod
314 317
     def initialize(options):
315 318
         constants.dist = options.dist
316 319
new file mode 100755
... ...
@@ -0,0 +1,4 @@
0
+#!/usr/bin/bash
1
+while true; do
2
+    sleep 1
3
+done