예제 #1
0
    def run(self):
        # Index for simulation time
        sim_time = self.pump.sim_time() 
        tindex = (sim_time + self.ramp_up) / self.freq
        if tindex >= (self.min_ts_length - self.ramp_down / self.freq):
            print 'Driver exited!'
            print 'Shutting down simulation...'
            self.scoreboard.close() 
            self.pump.stop()
            return
        
        # Update slot count in scoreboard
        self.scoreboard.update_slot_count()
        
        # For all nodes update their domains and aggregate the load for the node
        for host in self.model.get_hosts(model.types.NODE):
            # Reset aggregated server load
            aggregated_load = 0
            
            # Go over all domains and update their load by their TS
            for domain in host.domains.values():
                load = domain.ts[tindex]
                 
                # Notify load to the domain
                self.__notify(sim_time, domain.name, 'psutilcpu', load)
                
                # Load aggregation for the node
                aggregated_load += nodes.to_node_load(load)
                                
                # Update aggregated cpu load
                self.scoreboard.add_cpu_load(load)

            # Add hypervisor load to the aggregated load
            # For the SSAPv this causes service level violations
            aggregated_load += BASE_LOAD
            
            # Add Migration overheads
            if host.active_migrations_out: 
                aggregated_load += host.active_migrations_out * MIGRATION_SOURCE
            
            if host.active_migrations_in:
                aggregated_load += host.active_migrations_in * MIGRATION_TARGET 
            
            self.__notify(sim_time, host.name, 'psutilcpu', aggregated_load)
            
            # Update overload counter
            if aggregated_load > 100:
                self.scoreboard.add_cpu_violations(1)
                
        
        # Schedule next call for run
        self.pump.callLater(self.report_rate, self.run) 
예제 #2
0
 def migrate_underload(self, node, nodes, source, domain, time_now, sleep_time, empty):
     # Try all targets for the migration
     for target in range(nodes.index(node) - 1):
         target = nodes[target]
         
         if len(target.domains) == 0 and empty == False:
             continue
         
         test = True
         test &= (target.percentile_load(self.PERCENTILE, self.K_VALUE) + nodesv.to_node_load(domain.percentile_load(self.PERCENTILE, self.K_VALUE))) < self.THRESHOLD_OVERLOAD # Overload threshold
         test &= len(target.domains) < 6
         test &= (time_now - target.blocked) > sleep_time
         test &= (time_now - source.blocked) > sleep_time
         
         if test: 
             migration_type = 'Underload (Empty=%s)' % (empty)
             self.migration_scheduler.add(domain, source, target, description=migration_type)                          
             raise StopIteration()
예제 #3
0
 def migrate_imbalance(self, time_now, sleep_time):
     # based on DSR algorithm
     
     # create snapshot of nodes and domains
     system_nodes = self.model.get_hosts(types.NODE)
     nodes = {}
     domains = {}
     for node in system_nodes:
         node_domains = {}
         
         for domain in node.domains.values():            
             new_domain = Host()
             new_domain.name = domain.name
             new_domain.cpu = nodesv.to_node_load(domain.percentile_load(self.PERCENTILE, self.K_VALUE))
             new_domain.source = node.name
             node_domains[domain.name] = new_domain
             domains[domain.name] = new_domain
             
         new_node = Host()
         new_node.name = node.name
         new_node.cpu = node.percentile_load(self.PERCENTILE, self.K_VALUE)
         new_node.domains = node_domains
         new_node.normalized_cpu = self.normalized_cpu(new_node)
         nodes[node.name] = new_node
     
     # run load balancing    
     imbalance = self.imbalance(nodes)
     migration_triggered = False
     num_migrations = 0
     max_migrations = 10
     
     while (imbalance > self.THRESHOLD_IMBALANCE) and (num_migrations < max_migrations):
         best_migration = None
         best_improvement = 0
         
         for domain in domains.itervalues():
             # for every domain
             tmp_nodes = nodes
             
             # save parent node extra
             source = tmp_nodes[domain.source]
             source_node = self.model.get_host(source.name)
             
             if len(source.domains) == 1:
                 # don't consider domains, which are alone on one node
                 continue
       
             for node in tmp_nodes.itervalues():
                 # consider every node as new parent for domain
                 # except the same node
                 if (node.name == source_node.name):
                     continue
                 
                 # calculate new cpu
                 target_node = self.model.get_host(node.name)
                 target_domain = self.model.get_host(domain.name)
                 old_domain_cpu = domain.cpu
                 domain.cpu = nodesv.to_node_load(target_domain.percentile_load(self.PERCENTILE, self.K_VALUE))
                 target_threshold = node.cpu + domain.cpu
                 
                 # don't migrate to empty node nor full node nor if overload threshold is exceeded
                 test = False
                 test |= len(target_node.domains) == 0
                 test |= len(target_node.domains) >= 6
                 test |= target_threshold > self.THRESHOLD_OVERLOAD
                 test |= (time_now - target_node.blocked) <= sleep_time
                 test |= (time_now - source_node.blocked) <= sleep_time
                 
                 if test:
                     continue
                 
                 # migrate domain to node (in snapshot) and check new imbalance of all nodes
                 node.domains[domain.name] = domain
                 del source.domains[domain.name]
                 old_normalized_cpu_node = node.normalized_cpu
                 old_normalized_cpu_source = source.normalized_cpu
                 node.normalized_cpu = self.normalized_cpu(node)
                 source.normalized_cpu = self.normalized_cpu(source)
                 new_imbalance = self.imbalance(tmp_nodes)
                 
                 # check if imbalance is improved
                 improvement = imbalance - new_imbalance
                 if improvement > self.MIN_IMPROVEMENT_IMBALANCE and improvement > best_improvement:
                     # safe nodes and domain with MODEL information as best migration
                     best_migration = Migration()
                     best_migration.domain = target_domain
                     best_migration.source = source_node
                     best_migration.target = target_node
                     
                     # safe nodes and domain with SNAPSHOT information as best migration
                     best_source = source
                     best_target = node
                     best_domain = domain
                     best_improvement = improvement                    
                 
                 # go back to previous state in snapshot
                 domain.cpu = old_domain_cpu
                 source.domains[domain.name] = domain
                 source.normalized_cpu = old_normalized_cpu_source
                 del node.domains[domain.name]
                 node.normalized_cpu = old_normalized_cpu_node
                             
         if best_migration is None:
             break
         
         # update imbalance with best improvement
         imbalance -= best_improvement 
         
         # update migration in snapshot
         best_domain.source = best_target.name
         best_target.domains[best_domain.name] = best_domain
         best_target.normalized_cpu = self.normalized_cpu(best_target)
         del best_source.domains[best_domain.name]
         best_source.normalized_cpu = self.normalized_cpu(best_source)
         num_migrations += 1
         
         # add migration that improves imbalance the most
         self.migration_scheduler.add(best_migration.domain, best_migration.source, best_migration.target, description='Imbalance')
         migration_triggered = True 
     
     return migration_triggered
