예제 #1
0
    def load(self, fleet_service, fleet_service_instance):
        if not isinstance(fleet_service_instance,
                          FleetService.FleetServiceInstance):
            raise IllegalArgumentError(
                "Error: Argument <fleet_service> not instance of type <dynamite.GENERAL.FleetService.FleetServiceInstance>"
            )

        if fleet_service_instance.state == FLEET_STATE_STRUCT.INACTIVE:
            response = self._change_state(fleet_service_instance,
                                          FLEET_STATE_STRUCT.LOADED)

            # Also load attached services after parent service was loaded
            if fleet_service_instance.has_attached_services():
                for attached_service_instance in fleet_service_instance.attached_services:
                    response = self._change_state(attached_service_instance,
                                                  FLEET_STATE_STRUCT.LOADED)

            return response
        elif fleet_service_instance.state is None:
            self.submit(fleet_service, fleet_service_instance)

            # Also load attached services after parent service was loaded
            if fleet_service_instance.has_attached_services():
                for attached_service_instance in fleet_service_instance.attached_services:
                    response = self._change_state(attached_service_instance,
                                                  FLEET_STATE_STRUCT.LOADED)

            response = self._change_state(fleet_service_instance,
                                          FLEET_STATE_STRUCT.LOADED)
            return response
        else:
            return None
예제 #2
0
    def _change_state(self, fleet_service_instance, new_state):

        if new_state not in FLEET_STATE_STRUCT.ALLOWED_STATES:
            raise IllegalArgumentError(
                "Error: <new_state> values not allowed. Only allowed values are: "
                + FLEET_STATE_STRUCT.ALLOWED_STATES)

        fleet_service_instance.state = new_state
        #fleet_service.unit_file_details_json_dict["desiredState"] = new_state

        service_name = fleet_service_instance.name

        request_url = self.fleet_units_url + service_name
        request_header = self.http_json_content_type_header
        request_data = json.dumps({"desiredState": new_state})

        # curl http://127.0.0.1:49153/fleet/v1/units/example.service -H "Content-Type: application/json" -X PUT -d '{"desiredState": "loaded"}'
        response = requests.put(request_url,
                                headers=request_header,
                                data=request_data)

        try:
            response.raise_for_status()
        except requests.HTTPError as httpError:
            raise FleetCommunicationError(
                "Unable to communicate with fleet while changing the state of unit {} to {}!"
                .format(service_name, new_state)) from httpError

        return response.status_code
예제 #3
0
    def add_new_fleet_service_instance(self, fleet_service_name):
        if not isinstance(fleet_service_name, str):
            raise IllegalArgumentError("Error: Argument <fleet_service_name> not of type <str>")

        if fleet_service_name in self.FleetServiceDict:
            fleet_service = self.FleetServiceDict[fleet_service_name]

            new_fleet_service_instance = self.FleetServiceHandler.create_new_fleet_service_instance(fleet_service)

            if new_fleet_service_instance is not None:
                try:
                    self.FleetServiceHandler.start(fleet_service, new_fleet_service_instance)
                except FleetSubmissionError as submissionError:
                    self.FleetServiceHandler.remove_fleet_service_instance(fleet_service, new_fleet_service_instance.name, False)
                    raise submissionError

            # save the updated fleet service into etcd (this is mainly done here to save the updated used_port_numbers
            # into etcd so that when dynamite restarts it handles those correctly
                self.save_fleet_service_state_to_etcd(fleet_service)

                fleet_service_instance_dict = new_fleet_service_instance.to_dict()
                fleet_service_instance_json = json.dumps(fleet_service_instance_dict)
                fleet_service_instance_name = fleet_service_instance_dict['name']
                etcd_instance_key = ETCDCTL.etcd_key_running_services + "/" + fleet_service.name + "/" + fleet_service_instance_name

                etcdctl = ETCDCTL.get_etcdctl()
                etcdctl.write(etcd_instance_key, fleet_service_instance_json)

                return new_fleet_service_instance
        return None
    def from_scaling_request(scaling_request, success):
        if not isinstance(success, bool):
            raise IllegalArgumentError(
                "Error: argument <success> needs to be of type <bool>")
        if not isinstance(scaling_request,
                          DynamiteScalingRequest) or scaling_request is None:
            raise IllegalArgumentError(
                "Error: argument <scaling_request_string> needs to be of type <str>"
            )

        scaling_response = DynamiteScalingResponse()
        scaling_response.success = success
        scaling_response.command = scaling_request.command
        scaling_response.service_name = scaling_request.service_name
        scaling_response.service_instance_name = scaling_request.service_instance_name
        scaling_response.failure_counter = scaling_request.failure_counter
        return scaling_response
