e2a8a494c5
We need to be able to handle when system uuids are upper or lower case because newer versions of dmidecode have normalized to lower case. Users who were on CentOS/RHEL 7.5 and older may have per-node customizations with upper case which turn lowercase with an update to 7.6. This affects hieradata customizations as well as os-net-config mapping files. This change outputs both an upper and lowercase hieradata uuid file to handle the both versions of the UUID. Additionally this change normalizes the id comparison for os-net-config mappings to lower case. Change-Id: I65f46056f8a908c60c99d1cee3738344a0bce6b7 Closes-Bug: #1816652
121 lines
4.3 KiB
YAML
121 lines
4.3 KiB
YAML
heat_template_version: rocky
|
|
|
|
description: >
|
|
Configure os-net-config mappings for specific nodes
|
|
Your environment file needs to look like:
|
|
parameter_defaults:
|
|
NetConfigDataLookup:
|
|
node1:
|
|
nic1: "00:c8:7c:e6:f0:2e"
|
|
node2:
|
|
nic1: "00:18:7d:99:0c:b6"
|
|
node3:
|
|
dmiString: 'system-uuid'
|
|
id: 'A8C85861-1B16-4803-8689-AFC62984F8F6'
|
|
nic1: em3
|
|
# Dell PowerEdge
|
|
nodegroup1:
|
|
dmiString: "system-product-name"
|
|
id: "PowerEdge R630"
|
|
nic1: em3
|
|
nic2: em1
|
|
nic3: em2
|
|
# Cisco UCS B200-M4"
|
|
nodegroup2:
|
|
dmiString: "system-product-name"
|
|
id: "UCSB-B200-M4"
|
|
nic1: enp7s0
|
|
nic2: enp6s0
|
|
|
|
This will result in the first node* entry where either:
|
|
a) a mac matches a local device
|
|
or b) a DMI String matches the specified id
|
|
being written as a mapping file for os-net-config in
|
|
/etc/os-net-config/mapping.yaml
|
|
|
|
parameters:
|
|
# Note this requires a liberty heat or newer in the undercloud due to
|
|
# the 2015-10-15 (which is required to enable str_replace serializing
|
|
# the json parameter to json, another approch with a string parameter
|
|
# will be required for older heat versions)
|
|
NetConfigDataLookup:
|
|
type: json
|
|
default: {}
|
|
description: per-node configuration map
|
|
|
|
resources:
|
|
userdata:
|
|
type: OS::Heat::MultipartMime
|
|
properties:
|
|
parts:
|
|
- config: {get_resource: OsNetConfigMappings}
|
|
|
|
OsNetConfigMappings:
|
|
type: OS::Heat::SoftwareConfig
|
|
properties:
|
|
group: ungrouped
|
|
config:
|
|
str_replace:
|
|
template: |
|
|
#!/bin/sh
|
|
eth_addr=$(cat /sys/class/net/*/address | tr '\n' ',')
|
|
mkdir -p /etc/os-net-config
|
|
|
|
# needed to handle where python lives
|
|
function get_python() {
|
|
command -v python3 || command -v python2 || command -v python || exit 1
|
|
}
|
|
|
|
# Create an os-net-config mapping file, note this defaults to
|
|
# /etc/os-net-config/mapping.yaml, so we use that name despite
|
|
# rendering the result as json
|
|
echo '$node_lookup' | $(get_python) -c "
|
|
import json
|
|
import sys
|
|
import copy
|
|
from subprocess import PIPE, Popen
|
|
import yaml
|
|
|
|
def write_mapping_file(interface_mapping):
|
|
with open('/etc/os-net-config/mapping.yaml', 'w') as f:
|
|
yaml.safe_dump(interface_mapping, f, default_flow_style=False)
|
|
|
|
# cast to lower case for MAC address match
|
|
eth_addr='$eth_addr'.lower()
|
|
|
|
input = sys.stdin.readline() or '{}'
|
|
data = json.loads(input)
|
|
for node in data:
|
|
interface_mapping = {'interface_mapping':
|
|
copy.deepcopy(data[node])}
|
|
if 'dmiString' in interface_mapping['interface_mapping']:
|
|
del interface_mapping['interface_mapping']['dmiString']
|
|
if 'id' in interface_mapping['interface_mapping']:
|
|
del interface_mapping['interface_mapping']['id']
|
|
|
|
# Match on mac addresses first - cast all to lower case
|
|
lc_interface_mapping = copy.deepcopy(interface_mapping)
|
|
for key,x in lc_interface_mapping['interface_mapping'].items():
|
|
lc_interface_mapping['interface_mapping'][key] = x.lower()
|
|
if any(x in eth_addr.split(',') for x in lc_interface_mapping['interface_mapping'].values()):
|
|
write_mapping_file(lc_interface_mapping)
|
|
break
|
|
|
|
# If data contain dmiString and id keys, try to match node(group)
|
|
if 'dmiString' in data[node] and 'id' in data[node]:
|
|
ps = Popen([ 'dmidecode',
|
|
'--string', data[node].get('dmiString') ],
|
|
stdout=PIPE, universal_newlines=True)
|
|
out, err = ps.communicate()
|
|
# See LP#1816652
|
|
if data[node].get('id').lower() == out.rstrip().lower():
|
|
write_mapping_file(lc_interface_mapping)
|
|
break
|
|
"
|
|
params:
|
|
$node_lookup: {get_param: NetConfigDataLookup}
|
|
|
|
outputs:
|
|
OS::stack_id:
|
|
value: {get_resource: userdata}
|