2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.slc
.rpmfactory
.core
;
19 import java
.io
.IOException
;
20 import java
.text
.DateFormat
;
21 import java
.text
.SimpleDateFormat
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Calendar
;
24 import java
.util
.GregorianCalendar
;
25 import java
.util
.HashMap
;
26 import java
.util
.List
;
29 import javax
.jcr
.Node
;
30 import javax
.jcr
.Repository
;
31 import javax
.jcr
.RepositoryException
;
32 import javax
.jcr
.Session
;
34 import org
.apache
.commons
.io
.FileUtils
;
35 import org
.apache
.commons
.logging
.Log
;
36 import org
.apache
.commons
.logging
.LogFactory
;
37 import org
.argeo
.jcr
.JcrUtils
;
38 import org
.argeo
.slc
.SlcConstants
;
39 import org
.argeo
.slc
.SlcException
;
40 import org
.argeo
.slc
.core
.execution
.tasks
.SystemCall
;
41 import org
.argeo
.slc
.repo
.NodeIndexerVisitor
;
42 import org
.argeo
.slc
.repo
.RpmIndexer
;
43 import org
.argeo
.slc
.rpmfactory
.RpmFactory
;
44 import org
.argeo
.slc
.rpmfactory
.RpmRepository
;
47 * Defines a build environment. This information is typically used by other
48 * components performing the various actions related to RPM build.
50 public class RpmFactoryImpl
implements RpmFactory
{
51 private Log log
= LogFactory
.getLog(RpmFactoryImpl
.class);
53 private Repository rpmRepository
;
54 private Repository distRepository
;
57 private List
<RpmRepository
> repositories
= new ArrayList
<RpmRepository
>();
58 private List
<String
> archs
= new ArrayList
<String
>();
60 private String rpmBase
= "/mnt/slc/repos/rpm";
61 private String distBase
= "/mnt/slc/repos/dist";
62 private String mockVar
= "/var/lib/mock";
63 private String mockEtc
= "/etc/mock";
65 private DateFormat dateFormat
= new SimpleDateFormat("yyyyMMdd_HHmm");
67 private String gitWorkspace
= "git";
69 private String localUrlBase
= "http://localhost:7070/";
70 /** If not null or empty, this is a developer instance. */
71 private String gitDevBaseUrl
= null;
73 private Boolean withTestingRepository
= false;
75 private String yumConfigMainSection
= "cachedir=/var/cache/yum\n"
76 + "debuglevel=1\n" + "reposdir=/dev/null\n"
77 + "logfile=/var/log/yum.log\n" + "retries=20\n" + "obsoletes=1\n"
78 + "gpgcheck=0\n" + "assumeyes=1\n" + "syslog_ident=mock\n"
79 + "syslog_device=\n" + "http_caching=none\n";
81 private String defaultMacroFiles
= "/usr/lib/rpm/macros:"
82 + "/usr/lib/rpm/ia32e-linux/macros:"
83 + "/usr/lib/rpm/redhat/macros:" + "/etc/rpm/macros.*:"
84 + "/etc/rpm/macros:" + "/etc/rpm/ia32e-linux/macros:"
86 private Map
<String
, String
> rpmmacros
= new HashMap
<String
, String
>();
89 private String proxiedReposBase
;
90 private String managedReposBase
;
92 private String stagingWorkspace
;
93 private String testingWorkspace
;
94 private String stableWorkspace
;
96 private File rpmFactoryBaseDir
;
97 private File mockConfDir
;
98 private File yumConfDir
;
102 proxiedReposBase
= localUrlBase
+ "repo/rpm/";
103 managedReposBase
= localUrlBase
+ "data/public/rpm/";
106 rpmFactoryBaseDir
.mkdirs();
107 mockConfDir
= new File(rpmFactoryBaseDir
.getPath() + "/conf/mock");
108 mockConfDir
.mkdirs();
109 yumConfDir
= new File(rpmFactoryBaseDir
.getPath() + "/conf/yum");
112 // managed repositories
113 stagingWorkspace
= id
+ "-staging";
114 if (withTestingRepository
)
115 testingWorkspace
= id
+ "-testing";
116 stableWorkspace
= id
;
118 initDistWorkspace(stableWorkspace
);
120 initRpmWorkspace(stagingWorkspace
);
121 if (withTestingRepository
)
122 initRpmWorkspace(testingWorkspace
);
123 initRpmWorkspace(stableWorkspace
);
126 protected void initRpmWorkspace(String workspace
) {
127 Session session
= null;
129 session
= JcrUtils
.loginOrCreateWorkspace(rpmRepository
, workspace
);
130 JcrUtils
.addPrivilege(session
, "/", "anonymous", "jcr:read");
131 JcrUtils
.addPrivilege(session
, "/", SlcConstants
.ROLE_SLC
,
134 for (String arch
: archs
) {
135 Node archFolder
= JcrUtils
.mkfolders(session
, "/" + arch
);
137 File workspaceDir
= getWorkspaceDir(workspace
);
139 if (!archFolder
.hasNode("repodata")) {
140 // touch a file in order to make sure this is properly
142 File touch
= new File(workspaceDir
, ".touch");
143 touch
.createNewFile();
146 SystemCall createrepo
= new SystemCall();
147 createrepo
.arg("createrepo");
148 createrepo
.arg("-q");
149 File archDir
= new File(workspaceDir
, arch
);
150 createrepo
.arg(archDir
.getAbsolutePath());
153 } catch (IOException e
) {
154 log
.error(workspaceDir
+ " not properly mounted.", e
);
157 } catch (Exception e
) {
158 throw new SlcException("Cannot initialize workspace " + workspace
,
161 JcrUtils
.logoutQuietly(session
);
165 /** Caller must logout the underlying session. */
166 public Node
newDistribution(String distributionId
) {
167 Session session
= null;
169 session
= JcrUtils
.loginOrCreateWorkspace(rpmRepository
,
171 JcrUtils
.addPrivilege(session
, "/", "anonymous", "jcr:read");
172 JcrUtils
.addPrivilege(session
, "/", SlcConstants
.ROLE_SLC
,
175 Calendar now
= new GregorianCalendar();
176 String folderName
= dateFormat
.format(now
.getTime());
177 return JcrUtils
.mkfolders(session
, "/" + folderName
);
178 } catch (Exception e
) {
179 JcrUtils
.logoutQuietly(session
);
180 throw new SlcException("Cannot initialize distribution workspace "
181 + distributionId
, e
);
185 protected void initGitWorkspace() {
186 Session session
= null;
188 session
= JcrUtils
.loginOrCreateWorkspace(rpmRepository
,
190 JcrUtils
.addPrivilege(session
, "/", "anonymous", "jcr:read");
191 JcrUtils
.addPrivilege(session
, "/", SlcConstants
.ROLE_SLC
,
193 } catch (Exception e
) {
194 throw new SlcException("Cannot initialize workspace "
197 JcrUtils
.logoutQuietly(session
);
201 protected void initDistWorkspace(String workspace
) {
202 Session session
= null;
205 .loginOrCreateWorkspace(distRepository
, workspace
);
206 JcrUtils
.addPrivilege(session
, "/", "anonymous", "jcr:read");
207 } catch (RepositoryException e
) {
208 throw new SlcException("Cannot initialize workspace " + workspace
,
211 JcrUtils
.logoutQuietly(session
);
215 public void destroy() {
219 public String
generateMockConfigFile(String arch
, String branch
) {
220 StringBuffer buf
= new StringBuffer();
222 buf
.append("config_opts['root'] = '" + getIdWithArch(arch
) + "'\n");
223 buf
.append("config_opts['target_arch'] = '" + arch
+ "'\n");
224 buf
.append("config_opts['legal_host_arches'] = ('" + arch
+ "',)\n");
225 buf
.append("config_opts['chroot_setup_cmd'] = 'groupinstall buildsys-build'\n");
226 // buf.append("config_opts['dist'] = 'el6'\n");
227 buf
.append("config_opts['plugin_conf']['yum_cache_enable'] = False\n");
229 buf
.append("config_opts['scm'] = False\n");
230 buf
.append("config_opts['scm_opts']['method'] = 'git'\n");
231 buf
.append("config_opts['scm_opts']['spec'] = 'SCM_PKG.spec'\n");
232 buf
.append("config_opts['scm_opts']['ext_src_dir'] = '"
233 + getSourcesDir().getAbsolutePath() + "'\n");
234 buf
.append("config_opts['scm_opts']['git_timestamps'] = True\n");
237 if (gitDevBaseUrl
!= null && !gitDevBaseUrl
.trim().equals(""))
238 buf
.append("config_opts['scm_opts']['git_get'] = 'git clone "
239 + (branch
!= null ?
"-b " + branch
: "") + " "
240 + gitDevBaseUrl
+ "/SCM_PKG SCM_PKG'\n");
242 buf
.append("config_opts['scm_opts']['git_get'] = 'git clone "
243 + (branch
!= null ?
"-b " + branch
: "") + " "
244 + getGitBaseUrl() + "/SCM_PKG.git SCM_PKG'\n");
246 buf
.append("\nconfig_opts['yum.conf'] = \"\"\"\n");
247 buf
.append(generateYumConfigFile(arch
)).append('\n');
248 buf
.append("\"\"\"\n");
249 return buf
.toString();
252 public String
generateYumConfigFile(String arch
) {
253 StringBuffer buf
= new StringBuffer();
254 buf
.append("[main]\n");
255 buf
.append(yumConfigMainSection
).append('\n');
257 for (RpmRepository repository
: repositories
) {
258 buf
.append('[').append(repository
.getId()).append("]\n");
259 buf
.append("name=").append(repository
.getId()).append('\n');
260 if (repository
instanceof ThirdPartyRpmRepository
) {
261 buf
.append("#baseurl=").append(repository
.getUrl())
262 .append(arch
).append('/').append("\n");
263 buf
.append("baseurl=").append(proxiedReposBase
)
264 .append(repository
.getId()).append('/').append(arch
)
265 .append('/').append("\n");
266 if (((ThirdPartyRpmRepository
) repository
).getYumConf() != null)
268 ((ThirdPartyRpmRepository
) repository
).getYumConf()
269 .trim()).append('\n');
274 addManagedRepository(buf
, stagingWorkspace
, arch
);
275 if (withTestingRepository
)
276 addManagedRepository(buf
, testingWorkspace
, arch
);
277 addManagedRepository(buf
, stableWorkspace
, arch
);
278 return buf
.toString();
281 protected void addManagedRepository(StringBuffer buf
, String workspace
,
283 buf
.append('[').append(workspace
).append("]\n");
284 buf
.append("baseurl=").append(managedReposBase
).append(workspace
)
285 .append('/').append(arch
).append('/').append("\n");
286 buf
.append("gpgcheck=0").append("\n");
289 /** Creates a mock config file. */
290 public File
getMockConfigFile(String arch
, String branch
) {
291 File mockSiteDefaultsFile
= new File(mockConfDir
, "site-defaults.cfg");
292 File mockLoggingFile
= new File(mockConfDir
, "logging.ini");
293 File mockConfigFile
= new File(mockConfDir
, getIdWithArch(arch
)
296 if (!mockSiteDefaultsFile
.exists())
297 mockSiteDefaultsFile
.createNewFile();
298 if (!mockLoggingFile
.exists())
299 FileUtils
.copyFile(new File(mockEtc
+ "/logging.ini"),
302 FileUtils
.writeStringToFile(mockConfigFile
,
303 generateMockConfigFile(arch
, branch
));
304 return mockConfigFile
;
305 } catch (IOException e
) {
306 throw new SlcException("Cannot write mock config file to "
307 + mockConfigFile
, e
);
311 /** Creates a yum config file. */
312 public File
getYumRepoFile(String arch
) {
313 File yumConfigFile
= new File(yumConfDir
, getIdWithArch(arch
) + ".repo");
315 FileUtils
.writeStringToFile(yumConfigFile
,
316 generateYumConfigFile(arch
));
317 return yumConfigFile
;
318 } catch (IOException e
) {
319 throw new SlcException("Cannot write yum config file to "
324 public File
getResultDir(String arch
) {
325 return new File(mockVar
+ "/" + getIdWithArch(arch
) + "/result");
328 public File
getWorkspaceDir(String workspace
) {
329 return new File(rpmBase
+ "/" + workspace
);
332 public File
getSourcesDir() {
333 return new File(distBase
+ "/" + stableWorkspace
);
336 public String
getMockConfig(String arch
) {
337 return getIdWithArch(arch
);
340 public String
getIdWithArch(String arch
) {
341 return id
+ "-" + arch
;
344 public String
getGitBaseUrl() {
345 return managedReposBase
+ gitWorkspace
;
348 public void indexWorkspace(String workspace
) {
349 Session session
= null;
351 session
= rpmRepository
.login(workspace
);
352 session
.getRootNode().accept(
353 new NodeIndexerVisitor(new RpmIndexer()));
354 if (log
.isDebugEnabled())
355 log
.debug("Indexed workspace " + workspace
);
356 } catch (RepositoryException e
) {
357 throw new SlcException("Cannot index workspace " + workspace
, e
);
359 JcrUtils
.logoutQuietly(session
);
363 public Boolean
isDeveloperInstance() {
364 return gitDevBaseUrl
!= null;
367 /** Write (topdir)/rpmmacros and (topdir)/rpmrc */
368 public void writeRpmbuildConfigFiles(File topdir
) {
369 writeRpmbuildConfigFiles(topdir
, new File(topdir
, "rpmmacros"),
370 new File(topdir
, "rpmrc"));
373 public void writeRpmbuildConfigFiles(File topdir
, File rpmmacroFile
,
376 List
<String
> macroLines
= new ArrayList
<String
>();
377 macroLines
.add("%_topdir " + topdir
.getCanonicalPath());
378 for (String macroKey
: rpmmacros
.keySet()) {
379 macroLines
.add(macroKey
+ " " + rpmmacros
.get(macroKey
));
381 FileUtils
.writeLines(rpmmacroFile
, macroLines
);
383 List
<String
> rpmrcLines
= new ArrayList
<String
>();
384 rpmrcLines
.add("include: /usr/lib/rpm/rpmrc");
385 rpmrcLines
.add("macrofiles: " + defaultMacroFiles
+ ":"
386 + rpmmacroFile
.getCanonicalPath());
387 FileUtils
.writeLines(rpmrcFile
, rpmrcLines
);
388 } catch (IOException e
) {
389 throw new SlcException("Cannot write rpmbuild config files", e
);
394 public Map
<String
, String
> getRpmmacros() {
398 public void setRpmmacros(Map
<String
, String
> rpmmacros
) {
399 this.rpmmacros
= rpmmacros
;
402 public String
getDefaultMacroFiles() {
403 return defaultMacroFiles
;
406 public void setDefaultMacroFiles(String defaultMacroFiles
) {
407 this.defaultMacroFiles
= defaultMacroFiles
;
410 public void setArchs(List
<String
> archs
) {
414 public List
<String
> getArchs() {
418 public void setRpmBase(String stagingBase
) {
419 this.rpmBase
= stagingBase
;
422 public void setId(String id
) {
426 public void setMockVar(String mockVar
) {
427 this.mockVar
= mockVar
;
430 public void setRpmRepository(Repository rpmRepository
) {
431 this.rpmRepository
= rpmRepository
;
434 public void setDistRepository(Repository distRepository
) {
435 this.distRepository
= distRepository
;
438 public void setLocalUrlBase(String localUrlBase
) {
439 this.localUrlBase
= localUrlBase
;
442 public void setYumConfigMainSection(String yumConfigMainSection
) {
443 this.yumConfigMainSection
= yumConfigMainSection
;
446 public void setRepositories(List
<RpmRepository
> repositories
) {
447 this.repositories
= repositories
;
450 public void setRpmFactoryBaseDir(File rpmFactoryBaseDir
) {
451 this.rpmFactoryBaseDir
= rpmFactoryBaseDir
;
454 public String
getStagingWorkspace() {
455 return stagingWorkspace
;
458 public String
getTestingWorkspace() {
459 return testingWorkspace
;
462 public String
getStableWorkspace() {
463 return stableWorkspace
;
466 public void setWithTestingRepository(Boolean withTestingRepository
) {
467 this.withTestingRepository
= withTestingRepository
;
470 public void setGitDevBaseUrl(String gitBaseUrl
) {
471 this.gitDevBaseUrl
= gitBaseUrl
;