2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-29 09:13:08 +00:00

Merge pull request #4838 from xuweibj/rspconfig_dump

rspconfig dump in python
This commit is contained in:
zet809 2018-02-23 16:08:40 +08:00 committed by GitHub
commit 029cb0a27c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 266 additions and 17 deletions

View File

@ -37,6 +37,29 @@ class RestSession(object):
return response
def request_download(self, method, url, headers, file_path, using_curl=True):
if using_curl:
response = self._download_by_curl(method, url, headers, file_path)
else:
response = self.session.request('GET', url, headers=headers)
file_handle = open(file_path, "wb")
for chunk in response.iter_content(chunk_size=1024):
if chunk:
file_handle.write(chunk)
return response
def _download_by_curl(self, method, url, headers, file_path):
header_str = ' '.join([ "%s: %s" % (k, v) for k,v in headers.items() ])
request_cmd = 'curl -J -k -b sid=%s -H "%s" -X %s -o %s %s -s' % \
(self.cookies['sid'], header_str, method, file_path, url)
sub = Popen(request_cmd, stdout=PIPE, shell=True)
response, err = sub.communicate()
return response
def request_upload(self, method, url, headers, files, using_curl=True):
if using_curl:
return self._upload_by_curl(method, url, headers, files)

View File

@ -16,11 +16,11 @@ class BmcConfigInterface(object):
def dump_generate(self, task):
return task.run("dump_generate")
def dump_clear(self, task, id):
return task.run("dump_clear", id)
def dump_clear(self, task, clear_arg):
return task.run("dump_clear", clear_arg)
def dump_download(self, task, id):
return task.run("dump_download", id)
def dump_download(self, task, download_arg):
return task.run("dump_download", download_arg)
def dump_process(self, task):
return task.run("dump_process")

View File

