Example #1
0
    def __init__(self, application_id, plugin_info):
        self.logger = Log("single.controller.log", "controller.log")
        configure_logging()

        self.application_id = application_id
        self.instances = plugin_info["instances"]
        self.check_interval = plugin_info["check_interval"]
        self.trigger_down = plugin_info["trigger_down"]
        self.trigger_up = plugin_info["trigger_up"]
        self.min_cap = plugin_info["min_cap"]
        self.max_cap = plugin_info["max_cap"]
        self.actuation_size = plugin_info["actuation_size"]
        self.metric_rounding = plugin_info["metric_rounding"]
        self.actuator_type = plugin_info["actuator"]
        self.metric_source_type = plugin_info["metric_source"]

        self.running = True
        self.running_lock = threading.RLock()

        metric_source = MetricSourceBuilder().get_metric_source(
            self.metric_source_type, plugin_info)

        actuator = ActuatorBuilder().get_actuator(self.actuator_type,
                                                  plugin_info)

        self.alarm = BasicAlarm(actuator, metric_source, self.trigger_down,
                                self.trigger_up, self.min_cap, self.max_cap,
                                self.actuation_size, self.metric_rounding)
Example #2
0
    def __init__(self, app_id, plugin_info):
        self.logger = ScalingLog("pid.controller.log", "controller.log",
                                 app_id)

        self.app_id = app_id

        self.instances = plugin_info["instances"]
        self.check_interval = plugin_info["check_interval"]
        self.trigger_down = plugin_info["trigger_down"]
        self.trigger_up = plugin_info["trigger_up"]
        self.min_cap = plugin_info["min_cap"]
        self.max_cap = plugin_info["max_cap"]
        self.metric_rounding = plugin_info["metric_rounding"]
        self.actuator_type = plugin_info["actuator"]
        self.metric_source_type = plugin_info["metric_source"]
        self.heuristic_options = plugin_info["heuristic_options"]

        self.running = True
        self.running_lock = threading.RLock()

        metric_source = MetricSourceBuilder().get_metric_source(
            self.metric_source_type, plugin_info)

        actuator = ActuatorBuilder().get_actuator(self.actuator_type)

        self.alarm = PIDAlarm(actuator, metric_source, self.trigger_down,
                              self.trigger_up, self.min_cap, self.max_cap,
                              self.metric_rounding, self.heuristic_options,
                              self.app_id, self.instances)
Example #3
0
    def get_controller(self, name, app_id, plugin_info):
        if name == "basic":
            metric_source_type = plugin_info["policy"]["metric_source"]
            actuator_type = plugin_info["policy"]["actuator"]

            metric_source = MetricSourceBuilder().get_metric_source(
                metric_source_type)

            actuator = ActuatorBuilder().get_actuator(actuator_type)

            return BasicController(metric_source, actuator, plugin_info)

        elif name == "single":
            return SingleApplicationController(app_id, plugin_info)

        elif name == "progress_error":
            return GenericController(app_id, plugin_info)

        elif name == "proportional":
            return ProportionalController(app_id, plugin_info)

        elif name == "proportional_derivative":
            return ProportionalDerivativeController(app_id, plugin_info)

        elif name == "pid":
            return PIDController(app_id, plugin_info)

        elif name == "progress_tendency":
            return TendencyAwareProportionalController(app_id, plugin_info)

        else:
            # FIXME: exception type
            raise Exception("Unknown controller type")
