facter 3.11.3.cfacter.20180716 → 3.11.4.cfacter.20180821

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 59604eb95692d9fe7a11d3c65c28f32a4b807e11
4
- data.tar.gz: e11014d9bfff774641b5fe5c75f81c831671bbe1
3
+ metadata.gz: bcbeadda3a08eb363825fbaa0dbc28aa0ea7d722
4
+ data.tar.gz: 0ceba75967ddc26ded11b2349024518dfe99ab55
5
5
  SHA512:
6
- metadata.gz: dee599e4596509d648066b32ade20990dbe4d430c6a7b8364f3ee75423827e65a6194f871541301a05aed4c28b0e1f79c0590c3d1eabb0f7f12749b91389c6ff
7
- data.tar.gz: 68e4ab3e73b07dbba067e591582199a996a6fd2b58c5f887e010e0dbb4c220d31bed3d7da7eae085c1800233aa96791fb80fa34a6d2c91b9a94de1c17ce8324d
6
+ metadata.gz: be5fb3cf4c2f375c26cc4a0442a03aaa51459295c8851d8155328bcb5a287ec2fb2323a6267d175b4ec087619510932f53a65eb916c5178ea006ac0e1445b73a
7
+ data.tar.gz: f43786a9d453221a5bca2808ceb375aacca08044a0bcc487602cdc0f9c8b52b5d35f670d1161ea1d66f7afed5ffbc6873855ee629a18d39f5d95683983d7641d
@@ -1,5 +1,5 @@
1
1
  cmake_minimum_required(VERSION 3.2.2)
2
- project(FACTER VERSION 3.11.3)
2
+ project(FACTER VERSION 3.11.4)
3
3
 
4
4
  # Set this early, so it's available. AIX gets weird, man.
5
5
  if("${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
@@ -4,39 +4,5 @@ $LOAD_PATH << File.join(RAKE_ROOT, 'tasks')
4
4
  require 'rake'
5
5
  Dir['tasks/**/*.rake'].each { |t| load t }
6
6
 
7
- build_defs_file = File.join(RAKE_ROOT, 'ext', 'build_defaults.yaml')
8
- if File.exist?(build_defs_file)
9
- begin
10
- require 'yaml'
11
- @build_defaults ||= YAML.load_file(build_defs_file)
12
- rescue Exception => e
13
- STDERR.puts "Unable to load yaml from #{build_defs_file}:"
14
- raise e
15
- end
16
- @packaging_url = @build_defaults['packaging_url']
17
- @packaging_repo = @build_defaults['packaging_repo']
18
- raise "Could not find packaging url in #{build_defs_file}" if @packaging_url.nil?
19
- raise "Could not find packaging repo in #{build_defs_file}" if @packaging_repo.nil?
20
-
21
- namespace :package do
22
- desc "Bootstrap packaging automation, e.g. clone into packaging repo"
23
- task :bootstrap do
24
- if File.exist?(File.join(RAKE_ROOT, "ext", @packaging_repo))
25
- puts "It looks like you already have ext/#{@packaging_repo}. If you don't like it, blow it away with package:implode."
26
- else
27
- cd File.join(RAKE_ROOT, 'ext') do
28
- %x{git clone #{@packaging_url}}
29
- end
30
- end
31
- end
32
- desc "Remove all cloned packaging automation"
33
- task :implode do
34
- rm_rf File.join(RAKE_ROOT, "ext", @packaging_repo)
35
- end
36
- end
37
- end
38
-
39
- begin
40
- load File.join(RAKE_ROOT, 'ext', 'packaging', 'packaging.rake')
41
- rescue LoadError
42
- end
7
+ require 'packaging'
8
+ Pkg::Util::RakeUtils.load_packaging_tasks
@@ -1,6 +1,4 @@
1
1
  ---
2
- packaging_url: 'git@github.com:puppetlabs/packaging --branch=master'
3
- packaging_repo: 'packaging'
4
2
  deb_build_mirrors:
5
3
  - deb http://pl-build-tools.delivery.puppetlabs.net/debian __DIST__ main
6
4
  packager: 'puppetlabs'
@@ -91,6 +91,7 @@ if (UNIX)
91
91
  "src/facts/posix/cache.cc"
92
92
  "src/util/posix/scoped_addrinfo.cc"
93
93
  "src/util/posix/scoped_descriptor.cc"
94
+ "src/util/posix/utmpx_file.cc"
94
95
  "src/util/config/posix/config.cc"
95
96
  )
96
97
  if (OPENSSL_FOUND)
@@ -120,6 +121,7 @@ if (AIX)
120
121
  "src/facts/aix/disk_resolver.cc"
121
122
  "src/facts/aix/filesystem_resolver.cc"
122
123
  "src/facts/aix/kernel_resolver.cc"
124
+ "src/facts/aix/load_average_resolver.cc"
123
125
  "src/facts/aix/memory_resolver.cc"
124
126
  "src/facts/aix/networking_resolver.cc"
125
127
  "src/facts/aix/operating_system_resolver.cc"
@@ -38,7 +38,7 @@ PROJECT_NAME = facter
38
38
  # could be handy for archiving the generated documentation or if some version
39
39
  # control system is used.
40
40
 
41
- PROJECT_NUMBER = 3.11.3
41
+ PROJECT_NUMBER = 3.11.4
42
42
 
43
43
  # Using the PROJECT_BRIEF tag one can provide an optional one line description
44
44
  # for a project that appears at the top of each page and should give viewer a
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @file
3
+ * Declares the AIX load average fact resolver.
4
+ */
5
+ #pragma once
6
+
7
+ #include "../resolvers/load_average_resolver.hpp"
8
+
9
+ namespace facter { namespace facts { namespace aix {
10
+
11
+ /**
12
+ * Responsible for resolving the load average facts.
13
+ */
14
+ struct load_average_resolver : resolvers::load_average_resolver
15
+ {
16
+ protected:
17
+ /**
18
+ * Gets the load averages (for 1, 5 and 15 minutes period).
19
+ * @return The load averages.
20
+ */
21
+ virtual boost::optional<std::tuple<double, double, double>> get_load_averages() override;
22
+ };
23
+
24
+ }}} // namespace facter::facts::aix
@@ -117,7 +117,18 @@ namespace facter { namespace util { namespace aix {
117
117
  * @return true if the iterators are not equal
118
118
  */
119
119
  bool operator != (const iterator& rhs) {
120
- return _data != rhs._data && _owner != rhs._owner;
120
+ return _owner != rhs._owner || _data != rhs._data;
121
+ }
122
+
123
+ /**
124
+ * equality comparison.
125
+ * @param rhs the other iterator to compare to
126
+ * @return true if the iterators are equal
127
+ */
128
+ bool operator == (const iterator& rhs) {
129
+ // We could do !(*this != rhs) here, but it's better to inline
130
+ // the expression for performance reasons. It's simple enough.
131
+ return _owner == rhs._owner && _data == rhs._data;
121
132
  }
122
133
 
123
134
  /**
@@ -150,6 +161,14 @@ namespace facter { namespace util { namespace aix {
150
161
  return *_data;
151
162
  }
152
163
 
164
+ /**
165
+ * arrow operator
166
+ * @return a pointer to the held ODM data structure
167
+ */
168
+ const T* operator->() const{
169
+ return _data;
170
+ }
171
+
153
172
  /**
154
173
  * Destructor. Frees any held ODM data.
155
174
  */
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @file
3
+ * Declares an interface for querying the contents of the utmpx file
4
+ */
5
+ #pragma once
6
+
7
+ #include <utmpx.h>
8
+
9
+ namespace facter { namespace util { namespace posix {
10
+
11
+ /**
12
+ * Class representing a utmpx file. We create only one instance at a time since
13
+ * the utmpx API calls deal with global state. See https://linux.die.net/man/3/getutxid
14
+ * for the documentation.
15
+ */
16
+ class utmpx_file {
17
+ public:
18
+ /**
19
+ * Constructs a utmpx_file instance. We only do this if no other utmpx_file instance exists,
20
+ * which we can determine by querying the 'instance_exists' static variable. Otherwise,
21
+ * we throw an std::logic_error.
22
+ */
23
+ utmpx_file();
24
+
25
+ /// deleted copy constructor
26
+ utmpx_file(const utmpx_file&) = delete;
27
+
28
+ /// deleted assignment operator
29
+ /// @return nothing
30
+ utmpx_file& operator=(const utmpx_file&) = delete;
31
+
32
+ /**
33
+ * Destroys our utmpx_file instance. Here, we also set `instance_exists` to false so that another
34
+ * utmpx_file instance can be created.
35
+ */
36
+ ~utmpx_file();
37
+
38
+ /**
39
+ * Returns a pointer to the utmpx entry corresponding to the passed-in query. Make sure
40
+ * that the calling instance does not go out of scope after invoking this method, otherwise
41
+ * the data in the returned utmpx entry will be garbage. Note that this will move the
42
+ * underlying utmpx file pointer forward, so be sure to call reset() if you want subsequent
43
+ * calls to this routine to always start from the beginning of the utmpx file.
44
+ * @param query the utmpx query. See https://www.systutorials.com/docs/linux/man/5-utmpx/
45
+ * @return pointer to the utmpx entry satisfying the query
46
+ */
47
+ const utmpx* query(utmpx const& query) const;
48
+
49
+ /**
50
+ * Resets the utmpx file.
51
+ */
52
+ void reset() const;
53
+
54
+ private:
55
+ static bool instance_exists; // set to true if a utmpx_file instance exists, false otherwise
56
+ };
57
+ }}} // namespace facter::util::posix
@@ -2,6 +2,7 @@
2
2
  #include <internal/facts/aix/disk_resolver.hpp>
3
3
  #include <internal/facts/aix/filesystem_resolver.hpp>
4
4
  #include <internal/facts/aix/kernel_resolver.hpp>
5
+ #include <internal/facts/aix/load_average_resolver.hpp>
5
6
  #include <internal/facts/aix/memory_resolver.hpp>
6
7
  #include <internal/facts/aix/networking_resolver.hpp>
7
8
  #include <internal/facts/aix/operating_system_resolver.hpp>
@@ -19,6 +20,7 @@ namespace facter { namespace facts {
19
20
  add(make_shared<aix::disk_resolver>());
20
21
  add(make_shared<aix::filesystem_resolver>());
21
22
  add(make_shared<aix::kernel_resolver>());
23
+ add(make_shared<aix::load_average_resolver>());
22
24
  add(make_shared<aix::memory_resolver>());
23
25
  add(make_shared<aix::networking_resolver>());
24
26
  add(make_shared<aix::operating_system_resolver>());
@@ -0,0 +1,50 @@
1
+ #include <internal/facts/aix/load_average_resolver.hpp>
2
+ #include <leatherman/logging/logging.hpp>
3
+ #include <leatherman/locale/locale.hpp>
4
+
5
+ #include <sys/inttypes.h>
6
+ #include <sys/kinfo.h>
7
+
8
+ // Mark string for translation (alias for leatherman::locale::format)
9
+ using leatherman::locale::_;
10
+
11
+ using namespace std;
12
+
13
+ /**
14
+ * This system call lets us query the kernel directly for system
15
+ * information. We use it to get our current load averages.
16
+ *
17
+ * @param info the info we're retrieving from the kernel.
18
+ * @param buf the buffer that we'll store the information in
19
+ * @param buf_size a pointer to the variable containing the size of the buffer in bytes
20
+ * @param arg no idea what this param. represents. we will usually set this to 0.
21
+ * @return 0 if we successfully retrieve the information, else a negative value
22
+ */
23
+ extern "C" int getkerninfo(int info, char* buf, int* buf_size, int32long64_t arg);
24
+
25
+ // Converts the given integer average into a load average.
26
+ static double to_load_avg(double average) {
27
+ // 65536 is the load average scale on AIX machines.
28
+ return average / 65536;
29
+ }
30
+
31
+ namespace facter { namespace facts { namespace aix {
32
+
33
+ boost::optional<tuple<double, double, double> > load_average_resolver::get_load_averages()
34
+ {
35
+ // This approach was adapted from screen-4.6.2's loadav.c file. See
36
+ // https://www.mail-archive.com/opensuse-commit@opensuse.org/msg122486.html
37
+ array<long long, 3> averages;
38
+ int buf_size = averages.size() * sizeof(long long);
39
+ int rc = getkerninfo(KINFO_GET_AVENRUN, reinterpret_cast<char*>(averages.data()), &buf_size, 0);
40
+ if (rc < 0) {
41
+ LOG_DEBUG(_("failed to retrieve the load averages"));
42
+ return boost::none;
43
+ }
44
+
45
+ return make_tuple(
46
+ to_load_avg(averages[0]),
47
+ to_load_avg(averages[1]),
48
+ to_load_avg(averages[2]));
49
+ }
50
+ }}} // namespace facter::facts::aix
@@ -1,6 +1,7 @@
1
1
  #include <internal/facts/aix/memory_resolver.hpp>
2
2
  #include <internal/util/aix/odm.hpp>
3
3
 
4
+ #include <leatherman/logging/logging.hpp>
4
5
  #include <sys/vminfo.h>
5
6
  #include <sys/cfgodm.h>
6
7
  #include <sys/limits.h>
@@ -9,6 +10,15 @@
9
10
  using namespace std;
10
11
  using namespace facter::util::aix;
11
12
 
13
+ // This routine is useful to encapsulate knowledge of the PAGE_SIZE
14
+ // in one place and to also handle implicit conversions of numeric
15
+ // values to uint64_t, which is what we use to represent bytes. Otherwise,
16
+ // we risk accidentally capturing an overflowed value in our computed
17
+ // memory facts.
18
+ static uint64_t pages_to_bytes(uint64_t num_pages) {
19
+ return num_pages * PAGE_SIZE;
20
+ }
21
+
12
22
  namespace facter { namespace facts { namespace aix {
13
23
  memory_resolver::data memory_resolver::collect_data(collection& facts)
14
24
  {
@@ -19,8 +29,8 @@ namespace facter { namespace facts { namespace aix {
19
29
  if (res < 0) {
20
30
  throw system_error(errno, system_category());
21
31
  }
22
- result.mem_total = info.memsizepgs * PAGE_SIZE;
23
- result.mem_free = info.numfrb * PAGE_SIZE;
32
+ result.mem_total = pages_to_bytes(info.memsizepgs);
33
+ result.mem_free = pages_to_bytes(info.numfrb);
24
34
 
25
35
  auto cu_at_query = odm_class<CuAt>::open("CuAt").query("value=paging and attribute=type");
26
36
  for (auto& cu_at : cu_at_query) {
@@ -33,14 +43,19 @@ namespace facter { namespace facts { namespace aix {
33
43
  // swapqry the things that have an attribute we
34
44
  // expect, but ignore any errno values that look like
35
45
  // "this just wasn't a good device to query"
46
+ // ENXIO: No such device address.
36
47
  if (errno != ENODEV &&
37
48
  errno != ENOENT &&
38
- errno != ENOTBLK) {
39
- throw system_error(errno, system_category());
49
+ errno != ENOTBLK &&
50
+ errno != ENXIO) {
51
+ throw system_error(errno, system_category(), device);
52
+ } else {
53
+ LOG_DEBUG("cannot use device {1}: error is {2}", device, errno);
40
54
  }
41
55
  }
42
- result.swap_total += info.size * PAGE_SIZE;
43
- result.swap_free += info.free * PAGE_SIZE;
56
+
57
+ result.swap_total += pages_to_bytes(info.size);
58
+ result.swap_free += pages_to_bytes(info.free);
44
59
  }
45
60
 
46
61
  return result;
@@ -1,43 +1,72 @@
1
1
  #include <internal/facts/aix/operating_system_resolver.hpp>
2
+ #include <internal/util/aix/odm.hpp>
3
+ #include <facter/facts/collection.hpp>
4
+ #include <facter/facts/fact.hpp>
2
5
  #include <facter/facts/os.hpp>
3
- #include <leatherman/execution/execution.hpp>
4
- #include <leatherman/file_util/file.hpp>
6
+ #include <facter/facts/array_value.hpp>
7
+ #include <facter/facts/map_value.hpp>
8
+ #include <facter/facts/scalar_value.hpp>
5
9
  #include <leatherman/logging/logging.hpp>
6
- #include <leatherman/util/regex.hpp>
7
10
 
8
11
  #include <boost/algorithm/string.hpp>
12
+ #include <odmi.h>
13
+ #include <sys/cfgodm.h>
9
14
 
10
15
  using namespace std;
11
- using namespace leatherman::util;
12
- using namespace leatherman::file_util;
13
- using namespace boost;
14
- namespace execution = leatherman::execution;
16
+ using namespace facter::util::aix;
15
17
 
18
+ // This routine's meant to be a general utility function that replicates the behavior of
19
+ // lsattr -El <object> -a <field>. Although it's only used to get the modelname of the
20
+ // sys0 device, we still would like to have it here in case we ever need to separate it
21
+ // out to an AIX utils file to query other attributes. Part of what lsattr does is check
22
+ // PdAt if we don't have an entry for the object's attribute in CuAt, even though it is very
23
+ // unlikely that sys0.modelname will not have a CuAt entry. That is why we have the extra code
24
+ // in here.
16
25
  static string getattr(string object, string field)
17
26
  {
18
- string result;
19
-
20
- execution::each_line(
21
- "/usr/sbin/lsattr", {"-El", object, "-a", field},
22
- [&](string& line) {
23
- if (!line.empty()) {
24
- vector<string> tokens;
25
- boost::split(tokens, line, boost::is_space(), boost::token_compress_on);
26
- if (tokens.size() < 2) {
27
- return true;
28
- }
29
- result = tokens[1];
30
- return false;
31
- }
32
- return true;
33
- },
34
- nullptr,
35
- 0);
36
-
37
- if (result == "") {
38
- LOG_WARNING("Could not get a value from lsattr -El {1} -a {2}", object, field);
27
+ // High-level logic here is:
28
+ // * Check if there's an entry for our object's field attribute in CuAt (the device-specific
29
+ // attribute entry).
30
+ //
31
+ // * Else, check for the field attribute's default value in PdAt. We do this by first
32
+ // figuring out the PdDv type from the CuDv entry for the object, then use our PdDv type
33
+ // to query the field's default value in PdAt.
34
+ string query = (boost::format("name = %1% AND attribute = %2%") % object % field).str();
35
+ auto cuat_query = odm_class<CuAt>::open("CuAt").query(query);
36
+
37
+ // This is a more verbose way of saying that we only expect our query to have one element
38
+ auto cuat_ref = cuat_query.begin();
39
+ if (cuat_ref != cuat_query.end()) {
40
+ auto value = string(cuat_ref->value);
41
+ if (value.empty()) {
42
+ LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute.", object, field);
43
+ }
44
+ return value;
45
+ }
46
+
47
+ // Get the PdDv type from the CuDv entry
48
+ query = (boost::format("name = %1%") % object).str();
49
+ auto cudv_query = odm_class<CuDv>::open("CuDv").query(query);
50
+ auto cudv_ref = cudv_query.begin();
51
+ if (cudv_ref == cudv_query.end()) {
52
+ LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute: There is no CuDv entry for {1}.", object, field);
53
+ return "";
39
54
  }
40
- return result;
55
+ auto pddv_type = cudv_ref->PdDvLn_Lvalue;
56
+
57
+ query = (boost::format("uniquetype = %1% AND attribute = %2%") % pddv_type % field).str();
58
+ auto pdat_query = odm_class<PdAt>::open("PdAt").query(query);
59
+ auto pdat_ref = pdat_query.begin();
60
+ if (pdat_ref != pdat_query.end()) {
61
+ auto value = string(pdat_ref->deflt);
62
+ if (value.empty()) {
63
+ LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute.", object, field);
64
+ }
65
+ return value;
66
+ }
67
+
68
+ LOG_DEBUG("Could not get a value from the ODM for {1}'s '{2}' attribute: There is no PdAt entry for {1} with {2}.", object, field);
69
+ return "";
41
70
  }
42
71
 
43
72
  namespace facter { namespace facts { namespace aix {
@@ -53,9 +82,18 @@ namespace facter { namespace facts { namespace aix {
53
82
  boost::split(tokens, result.release, boost::is_any_of("-"));
54
83
  result.major = tokens[0];
55
84
 
56
- result.architecture = getattr("proc0", "type");
85
+ // Get the hardware
57
86
  result.hardware = getattr("sys0", "modelname");
58
87
 
88
+ // Now get the architecture. We use processor.models[0] for this information.
89
+ auto processors = facts.get<map_value>(fact::processors);
90
+ auto models = processors ? processors->get<array_value>("models") : nullptr;
91
+ if (! models || models->empty()) {
92
+ LOG_DEBUG("Could not get a value for the OS architecture. Your machine does not have any processors!");
93
+ } else {
94
+ result.architecture = models->get<string_value>(0)->value();
95
+ }
96
+
59
97
  return result;
60
98
  }
61
99
  }}}
@@ -148,7 +148,7 @@ namespace facter { namespace facts { namespace linux {
148
148
  "throw"
149
149
  };
150
150
 
151
- auto parse_route_line = [&known_route_types](string& line, std::vector<route>& routes) {
151
+ auto parse_route_line = [&known_route_types](string& line, int family, std::vector<route>& routes) {
152
152
  vector<boost::iterator_range<string::iterator>> parts;
153
153
  boost::split(parts, line, boost::is_space(), boost::token_compress_on);
154
154
 
@@ -181,6 +181,18 @@ namespace facter { namespace facts { namespace linux {
181
181
 
182
182
  route r;
183
183
  r.destination.assign(parts[dst_idx].begin(), parts[dst_idx].end());
184
+
185
+ // Check if we queried for the IPV6 routing tables. If yes, then check if our
186
+ // destination address is missing a ':'. If yes, then IPV6 is disabled since
187
+ // IPV6 addresses have a ':' in them. Our ip command has mistakenly outputted IPV4
188
+ // information. This is bogus data that we want to flush.
189
+ //
190
+ // See FACT-1475 for more details.
191
+ if (family == AF_INET6 && r.destination.find(':') == string::npos) {
192
+ routes = {};
193
+ return false;
194
+ }
195
+
184
196
  // Iterate over key/value pairs and add the ones we care
185
197
  // about to our routes entries
186
198
  for (size_t i = dst_idx+1; i < parts.size(); i += 2) {
@@ -197,10 +209,10 @@ namespace facter { namespace facts { namespace linux {
197
209
  };
198
210
 
199
211
  lth_exe::each_line(ip_command, { "route", "show" }, [this, &parse_route_line](string& line) {
200
- return parse_route_line(line, this->routes4);
212
+ return parse_route_line(line, AF_INET, this->routes4);
201
213
  });
202
214
  lth_exe::each_line(ip_command, { "-6", "route", "show" }, [this, &parse_route_line](string& line) {
203
- return parse_route_line(line, this->routes6);
215
+ return parse_route_line(line, AF_INET6, this->routes6);
204
216
  });
205
217
  }
206
218
 
@@ -61,11 +61,13 @@ namespace facter { namespace facts { namespace linux {
61
61
 
62
62
  operating_system_resolver::selinux_data operating_system_resolver::collect_selinux_data()
63
63
  {
64
+ static string SELINUX_CONFIG_FILE("/etc/selinux/config");
65
+
64
66
  selinux_data result;
65
67
  result.supported = true;
66
68
 
67
69
  string mountpoint = get_selinux_mountpoint();
68
- result.enabled = !mountpoint.empty();
70
+ result.enabled = !mountpoint.empty() && exists(SELINUX_CONFIG_FILE);
69
71
  if (!result.enabled) {
70
72
  return result;
71
73
  }
@@ -87,7 +89,7 @@ namespace facter { namespace facts { namespace linux {
87
89
  // Parse the SELinux config for mode and policy
88
90
  static boost::regex mode_regex("(?m)^SELINUX=(\\w+)$");
89
91
  static boost::regex policy_regex("(?m)^SELINUXTYPE=(\\w+)$");
90
- lth_file::each_line("/etc/selinux/config", [&](string& line) {
92
+ lth_file::each_line(SELINUX_CONFIG_FILE, [&](string& line) {
91
93
  if (re_search(line, mode_regex, &result.config_mode)) {
92
94
  return true;
93
95
  }
@@ -1,10 +1,19 @@
1
1
  #include <internal/facts/posix/uptime_resolver.hpp>
2
+ #include <internal/util/posix/utmpx_file.hpp>
2
3
  #include <leatherman/util/regex.hpp>
3
4
  #include <leatherman/execution/execution.hpp>
5
+ #include <leatherman/logging/logging.hpp>
6
+ #include <leatherman/locale/locale.hpp>
7
+
8
+ #include <ctime>
9
+
10
+ // Mark string for translation (alias for leatherman::locale::format)
11
+ using leatherman::locale::_;
4
12
 
5
13
  using namespace std;
6
14
  using namespace leatherman::util;
7
15
  using namespace leatherman::execution;
16
+ using namespace facter::util::posix;
8
17
 
9
18
  namespace facter { namespace facts { namespace posix {
10
19
 
@@ -43,6 +52,16 @@ namespace facter { namespace facts { namespace posix {
43
52
 
44
53
  int64_t uptime_resolver::get_uptime()
45
54
  {
55
+ LOG_DEBUG(_("Attempting to calculate the uptime from the utmpx file"));
56
+ utmpx query;
57
+ query.ut_type = BOOT_TIME;
58
+ utmpx_file file;
59
+ auto ent = file.query(query);
60
+ if (ent) {
61
+ return time(NULL) - ent->ut_tv.tv_sec;
62
+ }
63
+ LOG_DEBUG(_("Could not calculate the uptime from the utmpx file"));
64
+
46
65
  auto exec = execute("uptime");
47
66
  if (!exec.success) {
48
67
  return -1;
@@ -0,0 +1,36 @@
1
+ #include <internal/util/posix/utmpx_file.hpp>
2
+ #include <leatherman/locale/locale.hpp>
3
+ #include <leatherman/logging/logging.hpp>
4
+
5
+ // Mark string for translation (alias for leatherman::locale::format)
6
+ using leatherman::locale::_;
7
+
8
+ using namespace std;
9
+
10
+ namespace facter { namespace util { namespace posix {
11
+
12
+ bool utmpx_file::instance_exists = false;
13
+
14
+ utmpx_file::utmpx_file() {
15
+ if (utmpx_file::instance_exists) {
16
+ throw logic_error(_("only one utmpx_file instance can exist at a time!"));
17
+ }
18
+
19
+ utmpx_file::instance_exists = true;
20
+ reset();
21
+ }
22
+
23
+ utmpx_file::~utmpx_file() {
24
+ endutxent();
25
+ utmpx_file::instance_exists = false;
26
+ }
27
+
28
+ const utmpx* utmpx_file::query(utmpx const& query) const {
29
+ LOG_DEBUG(_("Reading the utmpx file ..."));
30
+ return getutxid(&query);
31
+ }
32
+
33
+ void utmpx_file::reset() const {
34
+ setutxent();
35
+ }
36
+ }}} // namespace facter::util::posix
@@ -6,7 +6,7 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: FACTER 3.11.3\n"
9
+ "Project-Id-Version: FACTER 3.11.4\n"
10
10
  "Report-Msgid-Bugs-To: docs@puppet.com\n"
11
11
  "POT-Creation-Date: \n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
@@ -316,6 +316,15 @@ msgstr ""
316
316
  msgid "querylv returned success but we got a null LV. WTF?"
317
317
  msgstr ""
318
318
 
319
+ #: lib/src/facts/aix/load_average_resolver.cc
320
+ msgid "failed to retrieve the load averages"
321
+ msgstr ""
322
+
323
+ #. debug
324
+ #: lib/src/facts/aix/memory_resolver.cc
325
+ msgid "cannot use device {1}: error is {2}"
326
+ msgstr ""
327
+
319
328
  #: lib/src/facts/aix/networking_resolver.cc
320
329
  msgid "getkerninfo call was unsuccessful"
321
330
  msgstr ""
@@ -352,9 +361,42 @@ msgstr ""
352
361
  msgid "got an unknown RT_IFLIST message: {1}"
353
362
  msgstr ""
354
363
 
355
- #. warning
356
364
  #: lib/src/facts/aix/operating_system_resolver.cc
357
- msgid "Could not get a value from lsattr -El {1} -a {2}"
365
+ msgid "name = %1% AND attribute = %2%"
366
+ msgstr ""
367
+
368
+ #. debug
369
+ #: lib/src/facts/aix/operating_system_resolver.cc
370
+ msgid "Could not get a value from the ODM for {1}'s '{2}' attribute."
371
+ msgstr ""
372
+
373
+ #: lib/src/facts/aix/operating_system_resolver.cc
374
+ msgid "name = %1%"
375
+ msgstr ""
376
+
377
+ #. debug
378
+ #: lib/src/facts/aix/operating_system_resolver.cc
379
+ msgid ""
380
+ "Could not get a value from the ODM for {1}'s '{2}' attribute: There is no "
381
+ "CuDv entry for {1}."
382
+ msgstr ""
383
+
384
+ #: lib/src/facts/aix/operating_system_resolver.cc
385
+ msgid "uniquetype = %1% AND attribute = %2%"
386
+ msgstr ""
387
+
388
+ #. debug
389
+ #: lib/src/facts/aix/operating_system_resolver.cc
390
+ msgid ""
391
+ "Could not get a value from the ODM for {1}'s '{2}' attribute: There is no "
392
+ "PdAt entry for {1} with {2}."
393
+ msgstr ""
394
+
395
+ #. debug
396
+ #: lib/src/facts/aix/operating_system_resolver.cc
397
+ msgid ""
398
+ "Could not get a value for the OS architecture. Your machine does not have "
399
+ "any processors!"
358
400
  msgstr ""
359
401
 
360
402
  #. debug
@@ -959,6 +1001,14 @@ msgstr ""
959
1001
  msgid "strftime failed: timezone is unavailable."
960
1002
  msgstr ""
961
1003
 
1004
+ #: lib/src/facts/posix/uptime_resolver.cc
1005
+ msgid "Attempting to calculate the uptime from the utmpx file"
1006
+ msgstr ""
1007
+
1008
+ #: lib/src/facts/posix/uptime_resolver.cc
1009
+ msgid "Could not calculate the uptime from the utmpx file"
1010
+ msgstr ""
1011
+
962
1012
  #. debug
963
1013
  #: lib/src/facts/posix/xen_resolver.cc
964
1014
  msgid "failure executing {1}: {2}"
@@ -1493,6 +1543,14 @@ msgstr ""
1493
1543
  msgid "a block is unexpected when passing a String"
1494
1544
  msgstr ""
1495
1545
 
1546
+ #: lib/src/util/posix/utmpx_file.cc
1547
+ msgid "only one utmpx_file instance can exist at a time!"
1548
+ msgstr ""
1549
+
1550
+ #: lib/src/util/posix/utmpx_file.cc
1551
+ msgid "Reading the utmpx file ..."
1552
+ msgstr ""
1553
+
1496
1554
  #: lib/src/util/solaris/k_stat.cc
1497
1555
  msgid "kstat_open failed"
1498
1556
  msgstr ""
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: facter
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.11.3.cfacter.20180716
4
+ version: 3.11.4.cfacter.20180821
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-07-16 00:00:00.000000000 Z
12
+ date: 2018-08-21 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: info@puppet.com
@@ -360,6 +360,7 @@ files:
360
360
  - ext/facter/facter/lib/inc/internal/facts/aix/disk_resolver.hpp
361
361
  - ext/facter/facter/lib/inc/internal/facts/aix/filesystem_resolver.hpp
362
362
  - ext/facter/facter/lib/inc/internal/facts/aix/kernel_resolver.hpp
363
+ - ext/facter/facter/lib/inc/internal/facts/aix/load_average_resolver.hpp
363
364
  - ext/facter/facter/lib/inc/internal/facts/aix/memory_resolver.hpp
364
365
  - ext/facter/facter/lib/inc/internal/facts/aix/networking_resolver.hpp
365
366
  - ext/facter/facter/lib/inc/internal/facts/aix/operating_system_resolver.hpp
@@ -485,6 +486,7 @@ files:
485
486
  - ext/facter/facter/lib/inc/internal/util/posix/scoped_addrinfo.hpp
486
487
  - ext/facter/facter/lib/inc/internal/util/posix/scoped_bio.hpp
487
488
  - ext/facter/facter/lib/inc/internal/util/posix/scoped_descriptor.hpp
489
+ - ext/facter/facter/lib/inc/internal/util/posix/utmpx_file.hpp
488
490
  - ext/facter/facter/lib/inc/internal/util/scoped_file.hpp
489
491
  - ext/facter/facter/lib/inc/internal/util/solaris/k_stat.hpp
490
492
  - ext/facter/facter/lib/inc/internal/util/solaris/scoped_kstat.hpp
@@ -501,6 +503,7 @@ files:
501
503
  - ext/facter/facter/lib/src/facts/aix/disk_resolver.cc
502
504
  - ext/facter/facter/lib/src/facts/aix/filesystem_resolver.cc
503
505
  - ext/facter/facter/lib/src/facts/aix/kernel_resolver.cc
506
+ - ext/facter/facter/lib/src/facts/aix/load_average_resolver.cc
504
507
  - ext/facter/facter/lib/src/facts/aix/memory_resolver.cc
505
508
  - ext/facter/facter/lib/src/facts/aix/networking_resolver.cc
506
509
  - ext/facter/facter/lib/src/facts/aix/operating_system_resolver.cc
@@ -641,6 +644,7 @@ files:
641
644
  - ext/facter/facter/lib/src/util/posix/scoped_addrinfo.cc
642
645
  - ext/facter/facter/lib/src/util/posix/scoped_bio.cc
643
646
  - ext/facter/facter/lib/src/util/posix/scoped_descriptor.cc
647
+ - ext/facter/facter/lib/src/util/posix/utmpx_file.cc
644
648
  - ext/facter/facter/lib/src/util/scoped_file.cc
645
649
  - ext/facter/facter/lib/src/util/solaris/k_stat.cc
646
650
  - ext/facter/facter/lib/src/util/solaris/scoped_kstat.cc