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