The College of Engineering has been running a Foreman service for tenants within our college (and some outside) for a few years now. Our involvement in cultivating and growing the Campus Linux Services (CLS) group has led to one inevitable terminus: It’s time for us to move all of our Puppet-based hosts from one CFM infrastructure to another!
We (the CLS community) will be making a set of posts here to share what we’re learning as we move hundreds of hosts from one environment to another. Several important documents detailing our process have already been posted to the CLS area on Google Team Drive (email group-campus-linux@ncsu.edu for access). One of MANY issues that have to be solved is actually doing the grunt-work of re-creating all Foreman hosts (and their dependencies) in the target infrastructure. This post covers ONE of those dependencies, subnets.
The CLS infrastructure treats subnet data very differently than our Engineering Foreman service did. Instead of synchronizing subnet data from our IPAM system as it’s own separate thing, we now attach subnets to tenant configuration. Take for example the “COEDEAN” (that’s us) tenant configuration:
global::infrastructure: tenants: COEDEAN: control_repository: git@github.ncsu.edu:itecs-puppet/coedean-control.git members_group: COE-Foreman.Administrators domains: - ce.ncsu.edu - che.ncsu.edu - eos.ncsu.edu - mae.ncsu.edu subnets: VLAN213-PA-ECO-CLIENTS-6: cidr: 152.1.68.0/24 vlanid: 213 VLAN37-DC-ITECS-Public: cidr: 152.1.0.0/24 vlanid: 37 VLAN912-DC0-ITECS-1: cidr: 152.7.130.64/26 vlanid: 912
This is our tenant configuration as of 7/25/2018. At this point, we had a few test machines in a few VLANs, but by no means had every VLAN we provision machines into represented. We needed an easy way to see which VLANs we were actually using so that we could send a pull request to add the VLANs that were missing.
Ruby to the rescue!
We use a Ruby script to call Hammer CLI commands on the source Foreman node. Basically, the gist is to iterate over every host record and scrape the “subnet_name” from it. From that information alone, we have all we need to provision the subnets in the CLS infrastructure. The script is hosted on GitHub, but here it is in its entirety for purposes of discussion in this post:
#!/bin/env ruby require 'yaml' require 'optparse' options = {} optparse = OptionParser.new do |opts| opts.banner = 'Usage: foreman_subnets.rb --slug="TENANT"' opts.on('-s', '--slug ARG', 'Root-level hostgroup name') do |arg| options[:slug] = arg end opts.on('--no-subnet', 'Find hosts with no subnet') do |arg| options[:no_subnet] = true end end optparse.parse! raise OptionParser::MissingArgument if options[:slug].nil? host_list = YAML.load(%x{ hammer --output=yaml host list --search="hostgroup_fullname ~ "#{options[:slug]}*"" }) if options[:no_subnet] hosts = host_list.map do |host| host["Name"] if host["Operating System"]["subnet_name"].nil? end.compact puts hosts else hosts = host_list.map do |host| host["Operating System"]["subnet_name"] end.uniq.compact puts hosts end
Using this command, you can do the following:
[root@engr-for-200 scripts]# ruby foreman_subnets.rb --slug=COEDEAN VLAN213-PA-ECO-CLIENTS-6 (152.1.68.0/24) VLAN209-MN-CE-1 (152.1.55.0/26) VLAN202-BR-MAE-1 (152.1.69.0/24) <snip> VLAN254-DAN-6 (152.1.108.0/24) VLAN910-JHL-STUDENT-NONVDI-1 (152.14.142.0/24) VLAN403-PT1-2 (152.14.20.128/26)
Finally, to catch any hosts who aren’t associated with any subnet at all…
[root@engr-for-200 scripts]# ruby foreman_subnets.rb --slug=COEDEAN --no-subnet itecs-lt-49.eos.ncsu.edu itecs-lt-50.eos.ncsu.edu logicbomb.eos.ncsu.edu
These machines will need to be fixed up before they can be migrated.
Up next
I’ll be making a post about exporting host data from one Foreman environment to be able to create new hosts in a separate target Foreman environment.