mirror of
https://opendev.org/x/pyghmi
synced 2026-01-11 18:52:33 +00:00
Add hostname for FPC and XCC
Provide access to hostname and dns domain on FPC. Also, make the webclient a bit more robust. Change-Id: I7176adf821a01c5cf7f20cc8227118a6b8dbd4a3
This commit is contained in:
@@ -1142,6 +1142,23 @@ class Command(object):
|
||||
if not ip == '0.0.0.0':
|
||||
self._assure_alert_policy(channel, destination)
|
||||
|
||||
def get_hostname(self):
|
||||
"""Get the hostname used by the BMC in various contexts
|
||||
|
||||
This can vary somewhat in interpretation, but generally speaking
|
||||
this should be the name that shows up on UIs and in DHCP requests and
|
||||
DNS registration requests, as applicable.
|
||||
|
||||
:return: current hostname
|
||||
"""
|
||||
self.oem_init()
|
||||
try:
|
||||
return self._oem.get_hostname()
|
||||
except exc.UnsupportedFunctionality:
|
||||
# Use the DCMI MCI field as a fallback, since it's the closest
|
||||
# thing in the IPMI Spec for this
|
||||
return self.get_mci()
|
||||
|
||||
def get_mci(self):
|
||||
"""Get the Management Controller Identifier, per DCMI specification
|
||||
|
||||
@@ -1149,6 +1166,20 @@ class Command(object):
|
||||
"""
|
||||
return self._chunkwise_dcmi_fetch(9)
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
"""Set the hostname to be used by the BMC in various contexts.
|
||||
|
||||
See get_hostname for details
|
||||
|
||||
:param hostname: The hostname to set
|
||||
:return: Nothing
|
||||
"""
|
||||
self.oem_init()
|
||||
try:
|
||||
return self._oem.set_hostname(hostname)
|
||||
except exc.UnsupportedFunctionality:
|
||||
return self.set_mci(hostname)
|
||||
|
||||
def set_mci(self, mci):
|
||||
"""Set the management controller identifier, per DCMI specification
|
||||
|
||||
|
||||
@@ -278,6 +278,18 @@ class OEMHandler(object):
|
||||
"""
|
||||
return
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
"""OEM specific hook to specify name information
|
||||
|
||||
"""
|
||||
raise exc.UnsupportedFunctionality()
|
||||
|
||||
def get_hostname(self):
|
||||
"""OEM specific hook to specify name information
|
||||
|
||||
"""
|
||||
raise exc.UnsupportedFunctionality()
|
||||
|
||||
def set_alert_ipv6_destination(self, ip, destination, channel):
|
||||
"""Set an IPv6 alert destination
|
||||
|
||||
|
||||
@@ -652,6 +652,8 @@ class OEMHandler(generic.OEMHandler):
|
||||
data=(4, i))
|
||||
name += rsp['data'][:]
|
||||
return name.rstrip('\x00')
|
||||
elif self.is_fpc:
|
||||
return self.smmhandler.get_domain()
|
||||
|
||||
def set_oem_domain_name(self, name):
|
||||
if self.has_tsm:
|
||||
@@ -669,6 +671,22 @@ class OEMHandler(generic.OEMHandler):
|
||||
|
||||
self._restart_dns()
|
||||
return
|
||||
elif self.is_fpc:
|
||||
self.smmhandler.set_domain(name)
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
if self.is_fpc:
|
||||
return self.smmhandler.set_hostname(hostname)
|
||||
elif self.has_xcc:
|
||||
return self.immhandler.set_hostname(hostname)
|
||||
return super(OEMHandler, self).set_hostname(hostname)
|
||||
|
||||
def get_hostname(self):
|
||||
if self.is_fpc:
|
||||
return self.smmhandler.get_hostname()
|
||||
elif self.has_xcc:
|
||||
return self.immhandler.get_hostname()
|
||||
return super(OEMHandler, self).get_hostname()
|
||||
|
||||
""" Gets a remote console launcher for a Lenovo ThinkServer.
|
||||
|
||||
|
||||
@@ -1123,6 +1123,16 @@ class XCCClient(IMMClient):
|
||||
if '_csrf_token' in wc.cookies:
|
||||
wc.set_header('X-XSRF-TOKEN', self.wc.cookies['_csrf_token'])
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
self.wc.grab_json_response('/api/dataset', {'IMM_HostName': hostname})
|
||||
self.wc.grab_json_response('/api/dataset', {'IMM_DescName': hostname})
|
||||
self.weblogout()
|
||||
|
||||
def get_hostname(self):
|
||||
rsp = self.wc.grab_json_response('/api/dataset/sys_info')
|
||||
self.weblogout()
|
||||
return rsp['items'][0]['system_name']
|
||||
|
||||
def update_firmware_backend(self, filename, data=None, progress=None,
|
||||
bank=None):
|
||||
self.weblogout()
|
||||
|
||||
@@ -233,6 +233,7 @@ def get_sensor_reading(name, ipmicmd, sz):
|
||||
|
||||
|
||||
class SMMClient(object):
|
||||
|
||||
def __init__(self, ipmicmd):
|
||||
self.ipmicmd = weakref.proxy(ipmicmd)
|
||||
self.smm = ipmicmd.bmc
|
||||
@@ -275,9 +276,64 @@ class SMMClient(object):
|
||||
self.st1 = data.text
|
||||
for data in authdata.findall('st2'):
|
||||
self.st2 = data.text
|
||||
if not self.st2:
|
||||
# This firmware puts tokens in the html file, parse that
|
||||
wc.request('GET', '/index.html')
|
||||
rsp = wc.getresponse()
|
||||
if rsp.status != 200:
|
||||
raise Exception(rsp.read())
|
||||
indexhtml = rsp.read()
|
||||
for line in indexhtml.split('\n'):
|
||||
if '"ST1"' in line:
|
||||
self.st1 = line.split()[-1].replace(
|
||||
'"', '').replace(',', '')
|
||||
if '"ST2"' in line:
|
||||
self.st2 = line.split()[-1].replace(
|
||||
'"', '').replace(',', '')
|
||||
wc.set_header('ST2', self.st2)
|
||||
return wc
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
self.wc.request('POST', '/data', 'set=hostname:' + hostname)
|
||||
rsp = self.wc.getresponse()
|
||||
if rsp.status != 200:
|
||||
raise Exception(rsp.read())
|
||||
rsp.read()
|
||||
self.logout()
|
||||
|
||||
def get_hostname(self):
|
||||
currinfo = self.get_netinfo()
|
||||
self.logout()
|
||||
for data in currinfo.find('netConfig').findall('hostname'):
|
||||
return data.text
|
||||
|
||||
def get_netinfo(self):
|
||||
self.wc.request('POST', '/data', 'get=hostname')
|
||||
rsp = self.wc.getresponse()
|
||||
data = rsp.read()
|
||||
if rsp.status == 400:
|
||||
self.wc.request('POST', '/data?get=hostname', '')
|
||||
rsp = self.wc.getresponse()
|
||||
data = rsp.read()
|
||||
if rsp.status != 200:
|
||||
raise Exception(data)
|
||||
currinfo = fromstring(data)
|
||||
return currinfo
|
||||
|
||||
def set_domain(self, domain):
|
||||
self.wc.request('POST', '/data', 'set=dnsDomain:' + domain)
|
||||
rsp = self.wc.getresponse()
|
||||
if rsp.status != 200:
|
||||
raise Exception(rsp.read())
|
||||
rsp.read()
|
||||
self.logout()
|
||||
|
||||
def get_domain(self):
|
||||
currinfo = self.get_netinfo()
|
||||
self.logout()
|
||||
for data in currinfo.find('netConfig').findall('dnsDomain'):
|
||||
return data.text
|
||||
|
||||
def get_ntp_enabled(self, variant):
|
||||
self.wc.request('POST', '/data', 'get=ntpOpMode')
|
||||
rsp = self.wc.getresponse()
|
||||
@@ -370,6 +426,6 @@ class SMMClient(object):
|
||||
|
||||
@property
|
||||
def wc(self):
|
||||
if not self._wc:
|
||||
if not self._wc or self._wc.broken:
|
||||
self._wc = self.get_webclient()
|
||||
return self._wc
|
||||
|
||||
@@ -69,6 +69,7 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
|
||||
**kwargs):
|
||||
if 'timeout' not in kwargs:
|
||||
kwargs['timeout'] = 60
|
||||
self.broken = False
|
||||
self.thehost = host
|
||||
self.theport = port
|
||||
httplib.HTTPConnection.__init__(self, host, port, strict, **kwargs)
|
||||
@@ -107,12 +108,16 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
|
||||
bincert)
|
||||
|
||||
def getresponse(self):
|
||||
rsp = super(SecureHTTPConnection, self).getresponse()
|
||||
for hdr in rsp.msg.headers:
|
||||
if hdr.startswith('Set-Cookie:'):
|
||||
c = Cookie.BaseCookie(hdr[11:])
|
||||
for k in c:
|
||||
self.cookies[k] = c[k].value
|
||||
try:
|
||||
rsp = super(SecureHTTPConnection, self).getresponse()
|
||||
for hdr in rsp.msg.headers:
|
||||
if hdr.startswith('Set-Cookie:'):
|
||||
c = Cookie.BaseCookie(hdr[11:])
|
||||
for k in c:
|
||||
self.cookies[k] = c[k].value
|
||||
except httplib.BadStatusLine:
|
||||
self.broken = True
|
||||
raise
|
||||
return rsp
|
||||
|
||||
def grab_json_response(self, url, data=None, referer=None):
|
||||
@@ -164,6 +169,8 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
|
||||
headers = self.stdheaders.copy()
|
||||
if method == 'GET' and 'Content-Type' in headers:
|
||||
del headers['Content-Type']
|
||||
if method == 'POST' and body and 'Content-Type' not in headers:
|
||||
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
if self.cookies:
|
||||
cookies = []
|
||||
for ckey in self.cookies:
|
||||
@@ -175,5 +182,9 @@ class SecureHTTPConnection(httplib.HTTPConnection, object):
|
||||
headers['Cookie'] += '; ' + '; '.join(cookies)
|
||||
if referer:
|
||||
headers['Referer'] = referer
|
||||
return super(SecureHTTPConnection, self).request(method, url, body,
|
||||
headers)
|
||||
try:
|
||||
return super(SecureHTTPConnection, self).request(method, url, body,
|
||||
headers)
|
||||
except httplib.CannotSendRequest:
|
||||
self.broken = True
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user