Add possibility to build packages inside docker
[integration/packaging.git] / rpm / README.markdown
1 Logic for building OpenDaylight's upstream Source RPMs.
2
3 SRPM/RPM builds are supported for the following OpenDaylight major releases, as well as various daily builds:
4
5 * Helium SR4
6 * Lithium
7 * Lithium SR1
8 * Lithium SR2
9 * Lithium SR3
10 * Lithium SR4
11 * Beryllium
12 * Beryllium SR1
13
14 ## Overview
15
16 OpenDaylight's Source RPMs (SRPMs) are built using the logic provided here.
17
18 When new builds are defined, the new SRPMs are uploaded to the CentOS
19 Community Build System's Koji-based RPM build system. From there they are
20 built into ready-to-install noarch RPMs and hosted for consumption.
21
22 Data that differs per-build is is defined in the `build_vars.yaml` YAML
23 configuration file. The build logic consumes that dynamic data, uses
24 JinJa2 templates to generate RPM spec files and builds the RPMs/SRPMs they
25 define.
26
27 See the Templates vs Macros section for details about why we use this design.
28
29 ## Vagrant Build Environment
30
31 The included Vagrantfile defines a consistent, known-working and easily
32 shared environment. It supports both VM and container-based providers.
33
34 ```
35 $ vagrant status
36 Current machine states:
37
38 default                   not created (virtualbox)
39 $ vagrant up
40 $ vagrant ssh
41 [vagrant@localhost vagrant]$ ls /vagrant/
42 build.py  build_vars.yaml  cache  connect.sh  Vagrantfile <snip>
43 ```
44
45 ### Docker provider
46
47 The Vagrantfile defines a Docker provider, enabling easy access to build.py
48 in a container. The general command format is:
49
50 ```
51 $ vagrant docker-run -- <flags to build.py>
52 ```
53
54 To pass 5.0 (Boron) as the version to build:
55
56 ```
57 $ vagrant docker-run -- -v 5 0
58 ```
59
60 Dockerfile can be also used directly to build container image:
61
62 ```
63 $ docker build -t "odl_rpm" .
64 $ docker run -v $(pwd):/build odl_rpm -v 5 0
65 ```
66
67 ## Defining New RPMs
68
69 The dynamic aspects of a build, such as ODL and RPM version info, have all
70 been extracted to a single YAML configuration file. For most RPM updates,
71 only that configuration file should need to be updated by humans.
72
73 The variables available for configuration are documented below. A build
74 definition should define all supported variables.
75
76 ### RPM Build Variables
77
78 #### `version_major`
79
80 The OpenDaylight major (element) version number of the release to build.
81
82 For example, Hydrogen is 1.x.x, Helium is 2.x.x, Lithium is 3.x.x and
83 so on down the periodic table.
84
85 #### `version_minor`
86
87 The OpenDaylight minor (SR) version number of the release to build.
88
89 OpenDaylight provides periodic Service Releases (SRs) for each currently
90 supported Major release. See the [Hydrogen][12], [Lithium][13] or
91 [Beryllium][13] release plan schedules for more information.
92
93 #### `version_patch`
94
95 The OpenDaylight patch version of the release to build (unused pending CR).
96
97 This version number isn't currently used by OpenDaylight, as there aren't
98 releases more frequent than Service Releases. However, the upstream
99 OpenDaylight community is working towards supporting a Continuous Release (CR)
100 model. Once that exists, this patch version will denote CR-level releases.
101
102 #### `rpm_release`
103
104 RPM version for the given ODL major.minor.patch version.
105
106 In addition to OpenDaylight's version, RPMs themselves have versions. These
107 are called "release versions". For a given OpenDaylight major.minor.patch
108 version, there will be one or more major.minor.patch-rpm_release RPMs.
109
110 #### `sysd_commit`
111
112 Version of ODL systemd unitfile to download and package in ODL RPM.
113
114 The version of OpenDaylight's systemd unitfile in the `packaging/rpm/unitfiles`
115 directory specified by this git commit hash is downloaded from the [Int/Pack
116 repo][16] and consumed by OpenDaylight's RPM builds as an RPM spec file Source.
117
118 #### `codename`
119
120 Elemental codename for the ODL release, including SR if applicable.
121
122 Examples include "Helium-SR4", "Lithium" and "Lithium-SR1".
123
124 #### `download_url`
125
126 The ODL RPM repackages the tarball build artifact produced by ODL's
127 autorelease build, because building Java projects from source directly
128 to RPMs is very difficult with current tooling. This is the URL to the
129 tarball ODL build to repackage into an RPM.
130
131 #### `changelog`
132
133 Entry in the RPM .spec file's changelog for this RPM.
134
135 When the RPM spec file template is specialized into per-build static RPM spec
136 files, a changelog is generated using these entries.
137
138 The changelog entry must follow a specific format. It's best to follow the
139 examples provided by existing build definitions closely. The `rpmbuild` tool
140 will fail and complain fairly clearly if the format isn't correct.
141
142 ## Building SRPMs/RPMs
143
144 The `build.py` helper script is used for building OpenDaylight SRPMs/RPMs.
145
146 All SRPM builds are done in the included Vagrant environment. SRPMs are then
147 uploaded to the CentOS Community Build System, built into noarch RPMs there
148 and hosted for distribution.
149
150 The `build.py` helper script builds noarch RPMs in addition to the (actually
151 used) SRPMs. The noarch RPMs are meant for quickly sanity checking that a
152 build worked as expected. They can be installed in the Vagrant build box or
153 another sandbox, then inspected.
154
155 The `build.py` helper script can build a set of SRPMs/RPMs based on provided
156 version arguments.
157
158 ```
159 [vagrant@localhost ~]$ /vagrant/build.py -h
160 usage: build.py [-h] [-v [major minor patch rpm [major minor patch rpm ...]]]
161
162 optional arguments:
163   -h, --help            show this help message and exit
164   -v [major minor patch rpm [major minor patch rpm ...]], --version [major minor patch rpm [major minor patch rpm ...]]
165                         RPM version(s) to build
166 ```
167
168 The `-v`/`--version` flag accepts a version number. Any build that matches
169 the portions provided will be built. If more than one build matches the
170 portions provided, all matching builds will be executed.
171
172 For example, `build.py -v 3` would execute the builds that match the regex
173 `3.*.*-*`. OpenDaylight 3.0.0-1 and 3.1.0-1, for example.
174
175 To only build a single RPM definition, provide enough version info to make
176 the match unique. For example, `build.py -v 2 4 0 1` could only match one
177 definition (Helium SR4, 2.4.0-1).
178
179 The `build.py` script uses the `cache/cache.py` script to handled downloading
180 and caching the artifacts required for the requested builds. Artifacts are
181 cached in the `packaging/rpm/cache/` directory.
182
183 The `build.py` script also uses the `specs/build_specs.py` script to generate
184 static RPM spec files from the `packaging/rpm/specs/opendaylight.spec` JinJa2
185 templates and the dynamic build data provided in `build_vars.yaml`. The
186 resulting RPM spec files are passed to `rpmbuild` by `build.py` to build
187 specific ODL SRPMs/RPMs.
188
189 ## Working with the ODL RPM
190
191 The familiar RPM-related commands apply to the OpenDaylight RPM.
192
193 ### Installing OpenDaylight via a local RPM
194
195 To install a local OpenDaylight RPM, perhaps as a sanity check after a
196 build, use `sudo yum install -y <path to ODL RPM>`.
197
198 Here's a walk-through of an install and the resulting system changes.
199
200 ```
201 # Note that there's nothing in /opt before the install
202 [vagrant@localhost ~]$ ls /opt/
203 # Note that there are no ODL systemd files before the install
204 [vagrant@localhost ~]$ ls /usr/lib/systemd/system | grep -i opendaylight
205 # Install an ODL RPM. Yum will handle installing ODL's Java dependency.
206 [vagrant@localhost ~]$ sudo yum install -y /vagrant/cache/<RPM filename>
207 # Note that ODL is now installed in /opt
208 [vagrant@localhost ~]$ ls /opt/
209 opendaylight
210 # Note that there's now a systemd .service file for ODL
211 [vagrant@localhost ~]$ ls /usr/lib/systemd/system | grep -i opendaylight
212 opendaylight.service
213 ```
214
215 ### Uninstalling OpenDaylight's RPM
216
217 To uninstall OpenDaylight's RPM, use `sudo yum remove -y opendaylight`.
218
219 Here's a walk-through of the uninstall and the resulting system changes.
220
221 ```
222 # Note that ODL is installed in /opt/
223 [vagrant@localhost vagrant]$ ls /opt/
224 opendaylight
225 # Note that there's a systemd .service file for ODL
226 [vagrant@localhost vagrant]$ ls /usr/lib/systemd/system | grep -i opendaylight
227 opendaylight.service
228 # Uninstall the ODL RPM
229 [vagrant@localhost vagrant]$ sudo  yum remove -y opendaylight
230 # Note that ODL has been removed from /opt/
231 [vagrant@localhost vagrant]$ ls /opt/
232 # Note that the ODL systemd .service file has been removed
233 [vagrant@localhost vagrant]$ ls /usr/lib/systemd/system | grep -i opendaylight
234 ```
235
236 ## Managing OpenDaylight via systemd
237
238 The OpenDaylight RPM ships with systemd support.
239
240 ### Starting OpenDaylight via systemd
241
242 ```
243 [vagrant@localhost vagrant]$ sudo systemctl start opendaylight
244 [vagrant@localhost vagrant]$ sudo systemctl status opendaylight
245 ● opendaylight.service - OpenDaylight SDN Controller
246    Loaded: loaded (/usr/lib/systemd/system/opendaylight.service; disabled)
247    Active: active (running) since Tue 2015-07-14 21:09:30 UTC; 4s ago
248      Docs: https://wiki.opendaylight.org/view/Main_Page
249            http://www.opendaylight.org/
250   Process: 18216 ExecStart=/opt/opendaylight/bin/start (code=exited, status=0/SUCCESS)
251  Main PID: 18223 (java)
252    CGroup: /system.slice/opendaylight.service
253            └─18223 /usr/bin/java -Djava.security.properties=/opt/opendaylight/etc/odl.jav...
254
255 Jul 14 21:09:30 localhost.localdomain systemd[1]: Started OpenDaylight SDN Controller.
256 ```
257
258 ### Stopping OpenDaylight via systemd
259
260 ```
261 [vagrant@localhost vagrant]$ sudo systemctl stop opendaylight
262 [vagrant@localhost vagrant]$ sudo systemctl status opendaylight
263 opendaylight.service - OpenDaylight SDN Controller
264    Loaded: loaded (/usr/lib/systemd/system/opendaylight.service; disabled)
265    Active: inactive (dead)
266      Docs: https://wiki.opendaylight.org/view/Main_Page
267            http://www.opendaylight.org/
268 # snip
269 ```
270
271 ## Connecting to the Karaf shell
272
273 A few seconds after OpenDaylight is started, its Karaf shell will be accessible.
274
275 The `connect.sh` script is provided as an example of how to connect to the Karaf shell.
276
277 ```
278 # Assuming you've started ODL
279 [vagrant@localhost ~]$ /vagrant/connect.sh
280 Installing sshpass. It's used connecting non-interactively
281 # snip
282 opendaylight-user@root>
283 ```
284
285 Additionally, here's an example of connecting manually (password: `karaf`):
286
287 ```
288 [vagrant@localhost vagrant]$ ssh -p 8101 -o StrictHostKeyChecking=no karaf@localhost
289 Authenticated with partial success.
290 Password authentication
291 Password: 
292                                                                                            
293     ________                       ________                .__  .__       .__     __       
294     \_____  \ ______   ____   ____ \______ \ _____  ___.__.|  | |__| ____ |  |___/  |_     
295      /   |   \\____ \_/ __ \ /    \ |    |  \\__  \<   |  ||  | |  |/ ___\|  |  \   __\    
296     /    |    \  |_> >  ___/|   |  \|    `   \/ __ \\___  ||  |_|  / /_/  >   Y  \  |      
297     \_______  /   __/ \___  >___|  /_______  (____  / ____||____/__\___  /|___|  /__|      
298             \/|__|        \/     \/        \/     \/\/            /_____/      \/          
299                                                                                            
300
301 Hit '<tab>' for a list of available commands
302 and '[cmd] --help' for help on a specific command.
303 Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown OpenDaylight.
304
305 opendaylight-user@root>^D
306 Connection to localhost closed.
307 [vagrant@localhost vagrant]$
308 ```
309
310 ## CentOS Community Build System
311
312 After building SRPMs as described above, we use the [CentOS Community Build
313 System][1] to build and host noarch RPMs for official consumption.
314
315 ### Access
316
317 OpenDaylight's CBS usage is under the umbrella of the CentOS Network Function
318 Virtulalization Special Interest Group (NFV SIG).
319
320 Committers to OpenDaylight Integration/Packaging [should][2] have CentOS CBS
321 commit access, which actually manifests as Koji "build" permissions.
322
323 To get access, [file a bug][3] against CentOS with `Project:Buildsys` and
324 `Category:community buildsys`. Include the Koji username you'd like, your
325 GPG public key (inclusion in OpenDaylight's web of trust is strongly
326 encouraged), your email address and the name of the SIG ("NFV" in our case).
327 For an example, see [Daniel Farrell's request][4]. For additional info, see
328 the [Quickstart section of the CBS docs][5].
329
330 As noted in those docs, you'll need to get the SIG chair to leave a note
331 on your bug to verify that you should have access. Dave Neary is the
332 current NFV SIG chair. The [Int/Pack][15] PTL (currently [Daniel Farrell][6])
333 can help you get his cooperation.
334
335 ### Using the CBS
336
337 The CentOS CBS is Koji-based, so the main way to interface with it via the
338 Koji CLI client. There's also a [Koji web UI][1].
339
340 Other than the [main CBS wiki][7] and Koji's help output, there aren't
341 substantial Koji docs. These docs strive to cover everything that's
342 commonly needed for ODL's RPMs.
343
344 Once you get access to the CBS, you'll be emailed a tarball with the
345 configuration and certificates required by the Koji CLI when interacting
346 with the CBS's Koji server.
347
348 Koji expects the contents of that tarball in the `~/.koji` directory.
349
350 ```
351 [~/.koji]$ ls
352 # Actually symlinks that point to files I decrypt only when necessary
353 clientca.crt  client.crt  config  serverca.crt
354 ```
355
356 Verify that you have the appropriate permissions.
357
358 ```
359 $ koji list-permissions
360 build
361 <snip>
362 ```
363
364 If you're building a new OpenDaylight major version, you'll need to raise
365 a bug like [this one][8] to get the target created. Once it's created,
366 a set build tags will be created for that major version. For now, we're
367 only using the `*-candidate` tags.
368
369 ```
370 $ koji list-tags | grep "opendaylight-.-candidate"
371 nfv7-opendaylight-2-candidate
372 nfv7-opendaylight-3-candidate
373 nfv7-opendaylight-4-candidate
374 ```
375
376 For new tags, the `opendaylight` package needs to be added before a build.
377
378 ```
379 $ koji add-pkg --owner "dfarrell07" nfv7-opendaylight-3-candidate opendaylight
380 ```
381
382 When submitting a build, it's typically a good idea to verify that everything
383 is in working order using the `--scratch` option.
384
385 ```
386 $ koji build --scratch nfv7-opendaylight-3-el7 opendaylight-3.0.0-1.el7.src.rpm
387 ```
388
389 If everything works, submit the actual build.
390
391 ```
392 $ koji build nfv7-opendaylight-3-el7 opendaylight-3.0.0-1.el7.src.rpm
393 ```
394
395 You can monitor the build using the Koji CLI `watch-logs` and `watch-task`
396 commands, or the [Koji web UI's][1] output of the same information.
397
398 If the RPM build is successful, it will appear [on the CBS][9] under the
399 appropriate `nfv7-opendaylight-<major version>-testing` repo. The resulting
400 RPM can be installed directly or via a [package manager config file][10].
401
402 ```
403 $ sudo curl -o /etc/yum.repos.d/opendaylight-3-candidate.repo \
404                    <URL to repo config>
405 $ sudo yum install -y opendaylight
406 ```
407
408 ## Templates vs Macros
409
410 This section documents _why_ we use the YAML+Py+JinJa2 design we do, whereas
411 the sections above document _how_.
412
413 Typically, RPM builds use the macro mechanism provided by RPM spec files
414 and the `rpmbuild` tool to customize specs for specific builds. This works
415 well for default macros that are gathered from the system automatically, like
416 `disttag` and `unitdir`.
417
418 However, once we needed to support multiple RPM builds at the same time, we
419 needed to either accept a large amount of logic duplication or use custom
420 macros to specialize a single spec file per-build. Custom macros work fine
421 for building locally, as they can be passed to `rpmbuild` as params from a
422 script like `build.sh` (as shown by past versions of this codebase). However,
423 once an SPRM is created and the spec file is packaged into it, it needs to
424 be uploaded to the CentOS Community Build System's Koji-based build system
425 to be built into a noarch RPM and hosted for distribution. The only way to
426 define custom macros in CBS builds is to create a second RPM to install a
427 macro definition file in the correct place on the build box. Maintaining a
428 second RPM is an unacceptable increase in complexity, and it's unclear if
429 Koji handles macro RPMs correctly anyway (potentially buggy, at least very
430 infrequently used).
431
432 Given this inability to define dynamic, custom macros in Koji-based builds,
433 but the need to extract variables to avoid manual duplication of a large
434 amount of spec file logic, a design that uses dynamic per-build data +
435 templates to build simi-static (only default macros) RPM spec files emerged.
436 The specifics (YAML, Python, JinJa2) were chosen because of their use in
437 other tools used by [Int/Pack][15], like Packer, Ansible and Puppet.
438
439
440 [1]: http://cbs.centos.org/koji/
441 [2]: https://trello.com/c/cgQmevT8/209-additional-access-to-centos-cbs
442 [3]: https://bugs.centos.org/
443 [4]: https://bugs.centos.org/view.php?id=8879
444 [5]: https://wiki.centos.org/HowTos/CommunityBuildSystem#head-00dad77f5720f3a984b0fac9f9bacac52047f73f
445 [6]: https://wiki.opendaylight.org/view/User:Dfarrell07
446 [7]: https://wiki.centos.org/HowTos/CommunityBuildSystem
447 [8]: https://bugs.centos.org/view.php?id=9472
448 [9]: http://cbs.centos.org/repos/
449 [10]: https://github.com/opendaylight/integration-packaging/tree/master/rpm/example_repo_configs
450 [11]: https://bugs.centos.org/view.php?id=9098#c23768
451 [12]: https://wiki.opendaylight.org/view/Simultaneous_Release:Helium_Release_Plan#Schedule
452 [13]: https://wiki.opendaylight.org/view/Simultaneous_Release:Lithium_Release_Plan#Schedule
453 [14]: https://wiki.opendaylight.org/view/Simultaneous_Release:Beryllium_Release_Plan#Schedule
454 [15]: https://wiki.opendaylight.org/view/Integration/Packaging
455 [16]: https://git.opendaylight.org/gerrit/gitweb?p=integration/packaging.git;a=tree;h=refs/heads/master;hb=refs/heads/master