Пример #1
0
    def loadbalance(self):
        """
		Run the loadbalancer on the cluster and migrate vm accordingly.
		See cxm.loadbalancer module for details about algorithm.
		"""
        if not core.cfg['QUIET']: print "Recording metrics..."

        current_state = {}
        vm_metrics = {}
        node_metrics = {}
        for node in self.get_nodes():
            node.metrics.init_cache(
            )  # Early call to increase timeslice used to compute rates
            vms = node.get_vms()

            # Get current cluster state
            current_state[node.get_hostname()] = [vm.name for vm in vms]

            # Get node's metrics
            node_metrics[node.get_hostname()] = {
                'ram': node.metrics.get_available_ram()
            }

            # Get VM's metrics
            cpu = node.metrics.get_vms_cpu_usage()
            io = node.metrics.get_vms_disk_io_rate()
            for vm in vms:
                vm_metrics[vm.name] = {}
                vm_metrics[vm.name]['ram'] = vm.get_ram()
                vm_metrics[vm.name]['cpu'] = cpu[vm.name]
                vm_metrics[
                    vm.name]['io'] = io[vm.name]['Read'] + io[vm.name]['Write']

        # Initialize loadbalancer
        lb = loadbalancer.LoadBalancer(current_state)
        lb.set_metrics(vm_metrics, node_metrics)
        solution = lb.get_solution()

        if not solution:
            print "No better solution found with a minimal gain of %s%%." % core.cfg[
                'LB_MIN_GAIN']
        else:
            # Ask the user for a confirmation
            if not core.cfg['QUIET']:
                print "Here is the proposed migration plan:"
                for path in solution.get_path():
                    print "  -> Migrate", path['vm'], "from", path[
                        'src'], "to", path['dst']

                if (raw_input("Proceed ? [y/N]:").upper() != "Y"):
                    print "Aborded by user."
                    return

            # Do migrations to put the cluster in the selected state
            for path in solution.get_path():
                if not core.cfg['QUIET']:
                    print "Migrating", path['vm'], "from", path[
                        'src'], "to", path['dst'], "..."
                self.migrate(path['vm'], path['src'], path['dst'])
Пример #2
0
    def loadbalance(self):
        """
		Run the loadbalancer on the cluster and migrate vm accordingly.
		See cxm.loadbalancer module for details about algorithm.
		"""
        if not core.cfg["QUIET"]:
            print "Recording metrics..."

        current_state = {}
        vm_metrics = {}
        node_metrics = {}
        for node in self.get_nodes():
            node.metrics.init_cache()  # Early call to increase timeslice used to compute rates
            vms = node.get_vms()

            # Get current cluster state
            current_state[node.get_hostname()] = [vm.name for vm in vms]

            # Get node's metrics
            node_metrics[node.get_hostname()] = {"ram": node.metrics.get_available_ram()}

            # Get VM's metrics
            cpu = node.metrics.get_vms_cpu_usage()
            io = node.metrics.get_vms_disk_io_rate()
            for vm in vms:
                vm_metrics[vm.name] = {}
                vm_metrics[vm.name]["ram"] = vm.get_ram()
                vm_metrics[vm.name]["cpu"] = cpu[vm.name]
                vm_metrics[vm.name]["io"] = io[vm.name]["Read"] + io[vm.name]["Write"]

                # Initialize loadbalancer
        lb = loadbalancer.LoadBalancer(current_state)
        lb.set_metrics(vm_metrics, node_metrics)
        solution = lb.get_solution()

        if not solution:
            print "No better solution found with a minimal gain of %s%%." % core.cfg["LB_MIN_GAIN"]
        else:
            # Ask the user for a confirmation
            if not core.cfg["QUIET"]:
                print "Here is the proposed migration plan:"
                for path in solution.get_path():
                    print "  -> Migrate", path["vm"], "from", path["src"], "to", path["dst"]

                if raw_input("Proceed ? [y/N]:").upper() != "Y":
                    print "Aborded by user."
                    return

                    # Do migrations to put the cluster in the selected state
            for path in solution.get_path():
                if not core.cfg["QUIET"]:
                    print "Migrating", path["vm"], "from", path["src"], "to", path["dst"], "..."
                self.migrate(path["vm"], path["src"], path["dst"])