Example #4
0
 def __init__(self, data):
     # TODO: Check parameters
     scaling_parameters = data["control_parameters"]
     self.metric_source = MetricSourceBuilder().\
         get_metric_source(scaling_parameters.get('metric_source'), data)
     self.app_id = data.get('app_id')
     scaling_parameters.update({'app_id': self.app_id})
     self.scheduler = self.setup_scheduler(scaling_parameters)
     self.actuator = self.setup_actuator(scaling_parameters)
     self.logger = ScalingLog("%s.generic.alarm.log" % (self.app_id),
                              "controller.log", self.app_id)
     self.cap_logger = ScalingLog("%s.cap.log" % (self.app_id),
                                  "cap.log", self.app_id)
     self.last_progress_error_timestamp = datetime.datetime.strptime(
         "0001-01-01T00:00:00.0Z", '%Y-%m-%dT%H:%M:%S.%fZ')
     self.last_action = ""
     self.cap = -1
    def setUp(self):
        self.application_id_0 = "app-00"
        self.application_id_1 = "app-01"
        self.application_id_2 = "app-02"
        self.application_id_3 = "app-03"
        self.application_id_4 = "app-04"

        self.timestamp_1 = datetime.datetime.strptime("2000-01-01T00:00:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_2 = datetime.datetime.strptime("2000-01-01T00:05:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_3 = datetime.datetime.strptime("2000-01-01T00:10:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_4 = datetime.datetime.strptime("2000-01-01T00:15:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')

        self.instance_name_1 = "instance1"
        self.instance_name_2 = "instance2"

        self.bigsea_username = "******"
        self.bigsea_password = "******"
        self.authorization_url = "authorization_url"
        # self.authorization_data = dict(
        #                                authorization_url=self.authorization_url,
        #                                bigsea_username=self.bigsea_username,
        #                                bigsea_password=self.bigsea_password)

        self.trigger_down = 30.0
        self.trigger_up = 10.0
        self.min_cap = 10.0
        self.max_cap = 100.0
        self.actuation_size = 10.0
        self.allocated_resources = 50
        self.metric_round = 2
        self.default_io_cap = 56

        compute_nodes = []
        compute_nodes_key = "key"
        self.instances = [self.instance_name_1, self.instance_name_2]
        self.metric_source = MetricSourceBuilder().get_metric_source("nop", {})
        self.instance_locator = InstanceLocator(SSHUtils({}), compute_nodes,
                                                compute_nodes_key)
        self.remote_kvm = RemoteKVM(SSHUtils({}), compute_nodes_key)
        self.actuator = KVMActuator(
            self.instance_locator,
            self.remote_kvm,
            # self.authorization_data,
            self.default_io_cap)

        self.alarm = BasicAlarm(self.actuator, self.metric_source,
                                self.trigger_down, self.trigger_up,
                                self.min_cap, self.max_cap,
                                self.actuation_size, self.metric_round)

        self.timestamps = [
            self.timestamp_1, self.timestamp_2, self.timestamp_3,
            self.timestamp_4
        ]
Example #6
0
    def __init__(self, application_id, parameters):
        self.logger = ScalingLog(
            "diff.controller.log", "controller.log", application_id)
        scaling_parameters = parameters["control_parameters"]
        self.application_id = application_id
        parameters.update({"app_id": application_id})

        # Read scaling parameters
        self.check_interval = scaling_parameters["check_interval"]
        self.actuator_metric = scaling_parameters["actuator_metric"]
        self.trigger_down = scaling_parameters["trigger_down"]
        self.trigger_up = scaling_parameters["trigger_up"]
        self.min_quota = scaling_parameters["min_quota"]
        self.max_quota = scaling_parameters["max_quota"]

        # The actuator plugin name
        self.actuator_type = scaling_parameters["actuator"]

        # The metric source plugin name
        self.metric_source_type = scaling_parameters["metric_source"]

        # We use a lock here to prevent race conditions when stopping the
        # controller
        self.running = True
        self.running_lock = threading.RLock()

        # Gets a new metric source plugin using the given name
        metric_source = MetricSourceBuilder().get_metric_source(
            self.metric_source_type, parameters)

        # TODO: Add new actuator as option in the ActuatorBuilder
        # Gets a new actuator plugin using the given name
        actuator = ActuatorBuilder().get_actuator(self.actuator_type,
                                                  parameters=parameters)

        # The alarm here is responsible for deciding whether to scale up or
        # down, or even do nothing
        self.alarm = Vertical(
            actuator,
            metric_source,
            self.actuator_metric,
            self.trigger_down,
            self.trigger_up,
            self.min_quota,
            self.max_quota,
            self.application_id)
    def __init__(self, application_id, plugin_info):
        self.logger = Log(
            "tendency.proportional.controller.log", "controller.log")
        configure_logging()

        plugin_info = plugin_info["plugin_info"]

        self.application_id = application_id
        self.instances = plugin_info["instances"]
        self.check_interval = plugin_info["check_interval"]
        self.trigger_down = plugin_info["trigger_down"]
        self.trigger_up = plugin_info["trigger_up"]
        self.min_cap = plugin_info["min_cap"]
        self.max_cap = plugin_info["max_cap"]
        self.metric_rounding = plugin_info["metric_rounding"]
        self.actuation_size = plugin_info["actuation_size"]
        self.actuator_type = plugin_info["actuator"]
        self.metric_source_type = plugin_info["metric_source"]

        self.running = True
        self.running_lock = threading.RLock()

        # Gets a new metric source plugin using the given name
        metric_source = MetricSourceBuilder().get_metric_source(
                            self.metric_source_type, plugin_info
                        )

        # Gets a new actuator plugin using the given name
        actuator = ActuatorBuilder().get_actuator(self.actuator_type,
                                                  plugin_info)

        """ The alarm here is responsible for deciding whether to scale up or
            down, or even do nothing """
        self.alarm = TendencyAwareProportionalAlarm(actuator, metric_source,
                                                    self.trigger_down,
                                                    self.trigger_up,
                                                    self.min_cap,
                                                    self.max_cap,
                                                    self.actuation_size,
                                                    self.metric_rounding)
    def setUp(self):
        config = ConfigParser.RawConfigParser()
        config.get = MagicMock()
        config.get.side_effect = self.config_values

        self.bigsea_username = "******"
        self.bigsea_password = "******"

        scaling_parameters = {
            "check_interval": self.CHECK_INTERVAL,
            "trigger_down": 10,
            "trigger_up": 10,
            "min_cap": 10,
            "max_cap": 100,
            "actuation_size": 20,
            "metric_rounding": 2
        }

        parameters = {
            "scaling_parameters": scaling_parameters,
            "bigsea_username": self.bigsea_username,
            "bigsea_password": self.bigsea_password
        }

        metric_source = MetricSourceBuilder().get_metric_source("nop", {})
        actuator = ActuatorBuilder().get_actuator("nop", parameters)

        self.controller = BasicController(metric_source, actuator,
                                          scaling_parameters)
        self.application_id_1 = "app-01"
        self.application_id_2 = "app-02"
        self.instance_1 = "instance-1"
        self.instance_2 = "instance-2"
        self.instances_1 = [self.instance_1, self.instance_2]
        self.instances_2 = [self.instance_2]
        self.parameters_1 = {"instances": self.instances_1}
        self.parameters_2 = {"instances": self.instances_2}
Example #9
0
    def __init__(self, application_id, plugin_info):
        self.logger = ScalingLog(
            "diff.controller.log", "controller.log", application_id)

        self.application_id = application_id

        self.instances = plugin_info["instances"]
        self.check_interval = plugin_info["check_interval"]
        self.trigger_down = plugin_info["trigger_down"]
        self.trigger_up = plugin_info["trigger_up"]
        self.min_cap = plugin_info["min_cap"]
        self.max_cap = plugin_info["max_cap"]
        self.actuation_size = plugin_info["actuation_size"]
        self.metric_rounding = plugin_info["metric_rounding"]
        self.actuator_type = plugin_info["actuator"]
        self.metric_source_type = plugin_info["metric_source"]

        """ We use a lock here to prevent race conditions
            when stopping the controller """
        self.running = True
        self.running_lock = threading.RLock()

        # Gets a new metric source plugin using the given name
        metric_source = MetricSourceBuilder().get_metric_source(
            self.metric_source_type, plugin_info)

        # Gets a new actuator plugin using the given name
        actuator = ActuatorBuilder().get_actuator(self.actuator_type)

        """ The alarm here is responsible for deciding whether to scale up
            or down, or even do nothing """
        self.alarm = GenericAlarm(actuator, metric_source, self.trigger_down,
                                  self.trigger_up, self.min_cap,
                                  self.max_cap, self.actuation_size,
                                  self.metric_rounding, application_id,
                                  self.instances)
    def setUp(self):
        self.application_id_0 = "app-00"
        self.application_id_1 = "app-01"
        self.application_id_2 = "app-02"

        self.timestamp_1 = datetime.datetime.strptime("2000-01-01T00:00:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_2 = datetime.datetime.strptime("2000-01-01T00:05:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_3 = datetime.datetime.strptime("2000-01-01T00:10:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')
        self.timestamp_4 = datetime.datetime.strptime("2000-01-01T00:15:00.0Z",
                                                      '%Y-%m-%dT%H:%M:%S.%fZ')

        self.instance_name_1 = "instance1"
        self.instance_name_2 = "instance2"
        self.instances = [self.instance_name_1, self.instance_name_2]

        self.trigger_down = 30.0
        self.trigger_up = 10.0
        self.min_cap = 10.0
        self.max_cap = 100.0
        self.actuation_size = 10.0
        self.allocated_resources = 50
        self.metric_round = 2
        self.default_io_cap = 78

        self.bigsea_username = "******"
        self.bigsea_password = "******"
        # self.authorization_url = "authorization_url"
        # self.authorization_data = dict(
        #                                authorization_url=self.authorization_url,
        #                                bigsea_username=self.bigsea_username,
        #                                bigsea_password=self.bigsea_password)

        compute_nodes = []
        compute_nodes_key = "key"
        self.instances = [self.instance_name_1, self.instance_name_2]
        self.metric_source = MetricSourceBuilder().get_metric_source("nop", {})
        self.instance_locator = InstanceLocator(SSHUtils({}), compute_nodes,
                                                compute_nodes_key)
        self.remote_kvm = RemoteKVM(SSHUtils({}), compute_nodes_key)
        self.actuator = KVMActuator(
            self.instance_locator,
            self.remote_kvm,
            # self.authorization_data,
            self.default_io_cap)

        self.proportional_factor = 1
        self.factor_up = 1
        self.factor_down = 0.5
        self.heuristic_options_error_proportional = {
            "heuristic_name": "error_proportional",
            "proportional_factor": self.proportional_factor
        }
        self.heuristic_options_error_proportional_up_down = \
            {"heuristic_name": "error_proportional_up_down",
             "factor_up": self.factor_up,
             "factor_down": self.factor_down}

        self.progress_error = {
            self.application_id_0: -20.0,
            self.application_id_1: 0.00,
            self.application_id_2: 30.0
        }

        self.timestamps = [
            self.timestamp_1, self.timestamp_2, self.timestamp_3,
            self.timestamp_4
        ]
    def setUp(self):
        self.application_id_0 = "app-00"
        self.application_id_1 = "app-01"
        self.application_id_2 = "app-02"
        self.application_id_3 = "app-03"
        self.application_id_4 = "app-04"
        self.application_id_5 = "app-05"
        self.application_id_6 = "app-06"
        self.application_id_7 = "app-07"
        self.application_id_8 = "app-08"
        self.application_id_9 = "app-09"

        self.timestamp_1 = datetime.datetime.strptime("2000-01-01T00:00:00.0Z",
                                                      "%Y-%m-%dT%H:%M:%S.%fZ")
        self.timestamp_2 = datetime.datetime.strptime("2000-01-01T00:05:00.0Z",
                                                      "%Y-%m-%dT%H:%M:%S.%fZ")
        self.timestamp_3 = datetime.datetime.strptime("2000-01-01T00:10:00.0Z",
                                                      "%Y-%m-%dT%H:%M:%S.%fZ")
        self.timestamp_4 = datetime.datetime.strptime("2000-01-01T00:15:00.0Z",
                                                      "%Y-%m-%dT%H:%M:%S.%fZ")

        self.timestamps = [
            self.timestamp_1, self.timestamp_2, self.timestamp_3,
            self.timestamp_4
        ]

        self.instance_name_1 = "instance1"
        self.instance_name_2 = "instance2"
        self.instances = [self.instance_name_1, self.instance_name_2]

        self.trigger_down = 0.0
        self.trigger_up = 0.0
        self.min_cap = 10.0
        self.max_cap = 100.0
        self.actuation_size = 10.0
        self.allocated_resources_scale_down = 100
        self.allocated_resources_scale_up = 10
        self.metric_round = 2
        self.default_io_cap = 34

        self.bigsea_username = "******"
        self.bigsea_password = "******"
        # self.authorization_url = "authorization_url"
        # self.authorization_data = dict(
        #                                authorization_url=self.authorization_url,
        #                                bigsea_username=self.bigsea_username,
        #                                bigsea_password=self.bigsea_password)

        compute_nodes = []
        compute_nodes_key = "key"
        self.instances = [self.instance_name_1, self.instance_name_2]
        self.metric_source = MetricSourceBuilder().get_metric_source("nop", {})
        self.instance_locator = InstanceLocator(SSHUtils({}), compute_nodes,
                                                compute_nodes_key)
        self.remote_kvm = RemoteKVM(SSHUtils({}), compute_nodes_key)
        self.actuator = KVMActuator(
            self.instance_locator,
            self.remote_kvm,
            # self.authorization_data,
            self.default_io_cap)

        self.proportional_factor = 1.5
        self.derivative_factor = 0.5
        self.integrative_factor = 1.5

        self.heuristic_options = {
            "heuristic_name": "error_pid",
            "proportional_factor": self.proportional_factor,
            "derivative_factor": self.derivative_factor,
            "integrative_factor": self.integrative_factor
        }

        self.progress_error = {
            # CASE 1
            self.application_id_0: {
                self.timestamp_1: -30.0,
                self.timestamp_2: -20.0,
                self.timestamp_3: -15.0
            },

            # CASE 2
            self.application_id_1: {
                self.timestamp_1: -30.0,
                self.timestamp_2: -40.0,
                self.timestamp_3: -60.0
            },

            # CASE 3
            self.application_id_2: {
                self.timestamp_1: 30.0,
                self.timestamp_2: 20.0,
                self.timestamp_3: 15.0
            },

            # CASE 4
            self.application_id_3: {
                self.timestamp_1: 30.0,
                self.timestamp_2: 40.0,
                self.timestamp_3: 55.0
            },

            # CASE 5
            self.application_id_4: {
                self.timestamp_1: 100.0,
                self.timestamp_2: 100.0,
                self.timestamp_3: 100.0
            },

            # CASE 6
            self.application_id_5: {
                self.timestamp_1: -100.0,
                self.timestamp_2: -100.0,
                self.timestamp_3: -100.0
            },

            # CASE 7
            self.application_id_6: {
                self.timestamp_1: -30.0,
                self.timestamp_2: 10.0,
                self.timestamp_3: 30.0
            },

            # CASE 8
            self.application_id_7: {
                self.timestamp_1: -5.0,
                self.timestamp_2: -1.0,
                self.timestamp_3: 2.0
            },

            # CASE 9
            self.application_id_8: {
                self.timestamp_1: -10.0,
                self.timestamp_2: -5.0,
                self.timestamp_3: 20.0,
                self.timestamp_4: -5.0
            },

            # CASE 10
            self.application_id_9: {
                self.timestamp_1: -10.0,
                self.timestamp_2: 0.0,
                self.timestamp_3: 10.0,
                self.timestamp_4: 5.0
            }
        }
Example #12
0
class KubeJobs:

    ERROR_METRIC_NAME = "application-progress.error"

    def __init__(self, data):
        # TODO: Check parameters
        scaling_parameters = data["control_parameters"]
        self.metric_source = MetricSourceBuilder().\
            get_metric_source(scaling_parameters.get('metric_source'), data)
        self.app_id = data.get('app_id')
        scaling_parameters.update({'app_id': self.app_id})
        self.scheduler = self.setup_scheduler(scaling_parameters)
        self.actuator = self.setup_actuator(scaling_parameters)
        self.logger = ScalingLog("%s.generic.alarm.log" % (self.app_id),
                                 "controller.log", self.app_id)
        self.cap_logger = ScalingLog("%s.cap.log" % (self.app_id),
                                     "cap.log", self.app_id)
        self.last_progress_error_timestamp = datetime.datetime.strptime(
            "0001-01-01T00:00:00.0Z", '%Y-%m-%dT%H:%M:%S.%fZ')
        self.last_action = ""
        self.cap = -1

    def setup_scheduler(self, parameters):
        strategy = parameters.get('schedule_strategy')
        if strategy == "default":
            return DefaultScheduler(parameters)

        elif strategy == "pid":
            return PidScheduler(parameters)

    def setup_actuator(self, parameters):
        actuator = parameters.get('actuator')
        return ActuatorBuilder().get_actuator(actuator,
                                              parameters)

    def check_application_state(self):
        """
            Checks the application progress by getting progress metrics from a
            metric source, checks if the metrics are new
            and tries to modify the
            amount of allocated resources if necessary.
        """
        # TODO: Check parameters
        progress_error_timestamp, progress_error = \
            self._get_progress_error(self.app_id)

        self.last_action = "Progress error-[%s]-%f" % \
            (str(progress_error_timestamp), progress_error)
        if self._check_measurements_are_new(progress_error_timestamp):
            self._scale(progress_error)
            if self.cap != -1:
                self.cap_logger.log("%.0f|%s|%s" % (time.time(),
                                    str(self.app_id), str(self.cap)))
            self.last_progress_error_timestamp = progress_error_timestamp
        else:
            self.last_action += " Could not acquire more recent metrics"
            self.logger.log(self.last_action)

    def _get_progress_error(self, app_id):
        self.last_action = "Getting progress error"
        self.logger.log(self.last_action)
        progress_error_measurement = self.metric_source.get_most_recent_value(
            app_id)
        progress_error_timestamp = progress_error_measurement[0]
        progress_error = progress_error_measurement[1]

        return progress_error_timestamp, progress_error

    def _scale(self, progress_error):

        last_replicas = self.actuator.get_number_of_replicas()

        info = {'last_replicas': last_replicas,
                'progress_error': progress_error}

        new_resource_allocation = self.scheduler.scale(info)

        if new_resource_allocation is not None:
            self.logger.log("Scaling from %d to %d" %
                            (last_replicas, new_resource_allocation))
            self.actuator.adjust_resources(new_resource_allocation)

    def _check_measurements_are_new(self, progress_error_timestamp):
        return self.last_progress_error_timestamp < progress_error_timestamp

    def status(self):
        return self.last_action