2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-06-13 09:50:19 +00:00

Merge pull request #4827 from zet809/rspconfig_get_netinfo

rspconfig in python to get network information
This commit is contained in:
xuweibj
2018-02-23 13:11:19 +08:00
committed by GitHub
3 changed files with 207 additions and 36 deletions

View File

@ -5,19 +5,27 @@
# -*- 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
#For rspconfig sshcfg
from pssh.ssh_client import SSHClient
from pssh.exceptions import UnknownHostException, AuthenticationException, \
ConnectionErrorException, SSHException
from scp import SCPClient
import logging
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,11 +43,74 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand):
def dump_process(self, **kw):
return self.callback.info("dump_process: trigger, list and download")
def pre_set_sshcfg(self, *arg, **kw):
local_home_dir=os.path.expanduser('~')
self.local_ssh_dir = local_home_dir + "/.ssh/"
self.local_public_key = self.local_ssh_dir + "id_rsa.pub"
self.copy_sh_file = self.local_ssh_dir + "./copy.sh"
f = open(self.copy_sh_file, '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 >> $home/.ssh/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(self.copy_sh_file,stat.S_IRWXU)
if self.verbose:
self.callback.info("Prepared %s file done" % self.copy_sh_file)
def set_sshcfg(self, **kw):
return self.callback.info("set_sshcfg")
node = kw['node']
nodeinfo = kw['nodeinfo']
tmp_remote_dir = "/tmp/%s/.ssh/" % nodeinfo['username']
#try:
ssh_client = SSHClient(nodeinfo['bmcip'], user=nodeinfo['username'], password=nodeinfo['password'])
#except (SSHException, NoValidConnectionsError,BadHostKeyException) as e:
# self.callback.info("%s: %s" % (node, e))
if not ssh_client.client.get_transport().is_active():
self.callback.info("SSH session is not active")
if not ssh_client.client.get_transport().is_authenticated():
self.callback.info("SSH session is not authenticated")
try:
ssh_client.client.exec_command("/bin/mkdir -p %s\n" % tmp_remote_dir)
except (SSHException, ConnectionErrorException) as e:
self.callback.info("%s: ----%s------" % (host, e))
scp = SCPClient(ssh_client.client.get_transport())
scp.put(self.copy_sh_file, tmp_remote_dir + "copy.sh")
scp.put(self.local_public_key, tmp_remote_dir + "id_rsa.pub")
ssh_client.client.exec_command("%s/copy.sh %s" % (tmp_remote_dir, nodeinfo['username']))
ssh_client.client.close()
return self.callback.info("ssh keys copied to %s" % nodeinfo['bmcip'])
def set_ipdhcp(self, **kw):
return self.callback.info("set_ipdhcp")
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
obmc.set_ipdhcp()
except (SelfServerException, SelfClientException) as e:
self.callback.info("%s: %s" % (node, e.message))
return
self.callback.info("%s: BMC Setting IP to DHCP..." % (node))
try:
obmc.reboot_bmc()
except (SelfServerException, SelfClientException) as e:
self.callback.info("%s: %s" % (node, e.message))
def get_attributes(self, attributes, **kw):
netinfo_dict={}
@ -47,13 +118,14 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand):
if attr in RSPCONFIG_GET_NETINFO:
netinfo_dict[attr]=True
getnet=1
elif openbmc.RSPCONFIG_APIS.has_key(attr):
elif attr in openbmc.RSPCONFIG_APIS:
self._get_apis_values(attr, **kw)
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.get('ip', False), ipsrc=netinfo_dict.get('ipsrc', False), netmask=netinfo_dict.get('netmask', False),
gateway=netinfo_dict.get('gateway', False),vlan= netinfo_dict.get('vlan', False),
hostname=netinfo_dict.get('hostname', False), **kw)
def set_attributes(self, attributes, **kw):
netinfo_dict={'vlan':False}
@ -63,24 +135,28 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand):
netinfo_dict[k] = v
elif k == 'hostname':
self._set_hostname(v, **kw)
elif openbmc.RSPCONFIG_APIS.has_key(k):
elif k in openbmc.RSPCONFIG_APIS:
self._set_apis_values(k, v, **kw)
else:
return self.callback.error("set_attributes unsupported attribute:%s" % k)
if len(netinfo_dict) > 1 and (not netinfo_dict.has_key('ip') or not netinfo_dict.has_key('netmask') or not netinfo_dict.has_key('gateway')):
if len(netinfo_dict) > 1 and ('ip' not in netinfo_dict or 'netmask' not in netinfo_dict or 'gateway' not in netinfo_dict):
self.callback.info("set_attributes miss either ip, netmask or gateway to set network information")
elif len(netinfo_dict) <= 1:
return
else:
self._set_netinfo(netinfo_dict['ip'], netinfo_dict['netmask'],
netinfo_dict['gateway'], netinfo_dict['vlan'])
def _set_hostname(self, hostname, **kw):
node = kw['node']
if hostname == '*':
if kw['nodeinfo']['bmc'] != kw['nodeinfo']['bmcip']:
hostname = kw['nodeinfo']['bmc']
else:
hostname = '%s-bmc' % kw['node']
return self.callback.info("set_hostname: %s" % hostname)
if kw['nodeinfo']['bmc'] == kw['nodeinfo']['bmcip']:
self.callback.info("%s: set BMC ip as BMC Hostname" % node)
hostname = kw['nodeinfo']['bmc']
self._set_apis_values("hostname", hostname, **kw)
self._get_netinfo(hostname=True, ntpserver=False, **kw)
return
def _set_apis_values(self, key, value, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
@ -115,18 +191,58 @@ 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_netinfo(self, ip=False, ipsrc=False, netmask=False, gateway=False, vlan=False, hostname=False, ntpserver=True, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
netinfo = obmc.get_netinfo()
except (SelfServerException, SelfClientException) as e:
self.callback.info('%s: %s' % (node, e.message))
return
if not netinfo:
return self.callback.error("%s: No network information get" % node)
defaultgateway = "n/a"
bmchostname = ""
if 'defaultgateway' in netinfo:
defaultgateway = netinfo["defaultgateway"]
del netinfo["defaultgateway"]
if 'hostname' in netinfo:
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)
netinfodict = {'ip':[], 'netmask':[], 'gateway':[],
'vlan':[], 'ipsrc':[], 'ntpserver':[]}
for nic,attrs in netinfo.items():
addon_string = ''
if dic_length > 1:
addon_string = " for %s" % nic
netinfodict['ip'].append("BMC IP"+addon_string+": %s" % attrs["ip"])
netinfodict['netmask'].append("BMC Netmask"+addon_string+": %s" % attrs["netmask"])
netinfodict['gateway'].append("BMC Gateway"+addon_string+": %s (default: %s)" % (attrs["gateway"], defaultgateway))
netinfodict['vlan'].append("BMC VLAN ID"+addon_string+": %s" % attrs["vlanid"])
netinfodict['ipsrc'].append("BMC IP Source"+addon_string+": %s" % attrs["ipsrc"])
netinfodict['ntpserver'].append("BMC NTP Servers"+addon_string+": %s" % attrs["ntpservers"])
if ip:
for i in netinfodict['ip']:
self.callback.info("%s: %s" % (node, i))
if netmask:
for i in netinfodict['netmask']:
self.callback.info("%s: %s" % (node, i))
if gateway:
for i in netinfodict['gateway']:
self.callback.info("%s: %s" % (node, i))
if ipsrc:
for i in netinfodict['ipsrc']:
self.callback.info("%s: %s" % (node, i))
if vlan:
result += "Get BMC vlan."
return self.callback.info("get_netinfo: %s" % result)
for i in netinfodict['vlan']:
self.callback.info("%s: %s" % (node, i))
if ntpserver:
for i in netinfodict['netserver']:
self.callback.info("%s: %s" % (node, i))
return netinfo

View File

@ -9,7 +9,7 @@ import requests
import json
import time
from common import rest
from common import utils, rest
from common.exceptions import SelfClientException, SelfServerException
import logging
@ -141,7 +141,20 @@ FIRM_URLS = {
}
}
RSPCONFIG_NETINFO_URL = {
'get_netinfo': "/network/enumerate",
'nic_ip': "/network/#NIC#/action/IP",
'vlan': "/network/action/VLAN",
'ipdhcp': "/network/action/Reset",
'ntpserver': "/network/#NIC#/attr/NTPServers",
}
RSPCONFIG_APIS = {
'hostname': {
'baseurl': "/network/config/",
'set_url': "attr/HostName",
'display_name': "BMC Hostname",
},
'autoreboot' : {
'baseurl': "/control/host0/auto_reboot/",
'set_url': "attr/AutoReboot",
@ -488,10 +501,10 @@ class OpenBMCRest(object):
def set_apis_values(self, key, value):
attr_info = RSPCONFIG_APIS[key]
if not attr_info.has_key('set_url'):
if 'set_url' not in attr_info:
raise SelfServerException("config %s failed, not url available" % key)
set_url = attr_info['baseurl']+attr_info['set_url']
if attr_info.has_key('attr_values') and attr_info['attr_values'].has_key(value):
if 'attr_values' in attr_info and value in attr_info['attr_values']:
data = attr_info['attr_values'][value]
else:
data = value
@ -499,18 +512,60 @@ class OpenBMCRest(object):
def get_apis_values(self, key):
attr_info = RSPCONFIG_APIS[key]
if not attr_info.has_key('get_url'):
if 'get_url' not in attr_info:
raise SelfServerException("Reading %s failed, not url available" % key)
get_url = attr_info['baseurl']+attr_info['get_url']
method = 'GET'
if attr_info.has_key('get_method'):
if 'get_method' in attr_info:
method = attr_info['get_method']
data = None
if attr_info.has_key('get_data'):
if 'get_data' in attr_info:
data={"data": attr_info['get_data']}
return self.request(method, get_url, payload=data, cmd="get_%s" % key)
def get_netinfo(self):
data = self.request('GET', RSPCONFIG_NETINFO_URL['get_netinfo'], cmd="get_netinfo")
try:
netinfo = {}
for k, v in data.items():
if 'network/config' in k:
if 'HostName' in v:
netinfo["hostname"] = v["HostName"]
if 'DefaultGateway' in v:
netinfo["defaultgateway"] = v["DefaultGateway"]
continue
dev,match,netid = k.partition("/ipv4/")
if netid:
if 'LinkLocal' in v["Origin"] or v["Address"].startswith("169.254"):
msg = "Found LinkLocal address %s for interface %s, Ignoring..." % (v["Address"], dev)
self._print_record_log(msg, 'get_netinfo')
continue
nicid = dev.split('/')[-1]
if nicid not in netinfo:
netinfo[nicid] = {}
if 'ip' in netinfo[nicid]:
msg = "%s: Another valid ip %s found." % (node, v["Address"])
self._print_record_log(msg, 'get_netinfo')
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 dev in data:
info = data[dev]
utils.update2Ddict(netinfo, nicid, "vlanid", info.get("Id", "Disable"))
utils.update2Ddict(netinfo, nicid, "mac", info["MACAddress"])
utils.update2Ddict(netinfo, nicid, "ntpservers", info["NTPServers"])
return netinfo
except KeyError:
error = 'Error: Received wrong format response: %s' % data
raise SelfServerException(error)
def set_ipdhcp(self):
return self.request('PUT', RSPCONFIG_NETINFO_URL['ipdhcp'], cmd="set_bmcip_dhcp")
class OpenBMCImage(object):
def __init__(self, rawid, data=None):
self.id = rawid.split('/')[-1]

View File

@ -736,7 +736,7 @@ class OpenBMCManager(base.BaseManager):
elif opts['get']:
unsupport_list=list(set(opts['<args>']) - set(RSPCONFIG_GET_OPTIONS))
if len(unsupport_list) > 0:
self.messager.error("Have unsupported option: %s" % unsupport_args)
self.messager.error("Have unsupported option: %s" % unsupport_list)
return
else:
DefaultBmcConfigManager().get_attributes(runner, opts['<args>'])
@ -744,7 +744,7 @@ class OpenBMCManager(base.BaseManager):
rc=0
for attr in opts['<args>']:
k,v = attr.split('=')
if not RSPCONFIG_SET_OPTIONS.has_key(k):
if k not in RSPCONFIG_SET_OPTIONS:
self.messager.error("The attribute %s is not support to set" % k)
rc=1
elif not re.match(RSPCONFIG_SET_OPTIONS[k], v):