예제 #4
0
    def migrate_swap(self, time_now, sleep_time):
        ############################################
        ## HOTSPOT DETECTOR ########################
        ############################################
        for node in self.model.get_hosts(types.NODE):
            # Check past readings
            readings = node.get_readings()
            
            # m out of the k last measurements are used to detect overloads 
            k = self.K_VALUE
            overload = 0
            underload = 0
            for reading in readings[-k:]:
                if reading > self.THRESHOLD_OVERLOAD: overload += 1
                if reading < self.THRESHOLD_UNDERLOAD: underload += 1

            m = self.M_VALUE
            overload = (overload >= m)
            underload = (underload >= m)
             
            if overload:
                print 'Overload in %s - %s' % (node.name, readings[-k:])  
             
            # Update overload                                
            node.overloaded = overload
            node.underloaded = underload
            
            
        ############################################
        ## MIGRATION MANAGER #######################
        ############################################
        # Calculate volumes of each node
        nodes = []
        domains = []
        for node in self.model.get_hosts():
            volume = 1.0 / max(0.001, float(100.0 - node.percentile_load(self.PERCENTILE, k)) / 100.0)
            node.volume = volume
            node.volume_size = volume / 8.0 # 8 GByte
            
            if node.type == types.NODE:
                nodes.append(node)
            elif node.type == types.DOMAIN: 
                domains.append(node)
       
        # Sort nodes to their volume in DECREASING order
        # Multiplication with a big value to shift post comma digits to the front (integer)
        nodes.sort(lambda a, b: int((b.volume - a.volume) * 100000))
       
        
        ############################################
        ## MIGRATION TRIGGER #######################
        ############################################
        migration_triggered = False
        for node in nodes:
            node.dump()
            
            # Overload situation
            try:
                if node.overloaded:
                    # Source node to migrate from 
                    source = node
                    
                    # Sort domains by their VSR value in decreasing order 
                    node_domains = []
                    node_domains.extend(node.domains.values())
                    node_domains.sort(lambda a, b: int(b.volume_size - a.volume_size))
                    
                    # Try to migrate all domains by decreasing VSR value
                    for domain in node_domains:
                        
                        # Try all targets for swapping
                        for target_node in reversed(range(nodes.index(node) + 1, len(nodes))):
                            target_node = nodes[target_node]
                            
                            if len(target_node.domains) == 0:
                                continue
                            
                            # Sort domains of target by their VSR value in ascending order
                            target_domains = []
                            target_domains.extend(target_node.domains.values())
                            target_domains.sort(lambda a, b: int((a.volume_size - b.volume_size)))
                            
                            # Try to find one or more low VSR VMs for swapping
                            for target in range(0, len(target_domains)):
                                targets = []
                                
                                # Get one or more VMs
                                for i in range(0, target+1):
                                    targets.append(target_domains[i])                
                
                                # Calculate new loads
                                new_target_node_load = target_node.percentile_load(self.PERCENTILE, k) + nodesv.to_node_load(domain.percentile_load(self.PERCENTILE, k))
                                new_source_node_load = node.percentile_load(self.PERCENTILE, k) - nodesv.to_node_load(domain.percentile_load(self.PERCENTILE, k))
                              
                                for target_domain in targets:
                                    new_target_node_load -= nodesv.to_node_load(target_domain.percentile_load(self.PERCENTILE, self.K_VALUE))
                                    new_source_node_load += nodesv.to_node_load(target_domain.percentile_load(self.PERCENTILE, self.K_VALUE))                              
                                
                                #Test if swap violates rules
                                test = True
                                test &= new_target_node_load < self.THRESHOLD_OVERLOAD
                                test &= new_source_node_load < self.THRESHOLD_OVERLOAD 
                                test &= len(node.domains) < 6
                                test &= (time_now - target_node.blocked) > sleep_time
                                test &= (time_now - source.blocked) > sleep_time
                                
                                if test:
                                    self.migration_scheduler.add(domain, source, target_node, description='Swap Part 1')
                                    for target_domain in targets:
                                        self.migration_scheduler.add(target_domain, target_node, source, description='Swap Part 2')
                                    
                                    raise StopIteration() 
                            
            except StopIteration: 
                migration_triggered = True
                pass 
        
        return migration_triggered