3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
17 from .bmctools import BMC, BMCException
20 def __init__(self, host, user, passwd, priv_level='ADMINISTRATOR', log_path=None):
21 super(OR18, self).__init__(host, user, passwd, priv_level, log_path)
23 def _clear_ris_configuration(self):
24 # Clear RIS configuration
26 logging.debug('Clear RIS configuration.')
27 self._run_ipmitool_raw_command('0x32 0x9f 0x01 0x0d')
28 except Exception as err:
29 logging.warning('Exception when clearing RIS NFS configuration: %s', str(err))
33 def _check_virtual_media_started(self):
34 # check virtmedia service status
36 out = self._run_ipmitool_raw_command('0x32 0xca 0x08')
37 logging.debug('Virtual media service status: %s', str(out[0]))
38 except Exception as err:
39 logging.warning('Exception when checking virtual media service: %s', str(err))
44 def _start_virtual_media(self):
45 # Enable "Remote Media Support" in GUI (p145)
47 logging.debug('Start virtual media service')
48 self._run_ipmitool_raw_command('0x32 0xcb 0x08 0x01')
49 except Exception as err:
50 logging.warning('Exception when starting virtual media service: %s', str(err))
52 def _set_setup_nfs(self, nfs_host, mount_path):
56 logging.debug('Virtual media share type to NFS.')
57 self._run_ipmitool_raw_command('0x32 0x9f 0x01 0x05 0x00 0x6e 0x66 0x73 0x00 0x00 0x00')
58 except Exception as err:
59 logging.warning('Exception when setting virtual media service type NFS: %s', str(err))
64 cmd = '0x32 0x9f 0x01 0x02 0x00 %s' % (self._convert_to_hex(nfs_host, True, 63))
65 logging.debug('Virtual media server "%s"', nfs_host)
66 self._run_ipmitool_raw_command(cmd)
67 except Exception as err:
68 logging.warning('Exception when setting virtual media server: %s', str(err))
71 # Set NFS Mount Root path
73 logging.debug('Virtual media path to "%s"', mount_path)
74 # set progress bit (hmm. seems to return error if it is already set.. So should check..)
76 cmd = '0x32 0x9f 0x01 0x01 0x00 0x00'
77 self._run_ipmitool_raw_command(cmd)
79 cmd = '0x32 0x9f 0x01 0x01 0x00 0x01'
80 self._run_ipmitool_raw_command(cmd)
82 cmd = '0x32 0x9f 0x01 0x01 0x01 %s' % (self._convert_to_hex(mount_path, True, 64))
83 self._run_ipmitool_raw_command(cmd)
86 cmd = '0x32 0x9f 0x01 0x01 0x00 0x00'
87 self._run_ipmitool_raw_command(cmd)
88 except Exception as err:
89 logging.warning('Exception when setting virtual media path: %s', str(err))
93 def _enable_virtual_media(self):
94 logging.debug('Enable Virtual Media')
96 # 0x32 0xcb command will cause vmedia service restart automatically after 2 seconds according doc.
97 # restart is delayed by 2 seconds if new command is received during 2 second delay
98 # In other words, do all config in batch and it will only be restarted once.
100 # Speed up things if it service is already running
101 if self._check_virtual_media_started():
102 logging.debug('Virtual media service already running.')
103 # Service is already started
106 self._start_virtual_media()
110 # Just enabling the service doe not seem to start it (in all HW)
111 # Resetting it after enabling helps
112 self._restart_virtual_media_service()
113 while not self._check_virtual_media_started():
114 if _try > _max_tries:
115 logging.warning('Ensure virtual media service start failed, attempts exceeded.')
121 def _get_virtual_media_device_count(self, devicetype):
124 # Get num of enabled devices
125 if devicetype == 'CD':
127 logging.debug('Get virtual CD count')
128 elif devicetype == 'FD':
130 logging.debug('Get virtual FD count')
131 elif devicetype == 'HD':
133 logging.debug('Get virtual HD count')
135 logging.warning('Unknown device type "%s"', devicetype)
138 cmd = '0x32 0xca %s' % _devparam
139 out = self._run_ipmitool_raw_command(cmd)
140 _num_inst = int(out[0], 16)
142 logging.debug('Number of enabled %s devices is %d', devicetype, _num_inst)
145 except Exception as err:
146 raise BMCException('Exception when getting number of enabled %s devices. error: %s' % (devicetype, str(err)))
148 def _set_virtual_media_device_count(self, devicetype, devicecount):
149 # Chapter 46.2 page 181
150 if not 0 <= devicecount <= 4:
151 logging.warning('Number of devices must be in range 0 to 4')
154 if devicetype == 'CD':
156 logging.debug('Setting virtual CD count to %d', devicecount)
157 elif devicetype == 'HD':
159 logging.debug('Setting virtual HD count to %d', devicecount)
161 logging.warning('_set_virtual_media_device_count: Unknown device type "%s"', devicetype)
165 cmd = '0x32 0xcb %s 0x%s' % (_devparam, str(devicecount))
166 self._run_ipmitool_raw_command(cmd)
168 _conf_device_num = self._get_virtual_media_device_count(devicetype)
170 while _conf_device_num != devicecount and _tries > 0:
171 logging.debug('Virtual %s count is %d expecting %d', devicetype, _conf_device_num, devicecount)
173 _conf_device_num = self._get_virtual_media_device_count(devicetype)
175 except Exception as err:
176 raise BMCException('Exception when setting virtual media device count : %s' % str(err))
179 def _restart_virtual_media_service(self):
181 cmd = '0x32 0xcb 0x0a 0x01'
182 logging.debug('Restart virtual media service')
183 self._run_ipmitool_raw_command(cmd)
184 except Exception as err:
185 raise BMCException('Exception when restarting virtual media service: %s' % str(err))
187 def _restart_ris(self):
189 logging.debug('Restart RIS')
190 cmd = '0x32 0x9f 0x08 0x0b'
191 self._run_ipmitool_raw_command(cmd)
192 except Exception as err:
193 raise BMCException('Exception when restarting RIS: %s'% str(err))
197 def _restart_ris_cd(self):
199 logging.debug('Restart RIS CD media')
200 cmd = '0x32 0x9f 0x01 0x0b 0x01'
201 self._run_ipmitool_raw_command(cmd)
202 except Exception as err:
203 raise BMCException('Exception when restarting RIS CD media: %s' % str(err))
207 def _check_cd_dvd_enabled(self, enabled):
209 out = self._run_ipmitool_raw_command('0x32 0xca 0x0')
210 logging.debug('Virtual cd_dvd status: %s', str(out[0]))
211 except Exception as err:
212 logging.warning('Exception when checking cd_dvd status: %s', str(err))
213 if (out[0] == '01' and enabled) or (out[0] == '00' and not enabled):
217 def _enable_disable_cd_dvd(self, enabled):
220 logging.debug('Enable/Disable cd_dvd')
221 while not self._check_cd_dvd_enabled(enabled):
222 if _try > _max_tries:
223 logging.warning('Ensure cd_dvd enable/disable failed, attempts exceeded. Ignoring and trying to continue.')
229 def _toggle_virtual_device(self, enabled):
230 # Enable "Mount CD/DVD" in GUI (p144) should cause vmedia restart withing 2 seconds.
231 # Seems "Mount CD/DVD" need to be enabled (or toggled) after config. refresh/vmedia restart
234 logging.debug('Enable/Disable mount CD/DVD.')
236 #This will fail with new firmware on OR18
237 self._run_ipmitool_raw_command('0x32 0xcb 0x00 0x0%s' %(str(int(enabled))))
238 return self._enable_disable_cd_dvd(enabled)
239 except Exception as err:
240 logging.warning('Exception when CD/DVD virtual media new firmware? ignoring... Error: %s', str(err))
243 def _mount_virtual_device(self):
244 return self._toggle_virtual_device(True)
246 def _demount_virtual_device(self):
247 return self._toggle_virtual_device(False)
249 def _get_mounted_image_count(self):
252 out = self._run_ipmitool_raw_command('0x32 0xd8 0x00 0x01')
253 count = int(out[1], 16)
254 logging.warning('Available image count: %d', count)
255 except Exception as err:
256 logging.warning('Exception when trying to get the image count: %s', str(err))
259 def _wait_for_mount_count(self):
260 # Poll until we got some images from server
263 while self._get_mounted_image_count() == 0:
264 logging.debug('Check available images count try %d/%d', _try, _max_tries)
265 if _try > _max_tries:
266 logging.warning('Available images count 0, attempts exceeded.')
272 def _set_image_name(self, image_filename):
274 logging.debug('Setting virtual media image: %s', image_filename)
275 self._run_ipmitool_raw_command('0x32 0xd7 0x01 0x01 0x01 0x01 %s' % (self._convert_to_hex(image_filename, True, 64)))
276 except Exception as err:
277 logging.debug('Exception when setting virtual media image: %s', str(err))
281 def _get_bmc_nfs_service_status(self):
282 # Check NFS Service Status
284 out = self._run_ipmitool_raw_command('0x32 0xd8 0x06 0x01 0x01 0x00')
285 _image_name = str(bytearray.fromhex(''.join(out)))
290 def _stop_remote_redirection(self):
291 # Get num of enabled devices
292 _num_inst = self._get_virtual_media_device_count('CD')
293 for driveindex in range(0, _num_inst):
294 cmd = '0x32 0xd7 0x00 0x01 0x01 0x00 %s' % hex(driveindex)
295 logging.debug('Stop redirection CD/DVD drive index %d', driveindex)
297 out = self._run_ipmitool_raw_command(cmd)
298 logging.debug('ipmitool out = %s', (out))
299 except Exception as err:
300 # Drive might not be mounted to start with
301 logging.debug('_stop_remote_redirection: Ignoring exception when stopping redirection CD/DVD drive index %d error: %s', driveindex, str(err))
303 def _set_boot_from_virtual_media(self):
304 logging.debug('Set boot from cd (%s), and boot after that', self._host)
305 self._run_ipmitool_command('chassis bootdev cdrom options=persistent')
307 #logging.debug('Set boot from cd (%s), and boot after that', self._host)
309 # self._run_ipmitool_raw_command('0x00 0x08 0x05 0xC0 0x20 0x00 0x00 0x00')
310 #except Exception as err:
311 # logging.warning('Set Boot to CD failed: %s' % str(err))
312 # raise BMCException('Set Boot to CD failed')
314 def _detach_virtual_media(self):
315 logging.debug('Detach virtual media')
317 #Enable virtual media
318 if not self._enable_virtual_media():
319 raise BMCException("detach_virtual_cd: Failed to enable virtual media")
321 # Restart Remote Image Service
322 if not self._restart_ris():
323 raise BMCException("Failed to restart RIS")
326 self._stop_remote_redirection()
328 #Clear RIS configuration
329 if not self._clear_ris_configuration():
330 raise BMCException("detach_virtual_cd: Failed to clear RIS configuration")
332 #Demount virtual device
333 if not self._demount_virtual_device():
334 raise BMCException('detach_virtual_cd: Exception when disabling CD/DVD virtual media')
336 # Reduce the number of virtual devices (both HD and CD default to 4 devices each)
337 if not self._set_virtual_media_device_count('HD', 0):
338 BMCException('Failed to set virtual media device count for HD')
339 if not self._set_virtual_media_device_count('CD', 1):
340 BMCException('Failed to set virtual media device count for CD')
342 def attach_virtual_cd(self, nfs_host, nfs_mount, boot_iso_filename):
344 self._detach_virtual_media()
346 logging.debug('Attach virtual media')
348 #Enable virtual media
349 if not self._enable_virtual_media():
350 raise BMCException("Failed to enable virtual media")
352 #Enable CD/DVD device
353 if not self._toggle_virtual_device(True):
354 raise BMCException("Failed to enable virtual device")
356 #Clear RIS configuration
357 if not self._clear_ris_configuration():
358 raise BMCException("Failed to clear RIS configuration")
361 if not self._set_setup_nfs(nfs_host, nfs_mount):
362 raise BMCException("Failed to setup nfs")
364 # Restart Remote Image CD
365 if not self._restart_ris_cd():
366 raise BMCException("Failed to restart RIS CD")
368 #Wait for device to be mounted
369 if not self._wait_for_mount_count():
370 raise BMCException("Failed when waiting for the device to appear")
374 if not self._set_image_name(boot_iso_filename):
375 raise BMCException("Failed to set image name")
377 success = self._wait_for_bmc_nfs_service(90, 'mounted')
381 raise BMCException('NFS service setup failed')