예제 #5
0
    def create_fleet_service_dict_from_dynamite_config_object(self, dynamite_config):
        if not isinstance(dynamite_config, DynamiteConfig):
            raise IllegalArgumentError("Error: Argument <dynamite_config> not instance of type 'DynamiteConfig'")

        self.DynamiteConfig = dynamite_config

        fleet_service_dict = self.dynamite_config_2_fleet_service_dict(self.DynamiteConfig)

        if fleet_service_dict is not None:
            return fleet_service_dict
예제 #6
0
    def from_json_string(cls, scaling_request_string, message_processed_callback=None):
        if not isinstance(scaling_request_string, str):
            raise IllegalArgumentError("Error: argument <scaling_request_string> needs to be of type <str>")

        scaling_request_json = json.loads(scaling_request_string)
        scaling_request = DynamiteScalingRequest()
        scaling_request.message_processed_callback = message_processed_callback
        scaling_request.command = scaling_request_json["command"]
        scaling_request.service_name = scaling_request_json["service_name"]
        scaling_request.service_instance_name = scaling_request_json["service_instance_name"]
        scaling_request.failure_counter = scaling_request_json["failure_counter"]
        return scaling_request
    def generate_scaling_requests(self,
                                  scaling_command,
                                  service_name=None,
                                  service_instance_name=None,
                                  number_of_requests=1):

        if scaling_command not in DynamiteScalingCommand.ALLOWED_COMMANDS:
            raise IllegalArgumentError(
                "Error: argument <scaling_command> needs to either be 'scale_up' or 'scale_down'"
            )

        if not isinstance(number_of_requests, int) and number_of_requests < 1:
            raise IllegalArgumentError(
                "Error: argument <number_of_requests> needs to be of type <int> and can not"
                "be less than 1")

        if service_name is not None:
            scaling_request = {
                "command": scaling_command,
                "service_name": service_name,
                "service_instance_name": service_instance_name,
                "failure_counter": 0
            }
        else:
            raise IllegalArgumentError(
                "Error: argument <service_name> needs to always be set")

        scaling_request_string = json.dumps(scaling_request)

        for requests in range(number_of_requests):
            # scaling_request_string = self._create_scaling_request_string(scaling_command)

            self.rabbitmq_channel.basic_publish(
                exchange='',
                routing_key=self.dynamite_scaling_request,
                body=scaling_request_string)

            print("sent scaling request " + scaling_request_string +
                  " to queue: " + self.dynamite_scaling_request)
예제 #8
0
    def unload(self, fleet_service_instance):
        if not isinstance(fleet_service_instance,
                          FleetService.FleetServiceInstance):
            raise IllegalArgumentError(
                "Error: Argument <fleet_service> not instance of type <dynamite.GENERAL.FleetService.FleetServiceInstance>"
            )

        if fleet_service_instance.state == FLEET_STATE_STRUCT.LOADED or fleet_service_instance.state == FLEET_STATE_STRUCT.LAUNCHED:
            self._change_state(fleet_service_instance,
                               FLEET_STATE_STRUCT.INACTIVE)

        # Also unload attached services after parent service was unloaded
        if fleet_service_instance.has_attached_services():
            for attached_service_instances in fleet_service_instance.attached_services:
                self._change_state(attached_service_instances,
                                   FLEET_STATE_STRUCT.INACTIVE)
