# -*- coding:utf-8 -*- import json import subprocess import os import time import random trunk_start, trunk_end = 51, 128 can_used_trunks = set(range(trunk_start, trunk_end)) _cache_available_switch_trunks = {} resource_class = {} hp_info = { "vcpus": "40", "memory_mb": "262144", "local_gb": "446", "vendor": "HP" } resource_class['hp'] = hp_info dell256_info = { "vcpus": "40", "memory_mb": "262144", "local_gb": "446", "vendor": "Dell Inc." } resource_class['dell256'] = dell256_info dell512_info = { "vcpus": "40", "memory_mb": "524288", "local_gb": "446", "vendor": "Dell Inc." } resource_class['dell512'] = dell512_info hw_info = { "vcpus": "32", "memory_mb": "131072", "local_gb": "464", "vendor": "" } resource_class['huawei'] = hw_info def shell(cmd): sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = sp.communicate() return out, err def get_node_info(node): uuid = node.get("UUID") cmd = "openstack baremetal node show %s -f json" % uuid out, err = shell(cmd) return json.loads(out) def doinspect(node): uuid = node.get("UUID") cmd = "openstack baremetal node inspect %s " % uuid shell(cmd) os.system('echo %s >>inspect_log' % cmd) time.sleep(10) def port_group_node(kwargs): node_uuid = kwargs['UUID'] # kwargs['node_uuid'] = node_uuid ### The bond_mode here is fixed as 'balance-rr' kwargs.setdefault('bond_mode', 'balance-rr') ports = kwargs.get('ports', None) # if not ports: # print "the node_info hava no ports, please check" # return switch_ids = set() for port in ports: switch_id = port['Local Link Connection']['switch_id'] switch_ids.add(switch_id) port['switch_id'] = switch_id index = 0 for switch_id in switch_ids: eth_truck = _cache_available_switch_trunks[switch_id].pop() kwargs['eth_trunk'] = eth_truck kwargs['group_name'] = "pg_%s_%s" % (kwargs['Name'], index) index += 1 cmd = ("openstack --os-baremetal-api-version 1.26 baremetal port group create " "--node %(UUID)s --name %(group_name)s " "--mode %(bond_mode)s --property miimon=100 --property Eth-Trunk=%(eth_trunk)s " "--support-standalone-ports -f json" % kwargs) print(cmd) out, err = shell(cmd) group = json.loads(out) if not group: _cache_available_switch_trunks[switch_id].append(eth_trunk) group_uuid = group['uuid'] print('node:%s group:%s' % (node_uuid, group_uuid)) for port in ports: if port['switch_id'] == switch_id: cmd = "openstack --os-baremetal-api-version 1.26 baremetal port set %s --port-group %s" % ( port['UUID'], group_uuid) print(cmd) out, err = shell(cmd) print(err) def get_available_trunk(used_trunks): for switch_id, used_tunks in used_trunks.items(): swich_availe_trunks = _cache_available_switch_trunks.get(switch_id, None) if swich_availe_trunks is None: swich_availe_trunks = (can_used_trunks - set(used_tunks)) _cache_available_switch_trunks[switch_id] = swich_availe_trunks def check_resource_class(node_info): name = node_info.get('Name') node_res_info = { "vcpus": node_info['Properties'].get('cpus', ""), "memory_mb": node_info['Properties'].get('memory_mb', ""), "local_gb": node_info['Properties'].get('local_gb', ""), "vendor": node_info['Extra'].get('system_vendor', {}).get('manufacturer', "") } current_resource_class = node_info['Resource Class'] for i in resource_class: if cmp(resource_class[i], node_res_info) == 0: if i == current_resource_class: os.system('echo "%s resource class ok" >> res_check' % name) else: cmd = ("ironic node-update %s replace resource_class=%s" % (name, i)) shell(cmd) os.system('echo %s >> res_check' % cmd) else: writelog = "%s invaild properties %s" % (name, node_res_info) os.system('echo %s >> res_check' % writelog) def domanage(nodes): for node in nodes: name = node.get("Name") cmd = "openstack baremetal node manage %s" % name shell(cmd) os.system('echo %s >> exec_log' % cmd) def getports(): cmd = 'openstack baremetal port list --long -f json' out, err = shell(cmd) return json.loads(out) def getportgroups(): cmd = 'openstack baremetal port group list --long -f json' out, err = shell(cmd) return json.loads(out) def add_port(nodes_dict, ports): for port in ports: node_uuid = port["Node UUID"] node = nodes_dict.get(node_uuid, None) if node: node["ports"].append(port) def add_portgroup(nodes_dict, ports_info, portgroups_info, switch_infos=None): for port in ports_info: node_uuid = port["Node UUID"] group_uuid = port['Portgroup UUID'] if not group_uuid: continue node = nodes_dict.get(node_uuid, None) if node: node_portgroups = node['portgroups'] node_portgroups.setdefault(group_uuid, {}) node_portgroup = node_portgroups[group_uuid] node_portgroup.setdefault('ports', []) node_portgroup['ports'].append(port) switch_id = port['Local Link Connection']['switch_id'] default_switch_id = node_portgroup.setdefault('switch_id', switch_id) if switch_id != default_switch_id: print('ERROR::::portgroup %s switch_id(%s %s)' % (group_uuid, switch_id, default_switch_id)) for portgroup in portgroups_info: node_uuid = portgroup['Node UUID'] group_uuid = portgroup['UUID'] node = nodes_dict.get(node_uuid, None) if node: node_portgroups = node["portgroups"] node_portgroup = node_portgroups[group_uuid] switch_id = node_portgroup['switch_id'] eth_trunk = portgroup['Properties']['Eth-Trunk'] node_portgroup['eth_trunk'] = eth_trunk if isinstance(switch_infos, dict): switch_infos.setdefault(switch_id, {}) switch_infos[switch_id][group_uuid] = eth_trunk def portgroup_list_to_dict(portgroups): portgroup_dict = {} for portgroup in portgroups: group_uuid = portgroup['UUID'] portgroup_dict[group_uuid] = portgroup return portgroup_dict def get_used_trunk(ports, portgroups): portgroup_dict = portgroup_list_to_dict(portgroups) switch_trunks_used = {} for port in ports: switch_id = port['Local Link Connection']['switch_id'] switch_info = switch_trunks_used.setdefault(switch_id, {}) group_uuid = port['Portgroup UUID'] if not group_uuid: continue switch_info[group_uuid] = portgroup_dict[group_uuid]['Properties']['Eth-Trunk'] ret = {} for switch_id, trunks in switch_trunks_used.items(): ret[switch_id] = sorted(trunks.values()) return ret def node_list_to_dict(nodes): nodes_dict = {} for node in nodes: if node["Provisioning State"] not in ["enroll"]: node_uuid = node["UUID"] node["ports"] = [] node["portgroups"] = {} nodes_dict[node_uuid] = node return nodes_dict def doprovide(nodes): switch_infos = {} ports_info = getports() portgroups_info = getportgroups() random.shuffle(nodes) nodes_dict = node_list_to_dict(nodes) add_port(nodes_dict, ports_info) add_portgroup(nodes_dict, ports_info, portgroups_info, switch_infos) used_trunks = get_used_trunk(ports_info, portgroups_info) get_available_trunk(used_trunks) print _cache_available_switch_trunks node_need_provide = [] for uuid, node in nodes_dict.items(): properties = node['Properties'] if properties: # check resource class check_resource_class(node) # check node port node_ports = node["ports"] node_portgroups = node['portgroups'] if len(node_ports) ==2: if not node_portgroups or len(node_portgroups.keys()) < 1: port_group_node(node) else: node_need_provide.append(uuid) else: output = 'echo "%s %s port num:%s" >>ports_wrong' os.system(output % (name, state, len(node_ports))) else: doinspect(node) time.sleep(10) for node in node_need_provide: cmd='openstack baremetal node provide %s' % node out, err = shell(cmd) if err: print err def get_nodes(): cmd = "openstack baremetal node list --long -f json" out, err = shell(cmd) return json.loads(out) def dowithstatus(nodes): enro_list = [] manage_list = [] for node in nodes: name = node.get("Name") stat = node.get("Provisioning State") if stat == 'enroll': enro_list.append(node) elif stat == 'manageable': manage_list.append(node) elif stat == 'inspect failed': os.system("echo 'error! node %s status :inspect failed' >> node_faild " % name) elif stat == 'error': os.system("echo 'error! node %s status : error' >> node_faild " % name) else: pass allnodes = {"enroll": enro_list, "manageable": manage_list} allfuncs = {'enroll': domanage, 'manageable': doprovide} for key in ("enroll", "manageable"): nodes = allnodes.get(key) func = allfuncs.get(key) if nodes: func(nodes) if __name__ == "__main__": while True: nodes_info = get_nodes() dowithstatus(nodes_info) time.sleep(10)
但谈何容易。