def __initialize(self, **kwargs): # Controller and Log collector socket port self.port = kwargs.get('controller_port', 7878) # Controller address, void at the beginning self.server_address = kwargs.get('controller_ip_address', None) # Scenario folder, defaults to current directory self.scenario_folder = kwargs.get('scenario_folder', os.getcwd()) # Scenario file name, defaults to './scenario.py' self.scenario_file_path = utils.get_abs_path(kwargs.get('scenario_file', './scenario.py'), self.scenario_folder) # Results file path, defaults to './results/results.sqlite' self.results_file_path = utils.get_abs_path(kwargs.get('results_file', './results/results.sqlite'), self.scenario_folder) # Scenario name, defaults to 'Scenario' self.scenario_name = kwargs.get('scenario_name', 'Scenario') # Spawn quota for local spawner self.spawn_quota = kwargs.get('spawn_quota', 1) # Placeholder for scenario self.scenario = None # Armed flag, used to start and stop running self.armed = False # Elapsed time since scenario beginning self.elapsed_time = 0 # Internal message sender placeholder self.sender = Sender(self.server_address, self.port, 'UDP') if self.server_address else None # Sender spawn message poll interval self.sender_spawn_polling_interval = kwargs.get('sender_spawn_polling_interval', 5) self.sender_spawn_elapsed_time = 0.0 # Internal Sysmonitor object and related thread self.sysmonitor_polling_interval = kwargs.get('sysmonitor_polling_interval', 1.0) click.secho(utils.logify('Setting up Sysmonitor... ', 'Spawner')) self.sysmonitor = Sysmonitor(self.server_address, self.port, self.sysmonitor_polling_interval) click.secho(utils.logify('Sysmonitor started'), fg='green', bold=True)
def __init__(self, **kwargs): # Navigation name, defaults to class name self.name = kwargs.get('navigation_name', self.__class__.__name__) # Navigation settings and scenario self.settings = kwargs.get('settings', {}) self.scenario_folder = kwargs.get('scenario_folder', os.getcwd()) # Sender data self.server_address = kwargs.get('server_address', 'localhost') self.server_port = kwargs.get('server_port', 7878) self.sender = Sender(self.server_address, self.server_port, 'UDP') # Internal variables self.thread_variables = {} self.test_transactions = [] self.spawn_id = None self.iteration = 1 self.debug = False
class Navigation(object): __metaclass__ = abc.ABCMeta def __init__(self, **kwargs): # Navigation name, defaults to class name self.name = kwargs.get('navigation_name', self.__class__.__name__) # Navigation settings and scenario self.settings = kwargs.get('settings', {}) self.scenario_folder = kwargs.get('scenario_folder', os.getcwd()) # Sender data self.server_address = kwargs.get('server_address', 'localhost') self.server_port = kwargs.get('server_port', 7878) self.sender = Sender(self.server_address, self.server_port, 'UDP') # Internal variables self.thread_variables = {} self.test_transactions = [] self.spawn_id = None self.iteration = 1 self.debug = False @abc.abstractmethod def transactions(self): """ Insert here the transactions to be included in the test, in the execution order """ pass def configure(self): pass def add_setting(self, str_default_key, str_value): """ Add a setting value to the specified key """ self.settings[str_default_key] = str_value def set_variable(self, str_name, str_value): """ Add a variable to the thread variables dict """ self.thread_variables[str_name] = str_value def add_transaction(self, str_name, str_path): str_abspath = utils.get_abs_path(str_path, self.scenario_folder) obj_transaction = { 'name': str_name, 'path': str_abspath, 'class': utils.import_from_path(str_abspath, str_name, {'navigation_name': self.name}), 'server_address': self.server_address, 'server_port': self.server_port } self.test_transactions.append(obj_transaction) def run(self, str_spawn_id=None): self.spawn_id = str_spawn_id # Cycle through transactions for obj_transaction_item in self.test_transactions: # Send transaction start message self.sender.send('transactionStart', { 'hostName': utils.get_ip_address(), 'spawnID': self.spawn_id, 'testName': self.name, 'iteration': self.iteration, 'transactionName': obj_transaction_item['name'], 'startTimestamp': utils.get_timestamp() }) # Run the transaction self.settings,\ self.thread_variables = \ obj_transaction_item['class'].run(self.spawn_id, self.iteration, self.settings, self.thread_variables) # Send transaction end message self.sender.send('transactionEnd', { 'hostName': utils.get_ip_address(), 'spawnID': self.spawn_id, 'testName': self.name, 'iteration': self.iteration, 'transactionName': obj_transaction_item['name'], 'endTimestamp': utils.get_timestamp() }) self.iteration += 1 # Print line if in Debug mode if self.debug: print('ID: ' + str(self.spawn_id) + ' Timestamp: ' + utils.get_timestamp())
class Spawner(StoppableThread): def __init__(self, str_server_address, int_controller_port, str_scenario_folder, str_scenario_name, str_scenario_file_path, str_results_file_path, dbl_spawn_quota): # Initialize the father stoppable thread class super(Spawner, self).__init__() # Instantiates everything self.__initialize(controller_ip_address=str_server_address, controller_port=int_controller_port, scenario_folder=str_scenario_folder, scenario_file=str_scenario_file_path, scenario_name=str_scenario_name, results_file=str_results_file_path, spawn_quota=dbl_spawn_quota) self.__set_scenario_class() self.__arm() def run(self): self.__run() def __initialize(self, **kwargs): # Controller and Log collector socket port self.port = kwargs.get('controller_port', 7878) # Controller address, void at the beginning self.server_address = kwargs.get('controller_ip_address', None) # Scenario folder, defaults to current directory self.scenario_folder = kwargs.get('scenario_folder', os.getcwd()) # Scenario file name, defaults to './scenario.py' self.scenario_file_path = utils.get_abs_path(kwargs.get('scenario_file', './scenario.py'), self.scenario_folder) # Results file path, defaults to './results/results.sqlite' self.results_file_path = utils.get_abs_path(kwargs.get('results_file', './results/results.sqlite'), self.scenario_folder) # Scenario name, defaults to 'Scenario' self.scenario_name = kwargs.get('scenario_name', 'Scenario') # Spawn quota for local spawner self.spawn_quota = kwargs.get('spawn_quota', 1) # Placeholder for scenario self.scenario = None # Armed flag, used to start and stop running self.armed = False # Elapsed time since scenario beginning self.elapsed_time = 0 # Internal message sender placeholder self.sender = Sender(self.server_address, self.port, 'UDP') if self.server_address else None # Sender spawn message poll interval self.sender_spawn_polling_interval = kwargs.get('sender_spawn_polling_interval', 5) self.sender_spawn_elapsed_time = 0.0 # Internal Sysmonitor object and related thread self.sysmonitor_polling_interval = kwargs.get('sysmonitor_polling_interval', 1.0) click.secho(utils.logify('Setting up Sysmonitor... ', 'Spawner')) self.sysmonitor = Sysmonitor(self.server_address, self.port, self.sysmonitor_polling_interval) click.secho(utils.logify('Sysmonitor started'), fg='green', bold=True) def __set_scenario_class(self): # Load scenario from temporary folder self.scenario = utils.import_from_path(self.scenario_file_path, self.scenario_name, {'scenario_folder': self.scenario_folder}) self.scenario.rescale_spawns_by_factor(self.spawn_quota) def __arm(self): # Arm itself self.armed = True def __unarm(self): # Disarm itself self.armed = False def __run(self): click.secho(utils.logify('Starting Sysmonitor... ', 'Spawner'), nl=False) self.sysmonitor.start() click.secho('DONE', fg='green', bold=True) self.scenario.configure() self.scenario.navigations_definition() self.scenario.scenario_start = utils.get_timestamp(False) self.scenario.scenario_duration =\ self.scenario.get_scenario_duration() list_navigations = self.scenario.get_navigation_names() # Update sender spawn message elapsed time self.sender_spawn_elapsed_time += self.elapsed_time # Write beginning message click.secho(utils.logify('Running scenario...', 'Spawner'), fg='green') while self.elapsed_time <= self.scenario.scenario_duration and self.armed: # Get elapsed time time_elapsed = utils.get_timestamp(False) - self.scenario.scenario_start self.elapsed_time = time_elapsed.total_seconds() # Cycle through navigations for str_navigation_name in list_navigations: # Get planned and current spawn number self.scenario.navigations[str_navigation_name]['planned_spawns'] =\ self.scenario.get_planned_spawns(str_navigation_name, self.elapsed_time) self.scenario.navigations[str_navigation_name]['current_spawns'] =\ len(self.scenario.navigations[str_navigation_name]['threads']) # Send spawn message, but only if is passed enough time from last sending if self.sender_spawn_elapsed_time >= self.sender_spawn_polling_interval: self.sender.send('spawns', { 'hostName': utils.get_ip_address(), 'timestamp': utils.get_timestamp(), 'navigationName': str_navigation_name, 'plannedSpawns': self.scenario.navigations[str_navigation_name]['planned_spawns'], 'runningSpawns': self.scenario.navigations[str_navigation_name]['current_spawns'] }) self.sender_spawn_elapsed_time = 0.0 int_spawns_difference = self.scenario.navigations[str_navigation_name][ 'current_spawns'] - self.scenario.navigations[ str_navigation_name]['planned_spawns'] # If there are less spawns than planned, add some spawns if int_spawns_difference < 0: for int_counter in range(0, -int_spawns_difference): str_navigation_path = self.scenario.get_navigation_path(str_navigation_name) str_id = utils.random_id(16) print(str_id) obj_spawn = Spawn(str_id, str_navigation_name, str_navigation_path, self.scenario_folder, self.server_address, self.port, self.scenario.settings) obj_spawn.start() self.scenario.navigations[str_navigation_name]['threads'].append(obj_spawn) # If there are more spawns than planned, start killing older spawns elif int_spawns_difference > 0: for int_counter in range(0, int_spawns_difference): obj_spawn = self.scenario.navigations[str_navigation_name]['threads'].pop(0) obj_spawn.terminate() obj_spawn.join() print('Killed one') self.__unarm() # Clean all the remaining threads click.secho(utils.logify('Cleaning up... ', 'Spawner'), nl=False) for str_navigation_name in list_navigations: for int_counter in range(0, len(self.scenario.navigations[str_navigation_name]['threads'])): obj_spawn = self.scenario.navigations[str_navigation_name]['threads'].pop(0) obj_spawn.terminate() obj_spawn.join() print('Killed one - Cleanup') click.secho('DONE', fg='green', bold=True) # Close Sysmonitor thread click.secho(utils.logify('Closing Sysmonitor... ', 'Spawner'), nl=False) self.sysmonitor.terminate() self.sysmonitor.join() click.secho('DONE', fg='green', bold=True) click.secho(utils.logify('Scenario gracefully completed!', 'Spawner'), fg='green', bold=True)