def cal_cpu_cores(vnf_type, data_size, ddl, other_vnf_pro_times, ddl_type): if vnf_type.value[1] == 0: # single thread return 1 max_time = ddl - math.ceil(sum(other_vnf_pro_times)) logging.info("1: Max time left after previous procedures: " + str(max_time)) max_time -= vle.VirtualMachine.boot_time # Consider the boot time logging.info("2: Max time left after boot a VM: " + str(max_time)) max_time -= service_chain.NetworkFunction( vnf_type, 0).install_time # consider the install time of a VNF logging.info("3: Max time left after installing an instance: " + str(max_time)) max_time -= math.ceil(data_size / ni.trans_cap / ni.global_TS) # consider the egress latency logging.info("4: Max time left after transmitting to dst: " + str(max_time)) if ddl_type == 'fixed': max_time = max_time * 0.5 logging.info("MMMMax time 5: " + str(max_time)) if max_time <= 0: logging.info( "**cal_cpu_cores: Request will be blocked due to latency requirement, passed time:" + str(sum(other_vnf_pro_times)) + "DDL:" + str(ddl)) return -1 result = math.ceil(data_size / vnf_type.value[2] / (max_time * ni.global_TS)) if result <= ni.max_cpu_cores: if result == 0: result = 1 return result else: return -1
def find_nearest_vnf_in_other_zone(vnf_type, data_base, req, est_time): vms = data_base.get_vms_w_vnf(vnf_type) data_base.check_vms_at_time(vms, vnf_type, est_time[vnf_type]) short_dis = float('inf') near_vm = None for vm in vms: install_time = 0 if not vm.host_vnf(vnf_type): install_time += service_chain.NetworkFunction(vnf_type, 0).install_time process_time = math.ceil( req.data_size / (vm.cpu_cores * vnf_type.value[2]) / ni.global_TS) actual_start = vm.get_next_ava_time() if actual_start < est_time[vnf_type]: actual_start = est_time[vnf_type] pro_latency = data_base.propagation_latency(vm.location, req.dst) temp_ddl = req.deadline if req.ddl_type == data_base.tf_gen.ddl_type_list[1]: # variable ddl temp_ddl = req.deadline[1] if actual_start + process_time + install_time + math.ceil(req.data_size / ni.trans_cap / ni.global_TS) \ + pro_latency < temp_ddl + req.arr_time: if data_base.network.get_shortest_dis(req.src, vm.location) < short_dis: near_vm = vm short_dis = data_base.network.get_shortest_dis( req.src, vm.location) return near_vm
def update_vm_w_vnf(self, vnf_type, vm, data_size, start_time): vnf = service_chain.NetworkFunction(vnf_type, self.vnf_idle_length[vnf_type]) # print("SSS:", vnf.name, "IDLE Len:", vnf.idle_length) use_time = self.estimate_vm_alive_length(vnf, data_size, vm.cpu_cores) processing_time = use_time - vnf.idle_length - vnf.install_time start_process_vnf = vm.available_time if start_process_vnf < start_time: start_process_vnf = start_time # if vm has already hosted such a VNF: if not vm.host_vnf(vnf_type): self.install_vnf_to_vm(vnf, processing_time, vm, start_process_vnf + vnf.install_time) # return the value cost in the VNF, including processing time and install time return vnf.process_time, vnf.start_time # else, no need for installation else: self.install_vnf_to_vm(vnf, processing_time, vm, start_process_vnf) return vnf.process_time, vnf.start_time
def check_vms_for_vnf(vms, vnf_type, req, vnf_start_time, data_base): if not vms: return None # below is for the case that 'vms' is a vm, not a list of vms if not isinstance(vms, list): new_vms = [] new_vms.append(vms) vms = new_vms cand_vms = [] if vnf_type.value[1] == 0: # single thread for vm in vms: if vm.cpu_cores == 1: return vm else: for vm in vms: install_time = 0 # if the vm has already installed such a vnf, no installation is needed if not vm.host_vnf(vnf_type): install_time += service_chain.NetworkFunction(vnf_type, 0).install_time process_time = math.ceil(req.data_size / (vm.cpu_cores * vnf_type.value[2]) / ni.global_TS) # if the estimated start processing time of a VNF plus processing time and install time is less than the # required finish time, then the VM is possible to be qualified. But, because the actual start processing # time might be later than the value of 'est_time[vnf_type]', the actual consumed time is still longer than # the DDL requirement. To minimize the case, the transmission latency (from last VM's location to dst node) # is considered actual_start = vm.get_next_ava_time() if actual_start < vnf_start_time: actual_start = vnf_start_time pro_latency = data_base.propagation_latency(vm.location, req.dst) temp_ddl = req.deadline if req.ddl_type == data_base.tf_gen.ddl_type_list[1]: # variable temp_ddl = req.deadline[1] if actual_start + process_time + install_time + math.ceil(req.data_size / ni.trans_cap / ni.global_TS)\ + pro_latency < temp_ddl + req.arr_time: cand_vms.append(vm) final_vm = None cpu_cores = 0 for vm in cand_vms: if cpu_cores < vm.cpu_cores: cpu_cores = vm.cpu_cores final_vm = vm return final_vm
def create_vm_for_vnf(data_base, index, vnf_type, req_vnfs, req, est_time, other_vnf_pro_times, cand_dc): temp_ddl = req.deadline if req.ddl_type == data_base.tf_gen.ddl_type_list[1]: # variable temp_ddl = req.deadline[1] cpu_core = cal_cpu_cores(vnf_type, req.data_size, temp_ddl, other_vnf_pro_times, req.ddl_type) logging.info("CPU_required: " + str(cpu_core)) if cpu_core == -1: data_base.store_latency(req, float('inf')) return None if len(data_base.vms) > data_base.max_vms_online: data_base.store_latency(req, float('inf')) return None # below, is for the case that we start a VM before the data arrives it, to minimize the latency extra_time = 0 extra_time += vle.VirtualMachine.boot_time + service_chain.NetworkFunction( vnf_type, 0).install_time if extra_time >= est_time[vnf_type]: extra_time = est_time[vnf_type] (process_t, start_t, new_vm) = data_base.start_new_vm(est_time[vnf_type] - extra_time, cpu_core, cand_dc, vnf_type, req.data_size) # # if it is the first vnf, there is a propagation latency and transmission latency from the src to the vm location # if index == 0: # pro_latency = data_base.propagation_latency(req.src, ) # now, update time # print("pro:", process_t, "start_t:", start_t) if index < len(req_vnfs) - 1: next_vnf = req_vnfs[index + 1] est_time[next_vnf] = start_t + process_t other_vnf_pro_times.append(process_t + start_t - est_time[vnf_type]) elif index == len(req_vnfs) - 1: latency = start_t + process_t - req.arr_time # there are transmission latency and propagation latency from the last vm location to the dst node (trans_latency, pro_latency, fee) = data_base.internet_latency_fee(req.data_size, new_vm.location, req.dst) latency += pro_latency + trans_latency data_base.req_trans_fee[req] += fee # print("XXXX", latency) data_base.store_latency(req, latency) return new_vm
def start_new_vm(self, start_time, cpu, location, vnf_type, data_size): logging.debug("SS" + str(vnf_type) + "IDLE LENGTH:" + str(self.vnf_idle_length[vnf_type])) vnf = service_chain.NetworkFunction(vnf_type, self.vnf_idle_length[vnf_type]) use_time = self.estimate_vm_alive_length(vnf, data_size, cpu) processing_time = use_time - vnf.idle_length - vnf.install_time vm = self._start_new_vm(start_time, use_time, cpu, location) # print("XXXXXX", start_time, use_time) # print("Start a new VM:", vm) self.install_vnf_to_vm(vnf, processing_time, vm, start_time + vm.boot_time + vnf.install_time) # print(vm) # print("[VNF: " + str(vnf_type.value[0]) + ", VM: " + str(vm.index) + ", VNF processing time: " + # str(processing_time) + ", Actually total use time:" + str(use_time) + "]") timer = threading.Timer((vm.end_time - start_time) * ni.global_TS * self.tf_gen.control_factor, self._end_vm, args=(vm,)) # timer = threading.Thread(target=self._end_vm, args=(vm,)) # time.sleep((end_time - start_time) * ni.global_TS) timer.start() # t.join() # return an actual delay for the vnf, and the start process time for vnf return vnf.process_time, vnf.start_time, vm