Esempio n. 1
0
def greedy_least_batch():
    """ Maintenance strategy proposed in [1]. It is designed to
    minimize the number of maintenance steps necessary to update
    the data center.

    References
    ==========
    [1] Zheng, Zeyu, et al. "Least maintenance batch scheduling in cloud
    data center networks." IEEE communications letters 18.6 (2014): 901-904.
    """

    # Patching servers nonupdated servers that are not hosting VMs
    servers_to_patch = Server.ready_to_patch()
    if len(servers_to_patch) > 0:
        servers_patch_duration = []

        for server in servers_to_patch:
            patch_duration = server.update()
            servers_patch_duration.append(patch_duration)

        # As servers are updated simultaneously, we don't need to call the function
        # that quantifies the server maintenance duration for each server being patched
        yield SimulationEnvironment.first().env.timeout(max(servers_patch_duration))


    # Migrating VMs
    else:
        servers_being_emptied = []

        # Sorts the servers to empty based on their occupation rate (ascending)
        servers_to_empty = sorted(Server.nonupdated(), key=lambda sv: sv.occupation_rate())

        for server in servers_to_empty:
            # We consider as candidate hosts for the VMs every server
            # not being emptied in the current iteration
            candidate_servers = [cand_server for cand_server in Server.all()
                if cand_server not in servers_being_emptied and cand_server != server]

            vms = [vm for vm in server.virtual_machines]

            if Server.can_host_vms(candidate_servers, vms):
                for _ in range(len(server.virtual_machines)):
                    vm = vms.pop(0)

                    # Sorting servers by update status (updated ones first) and demand (more occupied ones first)
                    candidate_servers = sorted(candidate_servers, key=lambda cand_server:
                        (-cand_server.updated, -cand_server.occupation_rate()))

                    # Using a First-Fit strategy to select a candidate host for each VM
                    for cand_server in candidate_servers:
                        if cand_server.has_capacity_to_host(vm):
                            yield SimulationEnvironment.first().env.timeout(vm.migrate(cand_server))
                            break

            if len(server.virtual_machines) == 0:
                servers_being_emptied.append(server)
def worst_fit_like():
    """
    Worst-Fit-like maintenance strategy (presented by Severo et al.)
    ====================================================================
    Note: We use the term "empty" to refer to servers that are not hosting VMs.

    The maintenance process is divided in two tasks:
    (i) Patching empty servers (lines 25-35)
    (ii) Migrating VMs to empty more servers (lines 40-72)

    When choosing which servers will host the VMs, this
    strategy uses the Worst-Fit Decreasing heuristic.
    """

    # Patching servers nonupdated servers that are not hosting VMs
    servers_to_patch = Server.ready_to_patch()
    if len(servers_to_patch) > 0:
        servers_patch_duration = []

        for server in servers_to_patch:
            patch_duration = server.update()
            servers_patch_duration.append(patch_duration)

        # As servers are updated simultaneously, we don't need to call the function
        # that quantifies the server maintenance duration for each server being patched
        yield SimulationEnvironment.first().env.timeout(
            max(servers_patch_duration))

    # (ii) Migrating VMs to empty more servers
    else:
        servers_being_emptied = []

        # Getting the list of servers that still need to receive the patch
        servers_to_empty = Server.nonupdated()

        for server in servers_to_empty:
            # We consider as candidate hosts for the VMs all Server
            # objects not being emptied in the current maintenance step
            candidate_servers = [
                cand_server for cand_server in Server.all()
                if cand_server not in servers_being_emptied
                and cand_server != server
            ]

            # Sorting VMs by its demand (decreasing)
            vms = [vm for vm in server.virtual_machines]
            vms = sorted(vms, key=lambda vm: -vm.demand())

            for _ in range(len(server.virtual_machines)):
                vm = vms.pop(0)

                # Sorting servers (bins) to align with Worst-Fit's idea,
                # which is prioritizing servers with less space remaining
                candidate_servers = sorted(
                    candidate_servers, key=lambda cand: cand.occupation_rate())

                # Migrating VMs using the Worst-Fit heuristic
                for cand_server in candidate_servers:
                    if cand_server.has_capacity_to_host(vm):
                        # Migrating the VM and storing the migration duration to allow future analysis
                        yield SimulationEnvironment.first().env.timeout(
                            vm.migrate(cand_server))
                        break

            if len(server.virtual_machines) == 0:
                servers_being_emptied.append(server)