@ -6,6 +6,8 @@
#
from __future__ import print_function
import os, stat
import gevent
import time
from common import utils
from common.task import ParallelNodesCommand
@ -24,24 +26,158 @@ logger = logging.getLogger('xcatagent')
RSPCONFIG_GET_NETINFO=['ip', 'netmask', 'gateway', 'vlan', 'ipsrc', 'hostname']
RSPCONFIG_SET_NETINFO=['ip', 'netmask', 'gateway', 'vlan']
XCAT_LOG_DUMP_DIR = "/var/log/xcat/dump/"
class OpenBMCBmcConfigTask(ParallelNodesCommand):
def pre_dump_download(self, task, download_arg, **kw):
if download_arg == 'all':
self.callback.info('Downloading all dumps...')
if not os.path.exists(XCAT_LOG_DUMP_DIR):
os.makedirs(XCAT_LOG_DUMP_DIR)
def pre_dump_process(self, task, **kw):
self.callback.info('Capturing BMC Diagnostic information, this will take some time...')
def _dump_download(self, obmc, node, download_id, flag_dump_process=False):
formatted_time = time.strftime("%Y%m%d-%H%M", time.localtime(time.time()))
dump_log_file = '%s%s_%s_dump_%s.tar.xz' % (XCAT_LOG_DUMP_DIR, formatted_time, node, download_id)
if flag_dump_process:
self.callback.info('%s: Downloading dump %s to %s' % (node, download_id, dump_log_file))
obmc.download_dump(download_id, dump_log_file)
if os.path.exists(dump_log_file):
grep_cmd = '/usr/bin/grep -a'
path_not_found = '"Path not found"'
check_cmd = grep_cmd + ' ' + path_not_found + ' ' + dump_log_file
grep_string = os.popen(check_cmd).readlines()
if grep_string:
result = 'Invalid dump %s was specified. Use -l option to list.' % download_id
else:
result = 'Downloaded dump %s to %s.' % (download_id, dump_log_file)
else:
result = 'Failed to download dump %s to %s.' % (download_id, dump_log_file)
return result
def dump_list(self, **kw):
return self.callback.info('dump_list')
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
dump_info = []
try:
obmc.login()
dump_dict = obmc.list_dump_info()
if not dump_dict:
self.callback.info('%s: No attributes returned from the BMC.' % node)
return dump_info
keys = dump_dict.keys()
keys.sort()
for key in keys:
info = '[%d] Generated: %s, Size: %s' % \
(key, dump_dict[key]['Generated'], dump_dict[key]['Size'])
dump_info += info
self.callback.info('%s: %s' % (node, info))
except (SelfServerException, SelfClientException) as e:
self.callback.info('%s: %s' % (node, e.message))
return dump_info
def dump_generate(self, **kw):
return self.callback.info("dump_generate")
def dump_clear(self, id, **kw):
return self.callback.info("dump_clear id: %s" % id)
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
def dump_download(self, id, **kw):
return self.callback.info("dump_download id: %s" % id)
dump_id = None
try:
obmc.login()
dump_id = obmc.create_dump()
if not dump_id:
self.callback.info('%s: BMC returned 200 OK but no ID was returned. Verify manually on the BMC.' % node)
else:
self.callback.info('%s: [%s] success' % (node, dump_id))
except (SelfServerException, SelfClientException) as e:
self.callback.info('%s: %s' % (node, e.message))
return dump_id
def dump_clear(self, clear_arg, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
obmc.clear_dump(clear_arg)
result = '%s: [%s] clear' % (node, clear_arg)
except (SelfServerException, SelfClientException) as e:
result = '%s: %s' % (node, e.message)
self.callback.info(result)
def dump_download(self, download_arg, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
if download_arg != 'all':
result = self._dump_download(obmc, node, download_arg)
self.callback.info('%s: %s' % (node, result))
return
dump_dict = obmc.list_dump_info()
keys = dump_dict.keys()
keys.sort()
for key in keys:
result = self._dump_download(obmc, node, str(key))
self.callback.info('%s: %s' % (node, result))
except SelfServerException as e:
self.callback.info('%s: %s' % (node, e.message))
def dump_process(self, **kw):
return self.callback.info("dump_process: trigger, list and download")
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
flag = False
dump_id = obmc.create_dump()
self.callback.info('%s: Dump requested. Target ID is %s, waiting for BMC to generate...' % (node, dump_id))
for i in range(20):
dump_dict = obmc.list_dump_info()
if dump_id in dump_dict:
flag = True
break
if (20-i) % 8 == 0:
self.callback.info('%s: Still waiting for dump %s to be generated... ' % (node, dump_id))
gevent.sleep( 15 )
if flag:
result = self._dump_download(obmc, node, str(dump_id), flag_dump_process=True)
else:
result = 'Could not find dump %s after waiting %d seconds.' % (dump_id, 20 * 15)
self.callback.info('%s: %s' % (node, result))
except SelfServerException as e:
self.callback.info('%s: %s' % (node, e.message))
def pre_set_sshcfg(self, *arg, **kw):
local_home_dir=os.path.expanduser('~')

View File

@ -29,6 +29,23 @@ RBEACON_URLS = {
},
}
DUMP_URLS = {
"clear" : {
"path" : "/dump/entry/#ID#/action/Delete",
"field" : [],
},
"clear_all" : {
"path" : "/dump/action/DeleteAll",
"field" : [],
},
"create" : {
"path" : "/dump/action/CreateDump",
"field" : [],
},
"download" : "download/dump/#ID#",
"list" : "/dump/enumerate",
}
INVENTORY_URL = "/inventory/enumerate"
LEDS_URL = "/led/physical/enumerate"
@ -222,6 +239,7 @@ class OpenBMCRest(object):
self.session = rest.RestSession()
self.root_url = HTTP_PROTOCOL + self.bmcip + PROJECT_URL
self.download_root_url = HTTP_PROTOCOL + self.bmcip + '/'
def _print_record_log (self, msg, cmd):
@ -231,13 +249,16 @@ class OpenBMCRest(object):
self.messager.info(localtime + ' ' + log)
logger.debug(log)
def _log_request (self, method, url, headers, data=None, files=None, cmd=''):
def _log_request (self, method, url, headers, data=None, files=None, file_path=None, cmd=''):
header_str = ' '.join([ "%s: %s" % (k, v) for k,v in headers.items() ])
msg = 'curl -k -c cjar -b cjar -X %s -H \"%s\" ' % (method, header_str)
if files:
msg += '-T \'%s\' %s -s' % (files, url)
elif file_path:
msg = 'curl -J -k -c cjar -b cjar -X %s -H \"%s\" %s -o %s' % \
(method, header_str, url, file_path)
elif data:
if cmd == 'login':
data = data.replace(self.password, "xxxxxx")
@ -286,6 +307,32 @@ class OpenBMCRest(object):
self._print_record_log(error, cmd)
raise SelfServerException(error)
def download(self, method, resource, file_path, headers=None, cmd=''):
httpheaders = headers or OpenBMCRest.headers
url = resource
if not url.startswith(HTTP_PROTOCOL):
url = self.download_root_url + resource
request_cmd = self._log_request(method, url, httpheaders, file_path=file_path, cmd=cmd)
try:
response = self.session.request_download(method, url, httpheaders, file_path)
except SelfServerException as e:
self._print_record_log(e.message, cmd=cmd)
raise
except SelfClientException as e:
error = e.message
self._print_record_log(error, cmd=cmd)
raise
if not response:
self._print_record_log('No response received for command %s' % request_cmd, cmd=cmd)
return True
self._print_record_log(str(response.status_code), cmd=cmd)
return True
def upload (self, method, resource, files, headers=None, cmd=''):
httpheaders = headers or OpenBMCRest.headers
@ -524,6 +571,47 @@ class OpenBMCRest(object):
data={"data": attr_info['get_data']}
return self.request(method, get_url, payload=data, cmd="get_%s" % key)
def clear_dump(self, clear_arg):
if clear_arg == 'all':
payload = { "data": DUMP_URLS['clear_all']['field'] }
self.request('POST', DUMP_URLS['clear_all']['path'], payload=payload, cmd='clear_dump_all')
else:
path = DUMP_URLS['clear']['path'].replace('#ID#', clear_arg)
payload = { "data": DUMP_URLS['clear']['field'] }
self.request('POST', path, payload=payload, cmd='clear_dump')
def create_dump(self):
payload = { "data": DUMP_URLS['create']['field'] }
return self.request('POST', DUMP_URLS['create']['path'], payload=payload, cmd='create_dump')
def list_dump_info(self):
dump_data = self.request('GET', DUMP_URLS['list'], cmd='list_dump_info')
try:
dump_dict = {}
for key, value in dump_data.items():
if 'Size' not in value or 'Elapsed' not in value:
continue
key_id = int(key.split('/')[-1])
timestamp = value['Elapsed']
gen_time = time.strftime("%m/%d/%Y %H:%M:%S", time.localtime(timestamp))
dump_dict.update({key_id: {'Size': value['Size'], 'Generated': gen_time}})
return dump_dict
except KeyError:
error = 'Error: Received wrong format response: %s' % dump_data
raise SelfServerException(error)
def download_dump(self, download_id, file_path):
headers = {'Content-Type': 'application/octet-stream'}
path = DUMP_URLS['download'].replace('#ID#', download_id)
self.download('GET', path, file_path, headers=headers, cmd='download_dump')
def get_netinfo(self):
data = self.request('GET', RSPCONFIG_NETINFO_URL['get_netinfo'], cmd="get_netinfo")
try:
@ -564,7 +652,9 @@ class OpenBMCRest(object):
def set_ipdhcp(self):
return self.request('PUT', RSPCONFIG_NETINFO_URL['ipdhcp'], cmd="set_bmcip_dhcp")
payload = { "data": [] }
return self.request('PUT', RSPCONFIG_NETINFO_URL['ipdhcp'], payload=payload, cmd="set_bmcip_dhcp")
class OpenBMCImage(object):
def __init__(self, rawid, data=None):

View File

@ -724,9 +724,9 @@ class OpenBMCManager(base.BaseManager):
elif opts['--generate']:
DefaultBmcConfigManager().dump_generate(runner)
elif opts['--clear']:
DefaultBmcConfigManager().dump_clear(runner, opts['--clear'])
DefaultBmcConfigManager().dump_clear(runner, opts['--clear'][0])
elif opts['--download']:
DefaultBmcConfigManager().dump_download(runner, opts['--download'])
DefaultBmcConfigManager().dump_download(runner, opts['--download'][0])
else:
DefaultBmcConfigManager().dump_process(runner)
elif opts['sshcfg']: