github.com/eth-easl/loader@v0.0.0-20230908084258-8a37e1d94279/pkg/driver/deployment.go (about)

     1  /*
     2   * MIT License
     3   *
     4   * Copyright (c) 2023 EASL and the vHive community
     5   *
     6   * Permission is hereby granted, free of charge, to any person obtaining a copy
     7   * of this software and associated documentation files (the "Software"), to deal
     8   * in the Software without restriction, including without limitation the rights
     9   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10   * copies of the Software, and to permit persons to whom the Software is
    11   * furnished to do so, subject to the following conditions:
    12   *
    13   * The above copyright notice and this permission notice shall be included in all
    14   * copies or substantial portions of the Software.
    15   *
    16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    22   * SOFTWARE.
    23   */
    24  
    25  package driver
    26  
    27  import (
    28  	"bytes"
    29  	"fmt"
    30  	"math"
    31  	"os/exec"
    32  	"regexp"
    33  	"strconv"
    34  
    35  	"github.com/eth-easl/loader/pkg/common"
    36  
    37  	log "github.com/sirupsen/logrus"
    38  )
    39  
    40  const (
    41  	bareMetalLbGateway = "10.200.3.4.sslip.io" // Address of the bare-metal load balancer.
    42  	namespace          = "default"
    43  )
    44  
    45  var (
    46  	urlRegex = regexp.MustCompile("at URL:\nhttp://([^\n]+)")
    47  )
    48  
    49  func DeployFunctionsKnative(functions []*common.Function, yamlPath string, isPartiallyPanic bool, endpointPort int,
    50  	autoscalingMetric string) {
    51  	for i := 0; i < len(functions); i++ {
    52  		deployOne(functions[i], yamlPath, isPartiallyPanic, endpointPort, autoscalingMetric)
    53  	}
    54  }
    55  
    56  func deployOne(function *common.Function, yamlPath string, isPartiallyPanic bool, endpointPort int,
    57  	autoscalingMetric string) bool {
    58  	panicWindow := "\"10.0\""
    59  	panicThreshold := "\"200.0\""
    60  	if isPartiallyPanic {
    61  		panicWindow = "\"100.0\""
    62  		panicThreshold = "\"1000.0\""
    63  	}
    64  	autoscalingTarget := 100 // default for concurrency
    65  	if autoscalingMetric == "rps" {
    66  		autoscalingTarget = int(math.Round(1000.0 / function.RuntimeStats.Average))
    67  		// for rps mode use the average runtime in milliseconds to determine how many requests a pod can process per
    68  		// second, then round to an integer as that is what the knative config expects
    69  	}
    70  
    71  	cmd := exec.Command(
    72  		"bash",
    73  		"./pkg/driver/deploy.sh",
    74  		yamlPath,
    75  		function.Name,
    76  
    77  		strconv.Itoa(function.CPURequestsMilli)+"m",
    78  		strconv.Itoa(function.CPULimitsMilli)+"m",
    79  		strconv.Itoa(function.MemoryRequestsMiB)+"Mi",
    80  		strconv.Itoa(function.InitialScale),
    81  
    82  		panicWindow,
    83  		panicThreshold,
    84  
    85  		"\""+autoscalingMetric+"\"",
    86  		"\""+strconv.Itoa(autoscalingTarget)+"\"",
    87  	)
    88  
    89  	stdoutStderr, err := cmd.CombinedOutput()
    90  	log.Debug("CMD response: ", string(stdoutStderr))
    91  
    92  	if err != nil {
    93  		// TODO: there should be a toggle to turn off deployment because if this is fatal then we cannot test the thing locally
    94  		log.Warnf("Failed to deploy function %s: %v\n%s\n", function.Name, err, stdoutStderr)
    95  
    96  		return false
    97  	}
    98  
    99  	if endpoint := urlRegex.FindStringSubmatch(string(stdoutStderr))[1]; endpoint != function.Endpoint {
   100  		// TODO: check when this situation happens
   101  		log.Debugf("Update function endpoint to %s\n", endpoint)
   102  		function.Endpoint = endpoint
   103  	} else {
   104  		function.Endpoint = fmt.Sprintf("%s.%s.%s", function.Name, namespace, bareMetalLbGateway)
   105  	}
   106  
   107  	// adding port to the endpoint
   108  	function.Endpoint = fmt.Sprintf("%s:%d", function.Endpoint, endpointPort)
   109  
   110  	log.Debugf("Deployed function on %s\n", function.Endpoint)
   111  	return true
   112  }
   113  
   114  func CleanKnative() {
   115  	cmd := exec.Command("kn", "service", "delete", "--all")
   116  	var out bytes.Buffer
   117  	cmd.Stdout = &out
   118  	err := cmd.Run()
   119  	if err != nil {
   120  		log.Debugf("Unable to delete Knative services - %s", err)
   121  	}
   122  }