Esempio n. 3
0
def first_fit(env, maintenance_data):
    """
    First-Fit like maintenance strategy (presented by Severo et al. 2020)
    ====================================================================
    Note: We use the term "empty" to refer to servers that are not hosting VMs.

    The maintenance process is divided in two tasks:
    (i) Patching empty servers (lines 29-36)
    (ii) Migrating VMs to empty more servers (lines 40-73)

    When choosing which servers will host the VMs, this strategy uses the First-Fit heuristic.

    Parameters
    ==========
    env : SimPy.Environment
        Used to quantity the amount of simulation time spent by the migration

    maintenance_data : List
        Object that will be filled during the maintenance, storing metrics on each maintenance step
    """

    while len(Server.nonupdated()) > 0:
        # (i) Patching servers nonupdated servers that are not hosting VMs (lines 30-37)
        servers_to_patch = Server.ready_to_patch()
        if len(servers_to_patch) > 0:
            for server in servers_to_patch:
                server.updated = True

            # As servers are updated simultaneously, we don't need to call the function
            # that quantifies the server maintenance duration for each server being patched
            yield env.process(server_update(env, constants.PATCHING_TIME))

        # (ii) Migrating VMs to empty more servers (lines 41-74)

        servers_being_emptied = []

        # Getting the list of servers that still need to receive the patch
        servers_to_empty = Server.nonupdated()
        migrations_data = [
        ]  # Stores data on the migrations performed to allow future analysis

        for server in servers_to_empty:

            candidate_servers = [
                cand_server for cand_server in Server.all()
                if cand_server != server
                and cand_server not in servers_being_emptied
            ]

            vms_to_migrate = len(server.virtual_machines)
            servers_checked = 0

            while len(server.virtual_machines
                      ) > 0 and servers_checked <= vms_to_migrate * len(
                          candidate_servers):

                vm = server.virtual_machines[0]

                # Migrating VMs using the First-Fit heuristic, which suggests the
                # migration of VMs to the first server that has resources to host it
                for cand_server in candidate_servers:
                    servers_checked += 1
                    if cand_server.has_capacity_to_host(vm):

                        # Migrating the VM and storing the migration duration to allow future analysis
                        migration_duration = yield env.process(
                            vm.migrate(env, cand_server))

                        migrations_data.append({
                            'origin': server,
                            'destination': cand_server,
                            'vm': vm,
                            'duration': migration_duration
                        })

                        break

            if len(server.virtual_machines) == 0:
                servers_being_emptied.append(server)

        # Collecting metrics gathered in the current maintenance step (i.e., outer while loop iteration)
        maintenance_data.append(
            collect_metrics(env, 'First-Fit', servers_to_patch,
                            servers_being_emptied, migrations_data))