Пример #3
0
def cxm_list(cluster, options):
	"""List started VM on all nodes."""
	if options.node:
		nodes=[cluster.get_node(options.node)]
	else:
		nodes=cluster.get_nodes()
	
	for node in nodes:
		print "\nOn", node.get_hostname(), ":"
		if not core.cfg['QUIET']: 
			print "-----" + "-" * len(node.get_hostname())
			print '\n    %-40s %4s  %5s  %6s' % ("Name","Mem", "VCPUs","State")
		for vm in sorted(node.get_vms(),key=lambda x: x.name):
			print '    %-40s %4d  %5d  %6s' % (vm.name, vm.ram, vm.vcpu, vm.state)
Пример #4
0
	def getList(node):
		if core.cfg['QUIET']: 
			msg = ""
			for vm in sorted(node.get_vms(),key=lambda x: x.name):
				msg += vm.name + "\n"
		else:
			# Max 80 columns wide
			msg = "\nOn %s :\n" % (node.get_hostname())
			msg += "-----" + "-" * len(node.get_hostname()) + '\n'
			msg += '\n  %-60s %4s %5s %6s\n' % ("Name","Mem", "VCPUs","State")
			for vm in sorted(node.get_vms(),key=lambda x: x.name):
				msg += '  %-60s %4d %5d %6s\n' % (vm.name, vm.ram, vm.vcpu, vm.state)

		return (node.get_hostname(), msg)
Пример #5
0
def cxm_create(cluster, vm, options):
	"""Start the specified vm.

	If options.node is not given, vm is started where an autostart link is found.
	"""

	# Check if vm is't already started somewhere
	nodes=cluster.search_vm_started(vm)
	if(len(nodes)>0):
		print "** Nothing to do :"
		print "** " + vm + " is running on "+", ".join([n.get_hostname() for n in nodes])
		sys.exit(2)

	if options.node:
		node=cluster.get_node(options.node)
	else:
		nodes=cluster.search_vm_autostart(vm)
		if(len(nodes)>1):
			print "** Warning: duplicates autostart links found on :"
			print "**  ->  " + ", ".join([n.get_hostname() for n in nodes])
			print "** Don't know where to start the VM (correct the links or use --force-node)."
			sys.exit(2)

		try:
			node=nodes[0]
		except IndexError:
			node=cluster.get_local_node()
			print "** Warning: no autostart link found. Starting VM here."
	
	if not core.cfg['QUIET'] : print "Starting",vm,"on",node.get_hostname(),"..."
	cluster.start_vm(node,vm,options.console)
Пример #6
0
    def check_bridges(self):
        """Perform a check on briges' configurations.

		Return a corresponding exit code (0=sucess, 0!=error)
		"""
        if not core.cfg["QUIET"]:
            print "Checking bridges configurations..."
        safe = True

        # Get a dict with bridges of each nodes
        nodes_bridges = dict()
        for node in self.get_nodes():
            nodes_bridges[node.get_hostname()] = node.get_bridges()

        if core.cfg["DEBUG"]:
            print "DEBUG nodes_bridges =", nodes_bridges

        # Compare bridges lists for each nodes
        missing = dict()
        for node in nodes_bridges.keys():
            for bridges in nodes_bridges.values():
                missing.setdefault(node, []).extend(list(Set(bridges) - Set(nodes_bridges[node])))

                # Show missing bridges without duplicates
        for node in missing.keys():
            if missing[node]:
                print " ** WARNING : Missing bridges on %s : %s" % (node, ", ".join(list(Set(missing[node]))))
                safe = False

        return safe
