@@ -465,6 +465,43 @@ def prop_copy(prop):
465465 return copy .deepcopy (prop )
466466
467467
468+ def without_names (names , remove_names ):
469+ """
470+ Return a copy of the input names, with the specified names removed.
471+
472+ Parameters:
473+ names (iterable of str): Input names
474+ remove_names (iterable of str): Names to be removed
475+ """
476+ ret_names = []
477+ for name in names :
478+ if name in remove_names :
479+ continue
480+ ret_names .append (name )
481+ return ret_names
482+
483+
484+ def get_additional_properties (query_parms , wo_properties = None ):
485+ """
486+ Return the names of any additional-properties specified in the query
487+ parameter, not including the specified write-only properties.
488+
489+ The 'additional-properties' query parameter is remmoved from the
490+ query_parms parameter, if present.
491+
492+ Parameters:
493+ query_parms (dict): Query parameters
494+ wo_properties (iterable of str): Write-only properties
495+ """
496+ if 'additional-properties' in query_parms :
497+ add_props = query_parms .pop ('additional-properties' ).split (',' )
498+ if wo_properties :
499+ add_props = without_names (add_props , wo_properties )
500+ else :
501+ add_props = []
502+ return add_props
503+
504+
468505class UriHandler :
469506 """
470507 Handle HTTP methods against a set of known URIs and invoke respective
@@ -531,6 +568,10 @@ class GenericGetPropertiesHandler:
531568 Handler class for generic get of resource properties.
532569 """
533570
571+ # Write-only properties.
572+ # Is overridden by derived classes.
573+ wo_properties = []
574+
534575 # List of supported query parameters for the 'Get Properties' operation
535576 # of the resource type using this class.
536577 # Must be overridden in the derived resource handler class, if it supports
@@ -554,22 +595,28 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
554595 new_exc .__cause__ = None
555596 raise new_exc # zhmcclient.mock.InvalidResourceError
556597
557- subset_pnames = query_parms .get ('properties' , None )
558- if subset_pnames :
559- subset_pnames = subset_pnames .split (',' )
560- ret_props = {}
561- for pname in subset_pnames :
562- try :
563- ret_props [pname ] = resource .properties [pname ]
564- except KeyError :
565- new_exc = BadRequestError (
566- method , uri , reason = 14 ,
567- message = f"Invalid property { pname !r} in 'properties' "
568- f"query parameter for resource with URI { uri !r} " )
569- new_exc .__cause__ = None
570- raise new_exc # BadRequestError
571- return ret_props
572- return properties_copy (resource .properties )
598+ pnames = query_parms .get ('properties' , None )
599+ if pnames :
600+ pnames = pnames .split (',' )
601+ else :
602+ pnames = resource .properties .keys ()
603+ ret_props = {}
604+ for pname in pnames :
605+ if pname in cls .wo_properties :
606+ # Do not return write-only properties .
607+ # In case a write-only property is specified in the 'properties'
608+ # query parm, it should be ignored without raising an error.
609+ continue
610+ try :
611+ ret_props [pname ] = resource .properties [pname ]
612+ except KeyError :
613+ new_exc = BadRequestError (
614+ method , uri , reason = 14 ,
615+ message = f"Invalid property { pname !r} in 'properties' "
616+ f"query parameter for resource with URI { uri !r} " )
617+ new_exc .__cause__ = None
618+ raise new_exc # BadRequestError
619+ return ret_props
573620
574621
575622class GenericUpdatePropertiesHandler :
@@ -896,10 +943,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
896943 uri , query_parms = parse_query_parms (method , uri )
897944 check_invalid_query_parms (
898945 method , uri , query_parms , cls .valid_query_parms_get )
899- if 'additional-properties' in query_parms :
900- add_props = query_parms .pop ('additional-properties' ).split (',' )
901- else :
902- add_props = []
946+ add_props = get_additional_properties (
947+ query_parms , PartitionHandler .wo_properties )
903948 filter_args = query_parms
904949
905950 result_partitions = []
@@ -951,10 +996,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
951996 uri , query_parms = parse_query_parms (method , uri )
952997 check_invalid_query_parms (
953998 method , uri , query_parms , cls .valid_query_parms_get )
954- if 'additional-properties' in query_parms :
955- add_props = query_parms .pop ('additional-properties' ).split (',' )
956- else :
957- add_props = []
999+ add_props = get_additional_properties (
1000+ query_parms , LparHandler .wo_properties )
9581001 filter_args = query_parms
9591002
9601003 result_lpars = []
@@ -1011,10 +1054,9 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
10111054 uri , query_parms = parse_query_parms (method , uri )
10121055 check_invalid_query_parms (
10131056 method , uri , query_parms , cls .valid_query_parms_get )
1014- if 'additional-properties' in query_parms :
1015- add_props = query_parms .pop ('additional-properties' ).split (',' )
1016- else :
1017- add_props = []
1057+ add_props = get_additional_properties (
1058+ query_parms , PartitionHandler .wo_properties )
1059+
10181060 filter_args = query_parms
10191061
10201062 result_adapters = []
@@ -1159,6 +1201,8 @@ class UserHandler(GenericGetPropertiesHandler):
11591201 Handler class for HTTP methods on single User resource.
11601202 """
11611203
1204+ wo_properties = ["password" ]
1205+
11621206 @staticmethod
11631207 def post (method , hmc , uri , uri_parms , body , logon_required ,
11641208 wait_for_completion ):
@@ -1788,6 +1832,8 @@ class LdapServerDefinitionHandler(GenericGetPropertiesHandler,
17881832 Handler class for HTTP methods on single LdapServerDefinition resource.
17891833 """
17901834
1835+ wo_properties = ["bind-password" ]
1836+
17911837 @staticmethod
17921838 def post (method , hmc , uri , uri_parms , body , logon_required ,
17931839 wait_for_completion ):
@@ -1959,6 +2005,8 @@ class SSOServerDefinitionHandler(GenericGetPropertiesHandler,
19592005 Handler class for HTTP methods on single SSOServerDefinition resource.
19602006 """
19612007
2008+ wo_properties = ["client-secret" ]
2009+
19622010 @staticmethod
19632011 def post (method , hmc , uri , uri_parms , body , logon_required ,
19642012 wait_for_completion ):
@@ -3483,10 +3531,7 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
34833531 uri , query_parms = parse_query_parms (method , uri )
34843532 check_invalid_query_parms (
34853533 method , uri , query_parms , cls .valid_query_parms_get )
3486- if 'additional-properties' in query_parms :
3487- add_props = query_parms .pop ('additional-properties' ).split (',' )
3488- else :
3489- add_props = []
3534+ add_props = get_additional_properties (query_parms )
34903535 filter_args = query_parms
34913536
34923537 cpc_oid = uri_parms [0 ]
@@ -3901,10 +3946,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
39013946 uri , query_parms = parse_query_parms (method , uri )
39023947 check_invalid_query_parms (
39033948 method , uri , query_parms , cls .valid_query_parms_get )
3904- if 'additional-properties' in query_parms :
3905- add_props = query_parms .pop ('additional-properties' ).split (',' )
3906- else :
3907- add_props = []
3949+ add_props = get_additional_properties (
3950+ query_parms , PartitionHandler .wo_properties )
39083951 filter_args = query_parms
39093952
39103953 cpc_oid = uri_parms [0 ]
@@ -4147,6 +4190,8 @@ class PartitionHandler(GenericGetPropertiesHandler,
41474190
41484191 valid_query_parms_get = ['properties' ]
41494192
4193+ wo_properties = ["boot-ftp-password" , "ssc-master-pw" ]
4194+
41504195 # TODO: Add check_valid_cpc_status() in Update Partition Properties
41514196 # TODO: Add check_partition_status(transitional) in Update Partition Props
41524197 # TODO: Add check whether properties are modifiable in Update Part. Props
@@ -4919,10 +4964,7 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
49194964 uri , query_parms = parse_query_parms (method , uri )
49204965 check_invalid_query_parms (
49214966 method , uri , query_parms , cls .valid_query_parms_get )
4922- if 'additional-properties' in query_parms :
4923- add_props = query_parms .pop ('additional-properties' ).split (',' )
4924- else :
4925- add_props = []
4967+ add_props = get_additional_properties (query_parms )
49264968 filter_args = query_parms
49274969
49284970 cpc_oid = uri_parms [0 ]
@@ -5926,6 +5968,8 @@ class LparHandler(GenericGetPropertiesHandler):
59265968
59275969 valid_query_parms_get = ['properties' , 'cached-acceptable' , 'group-uri' ]
59285970
5971+ wo_properties = ["ssc-master-pw" ]
5972+
59295973 @staticmethod
59305974 def post (method , hmc , uri , uri_parms , body , logon_required ,
59315975 wait_for_completion ):
@@ -6588,10 +6632,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
65886632 uri , query_parms = parse_query_parms (method , uri )
65896633 check_invalid_query_parms (
65906634 method , uri , query_parms , cls .valid_query_parms_get )
6591- if 'additional-properties' in query_parms :
6592- add_props = query_parms .pop ('additional-properties' ).split (',' )
6593- else :
6594- add_props = []
6635+ add_props = get_additional_properties (
6636+ query_parms , ImageActProfileHandler .wo_properties )
65956637 filter_args = query_parms
65966638
65976639 cpc_oid = uri_parms [0 ]
@@ -6620,6 +6662,8 @@ class ImageActProfileHandler(GenericGetPropertiesHandler,
66206662
66216663 valid_query_parms_get = ['properties' , 'cached-acceptable' ]
66226664
6665+ wo_properties = ["ssc-master-pw" , "zaware-master-pw" ]
6666+
66236667
66246668class LoadActProfilesHandler :
66256669 """
0 commit comments