#!/usr/bin/python # # virtsched.py # # Copyright 2016 Todd Shadburn # # Licensed under the GNU GPL version 2 # from random import shuffle class VirtualMachine(object): def __init__(self, *args, **kwargs): self.vcpus = 1 self.memory = 1024000 self.timeslices = 0 self.missedslices = 0 if 'vcpus' in kwargs: self.vcpus = int(kwargs['vcpus']) return def stats(self): return (self.vcpus, self.memory, self.timeslices, self.missedslices) def get_vcpus(self): return self.vcpus def got_slice(self): self.timeslices += 1 return def missed_slice(self): self.missedslices += 1 return class VirtualHost(object): def __init__(self, *args, **kwargs): self.cores = 1 self.memory = 1024000 self.timeslices = 0 self.vms = [] # all vms on the host self.vmsrunable = [] # vms needing cpu self.vmsran = [] # vms already ran in this quanta self.vmsmissed = [] # vms missed in the preious quanta if 'cores' in kwargs: self.cores = int(kwargs['cores']) self.schedcount = [0 for i in range(self.cores+1)] return def stats(self): return (self.cores, self.memory, self.timeslices, self.schedcount) def add_vm(self, vm, *args, **kwargs): if not vm in self.vms: self.vms.append(vm) return def run_timeslice(self): c = self.cores vmlist = list(self.vms) uselist = [] misslist = [] ################################################################### # Simple scheduler (round robin, fair) # Schedule vms from the vmsrunable list # If a VM wont fit in this slice, add it to vmsmissed # When vmsrunable is empty: # If vmsmissed is not empty, move vmsmissed to vmsrunable, # else repopulate vmsrunable from vms ################################################################### # Reset runable list if needed if len(self.vmsrunable) == 0: if len(self.vmsmissed) > 0: self.vmsrunable = self.vmsmissed self.vmsmissed = [] else: self.vmsrunable = list(self.vms) self.vmsran = [] while c > 0 and len(self.vmsrunable): v = self.vmsrunable.pop(0) cc = v.get_vcpus() if c >= cc: #print 'schedule vm: vcpu=%d' %(v.vcpus) c -= cc uselist.append(v) self.vmsran.append(v) else: #print 'miss vm: vcpu=%d' %(v.vcpus) misslist.append(v) self.vmsran.append(v) self.vmsmissed.append(v) # Update timeslice data #print 'DEBUG: c=%s' % (c) self.timeslices += 1 self.schedcount[c] += 1 for v in uselist: v.got_slice() for v in misslist: v.missed_slice() return def shuffle_vms(self): # Randomly shuffle the list of vms shuffle(self.vms) return # test host = VirtualHost(cores=12) #for i in range(10): # vm = VirtualMachine(vcpus=1) # host.add_vm(vm) for i in range(10): vm = VirtualMachine(vcpus=2) host.add_vm(vm) for i in range(5): vm = VirtualMachine(vcpus=4) host.add_vm(vm) for i in range(5): vm = VirtualMachine(vcpus=8) host.add_vm(vm) for i in range(1): vm = VirtualMachine(vcpus=12) host.add_vm(vm) host.shuffle_vms() for i in range(1000000): host.run_timeslice() print host.stats() for vm in host.vms: print '%s: vcpus=%d slices=%d misses=%d' % (id(vm), vm.vcpus, vm.timeslices, vm.missedslices)