def init(e: Environment, **kwargs) -> None: global All_Capable_Server_Type_List All_Capable_Server_Type_List = list(e.get_server_config_dict().keys()) for vm_type, vm_config in e.get_vm_config_dict().items(): for server_type in All_Capable_Server_Type_List: if server_type not in vm_config.get_capable_server_type_dict( ).keys(): All_Capable_Server_Type_List.remove(server_type)
def read_vm_config(r: Reader, e: Environment) -> None: n = int(next(r.get_next_line)) for _ in range(n): vm_config_list = next(r.get_next_line).strip('(').strip(')').split(', ') vm_type, cpu, memory, is_double = vm_config_list vm_config = VMConfig( vm_type=vm_type.strip(' '), cpu=int(cpu), memory=int(memory), is_double=is_double == '1' ) e.add_vm_config(vm_config=vm_config)
def read_server_config(r: Reader, e: Environment) -> None: n = int(next(r.get_next_line)) for _ in range(n): server_config_list = next(r.get_next_line).strip('(').strip(')').split(',') server_type, cpu, memory, cost_purchase, cost_everyday = server_config_list server_config = ServerConfig( server_type=server_type.strip(' '), cpu=int(cpu), memory=int(memory), cost_purchase=int(cost_purchase), cost_everyday=int(cost_everyday) ) e.add_server_config(server_config=server_config)
def simulate_current_day(e: Environment, **kwargs) -> None: deploy_operations_list = [] for op in e.get_current_day_info().get_request_operation_list(): if isinstance(op, RemoveSingleVMOperation) or isinstance( op, RemoveDoubleVMOperation): simulate_current_stage( e=e, deploy_operations_list=deploy_operations_list) deploy_operations_list.clear() e.op_remove_vm(op=op) else: deploy_operations_list.append(op) simulate_current_stage(e=e, deploy_operations_list=deploy_operations_list)
def migrate_current_day(e: Environment, **kwargs) -> None: server_dict_dict = { server: { 'server': server, 'num_del_op': 0, 'num_vm': server.get_num_vm_of_node_a() + server.get_num_vm_of_node_b(), 'key': server.get_used_cpu_of_node_a() + server.get_used_cpu_of_node_b() + \ server.get_used_memory_of_node_a() + server.get_used_memory_of_node_b(), } for server in e.get_deployed_server_dict().values() } for remove_op in e.get_current_day_info().get_del_vm_operation_list(): server_dict_dict[remove_op.get_vm().get_server()]['num_del_op'] += 1 for server, server_dict in server_dict_dict.items(): server_dict_dict[server]['key'] += server.get_num_vm_of_node_a() + server.get_num_vm_of_node_b() + \ -server_dict_dict[server]['num_del_op'] server_dict_list = list(server_dict_dict.values()) server_dict_list.sort(key=lambda sd: sd['key'], reverse=False) num_total_vm = sum([sd['num_vm'] for sd in server_dict_list]) num_migrations = 0 max_migrations = num_total_vm * 3 // 100 available_server_list = [sd['server'] for sd in server_dict_list] available_server_list.reverse() for server_dict in server_dict_list: server = server_dict['server'] available_server_list.remove(server) for vm in server.get_vm_dict_of_node_a().copy().values(): num_migrations += migrate_vm( e=e, vm=vm, current_server=server, available_server_list=available_server_list) if num_migrations == max_migrations: return for vm in server.get_vm_dict_of_node_b().copy().values(): num_migrations += migrate_vm( e=e, vm=vm, current_server=server, available_server_list=available_server_list) if num_migrations == max_migrations: return
def write_day_operation(w: Writer, e: Environment) -> None: content_list = [] server_dict = {} for purchase_server_operation in e.get_current_day_info().get_purchase_server_operation_list(): server_id = purchase_server_operation.get_server().get_server_id() server_type = purchase_server_operation.get_server().get_server_type() if server_type in server_dict.keys(): server_dict[server_type].append(server_id) else: server_dict[server_type] = [server_id] # w.write(content=f'(purchase, {len(server_dict)})') content_list.append(f'(purchase, {len(server_dict)})') for server_type, server_id_list in server_dict.items(): # w.write(content=f'({server_type}, {len(server_id_list)})') content_list.append(f'({server_type}, {len(server_id_list)})') for server_id in server_id_list: w.set_mapped_server_id(server_id=server_id) # w.write(content=f'(migration, {len(e.get_current_day_info().get_migrate_vm_operation_list())})') content_list.append(f'(migration, {len(e.get_current_day_info().get_migrate_vm_operation_list())})') for op in e.get_current_day_info().get_migrate_vm_operation_list(): vm_id = op.get_vm().get_vm_id() server_id = op.get_server().get_server_id() if op.get_vm().is_double(): # w.write(content=f'({vm_id}, {server_id})') content_list.append(f'({vm_id}, {server_id})') else: node = op.get_node() # w.write(content=f'({vm_id}, {server_id}, {node})') content_list.append(f'({vm_id}, {server_id}, {node})') for op in e.get_current_day_info().get_request_operation_list(): if isinstance(op, DeploySingleVMOperation): mapped_server_id = w.get_mapped_server_id(server_id=op.get_server().get_server_id()) # w.write(content=f'({mapped_server_id}, {op.get_node()})') content_list.append(f'({mapped_server_id}, {op.get_node()})') elif isinstance(op, DeployDoubleVMOperation): mapped_server_id = w.get_mapped_server_id(server_id=op.get_server().get_server_id()) # w.write(content=f'({mapped_server_id})') content_list.append(f'({mapped_server_id})') content = '\n'.join(content_list) w.write(content=content) w.flush()
def purchase_the_best_server(e: Environment, vm: Union[SingleVM, DoubleVM]) -> Server: target_server_config = None for server_config in e.get_server_config_dict().values(): if server_config not in vm.get_vm_config( ).get_capable_server_type_dict().values(): continue if target_server_config is None: target_server_config = server_config continue if server_config_cost(e=e, server_config=server_config) < \ server_config_cost(e=e, server_config=target_server_config): target_server_config = server_config server = e.op_purchase_server(server_config=target_server_config) return server
def migrate_current_day(e: Environment, **kwargs) -> None: server_id_num_vm_list = [ (server.get_server_id(), server.get_num_vm_of_both_nodes()) for server in e.get_deployed_server_dict().values() ] server_id_num_vm_list.sort(key=lambda t: t[1]) num_total_vm = sum([t[1] for t in server_id_num_vm_list]) num_migrations = 0 max_migrations = num_total_vm * 3 // 100 for server_id, num_vm in server_id_num_vm_list: server = e.get_server_by_id(server_id=server_id) for vm in server.get_vm_dict_of_node_a().copy().values(): num_migrations += migrate_vm(e=e, vm=vm, current_server=server) if num_migrations == max_migrations: break if num_migrations == max_migrations: break
def select_idle_server_for_double_vm(e: Environment, vm: DoubleVM) -> Optional[Server]: target_server = None for server in e.get_non_deployed_server_dict().values(): if server.has_capacity_for_double_vm(vm=vm): if target_server is None or server_cost_d( vm, server) < server_cost_d(vm, target_server): target_server = server return target_server
def select_idle_server_for_single_vm( e: Environment, vm: SingleVM) -> Tuple[Optional[Server], Optional[str]]: target_server = None target_node = None for server in e.get_non_deployed_server_dict().values(): if server.has_capacity_for_single_vm(vm=vm, node='A'): if target_server is None or server_cost_s( vm, server, 'A') < server_cost_s(vm, target_server, 'A'): target_server, target_node = server, 'A' return target_server, target_node
def migrate_vm(e: Environment, vm: Union[SingleVM, DoubleVM], current_server: Server) -> int: if isinstance(vm, SingleVM): for server in e.get_deployed_server_dict().values(): if server == current_server: continue if server.has_capacity_for_single_vm(vm=vm, node='A'): e.op_migrate_single_vm(vm=vm, new_server=server, node='A') return 1 if server.has_capacity_for_single_vm(vm=vm, node='B'): e.op_migrate_single_vm(vm=vm, new_server=server, node='B') return 1 if isinstance(vm, DoubleVM): for server in e.get_deployed_server_dict().values(): if server == current_server: continue if server.has_capacity_for_double_vm(vm=vm): e.op_migrate_double_vm(vm=vm, new_server=server) return 1 return 0
def read_day_request(r: Reader, e: Environment, day: int) -> None: n = int(next(r.get_next_line)) for _ in range(n): request_list = next(r.get_next_line).strip('(').strip(')').split(', ') if request_list[0] == 'add': vm_type = request_list[1] vm_id = request_list[2] vm_config = e.get_vm_config_by_type(vm_type=vm_type) if vm_config.is_double(): vm = DoubleVM(vm_id=vm_id, vm_config=vm_config) op = DeployDoubleVMOperation(day=day, vm=vm) else: vm = SingleVM(vm_id=vm_id, vm_config=vm_config) op = DeploySingleVMOperation(day=day, vm=vm) e.add_non_deployed_vm(vm=vm) e.add_request_operation(day=day, op=op) elif request_list[0] == 'del': vm_id = request_list[1] vm = e.get_vm_by_id(vm_id=vm_id) if vm.is_double(): op = RemoveDoubleVMOperation(day=day, vm=vm) else: op = RemoveSingleVMOperation(day=day, vm=vm) e.add_request_operation(day=day, op=op)
def migrate_vm(e: Environment, vm: Union[SingleVM, DoubleVM], current_server: Server, available_server_list: List[Server]) -> int: if isinstance(vm, SingleVM): for server in available_server_list: if server == current_server: continue if server.has_capacity_for_single_vm(vm=vm, node='A'): e.op_migrate_single_vm(vm=vm, new_server=server, node='A') return 1 if server.has_capacity_for_single_vm(vm=vm, node='B'): e.op_migrate_single_vm(vm=vm, new_server=server, node='B') return 1 if isinstance(vm, DoubleVM): for server in available_server_list: if server == current_server: continue if server.has_capacity_for_double_vm(vm=vm): e.op_migrate_double_vm(vm=vm, new_server=server) return 1 return 0
def main(is_debug: bool = False, read_mode: str = 'console', read_filename: str = '', write_mode: str = 'console', write_filename: str = '', is_write_day_info: bool = False, is_write_day_operation: bool = True) -> int: # initialize r = Reader(mode=read_mode, filename=read_filename) w = Writer(is_console=True, is_file=(write_mode == 'file'), filename=write_filename) e = Environment() e.set_debug(is_debug=is_debug) # initial read DataIO.read_server_config(r=r, e=e) DataIO.read_vm_config(r=r, e=e) num_total_days, num_next_days = map(int, next(r.get_next_line).split(' ')) e.set_total_days(total_days=num_total_days) day_data_id = 0 for day_data_id in range(1, num_next_days + 1): DataIO.read_day_request(r=r, e=e, day=day_data_id) # previous actions Simulation.init(e=e) if is_write_day_info: DataIO.write_day_info_header(w=w) # main actions for day_id in range(1, num_total_days + 1): # simulate e.start_next_day() Simulation.migrate_current_day(e=e) Simulation.simulate_current_day(e=e) e.finish_current_day() # write if is_write_day_info: DataIO.write_day_info(w=w, e=e) if is_write_day_operation: DataIO.write_day_operation(w=w, e=e) # read day_data_id += 1 if day_data_id <= num_total_days: DataIO.read_day_request(r=r, e=e, day=day_data_id) # post actions return e.eval_get_accumulated_total_cost()
def simulate_current_stage(e: Environment, deploy_operations_list: List[Union[ DeploySingleVMOperation, DeployDoubleVMOperation]], **kwargs) -> None: deploy_operations_list.sort(key=lambda op: op.get_vm().get_cpu_of_one_node( ) + op.get_vm().get_memory_of_one_node(), reverse=True) for op in deploy_operations_list: vm = op.get_vm() if isinstance(op, DeploySingleVMOperation): server, node = select_running_server_for_single_vm(e=e, vm=vm) if server: e.op_deploy_single_vm(op=op, server=server, node=node) continue server, node = select_idle_server_for_single_vm(e=e, vm=vm) if server: e.op_deploy_single_vm(op=op, server=server, node=node) continue server = purchase_the_best_server(e=e, vm=vm) e.op_deploy_single_vm(op=op, server=server, node='A') elif isinstance(op, DeployDoubleVMOperation): server = select_running_server_for_double_vm(e=e, vm=vm) if server: e.op_deploy_double_vm(op=op, server=server) continue server = select_idle_server_for_double_vm(e=e, vm=vm) if server: e.op_deploy_double_vm(op=op, server=server) continue server = purchase_the_best_server(e=e, vm=vm) e.op_deploy_double_vm(op=op, server=server)
def server_config_cost(e: Environment, server_config: ServerConfig) -> float: return server_config.get_cost_purchase() + \ server_config.get_cost_everyday() * (e.get_total_days() - e.get_current_day())
def simulate_current_day(e: Environment, **kwargs) -> None: for op in e.get_current_day_info().get_request_operation_list(): vm = op.get_vm() if isinstance(op, DeploySingleVMOperation): server_config_dict = vm.get_vm_config( ).get_capable_server_type_dict() server_config = list(server_config_dict.values())[0] server = e.op_purchase_server(server_config=server_config) e.op_deploy_single_vm(op=op, server=server, node='A') elif isinstance(op, DeployDoubleVMOperation): server_config_dict = vm.get_vm_config( ).get_capable_server_type_dict() server_config = list(server_config_dict.values())[0] server = e.op_purchase_server(server_config=server_config) e.op_deploy_double_vm(op=op, server=server) elif isinstance(op, RemoveSingleVMOperation): e.op_remove_vm(op=op) elif isinstance(op, RemoveDoubleVMOperation): e.op_remove_vm(op=op)
def purchase_server(e: Environment) -> Server: server_type = random.choice(All_Capable_Server_Type_List) server_config = e.get_server_config_by_type(server_type=server_type) server = e.op_purchase_server(server_config=server_config) return server
def write_day_info(w: Writer, e: Environment) -> None: content_list = [ e.get_current_day(), '|', e.eval_get_accumulated_total_cost(), e.eval_get_accumulated_purchase_cost(), e.eval_get_accumulated_running_cost(), '|', e.get_current_day_info().eval_get_total_cost(), e.get_current_day_info().eval_get_purchase_cost(), e.get_current_day_info().eval_get_running_cost(), '|', len(e.get_deployed_vm_dict()) + len(e.get_non_deployed_vm_dict()), len(e.get_deployed_vm_dict()), len(e.get_non_deployed_vm_dict()), '|', len(e.get_deployed_server_dict()) + len(e.get_non_deployed_server_dict()), len(e.get_deployed_server_dict()), len(e.get_non_deployed_server_dict()), len(e.get_current_day_info().get_purchase_server_operation_list()), '|', e.get_current_day_info().get_num_add_vm_operation(), e.get_current_day_info().get_num_del_vm_operation(), '|', len(e.get_current_day_info().get_migrate_vm_operation_list()), '|', ] content_list = map(str, content_list) content = ','.join(content_list) w.write(content=content)
def simulate_current_day(e: Environment, **kwargs) -> None: for op in e.get_current_day_info().get_request_operation_list(): vm = op.get_vm() if isinstance(op, DeploySingleVMOperation): for server in e.get_deployed_server_dict().values(): if server.has_capacity_for_single_vm(vm=vm, node='A'): e.op_deploy_single_vm(op=op, server=server, node='A') break if server.has_capacity_for_single_vm(vm=vm, node='B'): e.op_deploy_single_vm(op=op, server=server, node='B') break if op.get_server() is None: for server in e.get_non_deployed_server_dict().values(): if server.has_capacity_for_single_vm(vm=vm, node='A'): e.op_deploy_single_vm(op=op, server=server, node='A') break if server.has_capacity_for_single_vm(vm=vm, node='B'): e.op_deploy_single_vm(op=op, server=server, node='B') break if op.get_server() is None: server = purchase_server(e=e) e.op_deploy_single_vm(op=op, server=server, node='A') elif isinstance(op, DeployDoubleVMOperation): for server in e.get_deployed_server_dict().values(): if server.has_capacity_for_double_vm(vm=vm): e.op_deploy_double_vm(op=op, server=server) break if op.get_server() is None: for server in e.get_non_deployed_server_dict().values(): if server.has_capacity_for_double_vm(vm=vm): e.op_deploy_double_vm(op=op, server=server) break if server.has_capacity_for_double_vm(vm=vm): e.op_deploy_double_vm(op=op, server=server) break if op.get_server() is None: server = purchase_server(e=e) e.op_deploy_double_vm(op=op, server=server) elif isinstance(op, RemoveSingleVMOperation): e.op_remove_vm(op=op) elif isinstance(op, RemoveDoubleVMOperation): e.op_remove_vm(op=op)