1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
|
The CFEngine 3 inventory modules are pieces of CFEngine policy that are loaded
and used by `promises.cf` in order to *inventory* the system.
CFEngine Enterprise has specific functionality to show and use inventory data,
but users of the Community Version can use them as well locally on each host.
## How It Works
The inventory modules are called in `promises.cf`:
```
body common control
{
bundlesequence => {
# Common bundle first (Best Practice)
inventory_control,
@(inventory.bundles),
...
```
As you see, this calls the `inventory_control` bundle, and then each
bundle in the list `inventory.bundles`. That list is built in the
top-level common `inventory` bundle, which will load the right things
for some common cases. The `any.cf` inventory module is always loaded;
the rest are loaded if they are appropriate for the platform. For
instance, Debian systems will load `debian.cf` and `linux.cf` and
`lsb.cf` but may load others as needed.
The effect for users is that the right inventory modules will be
loaded and evaluated.
The `inventory_control` bundle lives in `def.cf` and defines what
inventory modules should be disabled. You can simply set
`disable_inventory` to avoid the whole system, or you can look for the
`disable_inventory_xyz` class to disable module `xyz`.
Any inventory module works the same way, by doing some discovery work
and then tagging its classes and variables with the `report` or
`inventory` tags. For example:
```
vars:
"ports" slist => { @(mon.listening_ports) },
meta => { "inventory", "attribute_name=Ports listening" };
```
This defines a reported attribute "Ports listening" which contains a
list of strings representing the listening ports. More on this in a
second.
## Your Very Own Inventory Module
The good news is, writing an inventory module is incredibly easy.
They are just CFEngine bundles. You can see a simple one that collects
the listening ports in `any.cf`:
```cf3
bundle agent cfe_autorun_inventory_listening_ports
# @brief Inventory the listening ports
#
# This bundle uses `mon.listening_ports` and is always enabled by
# default, as it runs instantly and has no side effects.
{
vars:
"ports" slist => { @(mon.listening_ports) },
meta => { "inventory", "attribute_name=Ports listening" };
}
```
Well, the slist copy is a CFEngine detail (we get the listening ports from the
monitoring daemon), so just assume that the data is correct. What's important is
the second line that starts with [`meta`](https://docs.cfengine.com/docs/master/reference-promise-types.html#meta).
That defines metadata for the promise that CFEngine will use to determine that
this data is indeed inventory data and should be reported to the CFEngine
Enterprise Hub.
That's it. Really. The comments are optional but nice to have. You don't have to
put your new bundle in a file under the `inventory` directory, either. The
variables and classes can be declared anywhere as long as they have the right
tags. So you can use the `services` directory or whatever else makes sense to
you.
# CFEngine Enterprise vs. Community
In CFEngine Enterprise, the reported data is aggregated in the hub and
reported across the whole host population.
In CFEngine Community, users can use the `classesmatching()` and
`variablesmatching()` functions to collect all the inventory variables
and classes and report them in other ways.
## Implementation Best Practice for CFEngine Enterprise
It is important that inventory variables and classes are continually
defined. Only inventory variables and classes defined during the last
reported run are available for use by the inventory reporting interface.
Inventory items that change frequently can create a burden on the
Enterprise reporting infrastructure. Generally, inventory attributes
should change infrequently.
If you wish to inventory attributes that frequently change or are expensive to
discover consider implementing a sample interval and caching mechanism.
# What Modules Are Available?
As soon as you use the `promises.cf` provided in the parent directory,
quite a few inventory modules will be enabled (if appropriate for your
system). Here's the list of modules and what they provide. Note they
are all enabled by code in `def.cf` as explained above.
## Package Inventory
* lives in: `any.cf`
* applies to: All systems
* runs: package modules in order to report on packages installed and patches
available
* disable: define the class ```disable_inventory_package_refresh```. Note this
also disables the default package inventory used by the new packages promise
implementation. This will cause the ```packagesmatching()``` and
```packageupdatesmatching()``` functions to rely on data supplied by the
legacy package promise implementation.
## LSB
* lives in: `lsb.cf`
* applies to: LSB systems (most Linux distributions, basically)
* runs: `lsb_release -a`
* sample data:
```
Distributor ID: Ubuntu
Description: Ubuntu 14.04 LTS
Release: 14.04
Codename: trusty
```
* provides:
* classes `lsb_$(os)`, `lsb_$(os)_$(release)`, `lsb_$(os)_$(codename)`
* variables: `inventory_lsb.os` (Distributor ID), `inventory_lsb.codename`, `inventory_lsb.release`, `inventory_lsb.flavor`, `inventory_lsb.description`
* sample output:
```
% cf-agent -KI -binventory_control,inventory_lsb
R: inventory_lsb: OS = Ubuntu, codename = trusty, release = 14.04, flavor = Ubuntu_14_04, description = Ubuntu 14.04 LTS
```
## SUSE
* lives in: `suse.cf`
* applies to: SUSE Linux
* provides classes: `suse_pure` and `suse_derived`
## Debian
* lives in: `debian.cf`
* applies to: Debian and its derivatives
* provides:
* variables: `inventory_debian.mint_release` and `inventory_debian.mint_codename`
* classes: `debian_pure`, `debian_derived`, `linuxmint`, `lmde`, `linuxmint_$(mint_release)`, `linuxmint_$(mint_codename)`, `$(mint_codename)`
## Red Hat
* lives in: `redhat.cf`
* applies to: Red Hat and its derivatives
* provides classes: `redhat_pure`, `redhat_derived`
## Windows
* lives in: `windows.cf`
## Mac OS X
* lives in: `macos.cf`
## Generic (unknown OS)
* lives in: `generic.cf` (see `any.cf` for generally applicable inventory modules)
## LLDP
* lives in: `any.cf`
* runs `inventory_control.lldpctl_exec` through a Perl filter
* provides variables: `cfe_autorun_inventory_LLDP.K` for each `K` returned by the LLDB executable
## mtab
* lives in: `any.cf`
* parses: `/etc/mtab`
* provides classes: `have_mount_FSTYPE` and `have_mount_FSTYPE_MOUNTPOINT`
* sample output (note this is verbose mode with `-v` because there's a lot of output):
```
% cf-agent -Kv -binventory_control,cfe_autorun_inventory_mtab|grep 'cfe_autorun_inventory_mtab: we have'
R: cfe_autorun_inventory_mtab: we have a ext4 mount under /
...
R: cfe_autorun_inventory_mtab: we have a cgroup mount under /sys/fs/cgroup/systemd
R: cfe_autorun_inventory_mtab: we have a tmpfs mount under /run/shm
```
## fstab
* lives in: `any.cf`
* parses: `sys.fstab`
* provides classes: `have_fs_FSTYPE` `have_fs_MOUNTPOINT` and `have_fs_FSTYPE_MOUNTPOINT`
* sample output (note this is verbose mode with `-v` because there's a LOT of output):
```
% cf-agent -Kv -binventory_control,cfe_autorun_inventory_fstab|grep 'cfe_autorun_inventory_fstab: we have'
R: cfe_autorun_inventory_fstab: we have a ext4 fstab entry under /
R: cfe_autorun_inventory_fstab: we have a cifs fstab entry under /backups/load
R: cfe_autorun_inventory_fstab: we have a auto fstab entry under /mnt/cdrom
```
## DMI decoding
* lives in: `any.cf`
* runs: `dmidecode`
* provides variables: `cfe_autorun_inventory_dmidecode.dmi[K]` for each key K in the `dmidecode` output
* sample output (sudo is needed to access the DMI):
```
% sudo /var/cfengine/bin/cf-agent -KI -binventory_control,cfe_autorun_inventory_dmidecode
R: cfe_autorun_inventory_dmidecode: Obtained BIOS vendor = 'Intel Corp.'
R: cfe_autorun_inventory_dmidecode: Obtained BIOS version = 'BLH6710H.86A.0146.2013.1555.1888'
R: cfe_autorun_inventory_dmidecode: Obtained System serial number = ''
R: cfe_autorun_inventory_dmidecode: Obtained System manufacturer = ''
R: cfe_autorun_inventory_dmidecode: Obtained System version = ''
R: cfe_autorun_inventory_dmidecode: Obtained CPU model = 'Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz'
```
## Listening ports
* lives in: `any.cf`
* provides variables: `cfe_autorun_inventory_listening_ports.ports` as a copy of `mon.listening_ports`
## Disk space
* lives in: `any.cf`
* provides variables: `cfe_autorun_inventory_disk.free` as a copy of `mon.value_diskfree`
## Available memory
* lives in: `any.cf`
* provides variables: `cfe_autorun_inventory_memory.free` as a copy of `mon.value_mem_free` and `cfe_autorun_inventory_memory.total` as a copy of `mon.value_mem_total`
## Load average
* lives in: `any.cf`
* provides variables: `cfe_autorun_inventory_loadaverage.value` as a copy of `mon.value_loadavg`
## procfs
* lives in: `any.cf`
* parses: `consoles`, `cpuinfo`, `modules`, `partitions`, `version`
* provides variables: `cfe_autorun_inventory_proc.console_count`, `cfe_autorun_inventory_proc.cpuinfo[K]` for each CPU info key, `cfe_autorun_inventory_proc.paritions[K]` for each partition key
* provides classes: `_have_console_CONSOLENAME`, `have_module_MODULENAME`
* sample output (note this is verbose mode with `-v` because there's a LOT of output):
```
% cf-agent -Kv -binventory_control,cfe_autorun_inventory_proc|grep 'cfe_autorun_inventory_proc: we have'
R: cfe_autorun_inventory_proc: we have console tty0
R: cfe_autorun_inventory_proc: we have module snd_seq_midi
...
R: cfe_autorun_inventory_proc: we have module ghash_clmulni_intel
R: cfe_autorun_inventory_proc: we have cpuinfo flags = fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm ida arat epb xsaveopt pln pts dtherm tpr_shadow vnmi flexpriority ept vpid
...
R: cfe_autorun_inventory_proc: we have cpuinfo model name = Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
R: cfe_autorun_inventory_proc: we have partitions sr0 with 1048575 blocks
...
R: cfe_autorun_inventory_proc: we have partitions sda with 468851544 blocks
R: cfe_autorun_inventory_proc: we have kernel version 'Linux version 3.11.0-15-generic (buildd@roseapple) (gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu8) ) #25-Ubuntu SMP Thu Jan 30 17:22:01 UTC 2014'
```
|