Skip to content

Commit

Permalink
feat: refactor scale_up, consider vmss refresh mode in other funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
kristina-solovyova committed Jan 16, 2024
1 parent 3198ead commit 6a5d8b0
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 151 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ proxy_url = VALUE
| <a name="input_function_app_storage_account_prefix"></a> [function\_app\_storage\_account\_prefix](#input\_function\_app\_storage\_account\_prefix) | Weka storage account name prefix | `string` | `"weka"` | no |
| <a name="input_function_app_subnet_delegation_cidr"></a> [function\_app\_subnet\_delegation\_cidr](#input\_function\_app\_subnet\_delegation\_cidr) | Subnet delegation enables you to designate a specific subnet for an Azure PaaS service. | `string` | `"10.0.1.0/25"` | no |
| <a name="input_function_app_subnet_delegation_id"></a> [function\_app\_subnet\_delegation\_id](#input\_function\_app\_subnet\_delegation\_id) | Required to specify if subnet\_name were used to specify pre-defined subnets for weka. Function subnet delegation requires an additional subnet, and in the case of pre-defined networking this one also should be pre-defined | `string` | `""` | no |
| <a name="input_function_app_version"></a> [function\_app\_version](#input\_function\_app\_version) | Function app code version (hash) | `string` | `"60ec8c21cc5fd2b21d698fa9bb9e69ac"` | no |
| <a name="input_function_app_version"></a> [function\_app\_version](#input\_function\_app\_version) | Function app code version (hash) | `string` | `"93a261d4128c2c3aa7809fecc4b94746"` | no |
| <a name="input_get_weka_io_token"></a> [get\_weka\_io\_token](#input\_get\_weka\_io\_token) | The token to download the Weka release from get.weka.io. | `string` | `""` | no |
| <a name="input_hotspare"></a> [hotspare](#input\_hotspare) | Number of hotspares to set on weka cluster. Refer to https://docs.weka.io/overview/ssd-capacity-management#hot-spare | `number` | `1` | no |
| <a name="input_install_cluster_dpdk"></a> [install\_cluster\_dpdk](#input\_install\_cluster\_dpdk) | Install weka cluster with DPDK | `bool` | `true` | no |
Expand Down Expand Up @@ -459,6 +459,7 @@ proxy_url = VALUE
| <a name="input_tiering_obs_name"></a> [tiering\_obs\_name](#input\_tiering\_obs\_name) | Name of existing obs storage account | `string` | `""` | no |
| <a name="input_traces_per_ionode"></a> [traces\_per\_ionode](#input\_traces\_per\_ionode) | The number of traces per ionode. Traces are low-level events generated by Weka processes and are used as troubleshooting information for support purposes. | `number` | `10` | no |
| <a name="input_vm_username"></a> [vm\_username](#input\_vm\_username) | Provided as part of output for automated use of terraform, in case of custom AMI and automated use of outputs replace this with user that should be used for ssh connection | `string` | `"weka"` | no |
| <a name="input_vmss_instances_adding_step"></a> [vmss\_instances\_adding\_step](#input\_vmss\_instances\_adding\_step) | Number of instances to add to vmss in one iteration | `number` | `3` | no |
| <a name="input_vmss_single_placement_group"></a> [vmss\_single\_placement\_group](#input\_vmss\_single\_placement\_group) | Sets single\_placement\_group option for vmss. If true, a scale set is composed of a single placement group, and has a range of 0-100 VMs. | `bool` | `true` | no |
| <a name="input_vnet_name"></a> [vnet\_name](#input\_vnet\_name) | The virtual network name. | `string` | `""` | no |
| <a name="input_vnet_rg_name"></a> [vnet\_rg\_name](#input\_vnet\_rg\_name) | Resource group name of vnet. Will be used when vnet\_name is not provided. | `string` | `""` | no |
Expand Down
5 changes: 2 additions & 3 deletions blob.tf
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,9 @@ resource "azurerm_storage_blob" "vmss_state" {
type = "Block"

source_content = jsonencode({
vmss_created = false
vmss_version = 0
refresh_status = 0
current_config = {}
refresh_status = "none"
current_config = null
})

lifecycle {
Expand Down
11 changes: 11 additions & 0 deletions function-app/code/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,17 @@ func getScaleSet(ctx context.Context, subscriptionId, resourceGroupName, vmScale
return &scaleSet.VirtualMachineScaleSet, nil
}

func GetScaleSetOrNilOnNotFound(ctx context.Context, subscriptionId, resourceGroupName, vmScaleSetName string) (*armcompute.VirtualMachineScaleSet, error) {
vmss, err := getScaleSet(ctx, subscriptionId, resourceGroupName, vmScaleSetName)
if err != nil {
if getErr, ok := err.(*azcore.ResponseError); ok && getErr.ErrorCode == "ResourceNotFound" {
return nil, nil
}
return nil, err
}
return vmss, nil
}

// Gets single scale set info
func GetScaleSetInfo(ctx context.Context, subscriptionId, resourceGroupName, vmScaleSetName, keyVaultUri string) (*ScaleSetInfo, error) {
logger := logging.LoggerFromCtx(ctx)
Expand Down
13 changes: 4 additions & 9 deletions function-app/code/common/vmss_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,15 @@ func VmssConfigsDiff(old, new *VMSSConfig) string {
return cmp.Diff(new, old) // arguments order: (want, got)
}

type RefreshStatus uint8
type RefreshStatus string

const (
RefreshNone RefreshStatus = iota
RefreshInProgress RefreshStatus = iota
RefreshNeeded RefreshStatus = iota
RefreshNone RefreshStatus = "none"
RefreshInProgress RefreshStatus = "in_progress"
RefreshNeeded RefreshStatus = "needed"
)

func (s *RefreshStatus) String() string {
return []string{"none", "in_progress", "needed"}[*s]
}

type VMSSState struct {
VmssCreated bool `json:"vmss_created"`
VmssVersion uint16 `json:"vmss_version"`
RefreshStatus RefreshStatus `json:"refresh_status"`
CurrentConfig *VMSSConfig `json:"current_config,omitempty"`
Expand Down
17 changes: 4 additions & 13 deletions function-app/code/functions/clusterize/clusterize.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ type ClusterizationParams struct {
Location string
Prefix string
KeyVaultUri string
VmssVersion uint16

StateContainerName string
StateStorageName string
Expand Down Expand Up @@ -97,7 +96,8 @@ func HandleLastClusterVm(ctx context.Context, state protocol.ClusterState, p Clu
logger := logging.LoggerFromCtx(ctx)
logger.Info().Msg("This is the last instance in the cluster, creating obs and clusterization script")

vmScaleSetName := common.GetVmScaleSetName(p.Prefix, p.Cluster.ClusterName, p.VmssVersion)
version := 0 // on cluserization step we are sure that the vmss version is 0 as no refresh was done yet
vmScaleSetName := common.GetVmScaleSetName(p.Prefix, p.Cluster.ClusterName, uint16(version))

if p.Cluster.SetObs {
if p.Obs.AccessKey == "" {
Expand Down Expand Up @@ -178,7 +178,8 @@ func Clusterize(ctx context.Context, p ClusterizationParams) (clusterizeScript s

instanceName := strings.Split(p.VmName, ":")[0]
instanceId := common.GetScaleSetVmIndex(instanceName)
vmScaleSetName := common.GetVmScaleSetName(p.Prefix, p.Cluster.ClusterName, p.VmssVersion)
version := 0 // on cluserization step we are sure that the vmss version is 0 as no refresh was done yet
vmScaleSetName := common.GetVmScaleSetName(p.Prefix, p.Cluster.ClusterName, uint16(version))
vmName := p.VmName

ip, err := common.GetPublicIp(ctx, p.SubscriptionId, p.ResourceGroupName, vmScaleSetName, p.Prefix, p.Cluster.ClusterName, instanceId)
Expand Down Expand Up @@ -227,7 +228,6 @@ func Clusterize(ctx context.Context, p ClusterizationParams) (clusterizeScript s
func Handler(w http.ResponseWriter, r *http.Request) {
stateContainerName := os.Getenv("STATE_CONTAINER_NAME")
stateStorageName := os.Getenv("STATE_STORAGE_NAME")
vmssStateStorageName := os.Getenv("VMSS_STATE_STORAGE_NAME")
hostsNum, _ := strconv.Atoi(os.Getenv("HOSTS_NUM"))
clusterName := os.Getenv("CLUSTER_NAME")
subscriptionId := os.Getenv("SUBSCRIPTION_ID")
Expand Down Expand Up @@ -284,21 +284,12 @@ func Handler(w http.ResponseWriter, r *http.Request) {
return
}

vmssState, err := common.ReadVmssState(ctx, vmssStateStorageName, stateContainerName)
if err != nil {
err = fmt.Errorf("cannot read vmss state to read get vmss version: %v", err)
logger.Error().Err(err).Send()
common.WriteErrorResponse(w, err)
return
}

params := ClusterizationParams{
SubscriptionId: subscriptionId,
ResourceGroupName: resourceGroupName,
Location: location,
Prefix: prefix,
KeyVaultUri: keyVaultUri,
VmssVersion: vmssState.VmssVersion,
StateContainerName: stateContainerName,
StateStorageName: stateStorageName,
VmName: data.Vm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func Handler(w http.ResponseWriter, r *http.Request) {
}

vmScaleSetName := common.GetVmScaleSetName(prefix, clusterName, vmssState.VmssVersion)
// use the refresh vmss name if the cluster is in refresh mode
if vmssState.RefreshStatus != common.RefreshNone {
vmScaleSetName = common.GetRefreshVmssName(vmScaleSetName, vmssState.VmssVersion)
}

err = common.SetDeletionProtection(ctx, subscriptionId, resourceGroupName, vmScaleSetName, common.GetScaleSetVmIndex(data.Name), true)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions function-app/code/functions/protect/protect.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func Handler(w http.ResponseWriter, r *http.Request) {
}

vmScaleSetName := common.GetVmScaleSetName(prefix, clusterName, vmssState.VmssVersion)
// use the refresh vmss name if the cluster is in refresh mode
if vmssState.RefreshStatus != common.RefreshNone {
vmScaleSetName = common.GetRefreshVmssName(vmScaleSetName, vmssState.VmssVersion)
}

instanceName := strings.Split(data.Vm, ":")[0]
hostName := strings.Split(data.Vm, ":")[1]
Expand Down
5 changes: 5 additions & 0 deletions function-app/code/functions/resize/resize.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ func Handler(w http.ResponseWriter, r *http.Request) {
}

vmssName := common.GetVmScaleSetName(prefix, clusterName, vmssState.VmssVersion)
// use the refresh vmss name if the cluster is in refresh mode
if vmssState.RefreshStatus != common.RefreshNone {
vmssName = common.GetRefreshVmssName(vmssName, vmssState.VmssVersion)
}

err = updateDesiredClusterSize(ctx, *size.Value, subscriptionId, resourceGroupName, vmssName, stateContainerName, stateStorageName)
if err != nil {
logger.Error().Err(err).Send()
Expand Down
Loading

0 comments on commit 6a5d8b0

Please sign in to comment.