mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-06-13 01:40:26 +00:00
Merge pull request #4827 from zet809/rspconfig_get_netinfo
rspconfig in python to get network information
This commit is contained in:
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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):
|
||||
|
Reference in New Issue
Block a user