From 66b65768ed635d76562c7d7ae647bc28a68c4c52 Mon Sep 17 00:00:00 2001 From: Liyi Meng Date: Mon, 5 Oct 2015 09:55:20 +0200 Subject: Add AMT adapter This adapter allow fuel deploy over Intel AMT/vPro system. Please note that the adapter use amttool to interact with target system, which imply that it only support up to vPro v7. Change-Id: I75f0882ea914b57d7d62338ed803a45104bc2d4e Signed-off-by: Liyi Meng --- fuel/deploy/dha.py | 5 +- fuel/deploy/dha_adapters/amt_adapter.py | 98 ++++++++++++++++++++++ fuel/deploy/execution_environment.py | 2 +- .../hardware_environment/conf/opnfv_box/dha.yaml | 34 ++++---- 4 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 fuel/deploy/dha_adapters/amt_adapter.py diff --git a/fuel/deploy/dha.py b/fuel/deploy/dha.py index 1feee6039..cb413cbb0 100644 --- a/fuel/deploy/dha.py +++ b/fuel/deploy/dha.py @@ -14,7 +14,7 @@ import io from dha_adapters.libvirt_adapter import LibvirtAdapter from dha_adapters.ipmi_adapter import IpmiAdapter from dha_adapters.hp_adapter import HpAdapter - +from dha_adapters.amt_adapter import AmtAdapter class DeploymentHardwareAdapter(object): @@ -30,5 +30,6 @@ class DeploymentHardwareAdapter(object): return IpmiAdapter(yaml_path) if type == 'hp': return HpAdapter(yaml_path) - + if type == 'amt': + return AmtAdapter(yaml_path) return super(DeploymentHardwareAdapter, cls).__new__(cls) diff --git a/fuel/deploy/dha_adapters/amt_adapter.py b/fuel/deploy/dha_adapters/amt_adapter.py new file mode 100644 index 000000000..b92ec4ca6 --- /dev/null +++ b/fuel/deploy/dha_adapters/amt_adapter.py @@ -0,0 +1,98 @@ +############################################################################### +# Copyright (c) 2015 Ericsson AB and others. +# liyi.meng@ericsson.com +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################### + + +import common +from hardware_adapter import HardwareAdapter + +log = common.log +exec_cmd = common.exec_cmd +err = common.err + +''' +This is hardware adapter for Intel AMT based system. It use amttool to interact + with the targeting node. It dose not support vPro v9. if the targeting system + is v9 or later, we need to consider a new adpater with using lib + like https://github.com/sdague/amt +''' +class AmtAdapter(HardwareAdapter): + + def __init__(self, yaml_path): + super(AmtAdapter, self).__init__(yaml_path) + #amttool dose not allow you change bios setting permanently. + # so we have to make a workaround to make it IPMI like. + self.boot_order = {} + + def node_get_boot_dev(self, node_id): + if node_id in self.boot_order: + dev = self.boot_order[node_id][0] + if dev == 'pxe': + return 'PXE-boot' + elif dev == 'iso': + return 'cd-boot' + elif dev == 'disk': + return 'HD-boot' + else: + return 'HD-boot' + + def get_access_info(self, node_id): + ip = self.get_node_property(node_id, 'amtIp') + username = self.get_node_property(node_id, 'amtUser') + password = self.get_node_property(node_id, 'amtPass') + return ip, username, password + + def amt_cmd(self, node_id): + ip, username, password = self.get_access_info(node_id) + # We first Setup password for amttool, then use ping to wake up the node over LAN + cmd = 'export AMT_PASSWORD={0};' \ + 'ping {1} -W 5 -c 1 -q;' \ + 'yes | amttool {1}'.format(password, ip) + return cmd + + def get_node_pxe_mac(self, node_id): + mac_list = [] + mac_list.append(self.get_node_property(node_id, 'pxeMac').lower()) + return mac_list + + def node_power_on(self, node_id): + log('Power ON Node %s' % node_id) + cmd_prefix = self.amt_cmd(node_id) + resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False) + if 'Powerstate: S0' not in resp: + dev = self.node_get_boot_dev(node_id) + resp, ret = exec_cmd('{0} powerup {1}'.format(cmd_prefix, dev), check=False) + if 'pt_status: success' not in resp: + err('Could Not Power ON Node %s' % node_id) + + def node_power_off(self, node_id): + log('Power OFF Node %s' % node_id) + cmd_prefix = self.amt_cmd(node_id) + resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False) + if "Powerstate: S0" in resp: + resp, ret = exec_cmd('{0} powerdown'.format(cmd_prefix), check=False) + if 'pt_status: success' not in resp: + err('Could Not Power OFF Node %s' % node_id) + + def node_reset(self, node_id): + log('RESET Node %s' % node_id) + cmd_prefix = self.amt_cmd(node_id) + dev = self.node_get_boot_dev(node_id) + resp, ret = exec_cmd('{0} info'.format(cmd_prefix), check=False) + if 'Powerstate: S0' in resp: + resp, ret = exec_cmd('{0} reset {1}'.format(cmd_prefix, dev), check=False) + if 'pt_status: success' not in resp: + err('Could Not RESET Node %s' % node_id) + else: + err('Cannot RESET Node %s because it\'s not Active, state: %s' + % (node_id, resp)) + + def node_set_boot_order(self, node_id, boot_order_list): + log('Set boot order %s on Node %s' % (boot_order_list, node_id)) + self.boot_order[node_id] = boot_order_list + diff --git a/fuel/deploy/execution_environment.py b/fuel/deploy/execution_environment.py index e671463e4..cc6c33ea5 100644 --- a/fuel/deploy/execution_environment.py +++ b/fuel/deploy/execution_environment.py @@ -40,7 +40,7 @@ class ExecutionEnvironment(object): if type == 'libvirt': return LibvirtEnvironment(storage_dir, dha_path, dea, root_dir) - if type == 'ipmi' or type == 'hp': + if type in ['ipmi', 'hp', 'amt']: return VirtualFuel(storage_dir, pxe_bridge, dha_path, root_dir) return super(ExecutionEnvironment, cls).__new__(cls) diff --git a/fuel/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml b/fuel/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml index c2624f2ba..a058bbbde 100644 --- a/fuel/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml +++ b/fuel/deploy/templates/hardware_environment/conf/opnfv_box/dha.yaml @@ -5,7 +5,7 @@ created: comment: Config for OPNFV BOX # Adapter to use for this definition -adapter: ipmi +adapter: amt # Node list. # Mandatory property is id, all other properties are adapter specific. @@ -13,29 +13,29 @@ adapter: ipmi nodes: - id: 1 pxeMac: b8:ae:ed:76:4d:a4 - ipmiIp: - ipmiUser: - ipmiPass: + amtIp: + amtUser: + amtPass: - id: 2 pxeMac: b8:ae:ed:76:4d:94 - ipmiIp: - ipmiUser: - ipmiPass: + amtIp: + amtUser: + amtPass: - id: 3 pxeMac: b8:ae:ed:76:4c:eb - ipmiIp: - ipmiUser: - ipmiPass: + amtIp: + amtUser: + amtPass: - id: 4 pxeMac: b8:ae:ed:76:37:62 - ipmiIp: - ipmiUser: - ipmiPass: + amtIp: + amtUser: + amtPass: - id: 5 pxeMac: b8:ae:ed:76:4d:95 - ipmiIp: - ipmiUser: - ipmiPass: + amtIp: + amtUser: + amtPass: # Adding the Fuel node as node id 6 which may not be correct - please # adjust as needed. - id: 6 @@ -46,4 +46,4 @@ nodes: password: r00tme disks: - fuel: 50G \ No newline at end of file + fuel: 50G -- cgit 1.2.3-korg