gushiren

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
# -*- 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)
View Code

 

posted on 2018-08-22 11:02  gushiren  阅读(389)  评论(2编辑  收藏  举报