diff --git a/src/README.rst b/src/README.rst index f25b3eaa..6bb5af40 100644 --- a/src/README.rst +++ b/src/README.rst @@ -21,6 +21,7 @@ Unreleased - Added configuration overrides node commands. These commands will be available in the Service fabric runtime 7.0 version (#206) - Provide option to compress packages on application upload. By default, the newly generated compressed package is deleted after successful upload. (#191) - Update Create and Update service with new parameter, ServicePlacementTimeLimit (#200) +- Add min instance count/percentage configurations for stateless service update and service create APIs (#201) - Update knack version (#207) 8.0.0 diff --git a/src/sfctl/custom_service.py b/src/sfctl/custom_service.py index 5365d338..ac9885e3 100644 --- a/src/sfctl/custom_service.py +++ b/src/sfctl/custom_service.py @@ -160,7 +160,8 @@ def service_update_flags( # pylint: disable=too-many-arguments def validate_service_create_params(stateful, stateless, singleton_scheme, # pylint: disable=too-many-arguments int_scheme, named_scheme, instance_count, - target_rep_set_size, min_rep_set_size): + target_rep_set_size, min_rep_set_size, + min_instance_count, min_instance_percentage): """Validate service creation arguments""" if sum([stateful, stateless]) != 1: raise CLIError( @@ -181,6 +182,8 @@ def validate_service_create_params(stateful, stateless, singleton_scheme, # pyl raise CLIError( 'Cannot specify replica set sizes for stateless services' ) + if stateful and (min_instance_count is not None or min_instance_percentage is not None): + raise CLIError('Cannot specify min instance count or min instance percentage for stateful services') def parse_partition_policy(named_scheme, named_scheme_list, int_scheme, # pylint: disable=too-many-arguments @@ -325,7 +328,8 @@ def create( # pylint: disable=too-many-arguments, too-many-locals target_replica_set_size=None, min_replica_set_size=None, replica_restart_wait=None, quorum_loss_wait=None, stand_by_replica_keep=None, no_persisted_state=False, - instance_count=None, timeout=60, scaling_policies=None, service_placement_time=None): + instance_count=None, timeout=60, scaling_policies=None, service_placement_time=None, + min_instance_count=None, min_instance_percentage=None): """ Creates the specified Service Fabric service. :param str app_id: The identity of the application. This is @@ -399,13 +403,33 @@ def create( # pylint: disable=too-many-arguments, too-many-locals :param int service_placement_time: The duration for which replicas can stay InBuild before reporting that build is stuck. This applies to stateful services only. + :param int min_instance_count: Stateless service only. + MinInstanceCount is the minimum number of + instances that must be up to meet the EnsureAvailability safety check + during operations like upgrade or deactivate node. + The actual number that is used is max( MinInstanceCount, ceil( + MinInstancePercentage/100.0 * InstanceCount) ). + Note, if InstanceCount is set to -1, during MinInstanceCount computation + -1 is first converted into the number of nodes on which the instances are + allowed to be placed according to the placement constraints on the + service. + :param int min_instance_percentage: Stateless service only. + MinInstancePercentage is the minimum + percentage of InstanceCount that must be up to meet the EnsureAvailability + safety check during operations like upgrade or deactivate node. + The actual number that is used is max( MinInstanceCount, ceil( + MinInstancePercentage/100.0 * InstanceCount) ). + Note, if InstanceCount is set to -1, during MinInstancePercentage + computation, -1 is first converted into the number of nodes on which the + instances are allowed to be placed according to the placement constraints + on the service. """ from azure.servicefabric.models import StatelessServiceDescription, StatefulServiceDescription validate_service_create_params(stateful, stateless, singleton_scheme, int_scheme, named_scheme, instance_count, target_replica_set_size, - min_replica_set_size) + min_replica_set_size, min_instance_count, min_instance_percentage) partition_desc = parse_partition_policy(named_scheme, named_scheme_list, int_scheme, int_scheme_low, int_scheme_high, int_scheme_count, @@ -432,7 +456,9 @@ def create( # pylint: disable=too-many-arguments, too-many-locals is_default_move_cost_specified=bool(move_cost), service_package_activation_mode=activation_mode, service_dns_name=dns_name, - scaling_policies=scaling_policy_description) + scaling_policies=scaling_policy_description, + min_instance_count=min_instance_count, + min_instance_percentage=min_instance_percentage) if stateful: flags = stateful_flags(replica_restart_wait, quorum_loss_wait, @@ -467,7 +493,8 @@ def create( # pylint: disable=too-many-arguments, too-many-locals def validate_update_service_params(stateless, stateful, target_rep_set_size, # pylint: disable=too-many-arguments min_rep_set_size, rep_restart_wait, quorum_loss_wait, stand_by_replica_keep, - instance_count, service_placement_time): + instance_count, service_placement_time, + min_instance_count, min_instance_percentage): """Validate update service parameters""" if sum([stateless, stateful]) != 1: @@ -497,6 +524,9 @@ def validate_update_service_params(stateless, stateful, target_rep_set_size, # raise CLIError('Cannot specify an instance count for a stateful ' 'service') + if min_instance_count is not None or min_instance_percentage is not None: + raise CLIError('Cannot specify min instance count or min instance percentage for stateful services') + def update(client, service_id, stateless=False, stateful=False, # pylint: disable=too-many-locals,too-many-arguments constraints=None, correlation=None, correlated_service=None, @@ -504,7 +534,8 @@ def update(client, service_id, stateless=False, stateful=False, # pylint: disab move_cost=None, instance_count=None, target_replica_set_size=None, min_replica_set_size=None, replica_restart_wait=None, quorum_loss_wait=None, stand_by_replica_keep=None, timeout=60, - scaling_policies=None, service_placement_time=None): + scaling_policies=None, service_placement_time=None, + min_instance_count=None, min_instance_percentage=None): """ Updates the specified service using the given update description. :param str service_id: The identity of the service. This is typically the @@ -552,6 +583,26 @@ def update(client, service_id, stateless=False, stateful=False, # pylint: disab :param int service_placement_time: The duration for which replicas can stay InBuild before reporting that build is stuck. This applies to stateful services only. + :param int min_instance_count: Stateless service only. + MinInstanceCount is the minimum number of + instances that must be up to meet the EnsureAvailability safety check + during operations like upgrade or deactivate node. + The actual number that is used is max( MinInstanceCount, ceil( + MinInstancePercentage/100.0 * InstanceCount) ). + Note, if InstanceCount is set to -1, during MinInstanceCount computation + -1 is first converted into the number of nodes on which the instances are + allowed to be placed according to the placement constraints on the + service. + :param int min_instance_percentage: Stateless service only. + MinInstancePercentage is the minimum + percentage of InstanceCount that must be up to meet the EnsureAvailability + safety check during operations like upgrade or deactivate node. + The actual number that is used is max( MinInstanceCount, ceil( + MinInstancePercentage/100.0 * InstanceCount) ). + Note, if InstanceCount is set to -1, during MinInstancePercentage + computation, -1 is first converted into the number of nodes on which the + instances are allowed to be placed according to the placement constraints + on the service. """ from azure.servicefabric.models import (StatefulServiceUpdateDescription, StatelessServiceUpdateDescription) @@ -560,7 +611,8 @@ def update(client, service_id, stateless=False, stateful=False, # pylint: disab target_replica_set_size, min_replica_set_size, replica_restart_wait, quorum_loss_wait, stand_by_replica_keep, - instance_count, service_placement_time) + instance_count, service_placement_time, + min_instance_count, min_instance_percentage) cor_desc = correlation_desc(correlated_service, correlation) metric_desc = parse_load_metrics(load_metrics) @@ -600,7 +652,9 @@ def update(client, service_id, stateless=False, stateful=False, # pylint: disab service_placement_policies=place_desc, default_move_cost=move_cost, scaling_policies=scaling_policy_description, - instance_count=instance_count) + instance_count=instance_count, + min_instance_count=min_instance_count, + min_instance_percentage=min_instance_percentage) client.update_service(service_id, update_desc, timeout)