예제 #9
0
    def _initial_start_all_services_to_fleet(self, fleet_service_handler, fleet_service_dict):

        if not isinstance(fleet_service_handler, FleetServiceHandler):
            raise IllegalArgumentError("Error: Argument <FleetServiceHandler> not instance of type <dynamite.GENERAL.FleetServiceHandler")

        #       If service is not a template just create one instance
        for service_name, fleet_service in fleet_service_dict.items():
            if fleet_service.service_config_details.min_instance:
                min_instances = fleet_service.service_config_details.min_instance
            else:
                min_instances = 1

            for times in range(min_instances):
                fleet_service_instance = fleet_service_handler.create_new_fleet_service_instance(fleet_service)
                fleet_service_handler.submit(fleet_service, fleet_service_instance)
                fleet_service_handler.start(fleet_service, fleet_service_instance)
예제 #10
0
    def stop(self, fleet_service_instance):
        if not isinstance(fleet_service_instance,
                          FleetService.FleetServiceInstance):
            raise IllegalArgumentError(
                "Error: Argument <fleet_service> not instance of type <dynamite.GENERAL.FleetService.FleetServiceInstance>"
            )

        if fleet_service_instance.state == FLEET_STATE_STRUCT.LAUNCHED:
            response = self._change_state(fleet_service_instance,
                                          FLEET_STATE_STRUCT.LOADED)

            # Also stop service announcer after parent service was stopped
            if fleet_service_instance.has_attached_services():
                for attached_service_instance in fleet_service_instance.attached_services:
                    response = self._change_state(attached_service_instance,
                                                  FLEET_STATE_STRUCT.LOADED)

            return response
        else:
            return None
예제 #11
0
    def submit(self, fleet_service, fleet_service_instance):
        if not isinstance(fleet_service_instance,
                          FleetService.FleetServiceInstance):
            raise IllegalArgumentError(
                "Error: Argument <fleet_service> not instance of type <dynamite.GENERAL.FleetService.FleetServiceInstance>"
            )

        if fleet_service.has_attached_services():
            for attached_service in fleet_service.attached_services:
                for name, attached_service_instance in attached_service.fleet_service_instances.items(
                ):
                    self.submit(attached_service, attached_service_instance)

        if fleet_service_instance.state is None:
            service_name = fleet_service_instance.name

            # fleet_service_instance.unit_file_details_json_dict["desiredState"] = FLEET_STATE_STRUCT.INACTIVE
            fleet_service.unit_file_details_json_dict[
                "desiredState"] = FLEET_STATE_STRUCT.INACTIVE
            fleet_service_instance.state = FLEET_STATE_STRUCT.INACTIVE

            #service_json = json.dumps(fleet_service_instance.unit_file_details_json_dict)
            service_json = json.dumps(
                fleet_service.unit_file_details_json_dict)

            request_url = self.fleet_units_url + service_name
            request_header = self.http_json_content_type_header
            request_data = service_json

            # curl http://127.0.0.1:49153/fleet/v1/units/example.service -H "Content-Type: application/json" -X PUT -d @example.service.json
            response = requests.put(request_url,
                                    headers=request_header,
                                    data=request_data)

            self._check_if_unit_exists_and_retry_if_not(
                fleet_service_instance.name)
            return response.status_code
        else:
            return None
예제 #12
0
    def start(self, fleet_service, fleet_service_instance):
        if not isinstance(fleet_service_instance,
                          FleetService.FleetServiceInstance):
            raise IllegalArgumentError(
                "Error: Argument <fleet_service> not instance of type <dynamite.GENERAL.FleetService.FleetServiceInstance>"
            )

        if fleet_service_instance.state == FLEET_STATE_STRUCT.INACTIVE or fleet_service_instance.state == FLEET_STATE_STRUCT.LOADED:
            response = self._change_state(fleet_service_instance,
                                          FLEET_STATE_STRUCT.LAUNCHED)

            # Also start service announcer after parent service was started
            if fleet_service_instance.has_attached_services():
                for attached_service in fleet_service_instance.attached_services:
                    response = self._change_state(attached_service,
                                                  FLEET_STATE_STRUCT.LAUNCHED)

            return response
        elif fleet_service_instance.state is None:
            self.submit(fleet_service, fleet_service_instance)
            response = self._change_state(fleet_service_instance,
                                          FLEET_STATE_STRUCT.LAUNCHED)

            # Also start attached services after parent service was started
            if fleet_service_instance.has_attached_services():
                for attached_service_instance in fleet_service_instance.attached_services:
                    response = self._change_state(attached_service_instance,
                                                  FLEET_STATE_STRUCT.LAUNCHED)

            services_started = self._check_if_service_and_attached_services_started(
                fleet_service_instance)
            if not services_started:
                raise FleetStartError(
                    "Could not start Service {} and or attached services!".
                    format(fleet_service_instance.name))

            return response
        else:
            return None
