2 # Copyright 2019 Cachengo
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
20 from ironic.drivers.modules import ipmitool
21 from ironic.common.i18n import _translators
22 from oslo_concurrency import processutils
23 from ironic.common import exception
25 from .ironic_virtmedia_hw import IronicVirtMediaHW
27 class OpenBMCIronicVirtMediaHW(IronicVirtMediaHW):
28 def __init__(self, log):
29 super(OpenBMCIronicVirtMediaHW, self).__init__(log)
30 self.remote_share = '/remote_image_share_root/'
32 def get_disk_attachment_status(self, task):
33 """ Get the disk attachment status.
34 :param task: a TaskManager instance.
35 :returns: <str>: 'mounting' if operation is ongoing
37 'mounted' if the disk is successfully mounted
39 raise NotImplementedError
42 def hex_convert(string_value, padding=False, length=0):
44 string_value = string_value.ljust(length, '\0')
45 return ' '.join('0x%s' % x.encode('hex') for x in string_value)
47 def _issue_bmc_reset(self, driver_info, task):
48 """ Issues a bmc reset and waits till the BMC is ready for servicing
50 cmd = 'bmc reset cold'
51 node_uuid = task.node.uuid
52 self.log.debug("Issuing bmc cold reset to node %s" %(task.node.name))
54 out, err = ipmitool._exec_ipmitool(driver_info, cmd)
55 self.log.debug('bmc reset returned stdout: %(stdout)s, stderr:'
56 ' %(stderr)s', {'stdout': out, 'stderr': err})
57 except processutils.ProcessExecutionError as err:
58 self.log.exception(_translators.log_error('IPMI "bmc reset" failed for node %(node_id)s '
59 'with error: %(error)s.'),
60 {'node_id': node_uuid, 'error': err})
61 raise exception.IPMIFailure(cmd=cmd)
67 out, err = ipmitool._exec_ipmitool(driver_info, cmd)
68 self.log.debug('bmc reset returned stdout: %(stdout)s, stderr:'
69 ' %(stderr)s', {'stdout': out, 'stderr': err})
71 except processutils.ProcessExecutionError as err:
72 self.log.debug(_translators.log_error('IPMI "bmc info" failed for node %(node_id)s '
73 'with error: %(error)s. Sleeping and retrying later.'
74 'sleep_count: %(sleep_count)s'),
75 {'node_id': node_uuid, 'error': err, 'sleep_count': sleep_count})
80 self.log.exception('After bmc reset, connection to bmc is lost!')
81 raise exception.IPMIFailure(cmd='bmc reset')
84 def _wait_for_cd_mounting(self, driver_info, task):
86 while self.get_disk_attachment_status(task) == 'mounting' and sleep_count:
87 self.log.debug("Waiting for the CD to be Mounted")
94 self.log.warning("NFS mount timed out!. Trying BMC reset!")
95 self._issue_bmc_reset(driver_info, task)
97 def check_and_wait_for_cd_mounting(self, image_filename, task, driver_info):
98 mount_status = self.get_disk_attachment_status(task)
99 if mount_status == 'mounting':
100 if self._wait_for_cd_mounting(driver_info, task):
101 self.log.debug("Attached CD: %s" %(image_filename))
105 elif mount_status == 'nfserror':
106 self.log.exception("NFS mount failed!. Issue could be with NFS server status or connectivity to target.")
107 raise exception.InstanceDeployFailure(reason='NFS mount failed!')
108 elif mount_status == 'mounted':
109 self.log.debug("Attached CD: %s" %(image_filename))
112 self.log.exception("NFS mount failed!. Unknown error!")
113 raise exception.InstanceDeployFailure(reason='NFS mount failed!')