Esempio n. 4
0
def vulnerability_surface(env, maintenance_data):
    """
    Maintenance strategy proposed by Severo et al. 2020
    ===================================================
    Note: We use the term "empty" to refer to servers that are not hosting VMs

    When choosing which servers to empty, this heuristic prioritizes servers that
    take less time to be emptied, which can be achieved by having a small number
    of VMs or by hosting small VMs (that will take a negligible time to be migrated).

    The maintenance process is divided in two tasks:
    (i) Patching empty servers (lines 31-38)
    (ii) Migrating VMs to empty more servers (lines 42-90)

    Parameters
    ==========
    env : SimPy.Environment
        Used to quantity the amount of simulation time spent by the migration

    maintenance_data : List
        Object that will be filled during the maintenance, storing metrics on each maintenance step
    """

    while len(Server.nonupdated()) > 0:
        # Patching servers nonupdated servers that are not hosting VMs
        servers_to_patch = Server.ready_to_patch()
        if len(servers_to_patch) > 0:
            for server in servers_to_patch:
                server.updated = True

            # As servers are updated simultaneously, we don't need to call the function
            # that quantifies the server maintenance duration for each server being patched
            yield env.process(server_update(env, constants.PATCHING_TIME))

        # Migrating VMs

        servers_being_emptied = []

        # Sorts the servers to empty based on its update score. This score considers
        # the amount of time needed to migrate all VMs hosted by the server
        servers_to_empty = sorted(
            Server.nonupdated(),
            key=lambda cand_server: cand_server.update_cost())

        migrations_data = [
        ]  # Stores data on the migrations performed to allow future analysis

        for server in servers_to_empty:

            vms_to_migrate = len(server.virtual_machines)
            servers_checked = 0

            # We consider as candidate hosts for the VMs every server
            # not being emptied in the current iteration
            candidate_servers = [
                cand_server for cand_server in Server.all()
                if cand_server not in servers_being_emptied
                and cand_server != server
            ]

            while len(server.virtual_machines
                      ) > 0 and servers_checked < vms_to_migrate * len(
                          candidate_servers):
                # Sorting VMs by its demand (decreasing)
                vms = sorted(
                    server.virtual_machines,
                    key=lambda vm:
                    (-vm.cpu_demand, -vm.memory_demand, -vm.disk_demand))

                vm = server.virtual_machines[0]

                # Sorting servers by update status (updated ones first) and demand (decreasing)
                candidate_servers = sorted(
                    candidate_servers,
                    key=lambda cand_server:
                    (-cand_server.updated, -cand_server.cpu_demand,
                     -cand_server.memory_demand, -cand_server.disk_demand))

                if Server.can_host_vms(candidate_servers, vms):
                    # Using a First-Fit Decreasing strategy to select a candidate host for each VM
                    for cand_server in candidate_servers:
                        servers_checked += 1
                        if cand_server.has_capacity_to_host(vm):

                            # Migrating the VM and storing the migration duration to allow future analysis
                            migration_duration = yield env.process(
                                vm.migrate(env, cand_server))

                            migrations_data.append({
                                'origin':
                                server,
                                'destination':
                                cand_server,
                                'vm':
                                vm,
                                'duration':
                                migration_duration
                            })

                            break
                else:
                    break

            if len(server.virtual_machines) == 0:
                servers_being_emptied.append(server)

        # Collecting metrics gathered in the current maintenance step (i.e., outer while loop iteration)
        maintenance_data.append(
            collect_metrics(env, 'VS Heuristic', servers_to_patch,
                            servers_being_emptied, migrations_data))
Esempio n. 5
0
def salus():
    """ Salus is the Roman goddess of safety. This maintenance
    strategy was proposed by Severo et al. in 2020.
    
    Note: We use the term "empty" to refer to servers that are not hosting VMs

    When choosing which servers to empty, this heuristic prioritizes servers with
    a smaller update cost, which takes into account multiple factors such as server
    capacity and server's patch duration.

    The maintenance process is divided in two tasks:
    (i) Patching empty servers (lines 28-36)
    (ii) Migrating VMs to empty more servers (lines 41-74)
    """

    # Patching servers nonupdated servers that are not hosting VMs
    servers_to_patch = Server.ready_to_patch()
    if len(servers_to_patch) > 0:
        servers_patch_duration = []

        for server in servers_to_patch:
            patch_duration = server.update()
            servers_patch_duration.append(patch_duration)

        # As servers are updated simultaneously, we don't need to call the function
        # that quantifies the server maintenance duration for each server being patched
        yield SimulationEnvironment.first().env.timeout(max(servers_patch_duration))


    # Migrating VMs
    else:
        servers_being_emptied = []

        # Sorts the servers to empty based on its update score. This score considers the amount of time
        # needed to update the server (including VM migrations to draining the server) and its capacity
        servers_to_empty = sorted(Server.nonupdated(), key=lambda sv:
            (sv.maintenance_duration() * (1/(sv.capacity()+1))) ** (1/2))


        for server in servers_to_empty:
            # We consider as candidate hosts for the VMs all Server
            # objects not being emptied in the current maintenance step
            candidate_servers = [cand_server for cand_server in Server.all()
                if cand_server not in servers_being_emptied and cand_server != server]

            # Sorting VMs by its demand (decreasing)
            vms = [vm for vm in server.virtual_machines]
            vms = sorted(vms, key=lambda vm: -vm.demand())

            if Server.can_host_vms(candidate_servers, vms):
                for _ in range(len(server.virtual_machines)):
                    vm = vms.pop(0)

                    # Sorting servers by update status (updated ones first) and demand (decreasing)
                    candidate_servers = sorted(candidate_servers, key=lambda sv:
                        (-sv.updated, -sv.occupation_rate()))

                    # Using a Best-Fit Decreasing strategy to select a candidate host for each VM
                    for cand_server in candidate_servers:
                        if cand_server.has_capacity_to_host(vm):
                            yield SimulationEnvironment.first().env.timeout(vm.migrate(cand_server))
                            break

            if len(server.virtual_machines) == 0:
                servers_being_emptied.append(server)