예제 #13
0
    def dynamite_config_2_fleet_service_dict(self, dynamite_config):

        fleet_service_dict = {}

        if not isinstance(dynamite_config, DynamiteConfig):
            raise IllegalArgumentError("Error: Argument not instance of type 'DynamiteConfig'")

        # Collect necessary information of services defined in 'config.yaml' file and save them in 'service_dict'
        # dictionary
        service_dict = {}
        for service_attributes in dynamite_config.Service.__dict__.values():
            service_dict[service_attributes.name] = {"service_name": service_attributes.name,
                                                     "name_of_unit_file": service_attributes.name_of_unit_file,
                                                     "service_details": service_attributes}

        # Create a dictionary (file --> path) of the files contained in the folder(s) in
        # dynamite_config.ServiceFiles.PathList
        dict_of_files = {}
        for service_file_folder in dynamite_config.ServiceFiles.PathList:
            list_of_files = os.listdir(service_file_folder)

            for file in list_of_files:
                abs_path_of_file = os.path.join(service_file_folder, file)
                if os.path.isfile(abs_path_of_file):
                    if file in dict_of_files:
                        raise DuplicateServiceFileError("Error: " + file + " was found 2 times")
                    else:
                        dict_of_files[file] = abs_path_of_file

        # Go through all the services defined in the dynamite configuration (Dynamite.Service.<x>)
        #
        # Raises an error if any 'Dynamite.Service.<ServiceName>.name_of_unit_file' does not exists in any of the
        # paths defined in 'Dynamite.ServiceFiles.PathList
        #
        # If the file exits a new FleetService gets created
        #   If the file/service uses an attached service a FleetService for the attached service gets created and
        #   attached to the 'original/parent' FleetService
        #       that attaches the services as defined in the DynamiteConfig. The attached service should be saved in a
        #       list or dictionary
        for service_name, service_info_dict in service_dict.items():

            name_of_unit_file = service_info_dict["name_of_unit_file"]

            if name_of_unit_file in dict_of_files and service_info_dict["service_details"].type != "attached_service":

                service_details = service_info_dict["service_details"]
                path_to_unit_file = dict_of_files[name_of_unit_file]
                json_dict = self.unit2dict(path_to_unit_file)

                service_is_template = True if "@" in service_details.name_of_unit_file else False
                attached_services = []

                if service_details.attached_services is not None:
                    for attached_service in service_details.attached_services:
                        name_of_attached_service = attached_service
                        attached_service_details = getattr(dynamite_config.Service, name_of_attached_service)
                        name_of_attached_service_unit_file = attached_service_details.name_of_unit_file

                        if name_of_attached_service_unit_file in dict_of_files:
                            attached_service_is_template = True if "@" in service_details.name_of_unit_file else False
                            path_to_attached_service_unit_file = dict_of_files[name_of_attached_service_unit_file]
                            attached_service_json_dict = self.unit2dict(path_to_attached_service_unit_file)

                            attached_service = FleetService(name_of_attached_service,
                                                            path_to_attached_service_unit_file,
                                                            attached_service_json_dict,
                                                            attached_service_details,
                                                            is_template=attached_service_is_template,
                                                            attached_services=None)
                            attached_services.append(attached_service)
                        else:
                            self._logger.error(name_of_attached_service_unit_file + "> File was not found.")
                            #raise ServiceAnnouncerFileNotFoundError("Error: <" + name_of_attached_service_unit_file + "> File was not found.")

                fleet_service = FleetService(service_name,
                                             path_to_unit_file,
                                             json_dict,
                                             service_details,
                                             service_is_template,
                                             attached_services)

                fleet_service_dict[service_info_dict["service_name"]] = fleet_service
                # TODO: find out if attached service
            elif service_info_dict["service_details"].type == "attached_service":
                pass
            else:
                raise ServiceFileNotFoundError(name_of_unit_file + " Service-File was not found")

        return fleet_service_dict