Browse code

Refine docker build system

1. For BUILD folder, use host system's folder to avoid using
overlayFS. The reason is overlayFS causes makecheck to fail.

2. Add SYS_PTRACE to all docker instance requested by Alexey.

3. When docker instance is being created, add -t option
to fix make check hang in libarchive.

Change-Id: Id71992d5ea212c44d11b4c2083125223358d7819
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3831
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Vinay Kulkarni <kulkarniv@vmware.com>

Rui Gu authored on 2017/09/22 03:55:43
Showing 2 changed files
... ...
@@ -2,6 +2,7 @@ from PackageUtils import PackageUtils
2 2
 from Logger import Logger
3 3
 from ToolChainUtils import ToolChainUtils
4 4
 from CommandUtils import CommandUtils
5
+from ChrootUtils import ChrootUtils
5 6
 import os.path
6 7
 import sys
7 8
 from constants import constants
... ...
@@ -28,6 +29,17 @@ class BuildContainer(object):
28 28
         self.pkgBuildOptionFile = pkgBuildOptionFile
29 29
 
30 30
     def prepareBuildContainer(self, containerTaskName, packageName, isToolChainPackage=False):
31
+        # Prepare an empty chroot environment to let docker use the BUILD folder.
32
+        # This avoids docker using overlayFS which will cause make check failure.
33
+        chrootName="build-"+packageName
34
+        chrUtils = ChrootUtils(self.logName,self.logPath)
35
+        returnVal,chrootID = chrUtils.createChroot(chrootName)
36
+        if not returnVal:
37
+            raise Exception("Unable to prepare build root")
38
+        cmdUtils = CommandUtils()
39
+        cmdUtils.runCommandInShell("mkdir -p " + chrootID + constants.topDirPath)
40
+        cmdUtils.runCommandInShell("mkdir -p " + chrootID + constants.topDirPath + "/BUILD")
41
+
31 42
         containerID = None
32 43
         mountVols = {
33 44
                         constants.prevPublishRPMRepo: {'bind': '/publishrpms', 'mode': 'ro'},
... ...
@@ -36,6 +48,7 @@ class BuildContainer(object):
36 36
                         constants.rpmPath: {'bind': constants.topDirPath + "/RPMS", 'mode': 'rw'},
37 37
                         constants.sourceRpmPath: {'bind': constants.topDirPath + "/SRPMS", 'mode': 'rw'},
38 38
                         constants.logPath + "/" + self.logName: {'bind': constants.topDirPath + "/LOGS", 'mode': 'rw'},
39
+                        chrootID + constants.topDirPath + "/BUILD": {'bind': constants.topDirPath + "/BUILD", 'mode': 'rw'}
39 40
                     }
40 41
 
41 42
         containerName = containerTaskName
... ...
@@ -50,21 +63,20 @@ class BuildContainer(object):
50 50
         try:
51 51
             self.logger.info("BuildContainer-prepareBuildContainer: Starting build container: " + containerName)
52 52
             #TODO: Is init=True equivalent of --sig-proxy?
53
+            privilegedDocker = False
54
+            cap_list = ['SYS_PTRACE']
53 55
             if packageName in constants.listReqPrivilegedDockerForTest:
54
-                containerID = self.dockerClient.containers.run(self.buildContainerImage,
55
-                                                               detach=True,
56
-                                                               privileged=True,
57
-                                                               name=containerName,
58
-                                                               network_mode="host",
59
-                                                               volumes=mountVols,
60
-                                                               command="/bin/bash -l -c /wait.sh")
61
-            else:
62
-                containerID = self.dockerClient.containers.run(self.buildContainerImage,
56
+                privilegedDocker = True
57
+
58
+            containerID = self.dockerClient.containers.run(self.buildContainerImage,
63 59
                                                                detach=True,
60
+                                                               cap_add=cap_list,
61
+                                                               privileged=privilegedDocker,
64 62
                                                                name=containerName,
65 63
                                                                network_mode="host",
66 64
                                                                volumes=mountVols,
67 65
                                                                command="/bin/bash -l -c /wait.sh")
66
+
68 67
             self.logger.debug("Started Photon build container for task " + containerTaskName
69 68
                                + " ID: " + containerID.short_id)
70 69
             if not containerID:
... ...
@@ -72,7 +84,7 @@ class BuildContainer(object):
72 72
         except Exception as e:
73 73
             self.logger.debug("Unable to start Photon build container for task " + containerTaskName)
74 74
             raise e
75
-        return containerID
75
+        return containerID, chrootID
76 76
 
77 77
     def findPackageNameFromRPMFile(self, rpmfile):
78 78
         rpmfile = os.path.basename(rpmfile)
... ...
@@ -131,12 +143,13 @@ class BuildContainer(object):
131 131
         #should initialize a logger based on package name
132 132
         containerTaskName = "build-" + package
133 133
         containerID = None
134
+        chrootID = None
134 135
         isToolChainPackage = False
135 136
         if package in constants.listToolChainPackages:
136 137
             isToolChainPackage = True
137 138
         destLogPath = constants.logPath + "/build-"+package
138 139
         try:
139
-            containerID = self.prepareBuildContainer(containerTaskName, package, isToolChainPackage)
140
+            containerID, chrootID = self.prepareBuildContainer(containerTaskName, package, isToolChainPackage)
140 141
             if not os.path.isdir(destLogPath):
141 142
                 cmdUtils = CommandUtils()
142 143
                 cmdUtils.runCommandInShell("mkdir -p "+destLogPath)
... ...
@@ -192,6 +205,10 @@ class BuildContainer(object):
192 192
         # Remove the container
193 193
         if containerID is not None:
194 194
             containerID.remove(force=True)
195
+        # Remove the dummy chroot
196
+        if chrootID is not None:
197
+            chrUtils = ChrootUtils(self.logName,self.logPath)
198
+            chrUtils.destroyChroot(chrootID)
195 199
 
196 200
     def findRunTimeRequiredRPMPackages(self, rpmPackage):
197 201
         listRequiredPackages = SPECS.getData().getRequiresForPackage(rpmPackage)
... ...
@@ -615,7 +615,7 @@ class PackageUtils(object):
615 615
             rpmBuildCmd += ' --define \"%s\"' % macro
616 616
         rpmBuildCmd += " " + specFile
617 617
         rpmBuildCmd = "/bin/bash -l -c '" + rpmBuildCmd + " > " + rpmLogFile + " 2>&1'"
618
-        rpmBuildCmd = "docker exec " + str(containerID.short_id) + " " + rpmBuildCmd
618
+        rpmBuildCmd = "docker exec -t " + str(containerID.short_id) + " " + rpmBuildCmd
619 619
 
620 620
         cmdUtils = CommandUtils()
621 621
         self.logger.info("Building rpm for package: " + package)