From 5d1c8c7092616c3e2192c0fc5314372dacd2be3b Mon Sep 17 00:00:00 2001 From: zhao er tao Date: Fri, 2 Feb 2018 23:40:37 +0800 Subject: [PATCH 1/3] deal with rspconfig in python --- .../lib/python/agent/xcatagent/openbmc.py | 1 - xCAT-server/lib/xcat/plugins/openbmc2.pm | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py index 82ec20b8f..4346cb6f6 100644 --- a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py +++ b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py @@ -696,7 +696,6 @@ class OpenBMCManager(base.BaseManager): else: DefaultSensorManager().get_sensor_info(runner, action) - def _get_full_path(self,file_path): if type(self.cwd) == 'unicode': dir_path = self.cwd diff --git a/xCAT-server/lib/xcat/plugins/openbmc2.pm b/xCAT-server/lib/xcat/plugins/openbmc2.pm index 584e801e9..a34626dbd 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc2.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc2.pm @@ -113,6 +113,10 @@ sub process_request { $callback = shift; my $noderange = $request->{node}; my $check = parse_node_info($noderange); + if (&refactor_args($request)) { + xCAT::MsgUtils->message("E", { data => ["Failed to refactor arguments"] }, $callback); + return; + } $callback->({ errorcode => [$check] }) if ($check); return unless(%node_info); my $pid = xCAT::OPENBMC::start_python_agent(); @@ -298,4 +302,32 @@ sub parse_node_info { return $rst; } +#------------------------------------------------------- + +=head3 refactor_args + + refractor args to be easily dealt by python client + +=cut + +#------------------------------------------------------- + +sub refactor_args { + my $request = shift; + my $command = $request->{command}->[0]; + my $extrargs = $request->{arg}; + if ($command eq "rspconfig") { + if ($extrargs->[0] eq "dump") { + $request->{arg}->[0] = "--dump"; + } else { + foreach my $arg (@$extrargs) { + if ($arg !~ /^-/) { + $arg = "--".$arg; + } + } + } + } + return 0; +} + 1; From 6f397510cc0c2a1dcd71805e135689e0e50341b9 Mon Sep 17 00:00:00 2001 From: zhao er tao Date: Sun, 4 Feb 2018 23:22:59 +0800 Subject: [PATCH 2/3] rspconfig in python --- .../lib/python/agent/hwctl/bmcconfig.py | 42 ++++ .../agent/hwctl/executor/openbmc_bmcconfig.py | 198 ++++++++++++++++++ .../lib/python/agent/xcatagent/openbmc.py | 96 +++++++++ xCAT-server/lib/xcat/plugins/openbmc2.pm | 17 +- 4 files changed, 346 insertions(+), 7 deletions(-) create mode 100644 xCAT-openbmc-py/lib/python/agent/hwctl/bmcconfig.py create mode 100644 xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/bmcconfig.py b/xCAT-openbmc-py/lib/python/agent/hwctl/bmcconfig.py new file mode 100644 index 000000000..5bdb5bc1d --- /dev/null +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/bmcconfig.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +############################################################################### +# IBM(c) 2018 EPL license http://www.eclipse.org/legal/epl-v10.html +############################################################################### +# -*- coding: utf-8 -*- +# + +class BmcConfigInterface(object): + """Interface for bmc configuration related actions.""" + interface_type = 'bmcconfig' + version = '1.0' + + def dump_list(self, task): + return task.run('dump_list') + + def dump_generate(self, task): + return task.run("dump_generate") + + def dump_clear(self, task, id): + return task.run("dump_clear", id) + + def dump_download(self, task, id): + return task.run("dump_download", id) + + def dump_process(self, task): + return task.run("dump_process") + + def set_sshcfg(self, task): + return task.run("set_sshcfg") + + def set_ipdhcp(self, task): + return task.run("set_ipdhcp") + + def get_attributes(self, task, attributes): + return task.run("get_attributes", attributes) + + def set_attributes(self, task, attributes): + return task.run("set_attributes", attributes) + +class DefaultBmcConfigManager(BmcConfigInterface): + """Interface for BmcConfig actions.""" + pass diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py new file mode 100644 index 000000000..b0fe244b3 --- /dev/null +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py @@ -0,0 +1,198 @@ +#!/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 + +from common.task import ParallelNodesCommand +from common.exceptions import SelfClientException, SelfServerException +from hwctl import openbmc_client as openbmc + +import logging +logger = logging.getLogger('xcatagent') + +RSPCONFIG_GET_NETINFO=['ip', 'netmask', 'gateway', 'vlan', 'ipsrc', 'hostname'] +RSPCONFIG_SET_NETINFO=['ip', 'netmask', 'gateway', 'vlan'] + +RSPCONFIG_APIS = { + 'autoreboot' : { + 'baseurl': "/control/host0/auto_reboot/", + 'set_url': "attr/AutoReboot", + 'get_url': "attr/AutoReboot", + 'display_name': "BMC AutoReboot", + }, + 'powersupplyredundancy':{ + 'baseurl': "/sensors/chassis/PowerSupplyRedundancy/", + 'set_url': "/action/setValue", + 'get_url': "/action/getValue", + 'get_method': 'POST', + 'get_data': '[]', + 'display_name': "BMC PowerSupplyRedundancy", + 'attr_values': { + 'disabled': "Disables", + 'enabled': "Enabled", + }, + }, + 'powerrestorepolicy': { + 'baseurl': "/control/host0/power_restore_policy/", + 'set_url': "attr/PowerRestorePolicy", + 'get_url': "attr/PowerRestorePolicy", + 'display_name': "BMC PowerRestorePolicy", + 'attr_values': { + 'restore': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore", + 'always_on': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn", + 'always_off': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff", + }, + }, + 'bootmode': { + 'baseurl': "/control/host0/boot/", + 'set_url': "attr/BootMode", + 'get_url': "attr/BootMode", + 'display_name':"BMC BootMode", + 'attr_values': { + 'regular': "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular", + 'safe': "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe", + 'setup': "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup", + }, + }, +} + +class OpenBMCBmcConfigTask(ParallelNodesCommand): + + def dump_list(self, **kw): + return self.callback.info('dump_list') + + 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) + + def dump_download(self, id, **kw): + return self.callback.info("dump_download id: %s" % id) + + def dump_process(self, **kw): + return self.callback.info("dump_process: trigger, list and download") + + def set_sshcfg(self, **kw): + return self.callback.info("set_sshcfg") + + def set_ipdhcp(self, **kw): + return self.callback.info("set_ipdhcp") + + def get_attributes(self, attributes, **kw): + netinfo_dict={'ip':False, 'ipsrc':False, 'netmask':False, + 'gateway':False, 'vlan':False, 'hostname':False} + getnet=0 + for attr in attributes: + if attr in RSPCONFIG_GET_NETINFO: + netinfo_dict[attr]=True + getnet=1 + elif RSPCONFIG_APIS.has_key(attr): + return self._get_apis_values(attr, **kw) + else: + return self.callback.error("get_attributes can not deal with attr %s" % attr) + if getnet: + self._get_netinfo(netinfo_dict['ip'], netinfo_dict['ipsrc'], netinfo_dict['netmask'], + netinfo_dict['gateway'], netinfo_dict['vlan'], netinfo_dict['hostname'], **kw) + + def set_attributes(self, attributes, **kw): + netinfo_dict={'vlan':False} + for attr in attributes: + k,v = attr.split('=') + if k in RSPCONFIG_SET_NETINFO: + netinfo_dict[k] = v + elif k == 'hostname': + return self._set_hostname(v, **kw) + elif RSPCONFIG_APIS.has_key(k): + return self._set_apis_values(k, v, **kw) + else: + return self.callback.error("set_attributes unsupported attribute:%s" % k) + if (not netinfo_dict['ip']) or (not netinfo_dict['netmask']) or (not netinfo_dict['gateway']): + return self.callback.error("set_attributes miss either ip, netmask or gateway to set network information") + else: + self._set_netinfo(netinfo_dict['ip'], netinfo_dict['netmask'], + netinfo_dict['gateway'], netinfo_dict['vlan']) + + def _set_hostname(self, hostname, **kw): + 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) + + def _set_apis_values(self, key, value, **kw): + node = kw['node'] + attr_info = RSPCONFIG_APIS[key] + if not attr_info.has_key('set_url'): + return self.callback.error("config %s failed, not url available" % key) + set_url = attr_info['baseurl']+attr_info['set_url'] + + obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, + debugmode=self.debugmode, verbose=self.verbose) + + if attr_info.has_key('attr_values') and attr_info['attr_values'].has_key(value): + data = attr_info['attr_values'][value] + else: + data = value + + try: + obmc.login() + obmc.request('PUT', set_url, payload={"data": data}, cmd="set_%s" % key) + except (SelfServerException, SelfClientException) as e: + self.callback.info("%s: %s" % (node, e.message)) + + self.callback.info("%s: BMC Setting %s..." % (node, attr_info['display_name'])) + + def _get_apis_values(self, key, **kw): + node = kw['node'] + attr_info = RSPCONFIG_APIS[key] + if not attr_info.has_key('get_url'): + return self.callback.error("Reading %s failed, not url available" % key) + get_url = attr_info['baseurl']+attr_info['get_url'] + obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, + debugmode=self.debugmode, verbose=self.verbose) + try: + obmc.login() + method = 'GET' + if attr_info.has_key('get_method'): + method = attr_info['get_method'] + data = None + if attr_info.has_key('get_data'): + data={"data": attr_info['get_data']} + value = obmc.request(method, get_url, payload=data, cmd="get_%s" % key) + str_value = '0.'+str(value) + result = '%s: %s: %s' % (node, attr_info['display_name'], str_value.split('.')[-1]) + + except (SelfServerException, SelfClientException) as e: + result = '%s: %s' % (node, e.message) + + self.callback.info(result) + + def _set_netinfo(self, ip, netmask, gateway, vlan=False, **kw): + if vlan: + result = "set net(%s, %s, %s) for vlan %s" % (ip, netmask, gateway, vlan) + else: + 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, " + if hostname: + result += "Get BMC hostname, " + if vlan: + result += "Get BMC vlan." + return self.callback.info("get_netinfo: %s" % result) diff --git a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py index 4346cb6f6..b28d27ba2 100644 --- a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py +++ b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py @@ -9,6 +9,7 @@ import os import time import sys import gevent +import re from docopt import docopt from common import utils @@ -17,10 +18,12 @@ from hwctl.executor.openbmc_beacon import OpenBMCBeaconTask from hwctl.executor.openbmc_power import OpenBMCPowerTask from hwctl.executor.openbmc_setboot import OpenBMCBootTask from hwctl.executor.openbmc_sensor import OpenBMCSensorTask +from hwctl.executor.openbmc_bmcconfig import OpenBMCBmcConfigTask from hwctl.beacon import DefaultBeaconManager from hwctl.power import DefaultPowerManager from hwctl.setboot import DefaultBootManager from hwctl.sensor import DefaultSensorManager +from hwctl.bmcconfig import DefaultBmcConfigManager from xcatagent import base import openbmc_rest @@ -75,6 +78,46 @@ RFLASH_URLS = { } } +RSPCONFIG_GET_OPTIONS = ['ip','ipsrc','netmask','gateway','vlan','hostname','bootmode','autoreboot','powersupplyredundancy','powerrestorepolicy'] +RSPCONFIG_SET_OPTIONS = { + 'ip':'.*', + 'netmask':'.*', + 'gateway':'.*', + 'vlan':'\d+', + 'hostname':"\*|.*", + 'autoreboot':"^0|1$", + 'powersupplyredundancy':"^enabled$|^disabled$", + 'powerrestorepolicy':"^always_on$|^always_off$|^restore$", + 'bootmode':"^regular$|^safe$|^setup$", +} +RSPCONFIG_USAGE = """ +Handle rspconfig operations. + +Usage: + rspconfig -h|--help + rspconfig -V|--verbose + rspconfig dump [[-l|--list] | [-g|--generate] | [-c|--clear ] | [-d|--download ]] + rspconfig sshcfg + rspconfig ip=dhcp + rspconfig get [...] + rspconfig set [...] + +Options: + -l,--list List are dump files + -g,--generate Trigger a new dump file + -c,--clear The id of file to clear or all if specify 'all' + -d,--download The id of file to download or all if specify 'all' + +The supported attributes to get are: %s + +The supported attributes and its values to set are: + ip= netmask= gateway= [vlan=] + hostname=*| + autoreboot={0|1} + powersupplyredundancy={enabled|disabled} + powerrestorepolicy={always_on|always_off|restore} +""" % RSPCONFIG_GET_OPTIONS + XCAT_LOG_DIR = "/var/log/xcat" XCAT_LOG_RFLASH_DIR = XCAT_LOG_DIR + "/rflash/" @@ -623,7 +666,60 @@ class OpenBMCManager(base.BaseManager): DefaultPowerManager().reboot(runner, optype=action) else: DefaultPowerManager().set_power_state(runner, power_state=action) + def rspconfig(self, nodesinfo, args): + try: + new_args=[] + for a in args: + new_a = a.encode('utf-8') + new_args.append(new_a) + opts=docopt(RSPCONFIG_USAGE, argv=new_args) + self.verbose=opts.pop('--verbose') + except Exception as e: + self.messager.error("Failed to parse arguments for rspconfig: %s" % args) + return + runner = OpenBMCBmcConfigTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose) + + if opts['dump']: + if opts['--list']: + DefaultBmcConfigManager().dump_list(runner) + elif opts['--generate']: + DefaultBmcConfigManager().dump_generate(runner) + elif opts['--clear']: + DefaultBmcConfigManager().dump_clear(runner, opts['--clear']) + elif opts['--download']: + DefaultBmcConfigManager().dump_download(runner, opts['--download']) + else: + DefaultBmcConfigManager().dump_process(runner) + elif opts['sshcfg']: + DefaultBmcConfigManager().set_sshcfg(runner) + elif opts['ip=dhcp']: + DefaultBmcConfigManager().set_ipdhcp(runner) + elif opts['get']: + unsupport_list=list(set(opts['']) - set(RSPCONFIG_GET_OPTIONS)) + for attr in opts['']: + if attr not in RSPCONFIG_GET_OPTIONS: + self.messager.error("The attribute %s is not supported to get" % attr) + if len(unsupport_list) > 0: + return + else: + DefaultBmcConfigManager().get_attributes(runner, opts['']) + elif opts['set']: + rc=0 + for attr in opts['']: + k,v = attr.split('=') + if not RSPCONFIG_SET_OPTIONS.has_key(k): + self.messager.error("The attribute %s is not support to set" % k) + rc=1 + elif not re.match(RSPCONFIG_SET_OPTIONS[k], v): + self.messager.error("The value %s is invalid for %s" %(v, k)) + rc=1 + if rc: + return + else: + DefaultBmcConfigManager().set_attributes(runner, opts['']) + else: + self.messager.error("Failed to deal with rspconfig: %s" % args) def rsetboot(self, nodesinfo, args): # 1, parse args diff --git a/xCAT-server/lib/xcat/plugins/openbmc2.pm b/xCAT-server/lib/xcat/plugins/openbmc2.pm index a34626dbd..aded16a45 100644 --- a/xCAT-server/lib/xcat/plugins/openbmc2.pm +++ b/xCAT-server/lib/xcat/plugins/openbmc2.pm @@ -17,6 +17,7 @@ use xCAT::Utils; use xCAT::Usage; use xCAT::SvrUtils; use xCAT::OPENBMC; +use xCAT_plugin::openbmc; #------------------------------------------------------- @@ -35,6 +36,7 @@ sub handled_commands { rpower => 'nodehm:mgt=openbmc', rsetboot => 'nodehm:mgt=openbmc', rvitals => 'nodehm:mgt=openbmc', + rspconfig => 'nodehm:mgt=openbmc', }; } @@ -229,6 +231,8 @@ sub parse_args { unless ($subcommand =~ /^all$|^altitude$|^fanspeed$|^leds$|^power$|^temp$|^voltage$|^wattage$/) { return ([ 1, "Unsupported command: $command $subcommand" ]); } + } elsif ($command eq 'rspconfig') { + xCAT_plugin::openbmc::parse_args('rspconfig', $extrargs, $noderange); } else { return ([ 1, "Unsupported command: $command" ]); } @@ -317,13 +321,12 @@ sub refactor_args { my $command = $request->{command}->[0]; my $extrargs = $request->{arg}; if ($command eq "rspconfig") { - if ($extrargs->[0] eq "dump") { - $request->{arg}->[0] = "--dump"; - } else { - foreach my $arg (@$extrargs) { - if ($arg !~ /^-/) { - $arg = "--".$arg; - } + my $subcommand = $extrargs->[0]; + if ($subcommand !~ /^dump$|^sshcfg$|^ip=dhcp$/) { + if (grep /=/, @$extrargs) { + unshift @$extrargs, "set"; + } else { + unshift @$extrargs, "get"; } } } From b88f6e60f7805941ae03af57a1727a551aa06cee Mon Sep 17 00:00:00 2001 From: zhao er tao Date: Wed, 7 Feb 2018 16:51:28 +0800 Subject: [PATCH 3/3] update rspconfig framework,1: deal with unicode string for args, 2. move set/get attribute to openbmc_client class --- .../agent/hwctl/executor/openbmc_bmcconfig.py | 102 ++++-------------- .../lib/python/agent/hwctl/openbmc_client.py | 68 ++++++++++++ .../lib/python/agent/xcatagent/openbmc.py | 30 +++--- .../lib/python/agent/xcatagent/server.py | 6 +- 4 files changed, 104 insertions(+), 102 deletions(-) diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py index b0fe244b3..b7ae94bed 100644 --- a/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/executor/openbmc_bmcconfig.py @@ -18,49 +18,6 @@ logger = logging.getLogger('xcatagent') RSPCONFIG_GET_NETINFO=['ip', 'netmask', 'gateway', 'vlan', 'ipsrc', 'hostname'] RSPCONFIG_SET_NETINFO=['ip', 'netmask', 'gateway', 'vlan'] -RSPCONFIG_APIS = { - 'autoreboot' : { - 'baseurl': "/control/host0/auto_reboot/", - 'set_url': "attr/AutoReboot", - 'get_url': "attr/AutoReboot", - 'display_name': "BMC AutoReboot", - }, - 'powersupplyredundancy':{ - 'baseurl': "/sensors/chassis/PowerSupplyRedundancy/", - 'set_url': "/action/setValue", - 'get_url': "/action/getValue", - 'get_method': 'POST', - 'get_data': '[]', - 'display_name': "BMC PowerSupplyRedundancy", - 'attr_values': { - 'disabled': "Disables", - 'enabled': "Enabled", - }, - }, - 'powerrestorepolicy': { - 'baseurl': "/control/host0/power_restore_policy/", - 'set_url': "attr/PowerRestorePolicy", - 'get_url': "attr/PowerRestorePolicy", - 'display_name': "BMC PowerRestorePolicy", - 'attr_values': { - 'restore': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore", - 'always_on': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn", - 'always_off': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff", - }, - }, - 'bootmode': { - 'baseurl': "/control/host0/boot/", - 'set_url': "attr/BootMode", - 'get_url': "attr/BootMode", - 'display_name':"BMC BootMode", - 'attr_values': { - 'regular': "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular", - 'safe': "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe", - 'setup': "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup", - }, - }, -} - class OpenBMCBmcConfigTask(ParallelNodesCommand): def dump_list(self, **kw): @@ -85,20 +42,18 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): return self.callback.info("set_ipdhcp") def get_attributes(self, attributes, **kw): - netinfo_dict={'ip':False, 'ipsrc':False, 'netmask':False, - 'gateway':False, 'vlan':False, 'hostname':False} - getnet=0 + netinfo_dict={} for attr in attributes: if attr in RSPCONFIG_GET_NETINFO: netinfo_dict[attr]=True getnet=1 - elif RSPCONFIG_APIS.has_key(attr): - return self._get_apis_values(attr, **kw) + elif openbmc.RSPCONFIG_APIS.has_key(attr): + self._get_apis_values(attr, **kw) else: - return self.callback.error("get_attributes can not deal with attr %s" % attr) - if getnet: - self._get_netinfo(netinfo_dict['ip'], netinfo_dict['ipsrc'], netinfo_dict['netmask'], - netinfo_dict['gateway'], netinfo_dict['vlan'], netinfo_dict['hostname'], **kw) + 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) def set_attributes(self, attributes, **kw): netinfo_dict={'vlan':False} @@ -107,13 +62,13 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): if k in RSPCONFIG_SET_NETINFO: netinfo_dict[k] = v elif k == 'hostname': - return self._set_hostname(v, **kw) - elif RSPCONFIG_APIS.has_key(k): - return self._set_apis_values(k, v, **kw) + self._set_hostname(v, **kw) + elif openbmc.RSPCONFIG_APIS.has_key(k): + self._set_apis_values(k, v, **kw) else: return self.callback.error("set_attributes unsupported attribute:%s" % k) - if (not netinfo_dict['ip']) or (not netinfo_dict['netmask']) or (not netinfo_dict['gateway']): - return self.callback.error("set_attributes miss either ip, netmask or gateway to set network information") + 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')): + self.callback.info("set_attributes miss either ip, netmask or gateway to set network information") else: self._set_netinfo(netinfo_dict['ip'], netinfo_dict['netmask'], netinfo_dict['gateway'], netinfo_dict['vlan']) @@ -128,50 +83,29 @@ class OpenBMCBmcConfigTask(ParallelNodesCommand): def _set_apis_values(self, key, value, **kw): node = kw['node'] - attr_info = RSPCONFIG_APIS[key] - if not attr_info.has_key('set_url'): - return self.callback.error("config %s failed, not url available" % key) - set_url = attr_info['baseurl']+attr_info['set_url'] - obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, debugmode=self.debugmode, verbose=self.verbose) - - if attr_info.has_key('attr_values') and attr_info['attr_values'].has_key(value): - data = attr_info['attr_values'][value] - else: - data = value - try: obmc.login() - obmc.request('PUT', set_url, payload={"data": data}, cmd="set_%s" % key) + obmc.set_apis_values(key, value) except (SelfServerException, SelfClientException) as e: self.callback.info("%s: %s" % (node, e.message)) - self.callback.info("%s: BMC Setting %s..." % (node, attr_info['display_name'])) + self.callback.info("%s: BMC Setting %s..." % (node, openbmc.RSPCONFIG_APIS[key]['display_name'])) def _get_apis_values(self, key, **kw): node = kw['node'] - attr_info = RSPCONFIG_APIS[key] - if not attr_info.has_key('get_url'): - return self.callback.error("Reading %s failed, not url available" % key) - get_url = attr_info['baseurl']+attr_info['get_url'] obmc = openbmc.OpenBMCRest(name=node, nodeinfo=kw['nodeinfo'], messager=self.callback, debugmode=self.debugmode, verbose=self.verbose) try: obmc.login() - method = 'GET' - if attr_info.has_key('get_method'): - method = attr_info['get_method'] - data = None - if attr_info.has_key('get_data'): - data={"data": attr_info['get_data']} - value = obmc.request(method, get_url, payload=data, cmd="get_%s" % key) - str_value = '0.'+str(value) - result = '%s: %s: %s' % (node, attr_info['display_name'], str_value.split('.')[-1]) + value = obmc.get_apis_values(key) except (SelfServerException, SelfClientException) as e: - result = '%s: %s' % (node, e.message) + self.callback.info('%s: %s' % (node, e.message)) + str_value = '0.'+str(value) + result = '%s: %s: %s' % (node, openbmc.RSPCONFIG_APIS[key]['display_name'], str_value.split('.')[-1]) self.callback.info(result) def _set_netinfo(self, ip, netmask, gateway, vlan=False, **kw): diff --git a/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py b/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py index caa8c3cda..f4dc3e3a0 100644 --- a/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py +++ b/xCAT-openbmc-py/lib/python/agent/hwctl/openbmc_client.py @@ -139,6 +139,49 @@ FIRM_URLS = { } } +RSPCONFIG_APIS = { + 'autoreboot' : { + 'baseurl': "/control/host0/auto_reboot/", + 'set_url': "attr/AutoReboot", + 'get_url': "attr/AutoReboot", + 'display_name': "BMC AutoReboot", + }, + 'powersupplyredundancy':{ + 'baseurl': "/sensors/chassis/PowerSupplyRedundancy/", + 'set_url': "/action/setValue", + 'get_url': "/action/getValue", + 'get_method': 'POST', + 'get_data': '[]', + 'display_name': "BMC PowerSupplyRedundancy", + 'attr_values': { + 'disabled': "Disables", + 'enabled': "Enabled", + }, + }, + 'powerrestorepolicy': { + 'baseurl': "/control/host0/power_restore_policy/", + 'set_url': "attr/PowerRestorePolicy", + 'get_url': "attr/PowerRestorePolicy", + 'display_name': "BMC PowerRestorePolicy", + 'attr_values': { + 'restore': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.Restore", + 'always_on': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOn", + 'always_off': "xyz.openbmc_project.Control.Power.RestorePolicy.Policy.AlwaysOff", + }, + }, + 'bootmode': { + 'baseurl': "/control/host0/boot/", + 'set_url': "attr/BootMode", + 'get_url': "attr/BootMode", + 'display_name':"BMC BootMode", + 'attr_values': { + 'regular': "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular", + 'safe': "xyz.openbmc_project.Control.Boot.Mode.Modes.Safe", + 'setup': "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup", + }, + }, +} + RESULT_OK = 'ok' RESULT_FAIL = 'fail' @@ -404,6 +447,31 @@ class OpenBMCRest(object): return bool(func_list), fw_dict + def set_apis_values(self, key, value): + attr_info = RSPCONFIG_APIS[key] + if not attr_info.has_key('set_url'): + 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): + data = attr_info['attr_values'][value] + else: + data = value + self.request('PUT', set_url, payload={"data": data}, cmd="set_%s" % key) + + def get_apis_values(self, key): + attr_info = RSPCONFIG_APIS[key] + if not attr_info.has_key('get_url'): + 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'): + method = attr_info['get_method'] + data = None + if attr_info.has_key('get_data'): + data={"data": attr_info['get_data']} + return self.request(method, get_url, payload=data, cmd="get_%s" % key) + class OpenBMCImage(object): def __init__(self, rawid, data=None): self.id = rawid.split('/')[-1] diff --git a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py index b28d27ba2..6f56625cc 100644 --- a/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py +++ b/xCAT-openbmc-py/lib/python/agent/xcatagent/openbmc.py @@ -10,7 +10,7 @@ import time import sys import gevent import re -from docopt import docopt +from docopt import docopt,DocoptExit from common import utils from common import exceptions as xcat_exception @@ -95,14 +95,14 @@ Handle rspconfig operations. Usage: rspconfig -h|--help - rspconfig -V|--verbose - rspconfig dump [[-l|--list] | [-g|--generate] | [-c|--clear ] | [-d|--download ]] - rspconfig sshcfg - rspconfig ip=dhcp - rspconfig get [...] - rspconfig set [...] + rspconfig dump [[-l|--list] | [-g|--generate] | [-c|--clear ] | [-d|--download ]] [-V|--verbose] + rspconfig sshcfg [-V|--verbose] + rspconfig ip=dhcp [-V|--verbose] + rspconfig get [...] [-V|--verbose] + rspconfig set [...] [-V|--verbose] Options: + -V,--verbose Show verbose message -l,--list List are dump files -g,--generate Trigger a new dump file -c,--clear The id of file to clear or all if specify 'all' @@ -668,16 +668,14 @@ class OpenBMCManager(base.BaseManager): DefaultPowerManager().set_power_state(runner, power_state=action) def rspconfig(self, nodesinfo, args): try: - new_args=[] - for a in args: - new_a = a.encode('utf-8') - new_args.append(new_a) - opts=docopt(RSPCONFIG_USAGE, argv=new_args) - self.verbose=opts.pop('--verbose') + opts=docopt(RSPCONFIG_USAGE, argv=args) + except DocoptExit as e: + self.messager.error("Failed to parse args by docopt: %s" % e) + return except Exception as e: self.messager.error("Failed to parse arguments for rspconfig: %s" % args) return - + self.verbose=opts.pop('--verbose') runner = OpenBMCBmcConfigTask(nodesinfo, callback=self.messager, debugmode=self.debugmode, verbose=self.verbose) if opts['dump']: @@ -697,10 +695,8 @@ class OpenBMCManager(base.BaseManager): DefaultBmcConfigManager().set_ipdhcp(runner) elif opts['get']: unsupport_list=list(set(opts['']) - set(RSPCONFIG_GET_OPTIONS)) - for attr in opts['']: - if attr not in RSPCONFIG_GET_OPTIONS: - self.messager.error("The attribute %s is not supported to get" % attr) if len(unsupport_list) > 0: + self.messager.error("Have unsupported option: %s" % unsupport_args) return else: DefaultBmcConfigManager().get_attributes(runner, opts['']) diff --git a/xCAT-openbmc-py/lib/python/agent/xcatagent/server.py b/xCAT-openbmc-py/lib/python/agent/xcatagent/server.py index 86a6867de..f9b16bda4 100644 --- a/xCAT-openbmc-py/lib/python/agent/xcatagent/server.py +++ b/xCAT-openbmc-py/lib/python/agent/xcatagent/server.py @@ -92,8 +92,12 @@ class Server(object): if not hasattr(manager, req['command']): messager.error("command %s is not supported" % req['command']) func = getattr(manager, req['command']) + # translate unicode string to normal string to avoid docopt error + new_args=[] + for a in req['args']: + new_args.append(a.encode('utf-8')) # call the function in the specified manager - func(req['nodeinfo'], req['args']) + func(req['nodeinfo'], new_args) # after the method returns, the request should be handled # completely, close the socket for client if not self.standalone: