From d1946af0d57f2fd7b17076acc4b6e38247111a44 Mon Sep 17 00:00:00 2001 From: ertaozh Date: Tue, 13 Feb 2018 09:19:08 -0500 Subject: [PATCH] add rspconfig get network information --- .../agent/hwctl/executor/openbmc_bmcconfig.py | 177 ++++++++++++++++-- .../lib/python/agent/hwctl/openbmc_client.py | 12 ++ 2 files changed, 171 insertions(+), 18 deletions(-) diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py index b7ae94bed..565a7d312 100644 --- a/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py @@ -5,12 +5,15 @@ # -*- coding: utf-8 -*- # from __future__ import print_function -import gevent -import time +import os, stat +from common import utils from common.task import ParallelNodesCommand from common.exceptions import SelfClientException, SelfServerException from hwctl import openbmc_client as openbmc +#from paramiko import SSHClient +from pssh.pssh_client import ParallelSSHClient +from gevent import joinall import logging logger = logging.getLogger('xcatagent') @@ -18,6 +21,8 @@ logger = logging.getLogger('xcatagent') RSPCONFIG_GET_NETINFO=['ip', 'netmask', 'gateway', 'vlan', 'ipsrc', 'hostname'] RSPCONFIG_SET_NETINFO=['ip', 'netmask', 'gateway', 'vlan'] + + class OpenBMCBmcConfigTask(ParallelNodesCommand): def dump_list(self, **kw): @@ -35,8 +40,65 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): def dump_process(self, **kw): return self.callback.info("dump_process: trigger, list and download") + def _create_copy_file(self, filename): + f = open(filename, 'w') + f.write("#!/bin/sh \n\ +umask 0077 \n\ +userid=$1 \n\ +home=`egrep \"^$userid:\" /etc/passwd | cut -f6 -d :` \n\ +if [ -n \"$home\" ]; then \n\ + dest_dir=\"$home/.ssh\" \n\ +else \n\ + home=`su - root -c pwd` \n\ + dest_dir=\"$home/.ssh\" \n\ +fi \n\ +mkdir -p $dest_dir \n\ +cat /tmp/$userid/.ssh/id_rsa.pub >> $dest_dir/authorized_keys 2>&1 \n\ +rm -f /tmp/$userid/.ssh/* 2>&1 \n\ +rmdir \"/tmp/$userid/.ssh\" \n\ +rmdir \"/tmp/$userid\" \n") + + f.close() + os.chmod(filename,stat.S_IRWXU) + return + + def _prepare_hosts_cfg(self, nodesinfo): + host_config = {} + for node in nodesinfo.keys(): + nodeinfo = nodesinfo[node] + utils.update2Ddict(host_config, nodeinfo['bmcip'], 'user', nodeinfo['username']) + utils.update2Ddict(host_config, nodeinfo['bmcip'], 'password', nodeinfo['password']) + return host_config + + def pre_set_sshcfg(self, *arg, **kw): + self.callback.syslog("Run into pre_set_sshcfg") + local_home_dir=os.path.expanduser('~') + local_ssh_dir = local_home_dir + "/.ssh/" + local_public_key = local_ssh_dir + "id_rsa.pub" + copy_sh_file = local_ssh_dir + "./copy.sh" + tmp_remote_dir = "/tmp/root/.ssh/" + self._create_copy_file(copy_sh_file) + self.callback.syslog("Generate %s file done" % copy_sh_file) + hosts_config = self._prepare_hosts_cfg(self.inventory) + + self.callback.syslog("Start to run SSH parallelly") + client = ParallelSSHClient(hosts_config.keys(), host_config=hosts_config) + self.callback.syslog("mkdir -p %s" % tmp_remote_dir) + client.run_command("/bin/mkdir -p %s" % tmp_remote_dir) + self.callback.info("Copy files to remote hosts: %s-->%s" % (local_ssh_dir, tmp_remote_dir)) + nodes_copy = client.copy_file(local_ssh_dir, tmp_remote_dir, recurse=True) + try: + joinall(nodes_copy, raise_error=True) + except Exception as e: + self.callback.info("Error: %s" % e) + self.callback.info("run copy.sh") + client.run_command("%s/copy.sh root" %(tmp_remote_dir, )) + return + def set_sshcfg(self, **kw): - return self.callback.info("set_sshcfg") + node = kw['node'] + nodeinfo = kw['nodeinfo'] + return self.callback.info("%s: ssh keys copied to %s" %(node, nodeinfo['bmcip'])) def set_ipdhcp(self, **kw): return self.callback.info("set_ipdhcp") @@ -52,8 +114,9 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): else: self.callback.error("get_attributes can not deal with attr %s" % attr) if len(netinfo_dict): - self._get_netinfo(netinfo_dict.has_key('ip'), netinfo_dict.has_key('ipsrc'), netinfo_dict.has_key('netmask'), - netinfo_dict.has_key('gateway'), netinfo_dict.has_key('vlan'), netinfo_dict.has_key('hostname'), **kw) + self._get_netinfo(ip=netinfo_dict.has_key('ip'), ipsrc=netinfo_dict.has_key('ipsrc'), netmask=netinfo_dict.has_key('netmask'), + gateway=netinfo_dict.has_key('gateway'),vlan= netinfo_dict.has_key('vlan'), + hostname=netinfo_dict.has_key('hostname'), **kw) def set_attributes(self, attributes, **kw): netinfo_dict={'vlan':False} @@ -115,18 +178,96 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): result = "set net(%s, %s, %s) for eth0" % (ip, netmask, gateway) return self.callback.info("set_netinfo %s" % result) - def _get_netinfo(self, ip=False, ipsrc=False, netmask=False, gateway=False, vlan=False, hostname=False, **kw): - result = '' - if ip: - result += "Get IP, " - if netmask: - result += "Get Mask, " - if gateway: - result += "Get Gateway, " - if ipsrc: - result += "Get IP source, " + def _get_and_parse_netinfo(self, **kw): + node = kw['node'] + obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, + debugmode=self.debugmode, verbose=self.verbose) + try: + obmc.login() + data = obmc.get_netinfo() + except (SelfServerException, SelfClientException) as e: + self.callback.info('%s: %s' % (node, e.message)) + return + netinfo = {} + for k, v in data.items(): + if k.find("network/config") >= 0: + if v.has_key("HostName"): + netinfo["hostname"] = v["HostName"] + if v.has_key("DefaultGateway"): + netinfo["defaultgateway"] = v["DefaultGateway"] + continue + dev,match,netid = k.partition("/ipv4/") + if netid: + if v["Origin"].find("LinkLocal") >= 0 or v["Address"].startswith("169.254"): + self.callback.info("%s: Found LinkLocal address %s for interface %s, Ignoring..." % (node, v["Address"], dev)) + continue + nicid = dev.split('/')[-1] + if not netinfo.has_key(nicid): + netinfo[nicid] = {} + if netinfo[nicid].has_key("ip"): + self.callback.error("%s: Another valid ip %s found." % (node, v["Address"])) + continue + utils.update2Ddict(netinfo, nicid, "ipsrc", v["Origin"].split('.')[-1]) + utils.update2Ddict(netinfo, nicid, "netmask", v["PrefixLength"]) + utils.update2Ddict(netinfo, nicid, "gateway", v["Gateway"]) + utils.update2Ddict(netinfo, nicid, "ip", v["Address"]) + if data.has_key(dev): + info = data[dev] + utils.update2Ddict(netinfo, nicid, "vlanid", info["Id"]) + utils.update2Ddict(netinfo, nicid, "mac", info["MACAddress"]) + utils.update2Ddict(netinfo, nicid, "ntpservers", info["NTPServers"]) + self.callback.info("Netinfo: %s" % netinfo) + return netinfo + def _get_netinfo(self, ip=False, ipsrc=False, netmask=False, gateway=False, vlan=False, hostname=False, ntpserver=True, **kw): + node = kw["node"] + netinfo = self._get_and_parse_netinfo(**kw) + if not netinfo: + return self.callback.error("%s: No network information get" % node) + defaultgateway = "n/a" + bmchostname = "" + if netinfo.has_key("defaultgateway"): + defaultgateway = netinfo["defaultgateway"] + del netinfo["defaultgateway"] + if netinfo.has_key("hostname"): + bmchostname = netinfo["hostname"] + del netinfo["hostname"] + if hostname: - result += "Get BMC hostname, " + self.callback.info("%s: BMC Hostname: %s" %(node, bmchostname)) + dic_length = len(netinfo) + self.callback.info("dic_length: %s: %s" %(dic_length, netinfo)) + ip_list = [] + ipsrc_list = [] + netmask_list = [] + gateway_list = [] + vlan_list = [] + ntpserver_list = [] + for nic,attrs in netinfo.items(): + addon_string = '' + if dic_length > 1: + addon_string = " for %s" % nic + ip_list.append("BMC IP"+addon_string+": %s" % attrs["ip"]) + netmask_list.append("BMC Netmask"+addon_string+": %s" % attrs["netmask"]) + gateway_list.append("BMC Gateway"+addon_string+": %s (default: %s)" % (attrs["gateway"], defaultgateway)) + vlan_list.append("BMC VLAN ID"+addon_string+": %s" % attrs["vlanid"]) + ipsrc_list.append("BMC IP Source"+addon_string+": %s" % attrs["ipsrc"]) + ntpserver_list.append("BMC NTP Servers"+addon_string+": %s" % attrs["ntpservers"]) + if ip: + for i in ip_list: + self.callback.info("%s: %s" % (node, i)) + if netmask: + for i in netmask_list: + self.callback.info("%s: %s" % (node, i)) + if gateway: + for i in gateway_list: + self.callback.info("%s: %s" % (node, i)) + if ipsrc: + for i in ipsrc_list: + self.callback.info("%s: %s" % (node, i)) if vlan: - result += "Get BMC vlan." - return self.callback.info("get_netinfo: %s" % result) + for i in vlan_list: + self.callback.info("%s: %s" % (node, i)) + if ntpserver: + for i in ntpserver_list: + self.callback.info("%s: %s" % (node, i)) + return diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py b/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py index f1fa55057..64d07dd9b 100644 --- a/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py @@ -141,6 +141,15 @@ FIRM_URLS = { } } +RSPCONFIG_NETINFO_URL = { + 'get_netinfo': "/network/enumerate", + 'hostname': "/network/config/attr/HostName", + 'nic_ip': "/network/#NIC#/action/IP", + 'vlan': "/network/action/VLAN", + 'ipdhcp': "/network/action/Reset", + 'ntpserver': "/network/#NIC#/attr/NTPServers", +} + RSPCONFIG_APIS = { 'autoreboot' : { 'baseurl': "/control/host0/auto_reboot/", @@ -511,6 +520,9 @@ class OpenBMCRest(object): data={"data": attr_info['get_data']} return self.request(method, get_url, payload=data, cmd="get_%s" % key) + def get_netinfo(self): + return self.request('GET', RSPCONFIG_NETINFO_URL['get_netinfo'], cmd="get_netinfo") + class OpenBMCImage(object): def __init__(self, rawid, data=None): self.id = rawid.split('/')[-1]