Пример #7
0
    def check_bridges(self):
        """Perform a check on briges' configurations.

		Return a corresponding exit code (0=sucess, 0!=error)
		"""
        if not core.cfg['QUIET']: print "Checking bridges configurations..."
        safe = True

        # Get a dict with bridges of each nodes
        nodes_bridges = dict()
        for node in self.get_nodes():
            nodes_bridges[node.get_hostname()] = node.get_bridges()

        if core.cfg['DEBUG']: print "DEBUG nodes_bridges =", nodes_bridges

        # Compare bridges lists for each nodes
        missing = dict()
        for node in nodes_bridges.keys():
            for bridges in nodes_bridges.values():
                missing.setdefault(node, []).extend(
                    list(Set(bridges) - Set(nodes_bridges[node])))

        # Show missing bridges without duplicates
        for node in missing.keys():
            if missing[node]:
                print " ** WARNING : Missing bridges on %s : %s" % (
                    node, ", ".join(list(Set(missing[node]))))
                safe = False

        return safe
Пример #8
0
def cxm_infos(cluster):
	"""Print the status of the cluster."""
	print '%-40s %3s  %3s  %8s  %4s' % ("Node name","VM", "IRQ","Free-RAM","Load")
	for node in cluster.get_nodes():
		metrics=node.get_metrics()
		print '%-40s %3d  %3d  %8d  %3d%%' % (node.get_hostname(),node.get_vm_started(),
			metrics.get_used_irq(),metrics.get_free_ram(),metrics.get_load())
Пример #9
0
def cxm_eject(cluster, options):
	"""Eject local node from cluster."""

	if options.node:
		node=cluster.get_node(options.node)
	else:
		node=cluster.get_local_node()

	if not core.cfg['QUIET'] : print "Ejecting all running VM from",node.get_hostname(),"..."
	cluster.emergency_eject(node)
Пример #10
0
def cxm_init(cluster, options):
	"""Initialize the cluster at startup."""

	if options.node:
		node=cluster.get_node(options.node)
	else:
		node=cluster.get_local_node()

	if not core.cfg['QUIET'] : print "Initialize cluster on",node.get_hostname(),"..."
	node.deactivate_all_lv()
Пример #11
0
def cxm_migrate(cluster, vm, dest, options):
	"""Live migrate the vm to the specified dest.

	If options.node is not given, search for the vm over the cluster.
	"""
	node=select_node_by_vm(cluster, vm, options)

	src_hostname=node.get_hostname()
	if not core.cfg['QUIET'] : print "Migrating",vm,"from",src_hostname,"to",dest,"..."
	cluster.migrate(vm, src_hostname, dest)
Пример #12
0
def cxm_shutdown(cluster, vm, options):
	"""Properly shutdown the specified VM. 

	If options.node is not given, search for the vm over the cluster.
	"""

	node=select_node_by_vm(cluster, vm, options)

	if not core.cfg['QUIET'] : print "Shutting down",vm,"on",node.get_hostname(),"..."
	node.shutdown(vm, True)
Пример #13
0
def cxm_console(cluster, vm, options):
	"""Attach local console to the given VM."""
	
	node=select_node_by_vm(cluster, vm, options)

	if node.is_local_node():
		node.get_vm(vm).attach_console()
	else:
		print "** ERROR: Cannot attach console on a remote host !"
		print "** You should try on", node.get_hostname()
Пример #14
0
def cxm_reboot(cluster, options, vm):
	"""Reboot the specified VM. 

	If options.node is not given, search for the vm over the cluster.
	"""

	vm=os.path.basename(vm)
	node=select_node_by_vm(cluster, vm, options)

	if not core.cfg['QUIET'] : print "Rebooting",vm,"on",node.get_hostname(),"..."
	node.reboot(vm)
Пример #15
0
    def start_vm(self, node, vmname, console):
        """Start the specified VM on the given node.
		If there is not enough ram on the given node, the VM will be started 
		on the node with the highest free ram and the autostart link will be updated accordingly.

		node - (Node) Selected host
		vmname - (String) VM hostname 
		console - (boolean) Attach console to the domain
		"""

        # Resources checks
        needed_ram = vm.VM(vmname).get_ram()
        free_ram = node.metrics.get_free_ram()
        if needed_ram > free_ram:
            # Not enough ram, switching to another node
            old_node = node

            # Get the node with the highest free ram (first fit increasing algorithm)
            pool = self.get_nodes()
            pool.sort(key=lambda x: x.metrics.get_free_ram(), reverse=True)
            node = pool[0]

            # Last resources checks
            free_ram = node.metrics.get_free_ram()
            if needed_ram > free_ram:
                raise ClusterNodeError(
                    node.get_hostname(),
                    ClusterNodeError.NOT_ENOUGH_RAM,
                    "need " + str(needed_ram) + "M, has " + str(free_ram) + "M.",
                )

            if not core.cfg["QUIET"]:
                print " -> Not enough ram, starting it on %s." % node.get_hostname()

            # Start the VM
        self.activate_vm(node, vmname)
        try:
            node.start_vm(vmname)
        except Exception, e:
            node.deactivate_lv(vmname)
            raise e
