1# Development <a id="development"></a> 2 3This chapter provides hints on Icinga 2 debugging, 4development, package builds and tests. 5 6* [Debug Icinga 2](21-development.md#development-debug) 7 * [GDB Backtrace](21-development.md#development-debug-gdb-backtrace) 8 * [Core Dump](21-development.md#development-debug-core-dump) 9* [Test Icinga 2](21-development.md#development-tests) 10 * [Snapshot Packages (Nightly Builds)](21-development.md#development-tests-snapshot-packages) 11* [Develop Icinga 2](21-development.md#development-develop) 12 * [Preparations](21-development.md#development-develop-prepare) 13 * [Design Patterns](21-development.md#development-develop-design-patterns) 14 * [Build Tools](21-development.md#development-develop-builds-tools) 15 * [Unit Tests](21-development.md#development-develop-tests) 16 * [Style Guide](21-development.md#development-develop-styleguide) 17* [Development Environment](21-development.md#development-environment) 18 * [Linux Dev Environment](21-development.md#development-linux-dev-env) 19 * [macOS Dev Environment](21-development.md#development-macos-dev-env) 20 * [Windows Dev Environment](21-development.md#development-windows-dev-env) 21* [Package Builds](21-development.md#development-package-builds) 22 * [RPM](21-development.md#development-package-builds-rpms) 23 * [DEB](21-development.md#development-package-builds-deb) 24 * [Windows](21-development.md#development-package-builds-windows) 25* [Continuous Integration](21-development.md#development-ci) 26* [Advanced Tips](21-development.md#development-advanced) 27 28<!-- mkdocs requires 4 spaces indent for nested lists: https://github.com/Python-Markdown/markdown/issues/3 --> 29 30## Debug Icinga 2 <a id="development-debug"></a> 31 32This chapter targets all users who have been asked by developers to provide 33a stack trace or coredump if the application crashed. It is also useful 34for developers working with different debuggers. 35 36> **Note:** 37> 38> This is intentionally mentioned before any development insights 39> as debugging is a more frequent and commonly asked question. 40 41### Debug Requirements <a id="debug-requirements"></a> 42 43Make sure that the debug symbols are available for Icinga 2. 44The Icinga 2 packages provide a debug package which must be 45installed separately for all involved binaries, like `icinga2-bin` 46or `icinga2-ido-mysql`. 47 48Distribution | Command 49-------------------|------------------------------------------ 50Debian/Ubuntu | `apt-get install icinga2-dbg` 51RHEL/CentOS | `yum install icinga2-debuginfo` 52Fedora | `dnf install icinga2-debuginfo icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo` 53SLES/openSUSE | `zypper install icinga2-bin-debuginfo icinga2-ido-mysql-debuginfo` 54 55Furthermore, you may also have to install debug symbols for Boost and your C++ library. 56 57If you're building your own binaries, you should use the `-DCMAKE_BUILD_TYPE=Debug` cmake 58build flag for debug builds. 59 60 61### GDB as Debugger <a id="development-debug-gdb"></a> 62 63Install GDB in your development environment. 64 65Distribution | Command 66-------------------|------------------------------------------ 67Debian/Ubuntu | `apt-get install gdb` 68RHEL/CentOS | `yum install gdb` 69Fedora | `dnf install gdb` 70SLES/openSUSE | `zypper install gdb` 71 72#### GDB Run <a id="development-debug-gdb-run"></a> 73 74Run the icinga2 binary `/usr/lib{,64}/icinga2/sbin/icinga2` with gdb, `/usr/bin/icinga2` is a shell wrapper. 75 76``` 77gdb --args /usr/lib/icinga2/sbin/icinga2 daemon 78 79(gdb) set follow-fork-mode child 80``` 81 82When gdb halts on SIGUSR2, press `c` to continue. This signal originates from the umbrella 83process and can safely be ignored. 84 85 86> **Note** 87> 88> Since v2.11 we would attach to the umbrella process spawned with `/usr/lib/icinga2/sbin/icinga2`, 89> therefore rather attach to a running process. 90> 91```bash 92# Typically the order of PIDs is: 1) umbrella 2) spawn helper 3) main process 93pidof icinga2 94 95gdb -p $(pidof icinga2 | cut -d ' ' -f3) 96``` 97 98> **Note** 99> 100> If gdb tells you it's missing debug symbols, quit gdb and install 101> them: `Missing separate debuginfos, use: debuginfo-install ...` 102 103Run/restart the application. 104 105``` 106(gdb) r 107``` 108 109Kill the running application. 110 111``` 112(gdb) k 113``` 114 115Continue after breakpoint. 116 117``` 118(gdb) c 119``` 120 121#### GDB Core Dump <a id="development-debug-gdb-coredump"></a> 122 123Either attach to the running process using `gdb -p PID` or start 124a new gdb run. 125 126``` 127(gdb) r 128(gdb) generate-core-file 129``` 130 131#### GDB Backtrace <a id="development-debug-gdb-backtrace"></a> 132 133If Icinga 2 aborted its operation abnormally, generate a backtrace. 134 135> **Note** 136> 137> Please install the [required debug symbols](21-development.md#debug-requirements) 138> prior to generating a backtrace. 139 140`thread apply all` is important here since this includes all running threads. 141We need this information when e.g. debugging dead locks and hanging features. 142 143``` 144(gdb) bt 145(gdb) thread apply all bt full 146``` 147 148If gdb stops at a SIGPIPE signal please disable the signal before 149running Icinga 2. This isn't an error, but we need to workaround it. 150 151``` 152(gdb) handle SIGPIPE nostop noprint pass 153(gdb) r 154``` 155 156If you create a [new issue](https://github.com/Icinga/icinga2/issues), 157make sure to attach as much detail as possible. 158 159#### GDB Backtrace from Running Process <a id="development-debug-gdb-backtrace-running"></a> 160 161If Icinga 2 is still running, generate a full backtrace from the running 162process and store it into a new file (e.g. for debugging dead locks). 163 164> **Note** 165> 166> Please install the [required debug symbols](21-development.md#debug-requirements) 167> prior to generating a backtrace. 168 169Icinga 2 runs with 2 processes: main and command executor, therefore generate two backtrace logs 170and add them to the GitHub issue. 171 172```bash 173for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "thread apply all bt full" -ex "detach" -ex "q" > gdb_bt_${pid}_`date +%s`.log; done 174``` 175 176#### GDB Thread List from Running Process <a id="development-debug-gdb-thread-list-running"></a> 177 178Instead of a full backtrace, you sometimes just need a list of running threads. 179 180```bash 181for pid in $(pidof icinga2); do gdb -p $pid -batch -ex "info threads" -ex "detach" -ex "q" > gdb_threads_${pid}_`date +%s`.log; done 182``` 183 184#### GDB Backtrace Stepping <a id="development-debug-gdb-backtrace-stepping"></a> 185 186Identifying the problem may require stepping into the backtrace, analysing 187the current scope, attributes, and possible unmet requirements. `p` prints 188the value of the selected variable or function call result. 189 190``` 191(gdb) up 192(gdb) down 193(gdb) p checkable 194(gdb) p checkable.px->m_Name 195``` 196 197#### GDB Breakpoints <a id="development-debug-gdb-breakpoint"></a> 198 199To set a breakpoint to a specific function call, or file specific line. 200 201``` 202(gdb) b checkable.cpp:125 203(gdb) b icinga::Checkable::SetEnablePerfdata 204``` 205 206GDB will ask about loading the required symbols later, select `yes` instead 207of `no`. 208 209Then run Icinga 2 until it reaches the first breakpoint. Continue with `c` 210afterwards. 211 212``` 213(gdb) run 214(gdb) c 215``` 216 217In case you want to step into the next line of code, use `n`. If there is a 218function call where you want to step into, use `s`. 219 220``` 221(gdb) n 222 223(gdb) s 224``` 225 226If you want to delete all breakpoints, use `d` and select `yes`. 227 228``` 229(gdb) d 230``` 231 232> **Tip** 233> 234> When debugging exceptions, set your breakpoint like this: `b __cxa_throw`. 235 236Breakpoint Example: 237 238``` 239(gdb) b __cxa_throw 240(gdb) r 241(gdb) up 242.... 243(gdb) up 244#11 0x00007ffff7cbf9ff in icinga::Utility::GlobRecursive(icinga::String const&, icinga::String const&, boost::function<void (icinga::String const&)> const&, int) (path=..., pattern=..., callback=..., type=1) 245 at /home/michi/coding/icinga/icinga2/lib/base/utility.cpp:609 246609 callback(cpath); 247(gdb) l 248604 249605 #endif /* _WIN32 */ 250606 251607 std::sort(files.begin(), files.end()); 252608 BOOST_FOREACH(const String& cpath, files) { 253609 callback(cpath); 254610 } 255611 256612 std::sort(dirs.begin(), dirs.end()); 257613 BOOST_FOREACH(const String& cpath, dirs) { 258(gdb) p files 259$3 = std::vector of length 11, capacity 16 = {{static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/agent.conf"}, {static NPos = 18446744073709551615, 260 m_Data = "/etc/icinga2/conf.d/commands.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/downtimes.conf"}, {static NPos = 18446744073709551615, 261 m_Data = "/etc/icinga2/conf.d/groups.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/notifications.conf"}, {static NPos = 18446744073709551615, 262 m_Data = "/etc/icinga2/conf.d/satellite.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/services.conf"}, {static NPos = 18446744073709551615, 263 m_Data = "/etc/icinga2/conf.d/templates.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/test.conf"}, {static NPos = 18446744073709551615, 264 m_Data = "/etc/icinga2/conf.d/timeperiods.conf"}, {static NPos = 18446744073709551615, m_Data = "/etc/icinga2/conf.d/users.conf"}} 265``` 266 267 268### Core Dump <a id="development-debug-core-dump"></a> 269 270When the Icinga 2 daemon crashes with a `SIGSEGV` signal 271a core dump file should be written. This will help 272developers to analyze and fix the problem. 273 274#### Core Dump File Size Limit <a id="development-debug-core-dump-limit"></a> 275 276This requires setting the core dump file size to `unlimited`. 277 278 279##### Systemd 280 281``` 282systemctl edit icinga2.service 283 284[Service] 285... 286LimitCORE=infinity 287 288systemctl daemon-reload 289 290systemctl restart icinga2 291``` 292 293##### Init Script 294 295``` 296vim /etc/init.d/icinga2 297... 298ulimit -c unlimited 299 300service icinga2 restart 301``` 302 303##### Verify 304 305Verify that the Icinga 2 process core file size limit is set to `unlimited`. 306 307``` 308for pid in $(pidof icinga2); do cat /proc/$pid/limits; done 309 310... 311Max core file size unlimited unlimited bytes 312``` 313 314 315#### Core Dump Kernel Format <a id="development-debug-core-dump-format"></a> 316 317The Icinga 2 daemon runs with the SUID bit set. Therefore you need 318to explicitly enable core dumps for SUID on Linux. 319 320```bash 321sysctl -w fs.suid_dumpable=2 322``` 323 324Adjust the coredump kernel format and file location on Linux: 325 326```bash 327sysctl -w kernel.core_pattern=/var/lib/cores/core.%e.%p 328 329install -m 1777 -d /var/lib/cores 330``` 331 332MacOS: 333 334```bash 335sysctl -w kern.corefile=/cores/core.%P 336 337chmod 777 /cores 338``` 339 340#### Core Dump Analysis <a id="development-debug-core-dump-analysis"></a> 341 342Once Icinga 2 crashes again a new coredump file will be written. Please 343attach this file to your bug report in addition to the general details. 344 345Simple test case for a `SIGSEGV` simulation with `sleep`: 346 347``` 348ulimit -c unlimited 349sleep 1800& 350[1] <PID> 351kill -SEGV <PID> 352gdb `which sleep` /var/lib/cores/core.sleep.<PID> 353(gdb) bt 354rm /var/lib/cores/core.sleep.* 355``` 356 357Analyzing Icinga 2: 358 359``` 360gdb /usr/lib64/icinga2/sbin/icinga2 core.icinga2.<PID> 361(gdb) bt 362``` 363 364### LLDB as Debugger <a id="development-debug-lldb"></a> 365 366LLDB is available on macOS with the Xcode command line tools. 367 368```bash 369xcode-select --install 370``` 371 372In order to run Icinga 2 with LLDB you need to pass the binary as argument. 373Since v2.11 we would attach to the umbrella process, therefore rather 374attach to a running process. 375 376```bash 377# Typically the order of PIDs is: 1) umbrella 2) spawn helper 3) main process 378pidof icinga2 379 380lldb -p $(pidof icinga2 | cut -d ' ' -f3) 381``` 382 383In case you'll need to attach to the main process immediately, you can delay 384the forked child process and attach to the printed PID. 385 386``` 387$ icinga2 daemon -DInternal.DebugWorkerDelay=120 388Closed FD 6 which we inherited from our parent process. 389[2020-01-29 12:22:33 +0100] information/cli: Icinga application loader (version: v2.11.0-477-gfe8701d77; debug) 390[2020-01-29 12:22:33 +0100] information/RunWorker: DEBUG: Current PID: 85253. Sleeping for 120 seconds to allow lldb/gdb -p <PID> attachment. 391``` 392 393```bash 394lldb -p 85253 395``` 396 397When lldb halts on SIGUSR2, press `c` to continue. This signal originates from the umbrella 398process and can safely be ignored. 399 400 401Breakpoint: 402 403``` 404> b checkable.cpp:57 405> b icinga::Checkable::ProcessCheckResult 406``` 407 408Full backtrace: 409 410``` 411> bt all 412``` 413 414Select thread: 415 416``` 417> thr sel 5 418``` 419 420Step into: 421 422``` 423> s 424``` 425 426Next step: 427 428``` 429> n 430``` 431 432Continue: 433 434``` 435> c 436``` 437 438Up/down in stacktrace: 439 440``` 441> up 442> down 443``` 444 445 446### Debug on Windows <a id="development-debug-windows"></a> 447 448 449Whenever the application crashes, the Windows error reporting (WER) can be [configured](https://docs.microsoft.com/en-gb/windows/win32/wer/collecting-user-mode-dumps) 450to create user-mode dumps. 451 452 453Tail the log file with Powershell: 454 455``` 456Get-Content .\icinga2.log -tail 10 -wait 457``` 458 459 460#### Debug on Windows: Dependencies <a id="development-debug-windows-dependencies"></a> 461 462Similar to `ldd` or `nm` on Linux/Unix. 463 464Extract the dependent DLLs from a binary with Visual Studio's `dumpbin` tool 465in Powershell: 466 467``` 468C:> &'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\bin\Hostx64\x64\dumpbin.exe' /dependents .\debug\Bin\Debug\Debug\boosttest-test-base.exe 469DEBUG: 1+ >>>> &'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\bin\Hostx64\x64\dumpbin.exe' /dependents .\debug\Bin\Debug\Debug\boosttest-test-base.exe 470Microsoft (R) COFF/PE Dumper Version 14.22.27905.0 471Copyright (C) Microsoft Corporation. All rights reserved. 472 473 474Dump of file .\debug\Bin\Debug\Debug\boosttest-test-base.exe 475 476File Type: EXECUTABLE IMAGE 477 478 Image has the following dependencies: 479 480 boost_coroutine-vc142-mt-gd-x64-1_76.dll 481 boost_date_time-vc142-mt-gd-x64-1_76.dll 482 boost_filesystem-vc142-mt-gd-x64-1_76.dll 483 boost_thread-vc142-mt-gd-x64-1_76.dll 484 boost_regex-vc142-mt-gd-x64-1_76.dll 485 libssl-1_1-x64.dll 486 libcrypto-1_1-x64.dll 487 WS2_32.dll 488 dbghelp.dll 489 SHLWAPI.dll 490 msi.dll 491 boost_unit_test_framework-vc142-mt-gd-x64-1_76.dll 492 KERNEL32.dll 493 SHELL32.dll 494 ADVAPI32.dll 495 MSVCP140D.dll 496 MSWSOCK.dll 497 bcrypt.dll 498 VCRUNTIME140D.dll 499 ucrtbased.dll 500 501 Summary 502 503 1000 .00cfg 504 68000 .data 505 B000 .idata 506 148000 .pdata 507 69C000 .rdata 508 25000 .reloc 509 1000 .rsrc 510 E7A000 .text 511 1000 .tls 512``` 513 514 515## Test Icinga 2 <a id="development-tests"></a> 516 517### Snapshot Packages (Nightly Builds) <a id="development-tests-snapshot-packages"></a> 518 519Icinga provides snapshot packages as nightly builds from [Git master](https://github.com/icinga/icinga2). 520 521These packages contain development code which should be considered "work in progress". 522While developers ensure that tests are running fine with CI actions on PRs, 523things might break, or changes are not yet documented in the changelog. 524 525You can help the developers and test the snapshot packages, e.g. when larger 526changes or rewrites are taking place for a new major version. Your feedback 527is very much appreciated. 528 529Snapshot packages are available for all supported platforms including 530Linux and Windows and can be obtained from [https://packages.icinga.com](https://packages.icinga.com). 531 532The [Vagrant boxes](https://github.com/Icinga/icinga-vagrant) also use 533the Icinga snapshot packages to allow easier integration tests. It is also 534possible to use Docker with base OS images and installing the snapshot 535packages. 536 537If you encounter a problem, please [open a new issue](https://github.com/Icinga/icinga2/issues/new/choose) 538on GitHub and mention that you're testing the snapshot packages. 539 540#### RHEL/CentOS <a id="development-tests-snapshot-packages-rhel"></a> 541 5422.11+ requires the [EPEL repository](02-installation.md#package-repositories-rhel-epel) for Boost 1.66+. 543 544In addition to that, the `icinga-rpm-release` package already provides the `icinga-snapshot-builds` 545repository but it is disabled by default. 546 547```bash 548yum -y install https://packages.icinga.com/epel/icinga-rpm-release-7-latest.noarch.rpm 549yum -y install epel-release 550yum makecache 551 552yum install --enablerepo=icinga-snapshot-builds icinga2 553``` 554 555#### Debian <a id="development-tests-snapshot-packages-debian"></a> 556 5572.11+ requires Boost 1.66+ which either is provided by the OS, backports or Icinga stable repositories. 558It is advised to configure both Icinga repositories, stable and snapshot and selectively 559choose the repository with the `-t` flag on `apt-get install`. 560 561```bash 562apt-get update 563apt-get -y install apt-transport-https wget gnupg 564 565wget -O - https://packages.icinga.com/icinga.key | apt-key add - 566 567DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \ 568 echo "deb https://packages.icinga.com/debian icinga-${DIST} main" > \ 569 /etc/apt/sources.list.d/${DIST}-icinga.list 570 echo "deb-src https://packages.icinga.com/debian icinga-${DIST} main" >> \ 571 /etc/apt/sources.list.d/${DIST}-icinga.list 572 573DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \ 574 echo "deb http://packages.icinga.com/debian icinga-${DIST}-snapshots main" > \ 575 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list 576 echo "deb-src http://packages.icinga.com/debian icinga-${DIST}-snapshots main" >> \ 577 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list 578 579apt-get update 580``` 581 582On Debian Stretch, you'll also need to add Debian Backports. 583 584```bash 585DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \ 586 echo "deb https://deb.debian.org/debian ${DIST}-backports main" > \ 587 /etc/apt/sources.list.d/${DIST}-backports.list 588 589apt-get update 590``` 591 592Then install the snapshot packages. 593 594```bash 595DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \ 596apt-get install -t icinga-${DIST}-snapshots icinga2 597``` 598 599#### Ubuntu <a id="development-tests-snapshot-packages-ubuntu"></a> 600 601```bash 602apt-get update 603apt-get -y install apt-transport-https wget gnupg 604 605wget -O - https://packages.icinga.com/icinga.key | apt-key add - 606 607. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \ 608 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST} main" > \ 609 /etc/apt/sources.list.d/${DIST}-icinga.list 610 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST} main" >> \ 611 /etc/apt/sources.list.d/${DIST}-icinga.list 612 613. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \ 614 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST}-snapshots main" > \ 615 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list 616 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST}-snapshots main" >> \ 617 /etc/apt/sources.list.d/${DIST}-icinga-snapshots.list 618 619apt-get update 620``` 621 622Then install the snapshot packages. 623 624```bash 625. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \ 626apt-get install -t icinga-${DIST}-snapshots icinga2 627``` 628 629#### SLES <a id="development-tests-snapshot-packages-sles"></a> 630 631The required Boost packages are provided with the stable release repository. 632 633```bash 634rpm --import https://packages.icinga.com/icinga.key 635 636zypper ar https://packages.icinga.com/SUSE/ICINGA-release.repo 637zypper ref 638 639zypper ar https://packages.icinga.com/SUSE/ICINGA-snapshot.repo 640zypper ref 641``` 642 643Selectively install the snapshot packages using the `-r` parameter. 644 645```bash 646zypper in -r icinga-snapshot-builds icinga2 647``` 648 649 650### Unit Tests <a id="development-tests-unit"></a> 651 652Build the binaries and run the tests. 653 654 655```bash 656make -j4 -C debug 657make test -C debug 658``` 659 660Run a specific boost test: 661 662```bash 663debug/Bin/Debug/boosttest-test-base --run_test=remote_url 664``` 665 666 667 668## Develop Icinga 2 <a id="development-develop"></a> 669 670Icinga 2 can be built on many platforms such as Linux, Unix and Windows. 671There are limitations in terms of support, e.g. Windows is only supported for agents, 672not a full-featured master or satellite. 673 674Before you start with actual development, there is a couple of pre-requisites. 675 676### Preparations <a id="development-develop-prepare"></a> 677 678#### Choose your Editor <a id="development-develop-choose-editor"></a> 679 680Icinga 2 can be developed with your favorite editor. Icinga developers prefer 681these tools: 682 683- vim 684- CLion (macOS, Linux) 685- MS Visual Studio (Windows) 686- Atom 687 688Editors differ on the functionality. The more helpers you get for C++ development, 689the faster your development workflow will be. 690 691#### Get to know the architecture <a id="development-develop-get-to-know-the-architecture"></a> 692 693Icinga 2 can run standalone or in distributed environments. It contains a whole lot 694more than a simple check execution engine. 695 696Read more about it in the [Technical Concepts](19-technical-concepts.md#technical-concepts) chapter. 697 698#### Get to know the code <a id="development-develop-get-to-know-the-code"></a> 699 700First off, you really need to know C++ and portions of C++11 and the boost libraries. 701Best is to start with a book or online tutorial to get into the basics. 702Icinga developers gained their knowledge through studies, training and self-teaching 703code by trying it out and asking senior developers for guidance. 704 705Here's a few books we can recommend: 706 707* [Accelerated C++: Practical Programming by Example](https://www.amazon.com/Accelerated-C-Practical-Programming-Example/dp/020170353X) (Andrew Koenig, Barbara E. Moo) 708* [Effective C++](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876) (Scott Meyers) 709* [Boost C++ Application Development Cookbook - Second Edition: Recipes to simplify your application development](https://www.amazon.com/dp/1787282244/ref=cm_sw_em_r_mt_dp_U_dN1OCbERS00EQ) (Antony Polukhin) 710* [Der C++ Programmierer](https://www.amazon.de/Programmierer-lernen-Professionell-anwenden-L%C3%B6sungen/dp/3446416447), German (Ulrich Breymann) 711* [C++11 programmieren](https://www.amazon.de/gp/product/3836217325/), German (Torsten T. Will) 712 713In addition, it is a good bet to also know SQL when diving into backend development. 714 715* [SQL Performance Explained](https://www.amazon.de/gp/product/3950307826/) (Markus Winand) 716 717Last but not least, if you are developing on Windows, get to know the internals about services and the Win32 API. 718 719### Design Patterns <a id="development-develop-design-patterns"></a> 720 721Icinga 2 heavily relies on object-oriented programming and encapsulates common 722functionality into classes and objects. It also uses modern programming techniques 723to e.g. work with shared pointer memory management. 724 725Icinga 2 consists of libraries bundled into the main binary. Therefore you'll 726find many code parts in the `lib/` directory wheras the actual application is 727built from `icinga-app/`. Accompanied with Icinga 2, there's the Windows plugins 728which are standalone and compiled from `plugins/`. 729 730Library | Description 731---------------|------------------------------------ 732base | Objects, values, types, streams, tockets, TLS, utilities, etc. 733config | Configuration compiler, expressions, etc. 734cli | CLI (sub) commands and helpers. 735icinga | Icinga specific objects and event handling. 736remote | Cluster and HTTP client/server and REST API related code. 737checker | Checker feature, check scheduler. 738notification | Notification feature, notification scheduler. 739methods | Command execution methods, plugins and built-in checks. 740perfdata | Performance data related, including Graphite, Elastic, etc. 741db\_ido | IDO database abstraction layer. 742db\_ido\_mysql | IDO database driver for MySQL. 743db\_ido\_pgsql | IDO database driver for PgSQL. 744mysql\_shin | Library stub for linking against the MySQL client libraries. 745pgsql\_shim | Library stub for linking against the PgSQL client libraries. 746 747#### Class Compiler <a id="development-develop-design-patterns-class-compiler"></a> 748 749Another thing you will recognize are the `.ti` files which are compiled 750by our own class compiler into actual source code. The meta language allows 751developers to easily add object attributes and specify their behaviour. 752 753Some object attributes need to be stored over restarts in the state file 754and therefore have the `state` attribute set. Others are treated as `config` 755attribute and automatically get configuration validation functions created. 756Hidden or read-only REST API attributes are marked with `no_user_view` and 757`no_user_modify`. 758 759The most beneficial thing are getters and setters being generated. The actual object 760inherits from `ObjectImpl<TYPE>` and therefore gets them "for free". 761 762Example: 763 764``` 765vim lib/perfdata/gelfwriter.ti 766 767 [config] enable_tls; 768 769vim lib/perfdata/gelfwriter.cpp 770 771 if (GetEnableTls()) { 772``` 773 774The logic is hidden in `tools/mkclass/` in case you want to learn more about it. 775The first steps during CMake & make also tell you about code generation. 776 777### Build Tools <a id="development-develop-builds-tools"></a> 778 779#### CMake <a id="development-develop-builds-cmake"></a> 780 781In its early development stages in 2012, Icinga 2 was built with autoconf/automake 782and separate Windows project files. We've found this very fragile, and have changed 783this into CMake as our build tool. 784 785The most common benefits: 786 787* Everything is described in CMakeLists.txt in each directory 788* CMake only needs to know that a sub directory needs to be included. 789* The global CMakeLists.txt acts as main entry point for requirement checks and library/header includes. 790* Separate binary build directories, the actual source tree stays clean. 791* CMake automatically generates a Visual Studio project file `icinga2.sln` on Windows. 792 793#### Unity Builds <a id="development-develop-builds-unity-builds"></a> 794 795Another thing you should be aware of: Unity builds on and off. 796 797Typically, we already use caching mechanisms to reduce recompile time with ccache. 798For release builds, there's always a new build needed as the difference is huge compared 799to a previous (major) release. 800 801Therefore we've invented the Unity builds, which basically concatenates all source files 802into one big library source code file. The compiler then doesn't need to load the many small 803files but compiles and links this huge one. 804 805Unity builds require more memory which is why you should disable them for development 806builds in small sized VMs (Linux, Windows) and also Docker containers. 807 808There's a couple of header files which are included everywhere. If you touch/edit them, 809the cache is invalidated and you need to recompile a lot more files then. `base/utility.hpp` 810and `remote/zone.hpp` are good candidates for this. 811 812### Unit Tests <a id="development-develop-tests"></a> 813 814New functions and classes must implement new unit tests. Whenever 815you decide to add new functions, ensure that you don't need a complex 816mock or runtime attributes in order to test them. Better isolate 817code into function interfaces which can be invoked in the Boost tests 818framework. 819 820Look into the existing tests in the [test/](https://github.com/Icinga/icinga2/tree/master/test) directory 821and adopt new test cases. 822 823Specific tests require special time windows, they are only 824enabled in debug builds for developers. This is the case e.g. 825for testing the flapping algorithm with expected state change 826detection at a specific point from now. 827 828 829### Style Guide <a id="development-develop-styleguide"></a> 830 831Overview of project files: 832 833File Type | File Name/Extension | Description 834---------------|---------------------|----------------------------- 835Header | .hpp | Classes, enums, typedefs inside the icinga Namespace. 836Source | .cpp | Method implementation for class functions, static/global variables. 837CMake | CMakeLists.txt | Build configuration, source and header file references. 838CMake Source | .cmake | Source/Header files generated from CMake placeholders. 839ITL/conf.d | .conf | Template library and example files as configuration 840Class Compiler | .ti | Object classes in our own language, generates source code as `<filename>-ti.{c,h}pp`. 841Lexer/Parser | .ll, .yy | Flex/Bison code generated into source code from CMake builds. 842Docs | .md | Markdown docs and READMEs. 843 844Anything else are additional tools and scripts for developers and build systems. 845 846All files must include the copyright header. We don't use the 847current year as this implies yearly updates we don't want. 848 849Depending on the file type, this must be a comment. 850 851```cpp 852/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ 853``` 854 855```bash 856# Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ 857``` 858 859#### Code Formatting <a id="development-develop-code-formatting"></a> 860 861**Tabs instead of spaces.** Inside Visual Studio, choose to keep tabs instead of 862spaces. Tabs should use 4 spaces indent by default, depending on your likings. 863 864We follow the clang format, with some exceptions. 865 866- Curly braces for functions and classes always start at a new line. 867 868```cpp 869String ConfigObjectUtility::EscapeName(const String& name) 870{ 871//... 872} 873 874String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName, 875 bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs) 876{ 877//... 878} 879``` 880 881- Too long lines break at a parameter, the new line needs a tab indent. 882 883```cpp 884 static String CreateObjectConfig(const Type::Ptr& type, const String& fullName, 885 bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs); 886``` 887 888- Conditions require curly braces if it is not a single if with just one line. 889 890 891```cpp 892 if (s == "OK") { 893 //... 894 } else { 895 //... 896 } 897 898 if (!n) 899 return; 900``` 901 902- There's a space between `if` and the opening brace `(`. Also after the closing brace `)` and opening curly brace `{`. 903- Negation with `!` doesn't need an extra space. 904- Else branches always start in the same line after the closing curly brace. 905 906 907#### Code Comments <a id="development-develop-code-comments"></a> 908 909Add comments wherever you think that another developer will have a hard 910time to understand the complex algorithm. Or you might have forgotten 911it in a year and struggle again. Also use comments to highlight specific 912stages in a function. Generally speaking, make things easier for the 913team and external contributors. 914 915Comments can also be used to mark additional references and TODOs. 916If there is a specific GitHub issue or discussion going on, 917use that information as a summary and link over to it on purpose. 918 919- Single line comments may use `//` or `/* ... */` 920- Multi line comments must use this format: 921 922```cpp 923/* Ensure to check for XY 924 * This relies on the fact that ABC has been set before. 925 */ 926``` 927 928#### Function Docs <a id="development-develop-function-docs"></a> 929 930Function header documentation must be added. The current code basis 931needs rework, future functions must provide this. 932 933Editors like CLion or Visual Studio allow you to type `/**` followed 934by Enter and generate the skeleton from the implemented function. 935 936Add a short summary in the first line about the function's purpose. 937Edit the param section with short description on their intention. 938The `return` value should describe the value type and additional details. 939 940Example: 941 942```cpp 943/** 944 * Reads a message from the connected peer. 945 * 946 * @param stream ASIO TLS Stream 947 * @param yc Yield Context for ASIO 948 * @param maxMessageLength maximum size of bytes read. 949 * 950 * @return A JSON string 951 */ 952String JsonRpc::ReadMessage(const std::shared_ptr<AsioTlsStream>& stream, boost::asio::yield_context yc, ssize_t maxMessageLength) 953``` 954 955While we can generate code docs from it, the main idea behind it is 956to provide on-point docs to fully understand all parameters and the 957function's purpose in the same spot. 958 959 960#### Header <a id="development-develop-styleguide-header"></a> 961 962Only include other headers which are mandatory for the header definitions. 963If the source file requires additional headers, add them there to avoid 964include loops. 965 966The included header order is important. 967 968- First, include the library header `i2-<libraryname>.hpp`, e.g. `i2-base.hpp`. 969- Second, include all headers from Icinga itself, e.g. `remote/apilistener.hpp`. `base` before `icinga` before `remote`, etc. 970- Third, include third-party and external library headers, e.g. openssl and boost. 971- Fourth, include STL headers. 972 973#### Source <a id="development-develop-styleguide-source"></a> 974 975The included header order is important. 976 977- First, include the header whose methods are implemented. 978- Second, include all headers from Icinga itself, e.g. `remote/apilistener.hpp`. `base` before `icinga` before `remote`, etc. 979- Third, include third-party and external library headers, e.g. openssl and boost. 980- Fourth, include STL headers. 981 982Always use an empty line after the header include parts. 983 984#### Namespace <a id="development-develop-styleguide-namespace"></a> 985 986The icinga namespace is used globally, as otherwise we would need to write `icinga::Utility::FormatDateTime()`. 987 988```cpp 989using namespace icinga; 990``` 991 992Other namespaces must be declared in the scope they are used. Typically 993this is inside the function where `boost::asio` and variants would 994complicate the code. 995 996```cpp 997 namespace ssl = boost::asio::ssl; 998 999 auto context (std::make_shared<ssl::context>(ssl::context::sslv23)); 1000``` 1001 1002#### Functions <a id="development-develop-styleguide-functions"></a> 1003 1004Ensure to pass values and pointers as const reference. By default, all 1005values will be copied into the function scope, and we want to avoid this 1006wherever possible. 1007 1008```cpp 1009std::vector<EventQueue::Ptr> EventQueue::GetQueuesForType(const String& type) 1010``` 1011 1012C++ only allows to return a single value. This can be abstracted with 1013returning a specific class object, or with using a map/set. Array and 1014Dictionary objects increase the memory footprint, use them only where needed. 1015 1016A common use case for Icinga value types is where a function can return 1017different values - an object, an array, a boolean, etc. This happens in the 1018inner parts of the config compiler expressions, or config validation. 1019 1020The function caller is responsible to determine the correct value type 1021and handle possible errors. 1022 1023Specific algorithms may require to populate a list, which can be passed 1024by reference to the function. The inner function can then append values. 1025Do not use a global shared resource here, unless this is locked by the caller. 1026 1027 1028#### Conditions and Cases <a id="development-develop-styleguide-conditions"></a> 1029 1030Prefer if-else-if-else branches. When integers are involved, 1031switch-case statements increase readability. Don't forget about `break` though! 1032 1033Avoid using ternary operators where possible. Putting a condition 1034after an assignment complicates reading the source. The compiler 1035optimizes this anyways. 1036 1037Wrong: 1038 1039```cpp 1040 int res = s == "OK" ? 0 : s == "WARNING" ? 1; 1041 1042 return res; 1043``` 1044 1045Better: 1046 1047```cpp 1048 int res = 3; 1049 1050 if (s == "OK") { 1051 res = 0; 1052 } else if (s == "WARNING") { 1053 res = 1; 1054 } 1055``` 1056 1057Even better: Create a lookup map instead of if branches. The complexity 1058is reduced to O(log(n)). 1059 1060```cpp 1061 std::map<String, unsigned int> stateMap = { 1062 { "OK", 1 }, 1063 { "WARNING", 2 } 1064 } 1065 1066 auto it = stateMap.find(s); 1067 1068 if (it == stateMap.end()) { 1069 return 3 1070 } 1071 1072 return it.second; 1073``` 1074 1075The code is not as short as with a ternary operator, but one can re-use 1076this design pattern for other generic definitions with e.g. moving the 1077lookup into a utility class. 1078 1079Once a unit test is written, everything works as expected in the future. 1080 1081#### Locks and Guards <a id="development-develop-locks-guards"></a> 1082 1083Lock access to resources where multiple threads can read and write. 1084Icinga objects can be locked with the `ObjectLock` class. 1085 1086Object locks and guards must be limited to the scope where they are needed. Otherwise we could create dead locks. 1087 1088```cpp 1089 { 1090 ObjectLock olock(frame.Locals); 1091 for (const Dictionary::Pair& kv : frame.Locals) { 1092 AddSuggestion(matches, word, kv.first); 1093 } 1094 } 1095``` 1096 1097#### Objects and Pointers <a id="development-develop-objects-pointers"></a> 1098 1099Use shared pointers for objects. Icinga objects implement the `Ptr` 1100typedef returning an `intrusive_ptr` for the class object (object.hpp). 1101This also ensures reference counting for the object's lifetime. 1102 1103Use raw pointers with care! 1104 1105Some methods and classes require specific shared pointers, especially 1106when interacting with the Boost library. 1107 1108#### Value Types <a id="development-develop-styleguide-value-types"></a> 1109 1110Icinga has its own value types. These provide methods to allow 1111generic serialization into JSON for example, and other type methods 1112which are made available in the DSL too. 1113 1114- Always use `String` instead of `std::string`. If you need a C-string, use the `CStr()` method. 1115- Avoid casts and rather use the `Convert` class methods. 1116 1117```cpp 1118 double s = static_cast<double>(v); //Wrong 1119 1120 double s = Convert::ToDouble(v); //Correct, ToDouble also provides overloads with different value types 1121``` 1122 1123- Prefer STL containers for internal non-user interfaces. Icinga value types add a small overhead which may decrease performance if e.g. the function is called 100k times. 1124- `Array::FromVector` and variants implement conversions, use them. 1125 1126#### Utilities <a id="development-develop-styleguide-utilities"></a> 1127 1128Don't re-invent the wheel. The `Utility` class provides 1129many helper functions which allow you e.g. to format unix timestamps, 1130search in filesystem paths. 1131 1132Also inspect the Icinga objects, they also provide helper functions 1133for formatting, splitting strings, joining arrays into strings, etc. 1134 1135#### Libraries <a id="development-develop-styleguide-libraries"></a> 1136 11372.11 depends on [Boost 1.66](https://www.boost.org/doc/libs/1_66_0/). 1138Use the existing libraries and header-only includes 1139for this specific version. 1140 1141Note: Prefer C++11 features where possible, e.g. std::atomic and lambda functions. 1142 1143General: 1144 1145- [exception](https://www.boost.org/doc/libs/1_66_0/libs/exception/doc/boost-exception.html) (header only) 1146- [algorithm](https://www.boost.org/doc/libs/1_66_0/libs/algorithm/doc/html/index.html) (header only) 1147- [lexical_cast](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_lexical_cast.html) (header only) 1148- [regex](https://www.boost.org/doc/libs/1_66_0/libs/regex/doc/html/index.html) 1149- [uuid](https://www.boost.org/doc/libs/1_66_0/libs/uuid/doc/uuid.html) (header only) 1150- [range](https://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/index.html) (header only) 1151- [variant](https://www.boost.org/doc/libs/1_66_0/doc/html/variant.html) (header only) 1152- [multi_index](https://www.boost.org/doc/libs/1_66_0/libs/multi_index/doc/index.html) (header only) 1153- [function_types](https://www.boost.org/doc/libs/1_66_0/libs/function_types/doc/html/index.html) (header only) 1154- [circular_buffer](https://www.boost.org/doc/libs/1_66_0/doc/html/circular_buffer.html) (header only) 1155- [math](https://www.boost.org/doc/libs/1_66_0/libs/math/doc/html/index.html) (header only) 1156- [stacktrace](https://www.boost.org/doc/libs/1_66_0/doc/html/stacktrace.html) (header only) 1157 1158Events and Runtime: 1159 1160- [system](https://www.boost.org/doc/libs/1_66_0/libs/system/doc/index.html) 1161- [thread](https://www.boost.org/doc/libs/1_66_0/doc/html/thread.html) 1162- [signals2](https://www.boost.org/doc/libs/1_66_0/doc/html/signals2.html) (header only) 1163- [program_options](https://www.boost.org/doc/libs/1_66_0/doc/html/program_options.html) 1164- [date_time](https://www.boost.org/doc/libs/1_66_0/doc/html/date_time.html) 1165- [filesystem](https://www.boost.org/doc/libs/1_66_0/libs/filesystem/doc/index.htm) 1166 1167Network I/O: 1168 1169- [asio](https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio.html) (header only) 1170- [beast](https://www.boost.org/doc/libs/1_66_0/libs/beast/doc/html/index.html) (header only) 1171- [coroutine](https://www.boost.org/doc/libs/1_66_0/libs/coroutine/doc/html/index.html) 1172- [context](https://www.boost.org/doc/libs/1_66_0/libs/context/doc/html/index.html) 1173 1174Consider abstracting their usage into `*utility.{c,h}pp` files with 1175wrapping existing Icinga types. That also allows later changes without 1176rewriting large code parts. 1177 1178> **Note** 1179> 1180> A new Boost library should be explained in a PR and discussed with the team. 1181> 1182> This requires package dependency changes. 1183 1184If you consider an external library or code to be included with Icinga, the following 1185requirements must be fulfilled: 1186 1187- License is compatible with GPLv2+. Boost license, MIT works, Apache is not. 1188- C++11 is supported, C++14 or later doesn't work 1189- Header only implementations are preferred, external libraries require packages on every distribution. 1190- No additional frameworks, Boost is the only allowed. 1191- The code is proven to be robust and the GitHub repository is alive, or has 1k+ stars. Good libraries also provide a user list, if e.g. Ceph is using it, this is a good candidate. 1192 1193 1194#### Log <a id="development-develop-styleguide-log"></a> 1195 1196Icinga allows the user to configure logging backends, e.g. syslog or file. 1197 1198Any log message inside the code must use the `Log()` function. 1199 1200- The first parameter is the severity level, use them with care. 1201- The second parameter defines the location/scope where the log 1202happened. Typically we use the class name here, to better analyse 1203the logs the user provide in GitHub issues and on the community 1204channels. 1205- The third parameter takes a log message string 1206 1207If the message string needs to be computed from existing values, 1208everything must be converted to the String type beforehand. 1209This conversion for every value is very expensive which is why 1210we try to avoid it. 1211 1212Instead, use Log() with the shift operator where everything is written 1213on the stream and conversions are explicitly done with templates 1214in the background. 1215 1216The trick here is that the Log object is destroyed immediately 1217after being constructed once. The destructor actually 1218evaluates the values and sends it to registers loggers. 1219 1220Since flushing the stream every time a log entry occurs is 1221very expensive, a timer takes care of flushing the stream 1222every second. 1223 1224> **Tip** 1225> 1226> If logging stopped, the flush timer thread may be dead. 1227> Inspect that with gdb/lldb. 1228 1229Avoid log messages which could irritate the user. During 1230implementation, developers can change log levels to better 1231see what's going one, but remember to change this back to `debug` 1232or remove it entirely. 1233 1234 1235#### Goto <a id="development-develop-styleguide-goto"></a> 1236 1237Avoid using `goto` statements. There are rare occasions where 1238they are allowed: 1239 1240- The code would become overly complicated within nested loops and conditions. 1241- Event processing and C interfaces. 1242- Question/Answer loops within interactive CLI commands. 1243 1244#### Typedef and Auto Keywords <a id="development-develop-styleguide-typedef-auto"></a> 1245 1246Typedefs allow developers to use shorter names for specific types, 1247classes and structs. 1248 1249```cpp 1250 typedef std::map<String, std::shared_ptr<NamespaceValue> >::iterator Iterator; 1251``` 1252 1253These typedefs should be part of the Class definition in the header, 1254or may be defined in the source scope where they are needed. 1255 1256Avoid declaring global typedefs, unless necessary. 1257 1258Using the `auto` keyword allows to ignore a specific value type. 1259This comes in handy with maps/sets where no specific access 1260is required. 1261 1262The following example iterates over a map returned from `GetTypes()`. 1263 1264```cpp 1265 for (const auto& kv : GetTypes()) { 1266 result.insert(kv.second); 1267 } 1268``` 1269 1270The long example would require us to define a map iterator, and a slightly 1271different algorithm. 1272 1273```cpp 1274 typedef std::map<String, DbType::Ptr> TypeMap; 1275 typedef std::map<String, DbType::Ptr>::const_iterator TypeMapIterator; 1276 1277 TypeMap types = GetTypes(); 1278 1279 for (TypeMapIterator it = types.begin(); it != types.end(); it++) { 1280 result.insert(it.second); 1281 } 1282``` 1283 1284We could also use a pair here, but requiring to know 1285the specific types of the map keys and values. 1286 1287```cpp 1288 typedef std::pair<String, DbType::Ptr> kv_pair; 1289 1290 for (const kv_pair& kv : GetTypes()) { 1291 result.insert(kv.second); 1292 } 1293``` 1294 1295After all, `auto` shortens the code and one does not always need to know 1296about the specific types. Function documentation for `GetTypes()` is 1297required though. 1298 1299 1300 1301#### Whitespace Cleanup <a id="development-develop-choose-editor-whitespaces"></a> 1302 1303Patches must be cleaned up and follow the indent style (tabs instead of spaces). 1304You should also remove any trailing whitespaces. 1305 1306`git diff` allows to highlight such. 1307 1308``` 1309vim $HOME/.gitconfig 1310 1311[color "diff"] 1312 whitespace = red reverse 1313[core] 1314 whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol 1315``` 1316 1317`vim` also can match these and visually alert you to remove them. 1318 1319``` 1320vim $HOME/.vimrc 1321 1322highlight ExtraWhitespace ctermbg=red guibg=red 1323match ExtraWhitespace /\s\+$/ 1324autocmd BufWinEnter * match ExtraWhitespace /\s\+$/ 1325autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/ 1326autocmd InsertLeave * match ExtraWhitespace /\s\+$/ 1327autocmd BufWinLeave * call clearmatches() 1328``` 1329 1330 1331## Development Environment <a id="development-environment"></a> 1332 1333### Linux Dev Environment <a id="development-linux-dev-env"></a> 1334 1335Based on CentOS 7, we have an early draft available inside the Icinga Vagrant boxes: 1336[centos7-dev](https://github.com/Icinga/icinga-vagrant/tree/master/centos7-dev). 1337 1338If you're compiling Icinga 2 natively without any virtualization layer in between, 1339this usually is faster. This is also the reason why developers on macOS prefer native builds 1340over Linux or Windows VMs. Don't forget to test the actual code on Linux later! Socket specific 1341stuff like `epoll` is not available on Unix kernels. 1342 1343Depending on your workstation and environment, you may either develop and run locally, 1344use a container deployment pipeline or put everything in a high end resource remote VM. 1345 1346Fork https://github.com/Icinga/icinga2 into your own repository, e.g. `https://github.com/dnsmichi/icinga2`. 1347 1348Create two build directories for different binary builds. 1349 1350* `debug` contains the debug build binaries. They contain more debug information and run tremendously slower than release builds from packages. Don't use them for benchmarks. 1351* `release` contains the release build binaries, as you would install them on a live system. This helps comparing specific scenarios for race conditions and more. 1352 1353```bash 1354mkdir -p release debug 1355``` 1356 1357Proceed with the specific distribution examples below. Keep in mind that these instructions 1358are best effort and sometimes out-of-date. Git Master may contain updates. 1359 1360* [CentOS 7](21-development.md#development-linux-dev-env-centos) 1361* [Debian 10 Buster](21-development.md#development-linux-dev-env-debian) 1362* [Ubuntu 18 Bionic](21-development.md#development-linux-dev-env-ubuntu) 1363 1364 1365#### CentOS 7 <a id="development-linux-dev-env-centos"></a> 1366 1367```bash 1368yum -y install gdb vim git bash-completion htop 1369 1370yum -y install rpmdevtools ccache \ 1371 cmake make gcc-c++ flex bison \ 1372 openssl-devel boost169-devel systemd-devel \ 1373 mysql-devel postgresql-devel libedit-devel \ 1374 libstdc++-devel 1375 1376groupadd icinga 1377groupadd icingacmd 1378useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga 1379 1380ln -s /bin/ccache /usr/local/bin/gcc 1381ln -s /bin/ccache /usr/local/bin/g++ 1382 1383git clone https://github.com/icinga/icinga2.git && cd icinga2 1384``` 1385 1386The debug build binaries contain specific code which runs 1387slower but allows for better debugging insights. 1388 1389For benchmarks, change `CMAKE_BUILD_TYPE` to `RelWithDebInfo` and 1390build inside the `release` directory. 1391 1392First, off export some generics for Boost. 1393 1394```bash 1395export I2_BOOST="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib64/boost169 -DBOOST_INCLUDEDIR=/usr/include/boost169 -DBoost_ADDITIONAL_VERSIONS='1.69;1.69.0'" 1396``` 1397 1398Second, add the prefix path to it. 1399 1400```bash 1401export I2_GENERIC="$I2_BOOST -DCMAKE_INSTALL_PREFIX=/usr/local/icinga2" 1402``` 1403 1404Third, define the two build types with their specific CMake variables. 1405 1406```bash 1407export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC" 1408export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC" 1409``` 1410 1411Fourth, depending on your likings, you may add a bash alias for building, 1412or invoke the commands inside: 1413 1414```bash 1415alias i2_debug="cd /root/icinga2; mkdir -p debug; cd debug; cmake $I2_DEBUG ..; make -j2; sudo make -j2 install; cd .." 1416alias i2_release="cd /root/icinga2; mkdir -p release; cd release; cmake $I2_RELEASE ..; make -j2; sudo make -j2 install; cd .." 1417``` 1418 1419This is taken from the [centos7-dev](https://github.com/Icinga/icinga-vagrant/tree/master/centos7-dev) Vagrant box. 1420 1421 1422The source installation doesn't set proper permissions, this is 1423handled in the package builds which are officially supported. 1424 1425```bash 1426chown -R icinga:icinga /usr/local/icinga2/var/ 1427 1428/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2 1429/usr/local/icinga2/sbin/icinga2 api setup 1430vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf 1431 1432/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon 1433``` 1434 1435#### Debian 10 <a id="development-linux-dev-env-debian"></a> 1436 1437Debian Buster doesn't need updated Boost packages from packages.icinga.com, 1438the distribution already provides 1.66+. For older versions such as Stretch, 1439include the release repository for packages.icinga.com as shown in the [setup instructions](02-installation.md#package-repositories-debian-ubuntu-raspbian). 1440 1441```bash 1442docker run -ti debian:buster bash 1443 1444apt-get update 1445apt-get -y install apt-transport-https wget gnupg 1446 1447apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev bison flex default-libmysqlclient-dev libpq-dev libedit-dev monitoring-plugins 1448apt-get -y install libboost-all-dev 1449``` 1450 1451```bash 1452ln -s /usr/bin/ccache /usr/local/bin/gcc 1453ln -s /usr/bin/ccache /usr/local/bin/g++ 1454 1455groupadd icinga 1456groupadd icingacmd 1457useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga 1458 1459git clone https://github.com/icinga/icinga2.git && cd icinga2 1460 1461mkdir debug release 1462 1463export I2_DEB="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib/x86_64-linux-gnu -DBOOST_INCLUDEDIR=/usr/include -DCMAKE_INSTALL_RPATH=/usr/lib/x86_64-linux-gnu" 1464export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin" 1465export I2_DEBUG="$I2_DEB $I2_GENERIC -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF" 1466 1467cd debug 1468cmake .. $I2_DEBUG 1469cd .. 1470 1471make -j2 install -C debug 1472``` 1473 1474 1475The source installation doesn't set proper permissions, this is 1476handled in the package builds which are officially supported. 1477 1478```bash 1479chown -R icinga:icinga /usr/local/icinga2/var/ 1480 1481/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2 1482/usr/local/icinga2/sbin/icinga2 api setup 1483vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf 1484 1485/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon 1486``` 1487 1488 1489#### Ubuntu 18 Bionic <a id="development-linux-dev-env-ubuntu"></a> 1490 1491Requires Boost packages from packages.icinga.com. 1492 1493```bash 1494docker run -ti ubuntu:bionic bash 1495 1496apt-get update 1497apt-get -y install apt-transport-https wget gnupg 1498 1499wget -O - https://packages.icinga.com/icinga.key | apt-key add - 1500 1501. /etc/os-release; if [ ! -z ${UBUNTU_CODENAME+x} ]; then DIST="${UBUNTU_CODENAME}"; else DIST="$(lsb_release -c| awk '{print $2}')"; fi; \ 1502 echo "deb https://packages.icinga.com/ubuntu icinga-${DIST} main" > \ 1503 /etc/apt/sources.list.d/${DIST}-icinga.list 1504 echo "deb-src https://packages.icinga.com/ubuntu icinga-${DIST} main" >> \ 1505 /etc/apt/sources.list.d/${DIST}-icinga.list 1506 1507apt-get update 1508``` 1509 1510```bash 1511apt-get -y install gdb vim git cmake make ccache build-essential libssl-dev bison flex default-libmysqlclient-dev libpq-dev libedit-dev monitoring-plugins 1512 1513apt-get install -y libboost1.67-icinga-all-dev 1514 1515ln -s /usr/bin/ccache /usr/local/bin/gcc 1516ln -s /usr/bin/ccache /usr/local/bin/g++ 1517 1518groupadd icinga 1519groupadd icingacmd 1520useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga 1521 1522git clone https://github.com/icinga/icinga2.git && cd icinga2 1523 1524mkdir debug release 1525 1526export I2_DEB="-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_LIBRARYDIR=/usr/lib/x86_64-linux-gnu/icinga-boost -DBOOST_INCLUDEDIR=/usr/include/icinga-boost -DCMAKE_INSTALL_RPATH=/usr/lib/x86_64-linux-gnu/icinga-boost" 1527export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga2 -DICINGA2_PLUGINDIR=/usr/local/sbin" 1528export I2_DEBUG="$I2_DEB $I2_GENERIC -DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF" 1529 1530cd debug 1531cmake .. $I2_DEBUG 1532cd .. 1533``` 1534 1535```bash 1536make -j2 install -C debug 1537``` 1538 1539The source installation doesn't set proper permissions, this is 1540handled in the package builds which are officially supported. 1541 1542```bash 1543chown -R icinga:icinga /usr/local/icinga2/var/ 1544 1545/usr/local/icinga2/lib/icinga2/prepare-dirs /usr/local/icinga2/etc/sysconfig/icinga2 1546/usr/local/icinga2/sbin/icinga2 api setup 1547vim /usr/local/icinga2/etc/icinga2/conf.d/api-users.conf 1548 1549/usr/local/icinga2/lib/icinga2/sbin/icinga2 daemon 1550``` 1551 1552### macOS Dev Environment <a id="development-macos-dev-env"></a> 1553 1554It is advised to use Homebrew to install required build dependencies. 1555Macports have been reported to work as well, typically you'll get more help 1556with Homebrew from Icinga developers. 1557 1558The idea is to run Icinga with the current user, avoiding root permissions. 1559This requires at least v2.11. 1560 1561> **Note** 1562> 1563> This is a pure development setup for Icinga developers reducing the compile 1564> time in contrast to VMs. There are no packages, startup scripts or dependency management involved. 1565> 1566> **macOS agents are not officially supported.** 1567> 1568> macOS uses its own TLS implementation, Icinga relies on extra OpenSSL packages 1569> requiring updates apart from vendor security updates. 1570 1571#### Requirements 1572 1573Explicitly use OpenSSL 1.1.x, older versions are out of support. 1574 1575```bash 1576brew install ccache boost cmake bison flex openssl@1.1 mysql-connector-c++ postgresql libpq 1577``` 1578 1579##### ccache 1580 1581```bash 1582sudo mkdir /opt/ccache 1583 1584sudo ln -s `which ccache` /opt/ccache/clang 1585sudo ln -s `which ccache` /opt/ccache/clang++ 1586 1587vim $HOME/.bash_profile 1588 1589# ccache is managed with symlinks to avoid collision with cgo 1590export PATH="/opt/ccache:$PATH" 1591 1592source $HOME/.bash_profile 1593``` 1594 1595#### Builds 1596 1597Icinga is built as release (optimized build for packages) and debug (more symbols and details for debugging). Debug builds 1598typically run slower than release builds and must not be used for performance benchmarks. 1599 1600The preferred installation prefix is `/usr/local/icinga/icinga2`. This allows to put e.g. Icinga Web 2 into the `/usr/local/icinga` directory as well. 1601 1602```bash 1603mkdir -p release debug 1604 1605export I2_USER=$(id -u -n) 1606export I2_GROUP=$(id -g -n) 1607export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga/icinga2 -DICINGA2_USER=$I2_USER -DICINGA2_GROUP=$I2_GROUP -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib -DICINGA2_PLUGINDIR=/usr/local/sbin -DICINGA2_WITH_PGSQL=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" 1608export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC" 1609export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC" 1610 1611cd debug 1612cmake $I2_DEBUG .. 1613cd .. 1614 1615make -j4 -C debug 1616make -j4 install -C debug 1617``` 1618 1619In order to run Icinga without any path prefix, and also use Bash completion it is advised to source additional 1620things into the local dev environment. 1621 1622```bash 1623export PATH=/usr/local/icinga/icinga2/sbin/:$PATH 1624 1625test -f /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 && source /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 1626``` 1627 1628##### Build Aliases 1629 1630This is derived from [dnsmichi's flavour](https://github.com/dnsmichi/dotfiles) and not generally best practice. 1631 1632```bash 1633vim $HOME/.bash_profile 1634 1635export I2_USER=$(id -u -n) 1636export I2_GROUP=$(id -g -n) 1637export I2_GENERIC="-DCMAKE_INSTALL_PREFIX=/usr/local/icinga/icinga2 -DICINGA2_USER=$I2_USER -DICINGA2_GROUP=$I2_GROUP -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl@1.1/include -DOPENSSL_SSL_LIBRARY=/usr/local/opt/openssl@1.1/lib/libssl.dylib -DOPENSSL_CRYPTO_LIBRARY=/usr/local/opt/openssl@1.1/lib/libcrypto.dylib -DICINGA2_PLUGINDIR=/usr/local/sbin -DICINGA2_WITH_PGSQL=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" 1638 1639export I2_DEBUG="-DCMAKE_BUILD_TYPE=Debug -DICINGA2_UNITY_BUILD=OFF $I2_GENERIC" 1640export I2_RELEASE="-DCMAKE_BUILD_TYPE=RelWithDebInfo -DICINGA2_WITH_TESTS=ON -DICINGA2_UNITY_BUILD=ON $I2_GENERIC" 1641 1642alias i2_debug="mkdir -p debug; cd debug; cmake $I2_DEBUG ..; make -j4; make -j4 install; cd .." 1643alias i2_release="mkdir -p release; cd release; cmake $I2_RELEASE ..; make -j4; make -j4 install; cd .." 1644 1645export PATH=/usr/local/icinga/icinga2/sbin/:$PATH 1646test -f /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 && source /usr/local/icinga/icinga2/etc/bash_completion.d/icinga2 1647 1648 1649source $HOME/.bash_profile 1650``` 1651 1652#### Permissions 1653 1654`make install` doesn't set all required permissions, override this. 1655 1656```bash 1657chown -R $I2_USER:$I2_GROUP /usr/local/icinga/icinga2 1658``` 1659 1660#### Run 1661 1662Start Icinga in foreground. 1663 1664```bash 1665icinga2 daemon 1666``` 1667 1668Reloads triggered with HUP or cluster syncs just put the process into background. 1669 1670#### Plugins 1671 1672```bash 1673brew install monitoring-plugins 1674 1675sudo vim /usr/local/icinga/icinga2/etc/icinga2/constants.conf 1676``` 1677 1678``` 1679const PluginDir = "/usr/local/sbin" 1680``` 1681 1682#### Backends: Redis 1683 1684```bash 1685brew install redis 1686brew services start redis 1687``` 1688 1689#### Databases: MariaDB 1690 1691```bash 1692brew install mariadb 1693mkdir -p /usr/local/etc/my.cnf.d 1694brew services start mariadb 1695 1696mysql_secure_installation 1697``` 1698 1699``` 1700vim $HOME/.my.cnf 1701 1702[client] 1703user = root 1704password = supersecurerootpassword 1705 1706sudo -i 1707ln -s /Users/michi/.my.cnf $HOME/.my.cnf 1708exit 1709``` 1710 1711```bash 1712mysql -e 'create database icinga;' 1713mysql -e "grant all on icinga.* to 'icinga'@'localhost' identified by 'icinga';" 1714mysql icinga < $HOME/dev/icinga/icinga2/lib/db_ido_mysql/schema/mysql.sql 1715``` 1716 1717#### API 1718 1719```bash 1720icinga2 api setup 1721cd /usr/local/icinga/icinga2/var/lib/icinga2/certs 1722HOST_NAME=mbpmif.int.netways.de 1723icinga2 pki new-cert --cn ${HOST_NAME} --csr ${HOST_NAME}.csr --key ${HOST_NAME}.key 1724icinga2 pki sign-csr --csr ${HOST_NAME}.csr --cert ${HOST_NAME}.crt 1725echo "const NodeName = \"${HOST_NAME}\"" >> /usr/local/icinga/icinga2/etc/icinga2/constants.conf 1726``` 1727 1728#### Web 1729 1730While it is recommended to use Docker or the Icinga Web 2 development VM pointing to the shared IDO database resource/REST API, you can also install it locally on macOS. 1731 1732The required steps are described in [this script](https://github.com/dnsmichi/dotfiles/blob/master/icingaweb2.sh). 1733 1734 1735 1736### Windows Dev Environment <a id="development-windows-dev-env"></a> 1737 1738The following sections explain how to setup the required build tools 1739and how to run and debug the code. 1740 1741#### TL;DR 1742 1743If you're going to setup a dev environment on a fresh Windows machine 1744and don't care for the details, 1745 17461. ensure there are 35 GB free space on C: 17472. run the following in an administrative Powershell: 1748 1. `Enable-WindowsOptionalFeature -FeatureName "NetFx3" -Online` 1749 (reboot when asked!) 1750 2. `powershell -NoProfile -ExecutionPolicy Bypass -Command "Invoke-Expression (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/Icinga/icinga2/master/doc/win-dev.ps1')"` 1751 (will take some time) 1752 1753This installs everything needed for cloning and building Icinga 2 1754on the command line (Powershell) as follows: 1755 1756(Don't forget to open a new Powershell window 1757to be able to use the newly installed Git.) 1758 1759``` 1760git clone https://github.com/Icinga/icinga2.git 1761cd .\icinga2\ 1762mkdir build 1763cd .\build\ 1764 1765& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" ` 1766 -DBoost_INCLUDE_DIR=C:\local\boost_1_76_0-Win64 ` 1767 -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_bison.exe ` 1768 -DFLEX_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_flex.exe ` 1769 -DICINGA2_WITH_MYSQL=OFF -DICINGA2_WITH_PGSQL=OFF .. 1770 1771& "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe" .\icinga2.sln 1772``` 1773 1774Building icinga2.sln via Visual Studio itself seems to require a reboot 1775after installing the build tools and building once via command line. 1776 1777#### Chocolatey 1778 1779Open an administrative command prompt (Win key, type “cmd”, right-click and “run as administrator”) and paste the following instructions: 1780 1781``` 1782@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin 1783``` 1784 1785#### Git, Posh and Vim 1786 1787In case you are used to `vim`, start a new administrative Powershell: 1788 1789``` 1790choco install -y vim 1791``` 1792 1793The same applies for Git integration in Powershell: 1794 1795``` 1796choco install -y poshgit 1797``` 1798 1799![Powershell Posh Git](images/development/windows_powershell_posh_git.png) 1800 1801In order to fix the colors for commands like `git status` or `git diff`, 1802edit `$HOME/.gitconfig` in your Powershell and add the following lines: 1803 1804``` 1805vim $HOME/.gitconfig 1806 1807[color "status"] 1808 changed = cyan bold 1809 untracked = yellow bold 1810 added = green bold 1811 branch = cyan bold 1812 unmerged = red bold 1813 1814[color "diff"] 1815 frag = cyan 1816 new = green bold 1817 commit = yellow 1818 old = red white 1819 1820[color "branch"] 1821 current = yellow reverse 1822 local = yellow 1823 remote = green bold 1824 remote = red bold 1825``` 1826 1827#### Visual Studio 1828 1829Thanks to Microsoft they’ll now provide their Professional Edition of Visual Studio 1830as community version, free for use for open source projects such as Icinga. 1831The installation requires ~9GB disk space. [Download](https://www.visualstudio.com/downloads/) 1832the web installer and start the installation. 1833 1834Note: Only Visual Studio 2019 is covered here. Older versions are not supported. 1835 1836You need a free Microsoft account to download and also store your preferences. 1837 1838Install the following complete workloads: 1839 1840* C++ Desktop Development 1841* .NET Desktop Development 1842 1843In addition also choose these individual components on Visual Studio: 1844 1845* .NET 1846 * .NET Framework 4.x targeting packs 1847 * .NET Framework 4.x.y SDKs 1848* Code tools 1849 * Git for Windows 1850 * GitHub Extension for Visual Studio 1851 * NuGet package manager 1852* Compilers, build tools and runtimes 1853 * C# and Visual Basic Roslyn compilers 1854 * C++ 2019 Redistributable Update 1855 * C++ CMake tools for Windows 1856 * C++/CLI Support for v142 build tools (14.22) 1857 * MSBuild 1858 * MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.22) 1859* Debugging and testing 1860 * .NET profiling tools 1861 * C++ profiling tools 1862 * Just-in-Time debugger 1863* Development activities 1864 * C# and Visual Basic 1865 * C++ core features 1866 * IntelliCode 1867 * Live Share 1868* Games and Graphics 1869 * Graphics debugger and GPU profiler for DirectX (required by C++ profiling tools) 1870* SDKs, libraries and frameworks 1871 * Windows 10 SDK (10.0.18362.0 or later) 1872 * Windows Universal C Runtime 1873 1874![Visual Studio Installer](images/development/windows_visual_studio_installer_01.png) 1875![Visual Studio Installer](images/development/windows_visual_studio_installer_02.png) 1876![Visual Studio Installer](images/development/windows_visual_studio_installer_03.png) 1877 1878After a while, Visual Studio will be ready. 1879 1880##### Style Guide for Visual Studio 1881 1882Navigate into `Tools > Options > Text Editor` and repeat the following for 1883 1884- C++ 1885- C# 1886 1887Navigate into `Tabs` and set: 1888 1889- Indenting: Smart (default) 1890- Tab size: 4 1891- Indent size: 4 1892- Keep tabs (instead of spaces) 1893 1894![Visual Studio Tabs](images/development/windows_visual_studio_tabs_c++.png) 1895 1896 1897#### Flex and Bison 1898 1899Install it using [chocolatey](https://www.wireshark.org/docs/wsdg_html_chunked/ChSetupWin32.html): 1900 1901``` 1902choco install -y winflexbison 1903``` 1904 1905Chocolatey installs these tools into the hidden directory `C:\ProgramData\chocolatey\lib\winflexbison\tools`. 1906 1907#### OpenSSL 1908 1909Icinga 2 requires the OpenSSL library. [Download](https://slproweb.com/products/Win32OpenSSL.html) the Win64 package 1910and install it into `c:\local\OpenSSL-Win64`. 1911 1912Once asked for `Copy OpenSSLs DLLs to` select `The Windows system directory`. That way CMake/Visual Studio 1913will automatically detect them for builds and packaging. 1914 1915> **Note** 1916> 1917> We cannot use the chocolatey package as this one does not provide any development headers. 1918> 1919> Choose 1.1.1 LTS from manual downloads for best compatibility. 1920 1921#### Boost 1922 1923Icinga needs the development header and library files from the Boost library. 1924 1925Visual Studio translates into the following compiler versions: 1926 1927- `msvc-14.2` = Visual Studio 2019 1928 1929##### Pre-built Binaries 1930 1931Prefer the pre-built package over self-compiling, if the newest version already exists. 1932 1933Download the [boost-binaries](https://sourceforge.net/projects/boost/files/boost-binaries/) for 1934 1935- msvc-14.2 is Visual Studio 2019 1936- 64 for 64 bit builds 1937 1938``` 1939https://sourceforge.net/projects/boost/files/boost-binaries/1.76.0/boost_1_76_0-msvc-14.2-64.exe/download 1940``` 1941 1942Run the installer and leave the default installation path in `C:\local\boost_1_76_0`. 1943 1944 1945##### Source & Compile 1946 1947In order to use the boost development header and library files you need to [download](https://www.boost.org/users/download/) 1948Boost and then extract it to e.g. `C:\local\boost_1_76_0`. 1949 1950> **Note** 1951> 1952> Just use `C:\local`, the zip file already contains the sub folder. Extraction takes a while, 1953> the archive contains more than 70k files. 1954 1955In order to integrate Boost into Visual Studio, open the `Developer Command Prompt` from the start menu, 1956and navigate to `C:\local\boost_1_76_0`. 1957 1958Execute `bootstrap.bat` first. 1959 1960``` 1961cd C:\local\boost_1_76_0 1962bootstrap.bat 1963``` 1964 1965Once finished, specify the required `toolset` to compile boost against Visual Studio. 1966This takes quite some time in a Windows VM. Boost Context uses Assembler code, 1967which isn't treated as exception safe by the VS compiler. Therefore set the 1968additional compilation flag according to [this entry](https://lists.boost.org/Archives/boost/2015/08/224570.php). 1969 1970``` 1971b2 --toolset=msvc-14.2 link=static threading=multi runtime-link=static address-model=64 asmflags=\safeseh 1972``` 1973 1974![Windows Boost Build in VS Development Console](images/development/windows_boost_build_dev_cmd.png) 1975 1976#### TortoiseGit 1977 1978TortoiseGit provides a graphical integration into the Windows explorer. This makes it easier to checkout, commit 1979and whatnot. 1980 1981[Download](https://tortoisegit.org/download/) TortoiseGit on your system. 1982 1983In order to clone via Git SSH you also need to create a new directory called `.ssh` 1984inside your user's home directory. 1985Therefore open a command prompt (win key, type `cmd`, enter) and run `mkdir .ssh`. 1986Add your `id_rsa` private key and `id_rsa.pub` public key files into that directory. 1987 1988Start the setup routine and choose `OpenSSH` as default secure transport when asked. 1989 1990Open a Windows Explorer window and navigate into 1991 1992``` 1993cd %HOMEPATH%\source\repos 1994``` 1995 1996Right click and select `Git Clone` from the context menu. 1997 1998Use `ssh://git@github.com/icinga/icinga2.git` for SSH clones, `https://github.com/icinga/icinga2.git` otherwise. 1999 2000#### Packages 2001 2002CMake uses CPack and NSIS to create the setup executable including all binaries and libraries 2003in addition to setup dialogues and configuration. Therefore we’ll need to install [NSIS](http://nsis.sourceforge.net/Download) 2004first. 2005 2006We also need to install the Windows Installer XML (WIX) toolset. This has .NET 3.5 as a dependency which might need a 2007reboot of the system which is not handled properly by Chocolatey. Therefore install it first and reboot when asked. 2008 2009``` 2010Enable-WindowsOptionalFeature -FeatureName "NetFx3" -Online 2011choco install -y wixtoolset 2012``` 2013 2014#### CMake 2015 2016Icinga 2 uses CMake to manage the build environment. You can generate the Visual Studio project files 2017using CMake. [Download](https://cmake.org/download/) and install CMake. Select to add it to PATH for all users 2018when asked. 2019 2020> **Note** 2021> 2022> In order to properly detect the Boost libraries and VS 2019, install CMake 3.15.2+. 2023> 2024> **Tip** 2025> 2026> Cheatsheet: https://www.brianlheim.com/2018/04/09/cmake-cheat-sheet.html 2027 2028Once setup is completed, open a command prompt and navigate to 2029 2030``` 2031cd %HOMEPATH%\source\repos 2032``` 2033 2034Build Icinga with specific CMake variables. This generates a new Visual Studio project file called `icinga2.sln`. 2035 2036Visual Studio translates into the following: 2037 2038- `msvc-14.2` = Visual Studio 2019 2039 2040You need to specify the previously installed component paths. 2041 2042Variable | Value | Description 2043----------------------|----------------------------------------------------------------------|------------------------------------------------------- 2044`BOOST_ROOT` | `C:\local\boost_1_76_0` | Root path where you've extracted and compiled Boost. 2045`BOOST_LIBRARYDIR` | Binary: `C:\local\boost_1_76_0\lib64-msvc-14.2`, Source: `C:\local\boost_1_76_0\stage` | Path to the static compiled Boost libraries, directory must contain `lib`. 2046`BISON_EXECUTABLE` | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe` | Path to the Bison executable. 2047`FLEX_EXECUTABLE` | `C:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe` | Path to the Flex executable. 2048`ICINGA2_WITH_MYSQL` | OFF | Requires extra setup for MySQL if set to `ON`. Not supported for client setups. 2049`ICINGA2_WITH_PGSQL` | OFF | Requires extra setup for PgSQL if set to `ON`. Not supported for client setups. 2050`ICINGA2_UNITY_BUILD` | OFF | Disable unity builds for development environments. 2051 2052Tip: If you have previously opened a terminal, run `refreshenv` to re-read updated PATH variables. 2053 2054##### Build Scripts 2055 2056Icinga provides the build scripts inside the Git repository. 2057 2058Open a new Powershell and navigate into the cloned Git repository. Set 2059specific environment variables and run the build scripts. 2060 2061``` 2062cd %HOMEPATH%\source\repos\icinga2 2063 2064.\tools\win32\configure-dev.ps1 2065.\tools\win32\build.ps1 2066.\tools\win32\test.ps1 2067``` 2068 2069The debug MSI package is located in the `debug` directory. 2070 2071If you did not follow the above steps with Boost binaries and OpenSSL 2072paths, you can still modify the environment variables. 2073 2074``` 2075$env:CMAKE_GENERATOR='Visual Studio 16 2019' 2076$env:CMAKE_GENERATOR_PLATFORM='x64' 2077 2078$env:ICINGA2_INSTALLPATH = 'C:\Program Files\Icinga2-debug' 2079$env:ICINGA2_BUILDPATH='debug' 2080$env:CMAKE_BUILD_TYPE='Debug' 2081$env:OPENSSL_ROOT_DIR='C:\OpenSSL-Win64' 2082$env:BOOST_ROOT='C:\local\boost_1_76_0' 2083$env:BOOST_LIBRARYDIR='C:\local\boost_1_76_0\lib64-msvc-14.2' 2084``` 2085 2086#### Icinga 2 in Visual Studio 2087 2088This requires running the configure script once. 2089 2090Navigate to 2091 2092``` 2093cd %HOMEPATH%\source\repos\icinga2\debug 2094``` 2095 2096Open `icinga2.sln`. Log into Visual Studio when asked. 2097 2098On the right panel, select to build the `Bin/icinga-app` solution. 2099 2100The executable binaries are located in `Bin\Release\Debug` in your `icinga2` 2101project directory. 2102 2103Navigate there and run `icinga2.exe --version`. 2104 2105``` 2106cd %HOMEPATH%\source\repos\icinga2\Bin\Release\Debug 2107icinga2.exe --version 2108``` 2109 2110 2111#### Release Package 2112 2113This is part of the build process script. Override the build type and pick a different 2114build directory. 2115 2116``` 2117cd %HOMEPATH%\source\repos\icinga2 2118 2119$env:ICINGA2_BUILDPATH='release' 2120$env:CMAKE_BUILD_TYPE='RelWithDebInfo' 2121 2122.\tools\win32\configure-dev.ps1 2123.\tools\win32\build.ps1 2124.\tools\win32\test.ps1 2125``` 2126 2127The release MSI package is located in the `release` directory. 2128 2129 2130### Embedded Dev Env: Pi <a id="development-embedded-dev-env"></a> 2131 2132> **Note** 2133> 2134> This isn't officially supported yet, just a few hints how you can do it yourself. 2135 2136The following examples source from armhf on Raspberry Pi. 2137 2138#### ccache 2139 2140```bash 2141apt install -y ccache 2142 2143/usr/sbin/update-ccache-symlinks 2144 2145echo 'export PATH="/usr/lib/ccache:$PATH"' | tee -a ~/.bashrc 2146 2147source ~/.bashrc && echo $PATH 2148``` 2149 2150#### Build 2151 2152Copy the icinga2 source code into `$HOME/icinga2`. Clone the `deb-icinga2` repository into `debian/`. 2153 2154```bash 2155git clone https://github.com/Icinga/icinga2 $HOME/icinga2 2156git clone https://github.com/Icinga/deb-icinga2 $HOME/icinga2/debian 2157``` 2158 2159Then build a Debian package and install it like normal. 2160 2161```bash 2162dpkg-buildpackage -uc -us 2163``` 2164 2165## Package Builds <a id="development-package-builds"></a> 2166 2167This documentation is explicitly meant for packagers and the Icinga 2168build infrastructure. 2169 2170The following requirements need to be fulfilled in order to build the 2171Icinga application using a dist tarball (including notes for distributions): 2172 2173* cmake >= 2.6 2174* GNU make (make) or ninja-build 2175* C++ compiler which supports C++11 2176 * RHEL/Fedora/SUSE: gcc-c++ >= 4.7 (extra Developer Tools on RHEL5/6 see below) 2177 * Debian/Ubuntu: build-essential 2178 * Alpine: build-base 2179 * you can also use clang++ 2180* pkg-config 2181* OpenSSL library and header files >= 1.0.1 2182 * RHEL/Fedora: openssl-devel 2183 * SUSE: libopenssl-devel 2184 * Debian/Ubuntu: libssl-dev 2185 * Alpine: libressl-dev 2186* Boost library and header files >= 1.66.0 2187 * RHEL/Fedora: boost166-devel 2188 * Debian/Ubuntu: libboost-all-dev 2189 * Alpine: boost-dev 2190* GNU bison (bison) 2191* GNU flex (flex) >= 2.5.35 2192* systemd headers 2193 * Only required when using systemd 2194 * Debian/Ubuntu: libsystemd-dev 2195 * RHEL/Fedora: systemd-devel 2196 2197### Optional features <a id="development-package-builds-optional-features"></a> 2198 2199* MySQL (disable with CMake variable `ICINGA2_WITH_MYSQL` to `OFF`) 2200 * RHEL/Fedora: mysql-devel 2201 * SUSE: libmysqlclient-devel 2202 * Debian/Ubuntu: default-libmysqlclient-dev | libmysqlclient-dev 2203 * Alpine: mariadb-dev 2204* PostgreSQL (disable with CMake variable `ICINGA2_WITH_PGSQL` to `OFF`) 2205 * RHEL/Fedora: postgresql-devel 2206 * Debian/Ubuntu: libpq-dev 2207 * postgresql-dev on Alpine 2208* libedit (CLI console) 2209 * RHEL/Fedora: libedit-devel on CentOS (RHEL requires rhel-7-server-optional-rpms) 2210 * Debian/Ubuntu/Alpine: libedit-dev 2211* Termcap (only required if libedit doesn't already link against termcap/ncurses) 2212 * RHEL/Fedora: libtermcap-devel 2213 * Debian/Ubuntu: (not necessary) 2214 2215### Special requirements <a id="development-package-builds-special-requirements"></a> 2216 2217**FreeBSD**: libexecinfo (automatically used when Icinga 2 is installed via port or package) 2218 2219**RHEL6**: Requires a newer boost version which is available on packages.icinga.com 2220with a version suffixed name. 2221 2222### Runtime user environment <a id="development-package-builds-runtime-user-env"></a> 2223 2224By default Icinga will run as user `icinga` and group `icinga`. Additionally the 2225external command pipe and livestatus features require a dedicated command group 2226`icingacmd`. You can choose your own user/group names and pass them to CMake 2227using the `ICINGA2_USER`, `ICINGA2_GROUP` and `ICINGA2_COMMAND_GROUP` variables. 2228 2229```bash 2230groupadd icinga 2231groupadd icingacmd 2232useradd -c "icinga" -s /sbin/nologin -G icingacmd -g icinga icinga 2233``` 2234 2235On Alpine (which uses ash busybox) you can run: 2236 2237```bash 2238addgroup -S icinga 2239addgroup -S icingacmd 2240adduser -S -D -H -h /var/spool/icinga2 -s /sbin/nologin -G icinga -g icinga icinga 2241adduser icinga icingacmd 2242``` 2243 2244Add the web server user to the icingacmd group in order to grant it write 2245permissions to the external command pipe and livestatus socket: 2246 2247```bash 2248usermod -a -G icingacmd www-data 2249``` 2250 2251Make sure to replace "www-data" with the name of the user your web server 2252is running as. 2253 2254### Building Icinga 2: Example <a id="development-package-builds-example"></a> 2255 2256Once you have installed all the necessary build requirements you can build 2257Icinga 2 using the following commands: 2258 2259```bash 2260mkdir release && cd release 2261cmake .. 2262cd .. 2263make -C release 2264make install -C release 2265``` 2266 2267You can specify an alternative installation prefix using `-DCMAKE_INSTALL_PREFIX`: 2268 2269```bash 2270cmake .. -DCMAKE_INSTALL_PREFIX=/tmp/icinga2 2271``` 2272 2273### CMake Variables <a id="development-package-builds-cmake-variables"></a> 2274 2275In addition to `CMAKE_INSTALL_PREFIX` here are most of the supported Icinga-specific cmake variables. 2276 2277For all variables regarding defaults paths on in CMake, see 2278[GNUInstallDirs](https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html). 2279 2280Also see `CMakeLists.txt` for details. 2281 2282#### System Environment 2283 2284* `CMAKE_INSTALL_SYSCONFDIR`: The configuration directory; defaults to `CMAKE_INSTALL_PREFIX/etc` 2285* `CMAKE_INSTALL_LOCALSTATEDIR`: The state directory; defaults to `CMAKE_INSTALL_PREFIX/var` 2286* `ICINGA2_CONFIGDIR`: Main config directory; defaults to `CMAKE_INSTALL_SYSCONFDIR/icinga2` usually `/etc/icinga2` 2287* `ICINGA2_CACHEDIR`: Directory for cache files; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/cache/icinga2` usually `/var/cache/icinga2` 2288* `ICINGA2_DATADIR`: Data directory for the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/lib/icinga2` usually `/var/lib/icinga2` 2289* `ICINGA2_LOGDIR`: Logfiles of the daemon; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/log/icinga2 usually `/var/log/icinga2` 2290* `ICINGA2_SPOOLDIR`: Spooling directory ; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/spool/icinga2` usually `/var/spool/icinga2` 2291* `ICINGA2_INITRUNDIR`: Runtime data for the init system; defaults to `CMAKE_INSTALL_LOCALSTATEDIR/run/icinga2` usually `/run/icinga2` 2292* `ICINGA2_GIT_VERSION_INFO`: Whether to use Git to determine the version number; defaults to `ON` 2293* `ICINGA2_USER`: The user Icinga 2 should run as; defaults to `icinga` 2294* `ICINGA2_GROUP`: The group Icinga 2 should run as; defaults to `icinga` 2295* `ICINGA2_COMMAND_GROUP`: The command group Icinga 2 should use; defaults to `icingacmd` 2296* `ICINGA2_SYSCONFIGFILE`: Where to put the config file the initscript/systemd pulls it's dirs from; 2297* defaults to `CMAKE_INSTALL_PREFIX/etc/sysconfig/icinga2` 2298* `ICINGA2_PLUGINDIR`: The path for the Monitoring Plugins project binaries; defaults to `/usr/lib/nagios/plugins` 2299 2300#### Build Optimization 2301 2302* `ICINGA2_UNITY_BUILD`: Whether to perform a unity build; defaults to `ON`. Note: This requires additional memory and is not advised for building VMs, Docker for Mac and embedded hardware. 2303* `ICINGA2_LTO_BUILD`: Whether to use link time optimization (LTO); defaults to `OFF` 2304 2305#### Init System 2306 2307* `USE_SYSTEMD=ON|OFF`: Use systemd or a classic SysV initscript; defaults to `OFF` 2308* `INSTALL_SYSTEMD_SERVICE_AND_INITSCRIPT=ON|OFF` Force install both the systemd service definition file 2309 and the SysV initscript in parallel, regardless of how `USE_SYSTEMD` is set. 2310 Only use this for special packaging purposes and if you know what you are doing. 2311 Defaults to `OFF`. 2312 2313#### Features 2314 2315* `ICINGA2_WITH_CHECKER`: Determines whether the checker module is built; defaults to `ON` 2316* `ICINGA2_WITH_COMPAT`: Determines whether the compat module is built; defaults to `ON` 2317* `ICINGA2_WITH_LIVESTATUS`: Determines whether the Livestatus module is built; defaults to `ON` 2318* `ICINGA2_WITH_NOTIFICATION`: Determines whether the notification module is built; defaults to `ON` 2319* `ICINGA2_WITH_PERFDATA`: Determines whether the perfdata module is built; defaults to `ON` 2320* `ICINGA2_WITH_TESTS`: Determines whether the unit tests are built; defaults to `ON` 2321 2322#### MySQL or MariaDB 2323 2324The following settings can be tuned for the MySQL / MariaDB IDO feature. 2325 2326* `ICINGA2_WITH_MYSQL`: Determines whether the MySQL IDO module is built; defaults to `ON` 2327* `MYSQL_CLIENT_LIBS`: Client implementation used (mysqlclient / mariadbclient); defaults searches for `mysqlclient` and `mariadbclient` 2328* `MYSQL_INCLUDE_DIR`: Directory containing include files for the mysqlclient; default empty - 2329 checking multiple paths like `/usr/include/mysql` 2330 2331See [FindMySQL.cmake](https://github.com/Icinga/icinga2/blob/master/third-party/cmake/FindMySQL.cmake) 2332for implementation details. 2333 2334#### PostgreSQL 2335 2336The following settings can be tuned for the PostgreSQL IDO feature. 2337 2338* `ICINGA2_WITH_PGSQL`: Determines whether the PostgreSQL IDO module is built; defaults to `ON` 2339* `PostgreSQL_INCLUDE_DIR`: Top-level directory containing the PostgreSQL include directories 2340* `PostgreSQL_LIBRARY`: File path to PostgreSQL library : libpq.so (or libpq.so.[ver] file) 2341 2342See [FindPostgreSQL.cmake](https://github.com/Icinga/icinga2/blob/master/third-party/cmake/FindPostgreSQL.cmake) 2343for implementation details. 2344 2345#### Version detection 2346 2347CMake determines the Icinga 2 version number using `git describe` if the 2348source directory is contained in a Git repository. Otherwise the version number 2349is extracted from the [ICINGA2_VERSION](ICINGA2_VERSION) file. This behavior can be 2350overridden by creating a file called `icinga-version.h.force` in the source 2351directory. Alternatively the `-DICINGA2_GIT_VERSION_INFO=OFF` option for CMake 2352can be used to disable the usage of `git describe`. 2353 2354 2355### Building RPMs <a id="development-package-builds-rpms"></a> 2356 2357#### Build Environment on RHEL, CentOS, Fedora, Amazon Linux 2358 2359Setup your build environment: 2360 2361```bash 2362yum -y install rpmdevtools 2363``` 2364 2365#### Build Environment on SuSE/SLES 2366 2367SLES: 2368 2369```bash 2370zypper addrepo http://download.opensuse.org/repositories/devel:tools/SLE_12_SP4/devel:tools.repo 2371zypper refresh 2372zypper install rpmdevtools spectool 2373``` 2374 2375OpenSuSE: 2376 2377```bash 2378zypper addrepo http://download.opensuse.org/repositories/devel:tools/openSUSE_Leap_15.0/devel:tools.repo 2379zypper refresh 2380zypper install rpmdevtools spectool 2381``` 2382 2383#### Package Builds <a id="development-package-builds-rpms-package-builds"></a> 2384 2385Prepare the rpmbuild directory tree: 2386 2387```bash 2388cd $HOME 2389rpmdev-setuptree 2390``` 2391 2392Snapshot builds: 2393 2394```bash 2395curl https://raw.githubusercontent.com/Icinga/rpm-icinga2/master/icinga2.spec -o $HOME/rpmbuild/SPECS/icinga2.spec 2396``` 2397 2398> **Note** 2399> 2400> The above command builds snapshot packages. Change to the `release` branch 2401> for release package builds. 2402 2403Copy the tarball to `rpmbuild/SOURCES` e.g. by using the `spectool` binary 2404provided with `rpmdevtools`: 2405 2406```bash 2407cd $HOME/rpmbuild/SOURCES 2408spectool -g ../SPECS/icinga2.spec 2409 2410cd $HOME/rpmbuild 2411``` 2412 2413Install the build dependencies. Example for CentOS 7: 2414 2415```bash 2416yum -y install libedit-devel ncurses-devel gcc-c++ libstdc++-devel openssl-devel \ 2417cmake flex bison boost-devel systemd mysql-devel postgresql-devel httpd \ 2418selinux-policy-devel checkpolicy selinux-policy selinux-policy-doc 2419``` 2420 2421Note: If you are using Amazon Linux, systemd is not required. 2422 2423A shorter way is available using the `yum-builddep` command on RHEL based systems: 2424 2425```bash 2426yum-builddep SPECS/icinga2.spec 2427``` 2428 2429Build the RPM: 2430 2431```bash 2432rpmbuild -ba SPECS/icinga2.spec 2433``` 2434 2435#### Additional Hints <a id="development-package-builds-rpms-additional-hints"></a> 2436 2437##### SELinux policy module 2438 2439The following packages are required to build the SELinux policy module: 2440 2441* checkpolicy 2442* selinux-policy (selinux-policy on CentOS 6, selinux-policy-devel on CentOS 7) 2443* selinux-policy-doc 2444 2445##### RHEL/CentOS 6 2446 2447The RedHat Developer Toolset is required for building Icinga 2 beforehand. 2448This contains a modern version of flex and a C++ compiler which supports 2449C++11 features. 2450 2451```bash 2452cat >/etc/yum.repos.d/devtools-2.repo <<REPO 2453[testing-devtools-2-centos-\$releasever] 2454name=testing 2 devtools for CentOS $releasever 2455baseurl=https://people.centos.org/tru/devtools-2/\$releasever/\$basearch/RPMS 2456gpgcheck=0 2457REPO 2458``` 2459 2460Dependencies to devtools-2 are used in the RPM SPEC, so the correct tools 2461should be used for building. 2462 2463As an alternative, you can use newer Boost packages provided on 2464[packages.icinga.com](https://packages.icinga.com/epel). 2465 2466```bash 2467cat >$HOME/.rpmmacros <<MACROS 2468%build_icinga_org 1 2469MACROS 2470``` 2471 2472##### Amazon Linux 2473 2474If you prefer to build packages offline, a suitable Vagrant box is located 2475[here](https://atlas.hashicorp.com/mvbcoding/boxes/awslinux/). 2476 2477### Build Debian/Ubuntu packages <a id="development-package-builds-deb"></a> 2478 2479Setup your build environment on Debian/Ubuntu, copy the 'debian' directory from 2480the Debian packaging Git repository (https://github.com/Icinga/deb-icinga2) 2481into your source tree and run the following command: 2482 2483```bash 2484dpkg-buildpackage -uc -us 2485``` 2486 2487### Build Alpine Linux packages <a id="development-package-builds-alpine"></a> 2488 2489A simple way to setup a build environment is installing Alpine in a chroot. 2490In this way, you can set up an Alpine build environment in a chroot under a 2491different Linux distro. 2492There is a script that simplifies these steps with just two commands, and 2493can be found [here](https://github.com/alpinelinux/alpine-chroot-install). 2494 2495Once the build environment is installed, you can setup the system to build 2496the packages by following [this document](https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package). 2497 2498### Build Post Install Tasks <a id="development-package-builds-post-install-tasks"></a> 2499 2500After building Icinga 2 yourself, your package build system should at least run the following post 2501install requirements: 2502 2503* enable the `checker`, `notification` and `mainlog` feature by default 2504* run 'icinga2 api setup' in order to enable the `api` feature and generate TLS certificates for the node 2505 2506### Run Icinga 2 <a id="development-package-builds-run-icinga"></a> 2507 2508Icinga 2 comes with a binary that takes care of loading all the relevant 2509components (e.g. for check execution, notifications, etc.): 2510 2511``` 2512icinga2 daemon 2513 2514[2016-12-08 16:44:24 +0100] information/cli: Icinga application loader (version: v2.5.4-231-gb10a6b7; debug) 2515[2016-12-08 16:44:24 +0100] information/cli: Loading configuration file(s). 2516[2016-12-08 16:44:25 +0100] information/ConfigItem: Committing config item(s). 2517... 2518``` 2519 2520#### Init Script <a id="development-package-builds-init-script"></a> 2521 2522Icinga 2 can be started as a daemon using the provided init script: 2523 2524``` 2525/etc/init.d/icinga2 2526Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} 2527``` 2528 2529#### Systemd <a id="development-package-builds-systemd"></a> 2530 2531If your distribution uses systemd: 2532 2533``` 2534systemctl {start|stop|reload|status|enable|disable} icinga2 2535``` 2536 2537In case the distribution is running systemd >227, you'll also 2538need to package and install the `etc/initsystem/icinga2.service.limits.conf` 2539file into `/etc/systemd/system/icinga2.service.d`. 2540 2541#### openrc <a id="development-package-builds-openrc"></a> 2542 2543Or if your distribution uses openrc (like Alpine): 2544 2545``` 2546rc-service icinga2 2547Usage: /etc/init.d/icinga2 {start|stop|restart|reload|checkconfig|status} 2548``` 2549 2550Note: the openrc's init.d is not shipped by default. 2551A working init.d with openrc can be found here: (https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd). If you have customized some path, edit the file and adjust it according with your setup. 2552Those few steps can be followed: 2553 2554```bash 2555wget https://git.alpinelinux.org/cgit/aports/plain/community/icinga2/icinga2.initd 2556mv icinga2.initd /etc/init.d/icinga2 2557chmod +x /etc/init.d/icinga2 2558``` 2559 2560Icinga 2 reads a single configuration file which is used to specify all 2561configuration settings (global settings, hosts, services, etc.). The 2562configuration format is explained in detail in the [doc/](doc/) directory. 2563 2564By default `make install` installs example configuration files in 2565`/usr/local/etc/icinga2` unless you have specified a different prefix or 2566sysconfdir. 2567 2568 2569### Windows Builds <a id="development-package-builds-windows"></a> 2570 2571The Windows MSI packages are located at https://packages.icinga.com/windows/ 2572 2573The build infrastructure is based on GitLab CI and an Ansible provisioned 2574Windows VM running in OpenStack. 2575 2576The runner uses the scripts located in `tools/win32` to configure, build 2577and test the packages. Uploading them to the package repository is a 2578separate step. For manual package creation, please refer to [this chapter](21-development.md#development-windows-dev-env). 2579 2580![Windows build pipeline in GitLab](images/development/windows_builds_gitlab_pipeline.png) 2581 2582 2583## Continuous Integration <a id="development-ci"></a> 2584 2585Icinga uses the integrated CI capabilities on GitHub in the development workflow. 2586This ensures that incoming pull requests and branches are built on create/push events. 2587Contributors and developers can immediately see whether builds fail or succeed and 2588help the final reviews. 2589 2590* For Linux, we are currently using Travis CI. 2591* For Windows, AppVeyor has been integrated. 2592 2593Future plans involve making use of GitHub Actions. 2594 2595In addition to our development platform on GitHub, 2596we are using GitLab's CI platform to build binary packages for 2597all supported operating systems and distributions. 2598These CI pipelines provide even more detailed insights into 2599specific platform failures and developers can react faster. 2600 2601### CI: Travis CI 2602 2603[Travis CI](https://travis-ci.org/Icinga/icinga2) provides Ubuntu as base 2604distribution where Icinga is compiled from sources followed by running the 2605unit tests and a config validation check. 2606 2607For details, please refer to the [.travis.yml](https://github.com/Icinga/icinga2/blob/master/.travis.yml) 2608configuration file. 2609 2610### CI: AppVeyor 2611 2612[AppVeyor](https://ci.appveyor.com/project/icinga/icinga2) provides Windows 2613as platform where Visual Studio and Boost libraries come pre-installed. 2614 2615Icinga is built using the Powershell scripts located in `tools/win32`. 2616In addition to that, the unit tests are run. 2617 2618Please check the [appveyor.yml](https://github.com/Icinga/icinga2/blob/master/appveyor.yml) configuration 2619file for details. 2620 2621 2622## Advanced Development Tips <a id="development-advanced"></a> 2623 2624### GDB Pretty Printers <a id="development-advanced-gdb-pretty-printer"></a> 2625 2626Install the `boost`, `python` and `icinga2` pretty printers. Absolute paths are required, 2627so please make sure to update the installation paths accordingly (`pwd`). 2628 2629```bash 2630mkdir -p ~/.gdb_printers && cd ~/.gdb_printers 2631``` 2632 2633Boost Pretty Printers compatible with Python 3: 2634 2635``` 2636$ git clone https://github.com/mateidavid/Boost-Pretty-Printer.git && cd Boost-Pretty-Printer 2637$ git checkout python-3 2638$ pwd 2639/home/michi/.gdb_printers/Boost-Pretty-Printer 2640``` 2641 2642Python Pretty Printers: 2643 2644```bash 2645cd ~/.gdb_printers 2646svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python 2647``` 2648 2649Icinga 2 Pretty Printers: 2650 2651```bash 2652mkdir -p ~/.gdb_printers/icinga2 && cd ~/.gdb_printers/icinga2 2653wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/icingadbg.py 2654``` 2655 2656Now you'll need to modify/setup your `~/.gdbinit` configuration file. 2657You can download the one from Icinga 2 and modify all paths. 2658 2659Example on Fedora 22: 2660 2661``` 2662$ wget https://raw.githubusercontent.com/Icinga/icinga2/master/tools/debug/gdb/gdbinit -O ~/.gdbinit 2663$ vim ~/.gdbinit 2664 2665set print pretty on 2666 2667python 2668import sys 2669sys.path.insert(0, '/home/michi/.gdb_printers/icinga2') 2670from icingadbg import register_icinga_printers 2671register_icinga_printers() 2672end 2673 2674python 2675import sys 2676sys.path.insert(0, '/home/michi/.gdb_printers/python') 2677from libstdcxx.v6.printers import register_libstdcxx_printers 2678try: 2679 register_libstdcxx_printers(None) 2680except: 2681 pass 2682end 2683 2684python 2685import sys 2686sys.path.insert(0, '/home/michi/.gdb_printers/Boost-Pretty-Printer') 2687import boost_print 2688boost_print.register_printers() 2689end 2690``` 2691 2692If you are getting the following error when running gdb, the `libstdcxx` 2693printers are already preloaded in your environment and you can remove 2694the duplicate import in your `~/.gdbinit` file. 2695 2696``` 2697RuntimeError: pretty-printer already registered: libstdc++-v6 2698``` 2699 2700