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

rflash in python for OpenBMC

This commit is contained in:
XuWei 2018-03-19 04:17:58 -04:00
parent f047cc73e3
commit b8a489899b
11 changed files with 751 additions and 725 deletions

View File

@ -122,7 +122,7 @@ class RestSession(object):
response, err = sub.communicate()
if not response:
error = 'Error: Did not receive response from server after ' \
error = 'Did not receive response from server after ' \
'running command \'%s\'' % request_cmd
raise SelfServerException(error)

View File

@ -7,7 +7,7 @@
import struct
import sys
import inspect
import re
import re, os
import logging
from logging.handlers import SysLogHandler
@ -92,6 +92,11 @@ def mask_int2str(mask_int):
mask_num = (0x1 << 32) - (0x1 << (32 - mask_int))
return "%s.%s.%s.%s" % (str((mask_num >> 24) & 0xff), str((mask_num >>16)&0xff), str((mask_num >> 8) & 0xff), str(mask_num & 0xff))
def get_full_path(cwd, directory):
if not os.path.isabs(directory):
directory = '%s/%s' % (cwd, directory)
return directory
class Messager(object):
def __init__(self, name=None):
self.logger = logging.getLogger(name or 'xcatagent')

View File

@ -0,0 +1,562 @@
#!/usr/bin/env python
###############################################################################
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
###############################################################################
# -*- coding: utf-8 -*-
#
from __future__ import print_function
import gevent
import time
import os, re
from common import utils
from common.task import ParallelNodesCommand
from common.exceptions import SelfClientException, SelfServerException
from hwctl import openbmc_client as openbmc
import logging
logger = logging.getLogger('xcatagent')
XCAT_LOG_DIR = "/var/log/xcat"
XCAT_LOG_RFLASH_DIR = XCAT_LOG_DIR + "/rflash/"
class OpenBMCFlashTask(ParallelNodesCommand):
"""Executor for flash-related actions."""
activate_result = {}
firmware = {}
firmware_file = None
log_handle = {}
nodes_num = 0
def _msg_process(self, node, msg, msg_type='I', update_rc=False, checkv=False):
if msg_type == 'E':
self.callback.error(msg, node)
elif not checkv:
self.callback.info('%s: %s' % (node, msg))
elif self.verbose:
self.callback.info('%s: %s' % (node, msg))
if update_rc:
self.activate_result.update({node: msg})
if node not in self.log_handle:
log_file = XCAT_LOG_RFLASH_DIR + '/' + node + '.log'
self.log_handle.update({node: open(log_file, 'a')})
try:
self.log_handle[node].writelines(msg + '\n')
self.log_handle[node].flush()
except Exception as e:
self.callback.error('Failed to record rflash log for node %s' % node)
def _firmware_file_check(self, firmware_file, **kw):
target_file = utils.get_full_path(self.cwd, firmware_file)
self.firmware_file = target_file
if (not os.access(target_file, os.F_OK) or
not os.access(target_file, os.R_OK)):
error = 'Cannot access %s. Check the management ' \
'node and/or service nodes.' % target_file
self.callback.error(error)
raise Exception('Invalid firmware file %s' % target_file)
def validate_activate_firm(self, task, activate_arg, **kw):
if activate_arg.endswith('.tar'):
self._firmware_file_check(activate_arg)
else:
if not re.match('\A[0-9a-fA-F]+\Z', activate_arg):
self.callback.error('Invalid firmware ID %s' % activate_arg)
def validate_delete_firm(self, task, delete_id, **kw):
if not re.match('\A[0-9a-fA-F]+\Z', delete_id):
self.callback.error('Invalid firmware ID %s' % activate_arg)
def validate_upload_firm(self, task, upload_file, **kw):
self._firmware_file_check(upload_file)
def _get_firmware_version(self, target_file):
grep_cmd = '/usr/bin/grep -a'
version_cmd = grep_cmd + ' ^version= ' + target_file
purpose_cmd = grep_cmd + ' purpose= ' + target_file
firmware = os.popen(version_cmd).readlines()[0].split('=')[-1].strip()
purpose = os.popen(purpose_cmd).readlines()[0].split('=')[-1].strip().split('.')[-1]
return { firmware: {'purpose': purpose} }
def pre_activate_firm(self, task, activate_arg, **kw):
if not os.path.exists(XCAT_LOG_RFLASH_DIR):
os.makedirs(XCAT_LOG_RFLASH_DIR)
if activate_arg.endswith('.tar'):
version = self._get_firmware_version()
self.firmware.update(version)
self.callback.info('Attempting to upload %s, please wait...' % self.firmware_file)
else:
self.callback.info('Attempting to activate ID=%s, please wait..' % activate_arg)
self.nodes_num = len(self.inventory)
def pre_delete_firm(self, task, delete_id, **kw):
self.callback.info('Attempting to delete ID=%s, please wait..' % delete_id)
def pre_flash_process(self, task, directory, no_host_reboot, **kw):
if not os.path.exists(XCAT_LOG_RFLASH_DIR):
os.makedirs(XCAT_LOG_RFLASH_DIR)
directory = utils.get_full_path(self.cwd, directory)
tmp_dict = {'BMC': [], 'Host': []}
for filename in os.listdir(directory):
if filename.endswith('.tar'):
filename = os.path.join(directory, filename)
try:
version = self._get_firmware_version(filename)
except Exception as e:
continue
self.firmware.update(version)
for key, value in version.items():
tmp_dict[ value['purpose'] ].append(filename)
self.firmware[key].update({'file': filename})
bmc_file_num = len(tmp_dict['BMC'])
host_file_num = len(tmp_dict['Host'])
error = None
if not bmc_file_num:
error = 'No BMC tar file found in %s' % directory
elif not host_file_num:
error = 'No HOST tar file found in %s' % directory
elif bmc_file_num > 1:
error = 'More than 1 BMC tar file %s found in %s' \
% (' '.join(tmp_dict['BMC']), directory)
elif host_file_num > 1:
error = 'More than 1 HOST tar file %s found in %s' \
% (' '.join(tmp_dict['Host']), directory)
if error:
self.callback.error(error)
raise Exception('No or More tar file found')
self.callback.info('Attempting to upload %s and %s, please wait..' \
% (tmp_dict['BMC'][0], tmp_dict['Host'][0]))
self.nodes_num = len(self.inventory)
def pre_upload_firm(self, task, upload_arg, **kw):
if not os.path.exists(XCAT_LOG_RFLASH_DIR):
os.makedirs(XCAT_LOG_RFLASH_DIR)
self.callback.info('Attempting to upload %s, please wait...' % self.firmware_file)
def _get_firm_id(self, obmc, node):
mapping_ids = []
if self.firmware:
version_list = self.firmware.keys()
else:
return []
for i in range(6):
try:
has_functional, firm_obj_dict = obmc.list_firmware()
except (SelfServerException, SelfClientException) as e:
self._msg_process(node, e.message, msg_type='E', update_rc=True)
return []
for key, value in firm_obj_dict.items():
if value.version and value.version in version_list:
firm_id = key.split('-')[-1]
mapping_ids.append(firm_id)
msg = 'Firmware upload successful. ' \
'Attempting to activate firmware: %s (ID: %s)' \
% (value.version, firm_id)
self._msg_process(node, msg, update_rc=True)
version_list.remove(value.version)
if not version_list:
return mapping_ids
for i in version_list:
msg = 'Could not find ID for firmware %s to '\
'activate, waiting %d seconds and retry...' \
% (i, 10)
self._msg_process(node, msg, update_rc=True, checkv=True)
gevent.sleep ( 10 )
error = []
for i in version_list:
msg = 'Could not find firmware %s after waiting %d seconds.' % (i, 10*6)
error.qppend(msg)
self._msg_process(node, msg, msg_type='E')
if error:
msg = ' '.join(error)
self.activate_result.update({node: msg})
return []
def _check_id_status(self, obmc, check_ids, node, only_act=True):
firm_ids = check_ids
priority_ids = []
process_status = {}
for i in range(80):
try:
has_functional, firm_obj_dict = obmc.list_firmware()
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
for key, value in firm_obj_dict.items():
key_id = key.split('-')[-1]
if key_id in firm_ids:
activation_state = value.active
firm_version = value.version
if activation_state == 'Failed':
activation_msg = 'Firmware %s activation failed.' % (firm_version)
self._msg_process(node, activation_msg, msg_type='E', update_rc=True)
firm_ids.remove(key_id)
if activation_state == 'Active':
activation_msg = 'Firmware %s activation successful.' % (firm_version)
self._msg_process(node, activation_msg, update_rc=True)
firm_ids.remove(key_id)
if value.priority != 0:
priority_ids.append(key_id)
if activation_state == 'Activating':
activating_progress_msg = 'Activating %s ... %s%%' \
% (firm_version, value.progress)
process_status[key_id] = activating_progress_msg
self._msg_process(node, activating_progress_msg, checkv=True)
if not firm_ids:
break
gevent.sleep( 15 )
error = []
for i in firm_ids:
msg = 'After %d seconds check the firmware id %s current status is "%s"' \
% (80*15, process_status[i], i)
error.append(msg)
self._msg_process(node, msg, msg_type='E')
if error:
msg = ' '.join(error)
self.activate_result.update({node: msg})
return
for i in priority_ids:
try:
obmc.set_priority(i)
except (SelfServerException, SelfClientException) as e:
msg = e.message
error.append(msg)
self._msg_process(node, msg, msg_type='E')
if error:
msg = ' '.join(error)
self.activate_result.update({node: msg})
return
self.activate_result.update({node: 'SUCCESS'})
def _reboot_to_effect(self, obmc, no_host_reboot, node):
self._msg_process(node, 'Firmware will be flashed on reboot, deleting all BMC diagnostics...')
try:
obmc.clear_dump('all')
except (SelfServerException, SelfClientException) as e:
self.callback.warn('%s: Could not clear BMC diagnostics successfully %s, ignoring...' % (node, e.message))
try:
obmc.reboot_bmc()
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
self._msg_process(node, openbmc.RPOWER_STATES['bmcreboot'], update_rc=True)
gevent.sleep( 10 )
bmc_state = None
for i in range(20):
try:
obmc.login()
state = obmc.get_bmc_state()
bmc_state = state.get('bmc')
if bmc_state == 'Ready':
break
except (SelfServerException, SelfClientException) as e:
self._msg_process(node, e.message, checkv=True)
self._msg_process(node, 'Retry BMC state, wait for 15 seconds ...', update_rc=True)
gevent.sleep( 15 )
if bmc_state != 'Ready':
error = 'Sent bmcreboot but state did not change to BMC Ready after ' \
'waiting %s seconds. (State=BMC %s).' % (20*15, bmc_state)
return self._msg_process(node, error, msg_type='E', update_rc=True)
self._msg_process(node, 'BMC %s' % bmc_state, update_rc=True)
if no_host_reboot:
self.activate_result.update({node: 'SUCCESS'})
return
try:
obmc.set_power_state('off')
self.callback.update_node_attributes('status', node, 'powering-off')
off_flag = False
start_timeStamp = int(time.time())
for i in range (0, 30):
states = obmc.list_power_states()
state = obmc.get_host_state(states)
if openbmc.RPOWER_STATES.get(state) == 'off':
off_flag = True
break
gevent.sleep( 2 )
end_timeStamp = int(time.time())
if not off_flag:
error = 'Error: Sent power-off command but state did not change ' \
'to off after waiting %s seconds. (State= %s).' % (end_timeStamp - start_timeStamp, status)
return self._msg_process(node, error, update_rc=True)
ret = obmc.set_power_state('on')
self.callback.update_node_attributes('status', node, 'powering-on')
self._msg_process(node, 'reset')
self.activate_result.update({node: 'SUCCESS'})
except (SelfServerException, SelfClientException) as e:
self._msg_process(node, e.message, update_rc=True)
def activate_firm(self, activate_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()
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
firmware_version = ''
if self.firmware_file:
firmware_version = self.firmware.keys()[0]
try:
obmc.upload_firmware(self.firmware_file)
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
activate_ids = self._get_firm_id(obmc, node)
if not activate_ids:
return
activate_id = activate_ids[0]
else:
activate_id = activate_arg
error = ''
try:
obmc.activate_firmware(activate_id)
except SelfServerException as e:
error = e.message
except SelfClientException as e:
if e.code == 403:
error = 'Invalid ID provided to activate. ' \
'Use the -l option to view valid firmware IDs.'
else:
error = e.message
if error:
return self._msg_process(node, error, msg_type='E', update_rc=True)
msg = 'rflash %s started, please wait...' % firmware_version
self._msg_process(node, msg, checkv=True)
check_ids = [activate_id]
self._check_id_status(obmc, check_ids, node)
def delete_firm(self, delete_id, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
error = ''
try:
obmc.login()
except (SelfServerException, SelfClientException) as e:
return self.callback.error(e.message, node)
try:
has_functional, firm_obj_dict = obmc.list_firmware()
except (SelfServerException, SelfClientException) as e:
return self.callback.error(e.message, node)
host_flag = False
for key, value in firm_obj_dict.items():
key_id = key.split('-')[-1]
if key_id != delete_id:
continue
if value.functional or (value.priority == 0 and not has_functional):
if value.purpose == 'BMC':
return self.callback.error('Deleting currently active BMC firmware' \
' is not supported', node)
elif value.purpose == 'Host':
host_flag = True
break
else:
self.callback.error('Unable to determine the purpose of the ' \
'firmware to delete', node)
if host_flag:
try:
states = obmc.list_power_states()
state = obmc.get_host_state(states)
if openbmc.RPOWER_STATES.get(state) == 'on':
return self.callback.error('Deleting currently active firmware on' \
' powered on host is not supported', node)
except (SelfServerException, SelfClientException) as e:
return self.callback.error(e.message, node)
try:
obmc.delete_firmware(delete_id)
except SelfServerException as e:
error = e.message
except SelfClientException as e:
if e.code == 404:
error = 'Invalid ID provided to delete. ' \
'Use the -l option to view valid firmware IDs.'
else:
error = e.message
if error:
self.callback.error(error, node)
else:
self.callback.info('%s: [%s] Firmware removed' % (node, delete_id))
def flash_process(self, directory, no_host_reboot, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
try:
for key, value in self.firmware.items():
obmc.upload_firmware(value['file'])
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E', update_rc=True)
activate_ids = self._get_firm_id(obmc, node)
if not activate_ids:
return
for i in activate_ids:
error = ''
try:
obmc.activate_firmware(i)
except SelfServerException as e:
error = e.message
except SelfClientException as e:
if e.code == 403:
error = 'Invalid ID %s provided to activate. Use the -l option ' \
'to view valid firmware IDs.' % i
else:
error = e.message
if error:
return self._msg_process(node, error, msg_type='E', update_rc=True)
for key in self.firmware:
msg = 'rflash %s started, please wait...' % key
self._msg_process(node, msg, checkv=True)
self._check_id_status(obmc, activate_ids, node, only_act=False)
self._reboot_to_effect(obmc, no_host_reboot, node)
def list_firm_info(self, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
firm_info = []
try:
obmc.login()
has_functional, firm_obj_dict = obmc.list_firmware()
except (SelfServerException, SelfClientException) as e:
return self.callback.error(e.message, node)
firm_info.append('%-8s %-7s %-10s %-s' % ('ID', 'Purpose', 'State', 'Version'))
firm_info.append('-' * 55)
for key, value in firm_obj_dict.items():
status = value.active
if value.functional:
status += '(*)'
elif value.priority == 0:
if not has_functional:
status += '(*)'
else:
status += '(+)'
firm_info.append('%-8s %-7s %-10s %-s' % (key.split('-')[-1],
value.purpose, status, value.version))
for info in firm_info:
self.callback.info('%s: %s' % (node, info))
return firm_info
def upload_firm(self, upload_file, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,
debugmode=self.debugmode, verbose=self.verbose)
try:
obmc.login()
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E')
try:
obmc.upload_firmware(self.firmware_file)
self._msg_process(node, 'Firmware upload successful. Use -l option to list.')
except (SelfServerException, SelfClientException) as e:
return self._msg_process(node, e.message, msg_type='E')
def _flash_summary(self):
if not self.activate_result:
return self.callback.error('No summary infomation')
success_num = failed_num = 0
failed_list = []
for key, value in self.activate_result.items():
if value == 'SUCCESS':
success_num += 1
else:
failed_num += 1
failed_list.append('%s: %s' % (key, value))
self.callback.info('-' * 55)
self.callback.info('%s complete: Total=%d Success=%d Failed=%d' % \
('Firmware update', self.nodes_num, success_num, failed_num))
for i in failed_list:
self.callback.info(i)
self.callback.info('-' * 55)
def post_activate_firm(self, task, activate_arg, **kw):
self._flash_summary()
def post_flash_process(self, task, directory, no_host_reboot, **kw):
self._flash_summary()

View File

@ -8,6 +8,7 @@
from __future__ import print_function
import gevent
import time
import os
from common.task import ParallelNodesCommand
from common.exceptions import SelfClientException, SelfServerException
@ -20,6 +21,30 @@ logger = logging.getLogger('xcatagent')
class OpenBMCInventoryTask(ParallelNodesCommand):
"""Executor for inventory-related actions."""
def pre_get_firm_info(self, task, target_file=None, **kw):
if not target_file:
return
target_file = utils.get_full_path(self.cwd, target_file)
grep_cmd = '/usr/bin/grep -a'
version_cmd = grep_cmd + ' ^version= ' + target_file
purpose_cmd = grep_cmd + ' purpose= ' + target_file
purpose_ver = os.popen(purpose_cmd).readlines()
firmware_ver = os.popen(version_cmd).readlines()
if purpose_ver:
purpose_ver = purpose_ver[0].split('=')[-1].strip()
else:
purpose_ver = ''
if firmware_ver:
firmware_ver = firmware_ver[0].split('=')[-1].strip()
else:
firmware_ver = ''
self.callback.info('TAR %s Firmware Product Version: %s' \
% (purpose_ver,firmware_ver))
def _get_firm_info(self, firm_info_list):
(has_functional, firm_obj_dict) = firm_info_list
firm_info = []
@ -97,7 +122,7 @@ class OpenBMCInventoryTask(ParallelNodesCommand):
return inventory_info
def get_firm_info(self, **kw):
def get_firm_info(self, target_file=None, **kw):
node = kw['node']
obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback,

View File

@ -26,25 +26,6 @@ POWER_STATE_DB = {
class OpenBMCPowerTask(ParallelNodesCommand):
"""Executor for power-related actions."""
def _determine_state(self, states):
chassis_state = states.get('chassis')
host_state = states.get('host')
state = 'Unknown'
if chassis_state == 'Off':
state = chassis_state
elif chassis_state == 'On':
if host_state == 'Off':
state = 'chassison'
elif host_state in ['Quiesced', 'Running']:
state = host_state
else:
state = 'Unexpected host state=%s' % host_state
else:
state = 'Unexpected chassis state=%s' % chassis_state
return state
def get_state(self, **kw):
node = kw['node']
@ -54,7 +35,7 @@ class OpenBMCPowerTask(ParallelNodesCommand):
try:
obmc.login()
states = obmc.list_power_states()
state = self._determine_state(states)
state = obmc.get_host_state(states)
self.callback.info('%s: %s' % (node, openbmc.RPOWER_STATES.get(state, state)))
except (SelfServerException, SelfClientException) as e:
@ -115,7 +96,7 @@ class OpenBMCPowerTask(ParallelNodesCommand):
try:
obmc.login()
states = obmc.list_power_states()
status = self._determine_state(states)
status = obmc.get_host_state(states)
new_status =''
if optype == 'reset' and status in ['Off', 'chassison']:
@ -130,7 +111,7 @@ class OpenBMCPowerTask(ParallelNodesCommand):
start_timeStamp = int(time.time())
for i in range (0, 30):
states = obmc.list_power_states()
status = self._determine_state(states)
status = obmc.get_host_state(states)
if openbmc.RPOWER_STATES.get(status) == 'off':
off_flag = True
break

View File

@ -0,0 +1,54 @@
#!/usr/bin/env python
###############################################################################
# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html
###############################################################################
# -*- coding: utf-8 -*-
#
class FlashInterface(object):
"""Interface for flash-related actions."""
interface_type = 'flash'
version = '1.0'
def activate_firm(self, task, activate_arg):
"""Activate firmware.
:param task: a Task instance containing the nodes to act on.
:activate_arg: arg for activate
"""
return task.run('activate_firm', activate_arg)
def delete_firm(self, task, delete_id):
"""Delete firmware.
:param task: a Task instance containing the nodes to act on.
:param delete_id: firmware id want to delete
"""
return task.run('delete_firm', delete_id)
def flash_process(self, task, directory, no_host_reboot):
"""Upload and activate firmware
:param task: a Task instance containing the nodes to act on.
:directory: firmware directory
"""
return task.run('flash_process', directory, no_host_reboot)
def list_firm_info(self, task):
"""List firmware
:param task: a Task instance containing the nodes to act on.
"""
return task.run('list_firm_info')
def upload_firm(self, task, upload_file):
"""Upload firmware file.
:param task: a Task instance containing the nodes to act on.
:param upload_file: the file want to upload
"""
return task.run('upload_firm', upload_file)
class DefaultFlashManager(FlashInterface):
"""Interface for flash-related actions."""
pass

View File

@ -19,13 +19,14 @@ class InventoryInterface(object):
"""
return task.run('get_info', inventory_type)
def get_firm_info(self, task):
def get_firm_info(self, task, target_arg=None):
"""Return the firm info of the task's nodes.
:param task: a Task instance containing the nodes to act on.
:param check_arg: firmware file to check, for rflash check
:return firm info list
"""
return task.run('get_firm_info')
return task.run('get_firm_info', target_arg)
class DefaultInventoryManager(InventoryInterface):
"""Interface for inventory-related actions."""

View File

@ -145,15 +145,15 @@ BOOTSOURCE_SET_STATE = {
FIRM_URLS = {
"activate" : {
"path" : "/software/%(id)s/attr/RequestedActivation",
"field" : "Software.Activation.RequestedActivations.Active",
"path" : "/software/%s/attr/RequestedActivation",
"field" : "xyz.openbmc_project.Software.Activation.RequestedActivations.Active",
},
"delete" : {
"path" : "/software/%(id)s/action/Delete",
"path" : "/software/%s/action/Delete",
"field" : [],
},
"priority" : {
"path" : "/software/%(id)s/attr/Priority",
"path" : "/software/%s/attr/Priority",
"field" : False,
},
"list" : {
@ -426,6 +426,25 @@ class OpenBMCRest(object):
# TODO: Need special handling for bmc reset, as it is normal bmc may return error
pass
def get_host_state(self, states):
chassis_state = states.get('chassis')
host_state = states.get('host')
state = 'Unknown'
if chassis_state == 'Off':
state = chassis_state
elif chassis_state == 'On':
if host_state == 'Off':
state = 'chassison'
elif host_state in ['Quiesced', 'Running']:
state = host_state
else:
state = 'Unexpected host state=%s' % host_state
else:
state = 'Unexpected chassis state=%s' % chassis_state
return state
def set_one_time_boot_enable(self, enabled):
payload = { "data": enabled }
@ -542,6 +561,18 @@ class OpenBMCRest(object):
error = 'Received wrong format response: %s' % inventory_data
raise SelfServerException(error)
def activate_firmware(self, activate_id):
payload = { "data": FIRM_URLS['activate']['field'] }
url = FIRM_URLS['activate']['path'] % activate_id
return self.request('PUT', url, payload=payload, cmd='activate_firmware')
def delete_firmware(self, delete_id):
payload = { "data": FIRM_URLS['delete']['field'] }
url = FIRM_URLS['delete']['path'] % delete_id
return self.request('POST', url, payload=payload, cmd='delete_firmware')
def list_firmware(self):
data = self.request('GET', FIRM_URLS['list']['path'], cmd='list_firmware')
@ -564,6 +595,18 @@ class OpenBMCRest(object):
return bool(func_list), fw_dict
def upload_firmware(self, upload_file):
headers = {'Content-Type': 'application/octet-stream'}
path = HTTP_PROTOCOL + self.bmcip + '/upload/image/'
self.upload('PUT', path, upload_file, headers=headers, cmd='upload_firmware')
def set_priority(self, firm_id):
payload = { "data": FIRM_URLS['priority']['field'] }
url = FIRM_URLS['priority']['path'] % firm_id
return self.request('PUT', url, payload=payload, cmd='set_priority')
# Extract all eventlog info and parse it
def get_eventlog_info(self):

View File

@ -16,6 +16,7 @@ from common import utils
from common import exceptions as xcat_exception
from hwctl.executor.openbmc_beacon import OpenBMCBeaconTask
from hwctl.executor.openbmc_setboot import OpenBMCBootTask
from hwctl.executor.openbmc_flash import OpenBMCFlashTask
from hwctl.executor.openbmc_inventory import OpenBMCInventoryTask
from hwctl.executor.openbmc_power import OpenBMCPowerTask
from hwctl.executor.openbmc_sensor import OpenBMCSensorTask
@ -23,6 +24,7 @@ from hwctl.executor.openbmc_bmcconfig import OpenBMCBmcConfigTask
from hwctl.executor.openbmc_eventlog import OpenBMCEventlogTask
from hwctl.beacon import DefaultBeaconManager
from hwctl.setboot import DefaultBootManager
from hwctl.flash import DefaultFlashManager
from hwctl.inventory import DefaultInventoryManager
from hwctl.power import DefaultPowerManager
from hwctl.sensor import DefaultSensorManager
@ -30,7 +32,6 @@ from hwctl.bmcconfig import DefaultBmcConfigManager
from hwctl.eventlog import DefaultEventlogManager
from xcatagent import base
import openbmc_rest
import logging
logger = logging.getLogger('xcatagent')
if not logger.handlers:
@ -50,38 +51,6 @@ all_nodes_result = {}
# global variables of rbeacon
BEACON_SET_OPTIONS = ('on', 'off')
# global variables of rflash
RFLASH_OPTIONS = {
"-a" : "activate",
"--activate" : "activate",
"-c" : "check",
"--check" : "check",
"-d" : "direcory",
"--delete" : "delete",
"-l" : "list",
"--list" : "list",
"-u" : "upload",
"--upload" : "upload",
}
RFLASH_URLS = {
"activate" : {
"url" : PROJECT_URL + "/software/#ACTIVATE_ID#/attr/RequestedActivation",
"field" : "xyz.openbmc_project.Software.Activation.RequestedActivations.Active",
},
"delete" : {
"url" : PROJECT_URL + "/software/#DELETE_ID#/action/Delete",
"field" : [],
},
"upload" : {
"url" : "/upload/image/",
},
"priority" : {
"url" : PROJECT_URL + "/software/#PRIORITY_ID#/attr/Priority",
"field" : False,
}
}
RSPCONFIG_GET_OPTIONS = ['ip','ipsrc','netmask','gateway','vlan','ntpservers','hostname','bootmode','autoreboot','powersupplyredundancy','powerrestorepolicy']
RSPCONFIG_SET_OPTIONS = {
'ip':'.*',
@ -126,12 +95,6 @@ The supported attributes and its values to set are:
powerrestorepolicy={always_on|always_off|restore}
""" % RSPCONFIG_GET_OPTIONS
XCAT_LOG_DIR = "/var/log/xcat"
XCAT_LOG_RFLASH_DIR = XCAT_LOG_DIR + "/rflash/"
# global variable of firmware information
FIRM_URL = PROJECT_URL + "/software/enumerate"
#global variables of rinv
INVENTORY_OPTIONS = ('all', 'cpu', 'dimm', 'firm', 'model', 'serial')
@ -151,452 +114,6 @@ VITALS_OPTIONS = ('all', 'altitude', 'fanspeed', 'leds', 'power',
# global variables of reventlog
EVENTLOG_OPTIONS = ('list', 'clear', 'resolved')
class OpenBMC(base.BaseDriver):
headers = {'Content-Type': 'application/json'}
def __init__(self, messager, name, node_info):
super(OpenBMC, self).__init__(messager)
self.node = name
for key, value in node_info.items():
setattr(self, key, value)
global DEBUGMODE
self.client = openbmc_rest.OpenBMCRest(name, messager, DEBUGMODE)
def _login(self):
""" Login
:raise: error message if failed
"""
url = HTTP_PROTOCOL + self.bmcip + '/login'
data = { "data": [ self.username, self.password ] }
self.client.request('POST', url, OpenBMC.headers, data, 'login')
return RESULT_OK
def _msg_process_rflash (self, msg, update_dict, checkv):
"""deal with msg during rflash
:param msg: the msg want to process
"""
if not checkv:
self.messager.info('%s: %s' % (self.node, msg))
elif VERBOSE:
self.messager.info('%s: %s' % (self.node, msg))
self.rflash_log_handle.writelines(msg + '\n')
self.rflash_log_handle.flush()
if update_dict:
utils.update2Ddict(update_dict, self.node, 'result', [msg])
def _firm_info(self, status):
"""List firmware information including additional
called by rflash check and rinv firm
:returns: firmware information
"""
firm_output = []
try:
(has_functional, firm_info) = self._get_firm_info(status)
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
firm_output.append(e.message)
return firm_output
keys = firm_info.keys()
keys.sort()
for key in keys:
flag = ''
if 'is_functional' in firm_info[key]:
flag = '*'
elif ('Priority' in firm_info[key] and
firm_info[key]['Priority'] == '0'):
if not has_functional:
flag = '*'
else:
flag = '+'
if not flag and not VERBOSE:
continue
firm_output.append('%s Firmware Product: %s (%s)%s' %
(firm_info[key]['Purpose'],
firm_info[key]['Version'],
firm_info[key]['Activation'], flag))
if 'ExtendedVersion' in firm_info[key]:
extendeds = firm_info[key]['ExtendedVersion'].split(',')
extendeds.sort()
for extended in extendeds:
firm_output.append('%s Firmware Product: ' \
'-- additional info: %s' % \
(firm_info[key]['Purpose'], extended))
return firm_output
def _get_firm_info(self, status):
"""get firmware information
:param status: current status
:returns: firmware version information
"""
firm_info = {}
has_functional = False
url = HTTP_PROTOCOL + self.bmcip + FIRM_URL
response = self.client.request('GET', url, OpenBMC.headers, '', status)
functional_url = PROJECT_URL + '/software/functional'
for key in response['data']:
key_id = key.split('/')[-1]
if key_id == 'functional':
for endpoint in response['data'][key]['endpoints']:
purpose = response['data'][endpoint]['Purpose'].split('.')[-1]
key_sort = purpose + '-' + endpoint.split('/')[-1]
utils.update2Ddict(firm_info, key_sort, 'is_functional', True)
has_functional = True
if 'Version' in response['data'][key]:
purpose = response['data'][key]['Purpose'].split('.')[-1]
key_sort = purpose + '-' + key_id
if (functional_url in response['data'] and
key in response['data'][functional_url]['endpoints']):
utils.update2Ddict(firm_info, key_sort, 'is_functional', True)
utils.update2Ddict(firm_info, key_sort, 'Version',
response['data'][key]['Version'])
utils.update2Ddict(firm_info, key_sort, 'Purpose', purpose)
utils.update2Ddict(firm_info, key_sort, 'Activation',
response['data'][key]['Activation'].split('.')[-1])
if 'Priority' in response['data'][key]:
utils.update2Ddict(firm_info, key_sort, 'Priority',
str(response['data'][key]['Priority']))
if 'ExtendedVersion' in response['data'][key]:
utils.update2Ddict(firm_info, key_sort, 'ExtendedVersion',
response['data'][key]['ExtendedVersion'])
if 'Progress' in response['data'][key]:
utils.update2Ddict(firm_info, key_sort, 'Progress',
response['data'][key]['Progress'])
return (has_functional, firm_info)
def _get_firm_id(self, firm_list):
"""get firmware id
:param firm_list: the list of firmware versions
:return: result and info list
"""
firm_ids = []
url = HTTP_PROTOCOL + self.bmcip + FIRM_URL
for i in range(6):
try:
response = self.client.request('GET', url, OpenBMC.headers,
'', 'rflash_check_id')
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
self._msg_process_rflash(e.message, all_nodes_result, False)
return (RESULT_FAIL, [])
for key in response['data']:
if 'Version' in response['data'][key]:
if response['data'][key]['Version'] in firm_list:
firm_id = key.split('/')[-1]
upload_msg = 'Firmware upload successful. ' \
'Attempting to activate firmware: ' \
'%s (ID: %s)' % \
(response['data'][key]['Version'], firm_id)
self._msg_process_rflash(upload_msg, {}, False)
firm_ids.append(firm_id)
firm_list.remove(response['data'][key]['Version'])
if firm_list:
for firm_ver in firm_list:
retry_msg = 'Could not find ID for firmware %s to '\
'activate, waiting %d seconds and retry...' \
% (firm_ver, 10)
self._msg_process_rflash(upload_msg, {}, True)
gevent.sleep( 10 )
else:
break
if firm_list:
for firm_ver in firm_list:
error = 'Could not find firmware %s after waiting %d seconds.' \
% (firm_ver, 10*6)
self._msg_process_rflash(upload_msg, {}, False)
error_list.append(error)
utils.update2Ddict(all_nodes_result, self.node, 'result', error_list)
return (RESULT_FAIL, [])
return (RESULT_OK, firm_ids)
def _check_id_status(self, firm_id_list):
"""check firm id status
:param firm_id_list: list of firm ids want to check
:return: result
"""
result = RESULT_OK
set_priority_ids = []
process_status = {}
failed_msg = []
for i in range(80):
try:
(has_functional, firm_info) = self._get_firm_info('rflash_check_status')
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
self._msg_process_rflash(e.message, all_nodes_result, False)
return (RESULT_FAIL, set_priority_ids)
activation_num = 0
for key in firm_info:
firm_id = key.split('-')[-1]
if firm_id in firm_id_list:
activation_state = firm_info[key]['Activation']
firm_version = firm_info[key]['Version']
if activation_state == 'Failed':
activation_msg = 'Firmware %s activation failed.' % (firm_version)
self._msg_process_rflash(activation_msg, {}, False)
failed_msg.append(activation_msg)
result = RESULT_FAIL
firm_id_list.rempove(firm_id)
if activation_state == 'Active':
activation_msg = 'Firmware %s activation successful.' % (firm_version)
self._msg_process_rflash(activation_msg, {}, False)
firm_id_list.remove(firm_id)
priority = firm_info[key]['Priority']
if priority != '0':
set_priority_ids.append(firm_id)
if activation_state == 'Activating':
activating_progress_msg = 'Activating %s ... %s%%' \
% (firm_version, firm_info[key]['Progress'])
self._msg_process_rflash(activating_progress_msg, {}, True)
process_status[firm_id] = activating_progress_msg
if not firm_id_list:
break
gevent.sleep( 15 )
if firm_id_list:
result = RESULT_FAIL
for firm_id in firm_id_list:
if firm_id in process_status:
failed_msg.append('After %d seconds check the current status is %s' \
% (80*15, process_status[firm_id]))
if failed_msg:
utils.update2Ddict(all_nodes_result, self.node, 'result', [failed_msg])
return (result, set_priority_ids)
def _set_priority(self, priority_ids):
"""set firmware priority to 0
:param priority_ids: list of firmware ids
:return ok if success
:return error msg if failed
"""
for priority_id in priority_ids:
url = (HTTP_PROTOCOL + self.bmcip +
RFLASH_URLS['priority']['url'].replace('#PRIORITY_ID#', priority_id))
data = { "data": RFLASH_URLS['priority']['field'] }
try:
response = self.client.request('PUT', url, OpenBMC.headers,
data, 'rflash_set_priority')
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
return e.message
return RESULT_OK
def _rflash_activate_id(self, activate_id):
"""rflash activate id
:param activate_id: the id want to activate
:raise: error message if failed
"""
url = (HTTP_PROTOCOL + self.bmcip +
RFLASH_URLS['activate']['url'].replace('#ACTIVATE_ID#', activate_id))
data = { "data": RFLASH_URLS['activate']['field'] }
try:
response = self.client.request('PUT', url, OpenBMC.headers,
data, 'rflash_activate')
except xcat_exception.SelfServerException as e:
return e.message
except xcat_exception.SelfClientException as e:
code = e.code
if code == 403:
return 'Error: Invalid ID provided to activate. ' \
'Use the -l option to view valid firmware IDs.'
return e.message
return RESULT_OK
def _rflash_activate(self, activate_arg):
"""ACTIVATE firmware
called by rflash activate
:param activate_arg: firmware tar ball or firmware id
:return: ok if success
:raise: error message if failed
"""
activate_id = activate_version = ''
if 'activate_id' in activate_arg:
activate_id = activate_arg['activate_id']
if 'update_file' in activate_arg:
result = self._rflash_upload(activate_arg['update_file'])
if result != RESULT_OK:
self._msg_process_rflash(result, all_nodes_result, False)
return
activate_version = activate_arg['activate_version']
(result, info) = self._get_firm_id([activate_version])
if result == RESULT_OK:
activate_id = info.pop(0)
else:
return
result = self._rflash_activate_id(activate_id)
if result != RESULT_OK:
self._msg_process_rflash(result, all_nodes_result, False)
return
else:
flash_started_msg = 'rflash %s started, please wait...' % activate_version
self._msg_process_rflash(flash_started_msg, {}, False)
firm_id_list = [activate_id]
(result, priority_ids) = self._check_id_status(firm_id_list)
if result == RESULT_OK:
utils.update2Ddict(all_nodes_result, self.node, 'result', 'OK')
if priority_ids:
self._set_priority(priority_ids)
def _rflash_delete(self, delete_id):
"""Delete firmware on OpenBMC
called by rflash delete
:param delete_id: firmware id want to delete
:returns: ok if success
:raise: error message if failed
"""
url = (HTTP_PROTOCOL + self.bmcip +
RFLASH_URLS['delete']['url'].replace('#DELETE_ID#', delete_id))
data = { "data": RFLASH_URLS['delete']['field'] }
try:
response = self.client.request('POST', url, OpenBMC.headers,
data, 'rflash_delete')
except xcat_exception.SelfServerException as e:
return e.message
except xcat_exception.SelfClientException as e:
code = e.code
if code == 404:
return 'Error: Invalid ID provided to delete. ' \
'Use the -l option to view valid firmware IDs.'
return e.message
return RESULT_OK
def _rflash_list(self):
"""List firmware information
called by rflash list
:returns: firmware version if success
:raise: error message if failed
"""
firm_output = []
try:
(has_functional, firm_info) = self._get_firm_info('rflash_list')
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
firm_output.append(e.message)
return firm_output
firm_output.append('%-8s %-7s %-10s %-s' % ('ID', 'Purpose', 'State', 'Version'))
firm_output.append('-' * 55)
for key in firm_info:
status = firm_info[key]['Activation']
if 'is_functional' in firm_info[key]:
status += '(*)'
elif 'Priority' in firm_info[key] and firm_info[key]['Priority'] == '0':
if not has_functional:
status += '(*)'
else:
status += '(+)'
firm_output.append('%-8s %-7s %-10s %-s' % (key.split('-')[-1],
firm_info[key]['Purpose'], status, firm_info[key]['Version']))
return firm_output
def _rflash_upload(self, upload_file):
""" Upload *.tar file to OpenBMC server
:param upload_file: file to upload
"""
url = HTTP_PROTOCOL + self.bmcip + RFLASH_URLS['upload']['url']
headers = {'Content-Type': 'application/octet-stream'}
uploading_msg = 'Uploading %s ...' % upload_file
self._msg_process_rflash(uploading_msg, {}, True)
try:
self.client.request_upload('PUT', url, headers,
upload_file, 'rflash_upload')
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
result = e.message
return result
return RESULT_OK
def rflash(self, args):
"""handle rflash command
:param args: subcommands and parameters for rflash
"""
subcommand = args[0]
if subcommand == 'activate' or subcommand == 'upload':
self.rflash_log_file = XCAT_LOG_RFLASH_DIR + '/' + self.node + '.log'
self.rflash_log_handle = open(self.rflash_log_file, 'a')
try:
result = self._login()
except (xcat_exception.SelfServerException,
xcat_exception.SelfClientException) as e:
result = e.message
if result != RESULT_OK:
self.messager.info('%s: %s'% (self.node,result))
if subcommand == 'activate' or subcommand == 'upload':
self.rflash_log_handle.writelines(result + '\n')
self.rflash_log_handle.flush()
if subcommand == 'activate':
utils.update2Ddict(all_nodes_result, self.node, 'result', [result])
return
if subcommand == 'activate':
activate_arg = args[1]
self._rflash_activate(activate_arg)
if subcommand == 'check':
firm_info = self._firm_info('rflash_check')
for i in firm_info:
result = '%s: %s' % (self.node, i)
self.messager.info(result)
if subcommand == 'delete':
firmware_id = args[1]
result = self._rflash_delete(firmware_id)
if result == RESULT_OK:
result = '%s: [%s] Firmware removed' % (self.node, firmware_id)
self.messager.info(result)
else:
result = '%s: %s' % (self.node, result)
self.messager.info(result)
if subcommand == 'list':
firm_info = self._rflash_list()
for i in firm_info:
result = '%s: %s' % (self.node, i)
self.messager.info(result)
if subcommand == 'upload':
upload_file = args[1]
result = self._rflash_upload(upload_file)
if result == RESULT_OK:
result = 'Firmware upload successful. Use -l option to list.'
self._msg_process_rflash(result, {}, False)
else:
self._msg_process_rflash(result, {}, False)
if subcommand == 'activate' or subcommand == 'upload':
self.rflash_log_handle.close()
class OpenBMCManager(base.BaseManager):
def __init__(self, messager, cwd, nodes=None, envs=None):
super(OpenBMCManager, self).__init__(messager, cwd)
@ -642,6 +159,51 @@ class OpenBMCManager(base.BaseManager):
runner = OpenBMCBeaconTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose)
DefaultBeaconManager().set_beacon_state(runner, beacon_state=action)
def rflash(self, nodesinfo, args):
# 1, parse agrs
rflash_usage = """
Usage:
rflash [[-a|--activate <arg>] | [-c|--check <arg>] | [-d <arg> [--no-host-reboot]] | [--delete <arg>] | [-l|--list] | [-u|--upload <arg>]] [-V|--verbose]
Options:
-V,--verbose Show verbose message
-a,--activate <arg> Activate firmware
-c,--check Check firmware info
-d <arg> Upload and activate all firmware files under directory
-l,--list List firmware info
-u,--upload <arg> Upload firmware file
--delete <arg> Delete firmware
--no-host-reboot Not reboot host after activate
"""
try:
opts = docopt(rflash_usage, argv=args)
self.verbose = opts.pop('--verbose')
except Exception as e:
self.messager.error("Failed to parse arguments for rflash: %s" % args)
return
if opts['--check']:
check_arg = None
if opts['<arg>']:
check_arg = opts['<arg>']
runner = runner = OpenBMCInventoryTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose, cwd=self.cwd[0])
DefaultInventoryManager().get_firm_info(runner, check_arg)
return
runner = OpenBMCFlashTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose, cwd=self.cwd[0])
if opts['--activate']:
DefaultFlashManager().activate_firm(runner, opts['--activate'][0])
elif opts['--list']:
DefaultFlashManager().list_firm_info(runner)
elif opts['-d']:
DefaultFlashManager().flash_process(runner, opts['-d'], opts['--no-host-reboot'])
elif opts['--delete']:
DefaultFlashManager().delete_firm(runner, opts['--delete'])
elif opts['--upload']:
DefaultFlashManager().upload_firm(runner, opts['--upload'][0])
def rinv(self, nodesinfo, args):
# 1, parse agrs
@ -715,6 +277,7 @@ class OpenBMCManager(base.BaseManager):
DefaultPowerManager().reboot(runner, optype=action)
else:
DefaultPowerManager().set_power_state(runner, power_state=action)
def rspconfig(self, nodesinfo, args):
try:
opts=docopt(RSPCONFIG_USAGE, argv=args)
@ -768,6 +331,7 @@ class OpenBMCManager(base.BaseManager):
DefaultBmcConfigManager().set_attributes(runner, opts['<args>'])
else:
self.messager.error("Failed to deal with rspconfig: %s" % args)
def rsetboot(self, nodesinfo, args):
# 1, parse args
@ -884,98 +448,3 @@ class OpenBMCManager(base.BaseManager):
else:
DefaultEventlogManager().get_eventlog_info(runner, "all")
def _get_full_path(self,file_path):
if type(self.cwd) == 'unicode':
dir_path = self.cwd
else:
dir_path = self.cwd[0]
return '%s/%s' % (dir_path,file_path)
def _check_verbose(self, args):
verbose_list = ('-V', '--verbose')
for i in verbose_list:
if i in args:
global VERBOSE
VERBOSE = True
args.remove(i)
def _summary(self, nodes_num, title):
if all_nodes_result:
success_num = failed_num = 0
failed_list = []
for key in all_nodes_result:
if all_nodes_result[key]['result'] == 'OK':
success_num += 1
else:
failed_num += 1
for errors in all_nodes_result[key]['result']:
for error in errors:
failed_list.append('%s: %s' % (key, error))
self.messager.info('-' * 55)
self.messager.info('%s complete: Total=%d Success=%d Failed=%d' % \
(title, nodes_num, success_num, failed_num))
if failed_list:
for i in failed_list:
self.messager.info(i)
self.messager.info('-' * 55)
def rflash(self, nodeinfo, args):
if not os.path.exists(XCAT_LOG_RFLASH_DIR):
os.makedirs(XCAT_LOG_RFLASH_DIR)
nodes_num = len(self.nodes)
self._check_verbose(args)
for key,value in RFLASH_OPTIONS.items():
if key in args:
args.remove(key)
args.insert(0, value)
break
upload_file = None
activate_arg = {}
args_num = len(args)
subcommand = args[0]
if (subcommand == 'upload' or subcommand == 'activate' or
(subcommand == 'check' and args_num > 1)):
arg_type = args[1].split('.')[-1]
if arg_type == 'tar':
upload_file = args[1]
if not os.path.isabs(upload_file):
upload_file = self._get_full_path(upload_file)
if (not os.access(upload_file, os.F_OK) or
not os.access(upload_file, os.R_OK)):
error = 'Error: Cannot access %s. Check the management ' \
'node and/or service nodes.' % upload_file
self.messager.error(error)
return
activate_arg['update_file'] = upload_file
else:
activate_arg['activate_id'] = args[1]
if (subcommand == 'check' or subcommand == 'activate') and upload_file:
grep_cmd = '/usr/bin/grep -a'
version_cmd = grep_cmd + ' ^version= ' + upload_file
purpose_cmd = grep_cmd + ' purpose= ' + upload_file
firmware_ver = os.popen(version_cmd).readlines()[0].split('=')[-1].strip()
purpose_ver = os.popen(purpose_cmd).readlines()[0].split('=')[-1].strip()
if subcommand == 'check':
self.messager.info('TAR %s Firmware Product Version: %s' \
% (purpose_ver,firmware_ver))
else:
activate_arg['activate_version'] = firmware_ver
activate_arg['purpose'] = purpose_ver.split('.')[-1]
if subcommand == 'activate':
args[1] = activate_arg
if subcommand == 'upload':
args[1] = upload_file
if subcommand == 'upload' or subcommand == 'activate' and upload_file:
self.messager.info('Attempting to upload %s, please wait...' % upload_file)
super(OpenBMCManager, self).process_nodes_worker('openbmc', 'OpenBMC',
self.nodes, nodeinfo, 'rflash', args)
self._summary(nodes_num, 'Firmware update')

View File

@ -1,113 +0,0 @@
#!/usr/bin/env python
import requests
import json
import time
from common import rest
from common import exceptions as xcat_exception
class OpenBMCRest:
def __init__(self, name, messager, debugmode):
self.session = rest.RestSession()
self.name = name
self.messager = messager
self.debugmode = debugmode
def _print_record_log (self, log_string, status):
if self.debugmode :
localtime = time.asctime( time.localtime(time.time()) )
log = self.name + ': [openbmc_debug] ' + status + ' ' + log_string
self.messager.info(localtime + ' ' + log)
self.messager.syslog(log)
def _request_log (self, method, url, headers, data, files):
log_string = 'curl -k -c cjar -b cjar'
log_string += ' -X %s' % method
for key,value in headers.items():
header_data = key + ": " + value
log_string += ' -H "' + header_data + '"'
log_string += ' %s' % url
if data:
log_string += ' -d \'%s\'' % data
if files:
log_string += ' -T \'%s\'' % files
return log_string
def _response_check (self, response, response_dict, status):
if response.status_code != requests.codes.ok:
description = ''.join(response_dict['data']['description'])
error = 'Error: [%d] %s' % (response.status_code, description)
self._print_record_log(error, status)
code = response.status_code
raise xcat_exception.SelfClientException(error, code)
else:
self._print_record_log(response_dict['message'], status)
def request (self, method, url, headers, in_data, status):
data = log_data = ''
if in_data:
data = json.dumps(in_data)
log_data = data
if status == 'login':
in_data['data'][1] = 'xxxxxx'
log_data = json.dumps(in_data)
log_string = self._request_log(method, url, headers, log_data, '')
self._print_record_log(log_string, status)
try:
response = self.session.request(method, url, headers, data)
except xcat_exception.SelfServerException as e:
self._print_record_log(e.message, status)
raise xcat_exception.SelfServerException(e.message)
try:
response_dict = response.json()
except ValueError:
error = 'Error: Received wrong format response: %s' % response
self._print_record_log(error, status)
raise xcat_exception.SelfServerException(error)
self._response_check(response, response_dict, status)
return response_dict
def request_upload (self, method, url, headers, files, status):
for key,value in headers.items():
header_data = key + ': ' + value
request_cmd_log = 'curl -k -c cjar -b cjar -H "%s" -X %s -T %s %s -s' \
% (header_data, method, files, url)
log_string = self._request_log(method, url, headers, '', files)
self._print_record_log(log_string, status)
response = self.session.request_upload(method, url, header_data, files)
if not response:
error = 'Error: Did not receive response from OpenBMC after ' \
'running command form \'%s\'' % request_cmd_log
raise xcat_exception.SelfServerException(error)
try:
response_dict = json.loads(response)
except ValueError:
error = 'Error: Received wrong format response: %s: %s' % \
(request_cmd_log, response)
self._print_record_log(error, status)
raise xcat_exception.SelfServerException(error)
if response_dict['message'] != '200 OK':
error = 'Error: Failed to upload update file %s : %s-%s' % \
(files, response_dict['message'], \
''.join(response_dict['data']['description']))
self._print_record_log(error, status)
raise xcat_exception.SelfClientException(error, code)
self._print_record_log(response_dict['message'], status)
return

View File

@ -231,7 +231,6 @@ sub parse_args {
}
}
if ($directory) {
return ([ 1, "Unsupported command: $command '-d'" ]);
return ([ 1, "More than one directory specified is not supported."]) if ($#ARGV >= 1);
return ([ 1, "Invalid option specified with '-d'."]) if (!@ARGV);
}