2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-21 19:22:05 +00:00

rspconfig dump in python

This commit is contained in:
XuWei 2018-02-22 02:01:41 -05:00
parent 41c86021be
commit bfc367cb88
5 changed files with 264 additions and 16 deletions

View File

@ -37,6 +37,29 @@ class RestSession(object):
return response
def request_download(self, method, url, headers, file_path, using_curl=False):
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

@ -5,6 +5,7 @@
# -*- coding: utf-8 -*-
#
from __future__ import print_function
import os, stat
import gevent
import time
@ -18,22 +19,157 @@ 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)
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 set_sshcfg(self, **kw):
return self.callback.info("set_sshcfg")

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
@ -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"
@ -209,6 +226,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):
@ -218,13 +236,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")
@ -273,6 +294,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', 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
@ -511,6 +558,48 @@ 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 = 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' % inventory_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')
class OpenBMCImage(object):
def __init__(self, rawid, data=None):
self.id = rawid.split('/')[-1]

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']: