Details
-
Improvement
-
Status: Resolved
-
Normal
-
Resolution: Fixed
-
FACT 2.4.6
-
None
-
Nano Server TP5
-
-
Agent
-
2
-
Agent 2017-05-31
-
No Action
Description
Facter 2.x uses WIN32OLE.connect with a COM moniker:
"winmgmts:{impersonationLevel=impersonate}!//#{host}/root/cimv2"
to connect to the local machine WMI. However, Nano Server has removed COM monikers altogether, so that won't work in that environment. The alternative is to create an instance of WbemScripting.SWbemLocator, and then call ConnectServer against it.
Note that Facter::Util::WMI currently accepts a uri parameter to the connect method. Since this API is public, we may have to decompose the given URI into parts that can be passed to WbemScripting.SWbemLocator - a naive regex capture may be entirely sufficient in this case to support a minimum moniker string - see the specs at https://msdn.microsoft.com/en-us/library/aa389292(v=vs.85).aspx.
The alternative is to bump the Facter version to 2.5 in an effort to indicate an API change for anyone consuming Facter::Util::WMI, but that's probably unadvisable given this may be a common entry point for users writing custom facts. We can still easily remain backward compatible with those using execquery, but connect(uri) is the primary sticking point here. We could scan all of the modules uploaded to the Forge to identify module consumption of this API.
NOTE: Ruby relies on OleInitialize to be called internally as part of using its WIN32OLE class, which is documented to initialize COM with CoInitiailzeEx as an STA. Nano does not support STA, but in Nano TP5, OleInitialize succeeds because it is really initializing as MTA under the hood. It's possible that Microsoft will completely remove OleInitialize in the future, which might mean we have to give up on WIN32OLE or find other avenues of supporting WMI queries. One option is to reimplement WMI support with the native MI APIs (which are not supported on all the operating systems Puppet supports).
alexpilotti has spiked a quick PR to https://github.com/puppetlabs/facter/pull/1327/files#diff-6c0a571515f6f937e35e5b86cbeb8821R11 demonstrating a workaround. One thing that we could do is implement a new method connect_server(host, namespace) and call that from execquery, leaving the original connect intact.