Skip to content

Commit

Permalink
Merge pull request #139 from DMTF/Update-Operation-Apply-Time
Browse files Browse the repository at this point in the history
Added option to set an apply time for update requests
  • Loading branch information
mraineri authored Feb 9, 2024
2 parents 68cbc18 + fd1b34e commit d457102
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ optional arguments:
-h, --help show this help message and exit
--target TARGET, -t TARGET
The target resource to apply the image
--applytime {Immediate,OnReset,AtMaintenanceWindowStart,InMaintenanceWindowOnReset,OnStartUpdateRequest}, -at {Immediate,OnReset,AtMaintenanceWindowStart,InMaintenanceWindowOnReset,OnStartUpdateRequest}
The apply time for the update
--debug Creates debug file showing HTTP traces and exceptions
```
Expand Down
1 change: 1 addition & 0 deletions redfish_utilities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
from .systems import set_system_bios
from .systems import print_system_bios
from .tasks import poll_task_monitor
from .update import operation_apply_times
from .update import get_update_service
from .update import get_simple_update_info
from .update import simple_update
Expand Down
24 changes: 22 additions & 2 deletions redfish_utilities/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,27 @@
import errno
import math
from .messages import verify_response
from enum import Enum

class RedfishUpdateServiceNotFoundError( Exception ):
"""
Raised when the update service or an update action cannot be found
"""
pass

class operation_apply_times( Enum ):
"""
Values for operation apply time settings
"""
IMMEDIATE = "Immediate"
ON_RESET = "OnReset"
AT_MAINTENANCE_WINDOW_START = "AtMaintenanceWindowStart"
AT_MAINTENANCE_WINDOW_ON_RESET = "InMaintenanceWindowOnReset"
ON_START_UPDATE_REQUEST = "OnStartUpdateRequest"

def __str__( self ):
return self.value

def get_simple_update_info( context ):
"""
Locates the SimpleUpdate action and collects its information
Expand Down Expand Up @@ -93,7 +107,7 @@ def get_simple_update_info( context ):

return simple_update_uri, simple_update_parameters

def simple_update( context, image_uri, protocol = None, targets = None, username = None, password = None ):
def simple_update( context, image_uri, protocol = None, targets = None, username = None, password = None, apply_time = None ):
"""
Performs a SimpleUpdate request
Expand All @@ -104,6 +118,7 @@ def simple_update( context, image_uri, protocol = None, targets = None, username
targets: The targets receiving the update
username: The username for retrieving the update for the given URI
password: The password for retrieving the update for the given URI
apply_time: The apply time for the update
Returns:
The response from the request
Expand All @@ -124,6 +139,8 @@ def simple_update( context, image_uri, protocol = None, targets = None, username
body["Username"] = username
if password is not None:
body["Password"] = password
if apply_time is not None:
body["@Redfish.OperationApplyTime"] = apply_time.value

response = context.post( uri, body = body )
verify_response( response )
Expand All @@ -149,7 +166,7 @@ def get_size( file_path, unit = 'bytes' ):
size = file_size / 1024 ** exponents_map[unit]
return round( size, 3 )

def multipart_push_update( context, image_path, targets = None, timeout = None ):
def multipart_push_update( context, image_path, targets = None, timeout = None, apply_time = None ):
"""
Performs an HTTP Multipart push update request
Expand All @@ -158,6 +175,7 @@ def multipart_push_update( context, image_path, targets = None, timeout = None )
image_path: The filepath to the image for the update
targets: The targets receiving the update
timeout: The timeout to apply to the update
apply_time: The apply time for the update
Returns:
The response from the request
Expand Down Expand Up @@ -191,6 +209,8 @@ def multipart_push_update( context, image_path, targets = None, timeout = None )
update_parameters = {}
if targets is not None:
update_parameters["Targets"] = targets
if apply_time is not None:
update_parameters["@Redfish.OperationApplyTime"] = apply_time.value
body = {
"UpdateParameters": ( None, json.dumps( update_parameters ), "application/json" ),
"UpdateFile": ( image_path.split( os.path.sep )[-1], open( image_path, "rb" ), "application/octet-stream" )
Expand Down
7 changes: 4 additions & 3 deletions scripts/rf_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def print_error_payload( response ):
argget.add_argument( "--rhost", "-r", type = str, required = True, help = "The address of the Redfish service (with scheme)" )
argget.add_argument( "--image", "-i", type = str, required = True, help = "The URI or filepath of the image" )
argget.add_argument( "--target", "-t", type = str, help = "The target resource to apply the image" )
argget.add_argument( "--applytime", "-at", type = redfish_utilities.operation_apply_times, help = "The apply time for the update", choices = redfish_utilities.operation_apply_times )
argget.add_argument( "--debug", action = "store_true", help = "Creates debug file showing HTTP traces and exceptions" )
args = argget.parse_args()

Expand Down Expand Up @@ -120,7 +121,7 @@ def print_error_payload( response ):
if "MultipartHttpPushUri" in update_service.dict:
# Perform a multipart push update
print( "Pushing the image to the service directly; depending on the size of the image, this can take a few minutes..." )
response = redfish_utilities.multipart_push_update( redfish_obj, args.image, targets = targets )
response = redfish_utilities.multipart_push_update( redfish_obj, args.image, targets = targets, apply_time = args.applytime )
else:
# Host a local web server and perform a SimpleUpdate for the local image
web_server_thread = threading.Thread( target = local_web_server, args=( args.image, ) )
Expand All @@ -143,10 +144,10 @@ def print_error_payload( response ):
s.connect( ( groups.group(2), int( remote_port ) ) )
image_uri = "http://{}:{}/{}".format( s.getsockname()[0], WEB_SERVER_PORT, args.image.rsplit( os.path.sep, 1 )[-1] )
s.close()
response = redfish_utilities.simple_update( redfish_obj, image_uri, targets = targets )
response = redfish_utilities.simple_update( redfish_obj, image_uri, targets = targets, apply_time = args.applytime )
else:
# Remote image; always use SimpleUpdate
response = redfish_utilities.simple_update( redfish_obj, args.image, targets = targets )
response = redfish_utilities.simple_update( redfish_obj, args.image, targets = targets, apply_time = args.applytime )

# Monitor the response
print( "Update initiated..." )
Expand Down

0 comments on commit d457102

Please sign in to comment.