Skip to content

Commit

Permalink
Merge pull request #2126 from allmightyspiff/issues2124
Browse files Browse the repository at this point in the history
Added network flag to update-firmware
  • Loading branch information
allmightyspiff authored Feb 27, 2024
2 parents 16d18f2 + d5f1ed5 commit dab2c05
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 47 deletions.
3 changes: 1 addition & 2 deletions SoftLayer/CLI/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ def no_going_back(confirmation):
if not confirmation:
confirmation = 'yes'

prompt = ('This action cannot be undone! Type "%s" or press Enter '
'to abort' % confirmation)
prompt = f"This action cannot be undone! Type '{confirmation}' or press Enter to abort"

ans = click.prompt(prompt, default='', show_default=False)
if ans.lower() == str(confirmation):
Expand Down
20 changes: 14 additions & 6 deletions SoftLayer/CLI/hardware/update_firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,23 @@

@click.command(cls=SoftLayer.CLI.command.SLCommand, )
@click.argument('identifier')
@click.option('-i', '--ipmi', is_flag=True, help="Update IPMI firmware")
@click.option('-r', '--raid', is_flag=True, help="Update RAID firmware")
@click.option('-b', '--bios', is_flag=True, help="Update BIOS firmware")
@click.option('-d', '--harddrive', is_flag=True, help="Update Hard Drives firmware")
@click.option('-n', '--network', is_flag=True, help="Update Network Card firmware")
@environment.pass_env
def cli(env, identifier):
"""Update server firmware."""
def cli(env, identifier, ipmi, raid, bios, harddrive, network):
"""Update server firmware. By default will update all available server components."""

mgr = SoftLayer.HardwareManager(env.client)
hw_id = helpers.resolve_id(mgr.resolve_ids, identifier, 'hardware')
if not (env.skip_confirmations or
formatting.confirm('This will power off the server with id %s and '
'update device firmware. Continue?' % hw_id)):
confirm_message = f"This will power off the server with id {hw_id} and update device firmware. Continue?"
if not (env.skip_confirmations or formatting.confirm(confirm_message)):
raise exceptions.CLIAbort('Aborted.')

