Foreman and Chef integration with SUSE

Problem:
I am trying to get foreman, chef and SUSE all playing together nicely. I got it all setup following the git installation method (as the installer doesn’t like SUSE) and everything is kind of working, but when I looked at the hostlist once a server has checked in using chef-handler-foreman in the chef client there was no information about operating system and platform etc showing. I tracked that down to an error where the foreman_chef plugin was falling back to the generic type Operatingsystem class instead of using the suse class. This was due to the fact that lsb::id is being used for os_name and is set to “SUSE” in capitals which the plugin doesn’t take account off (it needs to be “Suse” I will raise a bug for this shortly.)

If I change the foreman_chef plugin fact_parser.rb to fix the above I then get a new host created every time a server checks with the FQDN as the host name instead of the hostname devoid of the domain (as it was before I fixed it) and I cannot work out why. Basically I either have it erroring in the logs and dropping to the generic os class or I get a constant stream of duplicate hosts if I fix it. It feels like something to do with report import and fact import now doing different things if I fix it.

Expected outcome:
Report and Facts are set against the same host each chef run, duplicate hosts are not created.

Foreman and Proxy versions:
Foreman 1.16, smart_proxy 1.16

Foreman and Proxy plugin versions:
foreman_chef 0.6, smart_proxy_chef 0.2.0

Other relevant data:
What would you like to see?

Make sure you receive correct fqdn, hostname, IP. Some of this could be omitted if you use fact blacklist/whitelist on chef-handler-foreman side. Did you set some limits? Publishing your fix might also help to see, if the patch can cause that. Perhaps the normalizing of lsb/id fact should happen on handler side, see https://github.com/theforeman/chef-handler-foreman/blob/master/lib/chef_handler_foreman/foreman_facts.rb#L63

I worked out that this seemed to be because the node name in Chef was uppercase and not FQDN. This seemed to be causing all the issues.

For info the change I made to the foreman_chef plugin was to change https://github.com/theforeman/foreman_chef/blob/master/app/models/foreman_chef/fact_parser.rb
The case statement at line 26 I added a new case when ‘SUSE’ as so:

  case os_name
    when 'CentOS'
      if major.to_i >= 7
        # get the minor.build number, e.g. 7.2.1511 -> 2.1511
        minor = release[2..-1]
      end
    when 'SUSE'
      os_name = os_name.capitalize
  end

Do avoid the exception occurring at line 35 which was:

2018-03-05T17:41:42 26e666c2 [foreman_chef] [D] Merging facts for 'xxxhost': added 8 
facts
2018-03-05T17:41:42 26e666c2 [foreman_chef] [I] Import facts for 'xxxhost' completed.  
Added: 8, Updated: 106, Deleted 1 facts
2018-03-05T17:41:42 26e666c2 [dynflow] [D] ExecutionPlan afeee7e9-1c19-4849-8f17-81ce91636a8f      
pending >>  planning
2018-03-05T17:41:42 26e666c2 [dynflow] [D]          Step afeee7e9-1c19-4849-8f17-81ce91636a8f: 1   
pending >>   running in phase     Plan Actions::ForemanChef::Host::Update
2018-03-05T17:41:42 26e666c2 [dynflow] [D]          Step afeee7e9-1c19-4849-8f17-81ce91636a8f: 1   
running >>   success in phase     Plan Actions::ForemanChef::Host::Update
2018-03-05T17:41:42 26e666c2 [dynflow] [D] ExecutionPlan afeee7e9-1c19-4849-8f17-81ce91636a8f     
planning >>   planned
2018-03-05T17:41:42 26e666c2 [app] [I] Completed 500 Internal Server Error in 136999ms (ActiveRecord: 
12330.1ms)
2018-03-05T17:41:42 26e666c2 [app] [F]
 | LoadError (Unable to autoload constant SUSE, expected 
/app/foreman/app/models/operatingsystems/suse.rb to define it):
 |   vendor/ruby/2.1.0/gems/foreman_chef-0.6.0/app/models/foreman_chef/fact_parser.rb:37:in 
`operatingsystem'
 |   app/models/host/base.rb:160:in `block in set_non_empty_values'
 |   app/models/host/base.rb:159:in `each'
 |   app/models/host/base.rb:159:in `set_non_empty_values'
 |   app/models/host/base.rb:153:in `populate_fields_from_facts'
 |   app/models/host/managed.rb:390:in `populate_fields_from_facts'
 |   app/models/host/base.rb:131:in `import_facts'
 |   app/models/host/managed.rb:294:in `import_facts'
 |   app/controllers/api/v2/hosts_controller.rb:285:in `facts'
 |   app/controllers/api/v2/base_controller.rb:152:in `disable_json_root'
 |   app/controllers/concerns/application_shared.rb:15:in `set_timezone'
 |   app/models/concerns/foreman/thread_session.rb:32:in `clear_thread'
 |   app/controllers/concerns/foreman/controller/topbar_sweeper.rb:12:in `set_topbar_sweeper_controller'
 |   lib/middleware/catch_json_parse_errors.rb:8:in `call'
 |   lib/middleware/session_safe_logging.rb:17:in `call'
 |   lib/middleware/tagged_logging.rb:18:in `call'
 |
 |

Which in itself causes foreman to end up with 2 nodes named the same in the hostlist one which ends up being the one that works and the other just sitting there never updating. Strange thing is the osname capitalised in chef-handler-foreman during fact processing, so I’m not sure what’s going on there.

It gets worse… SUSE 11 lsb.id is SUSE LINUX.

“lsb”: {
“id”: “SUSE LINUX”,
“description”: “SUSE Linux Enterprise Server 11 (x86_64)”,
“release”: “11”,
“codename”: “n/a”
},

2018-03-08T14:26:28 a996555e [foreman_chef] [D] unknown operating system SUSE LINUX, fallback to generic type
2018-03-08T14:26:29 a996555e [app] [W] Action failed
| ActiveRecord::RecordInvalid: Validation failed: Name can’t contain spaces.

Thinking of changing fact_parser.rb to only ever user the ‘platform’ variable. Seems to be an issue with AIX nodes through Chef as well.

I think it will need complicted if/else branch, similar to what we have for puppet, sadly I don’t have any host with such OS to help.