Пример #16
0
    def start_vm(self, node, vmname, console):
        """Start the specified VM on the given node.
		If there is not enough ram on the given node, the VM will be started 
		on the node with the highest free ram and the autostart link will be updated accordingly.

		node - (Node) Selected host
		vmname - (String) VM hostname 
		console - (boolean) Attach console to the domain
		"""

        # Resources checks
        needed_ram = vm.VM(vmname).get_ram()
        free_ram = node.metrics.get_free_ram()
        if needed_ram > free_ram:
            # Not enough ram, switching to another node
            old_node = node

            # Get the node with the highest free ram (first fit increasing algorithm)
            pool = self.get_nodes()
            pool.sort(key=lambda x: x.metrics.get_free_ram(), reverse=True)
            node = pool[0]

            # Last resources checks
            free_ram = node.metrics.get_free_ram()
            if needed_ram > free_ram:
                raise ClusterNodeError(
                    node.get_hostname(), ClusterNodeError.NOT_ENOUGH_RAM,
                    "need " + str(needed_ram) + "M, has " + str(free_ram) +
                    "M.")

            if not core.cfg['QUIET']:
                print " -> Not enough ram, starting it on %s." % node.get_hostname(
                )

        # Start the VM
        self.activate_vm(node, vmname)
        try:
            node.start_vm(vmname)
        except Exception, e:
            node.deactivate_lv(vmname)
            raise e
Пример #17
0
def cxm_deactivate(cluster, vm, options):
	"""Deactivate the logicals volumes of the specified VM.

	If options.node is not given, use local node.
	"""
	if options.node:
		node=cluster.get_node(options.node)
	else:
		node=cluster.get_local_node()

	if not core.cfg['QUIET'] : print "Deactivating LVs of",vm,"on",node.get_hostname(),"..."
	node.deactivate_lv(vm)
Пример #18
0
def cxm_activate(cluster, vm, options):	# Exclusive activation
	"""Activate the logicals volumes of the specified VM.

	If options.node is not given, activate on the local node and deactivate on all others.
	"""
	if options.node:
		node=cluster.get_node(options.node)
	else:
		node=cluster.get_local_node()
	
	if not core.cfg['QUIET'] : print "Activating LVs of",vm,"on",node.get_hostname(),"..."
	cluster.activate_vm(node,vm)
Пример #19
0
    def check(self):
        """Perform a sanity check of the cluster.

		Return a corresponding exit code (0=success, 0!=error)
		"""
        if not core.cfg["QUIET"]:
            print "Checking for duplicate VM..."
        safe = True

        # Get cluster wide VM list
        vm_by_node = dict()
        for node in self.get_nodes():
            vm_by_node[node.get_hostname()] = node.get_vms()

        if core.cfg["DEBUG"]:
            print "DEBUG vm_by_node=", vm_by_node

        # Invert key/value of the dict
        node_by_vm = dict()
        for node, vms in vm_by_node.items():
            for vm in vms:
                try:
                    node_by_vm[vm.name].append(node)
                except KeyError:
                    node_by_vm[vm.name] = [node]

        if core.cfg["DEBUG"]:
            print "DEBUG node_by_vm =", node_by_vm

        # Check duplicate VM
        for vm, nodes in node_by_vm.items():
            if len(nodes) > 1:
                print " ** WARNING : " + vm + " is running on " + " and ".join(nodes)
                safe = False

                # Check bridges
        if not self.check_bridges():
            safe = False

            # Other checks
        for node in self.get_nodes():
            # Check (non)activation of LVs
            if not node.check_lvs():
                safe = False

                # Check autostart link
            if not node.check_autostart():
                safe = False

        return safe
Пример #20
0
def cxm_destroy(cluster, vm, options):
	"""Terminate the specified VM immediately. 

	If options.node is not given, search for the vm over the cluster.
	"""

	node=select_node_by_vm(cluster, vm, options)

	if not core.cfg['QUIET']: 
		print "Destroying",vm,"on",node.get_hostname(),"..."
		if(raw_input("Are you really sure ? [y/N]:").upper() != "Y"):
			print "Aborded by user."
			return

	node.shutdown(vm, False)
Пример #21
0
    def activate_vm(self, selected_node, vmname):
        """Activate all the LVM logicals volumes of the specified VM exclusively on the selected node.

		selected_node - (Node) Node where to activate the LVs
		vmname - (String) hostname of the vm

		Raise a ClusterNodeError if the VM is running.
		"""
        for node in self.get_nodes():
            if node.is_vm_started(vmname):
                raise ClusterNodeError(node.get_hostname(), ClusterNodeError.VM_RUNNING, vmname)
            else:
                node.deactivate_lv(vmname)

        selected_node.activate_lv(vmname)
Пример #22
0
    def check(self):
        """Perform a sanity check of the cluster.

		Return a corresponding exit code (0=success, 0!=error)
		"""
        if not core.cfg['QUIET']: print "Checking for duplicate VM..."
        safe = True

        # Get cluster wide VM list
        vm_by_node = dict()
        for node in self.get_nodes():
            vm_by_node[node.get_hostname()] = node.get_vms()

        if core.cfg['DEBUG']: print "DEBUG vm_by_node=", vm_by_node

        # Invert key/value of the dict
        node_by_vm = dict()
        for node, vms in vm_by_node.items():
            for vm in vms:
                try:
                    node_by_vm[vm.name].append(node)
                except KeyError:
                    node_by_vm[vm.name] = [node]

        if core.cfg['DEBUG']: print "DEBUG node_by_vm =", node_by_vm

        # Check duplicate VM
        for vm, nodes in node_by_vm.items():
            if len(nodes) > 1:
                print " ** WARNING : " + vm + " is running on " + " and ".join(
                    nodes)
                safe = False

        # Check bridges
        if not self.check_bridges():
            safe = False

        # Other checks
        for node in self.get_nodes():
            # Check (non)activation of LVs
            if not node.check_lvs():
                safe = False

            # Check autostart link
            if not node.check_autostart():
                safe = False

        return safe
Пример #23
0
    def activate_vm(self, selected_node, vmname):
        """Activate all the LVM logicals volumes of the specified VM exclusively on the selected node.

		selected_node - (Node) Node where to activate the LVs
		vmname - (String) hostname of the vm

		Raise a ClusterNodeError if the VM is running.
		"""
        for node in self.get_nodes():
            if node.is_vm_started(vmname):
                raise ClusterNodeError(node.get_hostname(),
                                       ClusterNodeError.VM_RUNNING, vmname)
            else:
                node.deactivate_lv(vmname)

        selected_node.activate_lv(vmname)
Пример #24
0
def cxm_migrate(cluster, options, vm, dst):
	"""Live migrate the vm to the specified dest.

	If options.node is not given, search for the vm over the cluster.
	"""

	vm=os.path.basename(vm)
	node=select_node_by_vm(cluster, vm, options)

	src=node.get_hostname()
	
	if src == dst:
		if not core.cfg['QUIET']: print "Nothing to do, %s is already on %s." % (vm,dst)
	else:	
		if not core.cfg['QUIET'] : print "Migrating %s from %s to %s..." % (vm,src,dst)
		cluster.migrate(vm, src, dst)
Пример #25
0
	def getNodeMetrics(node):
		metrics=node.get_metrics()
		return '%-40s %3d  %3d  %8d  %3d%%' % (node.get_hostname(),node.get_vm_started(),
			metrics.get_used_irq(),metrics.get_free_ram(),metrics.get_load())