mgr.update_firmware(hw_id)
# If no options were specified, set them all to enabled.
if not any([ipmi, raid, bios, harddrive, network]):
ipmi = raid = bios = harddrive = network = 1
mgr.update_firmware(hw_id, ipmi, raid, bios, harddrive, network)
env.fout(f"[green]Firmware update for {identifier} started")
36 changes: 19 additions & 17 deletions SoftLayer/managers/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,44 +723,46 @@ def edit(self, hardware_id, userdata=None, hostname=None, domain=None,

return self.hardware.editObject(obj, id=hardware_id)

def update_firmware(self,
hardware_id,
ipmi=True,
raid_controller=True,
bios=True,
hard_drive=True):
def update_firmware(self, hardware_id: int,
ipmi: bool = True,
raid_controller: bool = True,
bios: bool = True,
hard_drive: bool = True,
network: bool = True):
"""Update hardware firmware.
This will cause the server to be unavailable for ~20 minutes.
https://sldn.softlayer.com/reference/services/SoftLayer_Hardware_Server/createFirmwareUpdateTransaction/
:param int hardware_id: The ID of the hardware to have its firmware
updated.
:param int hardware_id: The ID of the hardware to have its firmware updated.
:param bool ipmi: Update the ipmi firmware.
:param bool raid_controller: Update the raid controller firmware.
:param bool bios: Update the bios firmware.
:param bool hard_drive: Update the hard drive firmware.
:param bool network: Update the network card firmware
Example::
# Check the servers active transactions to see progress
result = mgr.update_firmware(hardware_id=1234)
"""

return self.hardware.createFirmwareUpdateTransaction(
bool(ipmi), bool(raid_controller), bool(bios), bool(hard_drive), id=hardware_id)
return self.client.call(
'SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
bool(ipmi), bool(raid_controller), bool(bios), bool(hard_drive), bool(network), id=hardware_id
)

def reflash_firmware(self,
hardware_id,
ipmi=True,
raid_controller=True,
bios=True):
def reflash_firmware(self, hardware_id: int,
ipmi: bool = True,
raid_controller: bool = True,
bios: bool = True,):
"""Reflash hardware firmware.
This will cause the server to be unavailable for ~60 minutes.
The firmware will not be upgraded but rather reflashed to the version installed.
https://sldn.softlayer.com/reference/services/SoftLayer_Hardware_Server/createFirmwareReflashTransaction/
:param int hardware_id: The ID of the hardware to have its firmware
reflashed.
:param int hardware_id: The ID of the hardware to have its firmware reflashed.
:param bool ipmi: Reflash the ipmi firmware.
:param bool raid_controller: Reflash the raid controller firmware.
:param bool bios: Reflash the bios firmware.
Expand Down
20 changes: 0 additions & 20 deletions tests/CLI/modules/hardware/hardware_basic_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,26 +498,6 @@ def test_edit_server_userfile(self):
self.assert_called_with('SoftLayer_Hardware_Server', 'setUserMetadata',
args=(['some data'],), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000'])

self.assert_no_fail(result)
self.assertEqual(result.output, "")
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((1, 1, 1, 1)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_reflash_firmware(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'reflash-firmware', '1000'])

self.assert_no_fail(result)
self.assertEqual(result.output, 'Successfully device firmware reflashed\n')
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareReflashTransaction',
args=((1, 1, 1)), identifier=1000)

def test_edit(self):
result = self.run_command(['server', 'edit',
'--domain=example.com',
Expand Down
109 changes: 109 additions & 0 deletions tests/CLI/modules/hardware/hardware_firmware_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
SoftLayer.tests.CLI.modules.hardware.hardware_firmware_tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This suite is for the firmware related tests.
:license: MIT, see LICENSE for more details.
"""
from SoftLayer.CLI import exceptions
from SoftLayer import testing
from unittest import mock as mock


class HardwareFirmwareTests(testing.TestCase):

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000'])
self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((1, 1, 1, 1, 1)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_ipmi(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-i'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((1, 0, 0, 0, 0)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_raid(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-r'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((0, 1, 0, 0, 0)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_bios(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-b'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((0, 0, 1, 0, 0)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_disk(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-d'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((0, 0, 0, 1, 0)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_nic(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-n'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((0, 0, 0, 0, 1)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_just_all(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'update-firmware', '1000', '-i', '-r', '-b', '-d', '-n'])

self.assert_no_fail(result)
self.assertIn("Firmware update for 1000 started", result.output)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
args=((1, 1, 1, 1, 1)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_update_firmware_no_confirm(self, confirm_mock):
confirm_mock.return_value = False

result = self.run_command(['server', 'update-firmware', '1000'])
self.assertEqual(result.exit_code, 2)
self.assertIsInstance(result.exception, exceptions.CLIAbort)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_reflash_firmware(self, confirm_mock):
confirm_mock.return_value = True
result = self.run_command(['server', 'reflash-firmware', '1000'])

self.assert_no_fail(result)
self.assertEqual(result.output, 'Successfully device firmware reflashed\n')
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareReflashTransaction',
args=((1, 1, 1)), identifier=1000)

@mock.patch('SoftLayer.CLI.formatting.confirm')
def test_reflash_firmware_no_confirm(self, confirm_mock):
confirm_mock.return_value = False

result = self.run_command(['server', 'reflash-firmware', '1000'])
self.assertEqual(result.exit_code, 2)
self.assertIsInstance(result.exception, exceptions.CLIAbort)
4 changes: 2 additions & 2 deletions tests/managers/hardware_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,14 +543,14 @@ def test_update_firmware(self):

self.assertEqual(result, True)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
identifier=100, args=(1, 1, 1, 1))
identifier=100, args=(1, 1, 1, 1, 1))

def test_update_firmware_selective(self):
result = self.hardware.update_firmware(100, ipmi=False, hard_drive=False)

self.assertEqual(result, True)
self.assert_called_with('SoftLayer_Hardware_Server', 'createFirmwareUpdateTransaction',
identifier=100, args=(0, 1, 1, 0))
identifier=100, args=(0, 1, 1, 0, 1))

def test_reflash_firmware(self):
result = self.hardware.reflash_firmware(100)
Expand Down

0 comments on commit dab2c05

Please sign in to comment.