def stress_cpu(filter: str = None,
               duration: int = 120,
               timeout: int = 60,
               instance_criteria: Iterable[Mapping[str, any]] = None,
               configuration: Configuration = None,
               secrets: Secrets = None):
    """
    Stresses the CPU of a random VMSS instances in your selected VMSS.
    Similar to the stress_cpu action of the machine.actions module.

    Parameters
    ----------
    filter : str, optional
        Filter the VMSS. If the filter is omitted all VMSS in
        the subscription will be selected as potential chaos candidates.
    duration : int, optional
        Duration of the stress test (in seconds) that generates high CPU usage.
        Defaults to 120 seconds.
    timeout : int
        Additional wait time (in seconds) for stress operation to be completed.
        Getting and sending data from/to Azure may take some time so it's not
        recommended to set this value to less than 30s. Defaults to 60 seconds.
    """
    logger.debug(
        "Starting stress_vmss_instance_cpu:"
        " configuration='{}', filter='{}',"
        " duration='{}', timeout='{}'".format(
            configuration, filter, duration, timeout))

    vmss_records = Records()
    vmss = fetch_vmss(filter, configuration, secrets)
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            command_id, script_content = command.prepare(instance,
                                                         'cpu_stress_test')
            parameters = {
                'command_id': command_id,
                'script': [script_content],
                'parameters': [
                    {'name': "duration", 'value': duration}
                ]
            }

            logger.debug(
                "Stressing CPU of VMSS instance: '{}'".format(
                    instance['instance_id']))
            _timeout = duration + timeout
            command.run(
                scale_set['resourceGroup'], instance, _timeout, parameters,
                secrets, configuration)
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #2
0
def stop_vmss(filter: str = None,
              instance_criteria: Iterable[Mapping[str, any]] = None,
              configuration: Configuration = None,
              secrets: Secrets = None):
    """
    Stops instances from the filtered scale set either at random or by
     a defined instance criteria.
     Parameters
    ----------
    filter : str
        Filter the virtual machine scale set. If the filter is omitted all
        virtual machine scale sets in the subscription will be selected as
        potential chaos candidates.
        Filtering example:
        'where resourceGroup=="myresourcegroup" and name="myresourcename"'
    instance_criteria :  Iterable[Mapping[str, any]]
        Allows specification of criteria for selection of a given virtual
        machine scale set instance. If the instance_criteria is omitted,
        an instance will be chosen at random. All of the criteria within each
        item of the Iterable must match, i.e. AND logic is applied.
        The first item with all matching criterion will be used to select the
        instance.
        Criteria example:
        [
         {"name": "myVMSSInstance1"},
         {
          "name": "myVMSSInstance2",
          "instanceId": "2"
         }
         {"instanceId": "3"},
        ]
        If the instances include two items. One with name = myVMSSInstance4
        and instanceId = 2. The other with name = myVMSSInstance2 and
        instanceId = 3. The criteria {"instanceId": "3"} will be the first
        match since both the name and the instanceId did not match on the
        first criteria.
    """
    logger.debug("Starting stop_vmss: configuration='{}', filter='{}'".format(
        configuration, filter))

    vmss = fetch_vmss(filter, configuration, secrets)
    vmss_records = Records()
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            logger.debug("Stopping instance: {}".format(instance['name']))
            client = init_compute_management_client(secrets, configuration)
            client.virtual_machine_scale_set_vms.power_off(
                scale_set['resourceGroup'], scale_set['name'],
                instance['instance_id'])
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #3
0
def network_latency(filter: str = None,
                    duration: int = 60,
                    delay: int = 200,
                    jitter: int = 50,
                    timeout: int = 60,
                    instance_criteria: Iterable[Mapping[str, any]] = None,
                    configuration: Configuration = None,
                    secrets: Secrets = None):
    """
    Increases the response time of the virtual machine. Similar to
    the network_latency action of the machine.actions module.
    """
    logger.debug(
        "Starting network_latency: configuration='{}', filter='{}',"
        " duration='{}', delay='{}', jitter='{}', timeout='{}'".format(
            configuration, filter, duration, delay, jitter, timeout))

    vmss = fetch_vmss(filter, configuration, secrets)
    vmss_records = Records()
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            command_id, script_content = command.prepare(
                instance, 'network_latency')
            parameters = {
                'command_id':
                command_id,
                'script': [script_content],
                'parameters': [{
                    'name': "duration",
                    'value': duration
                }, {
                    'name': "delay",
                    'value': delay
                }, {
                    'name': "jitter",
                    'value': jitter
                }]
            }

            logger.debug(
                "Increasing the latency of VMSS instance: '{}'".format(
                    instance['name']))
            _timeout = duration + timeout
            command.run(scale_set['resourceGroup'], instance, _timeout,
                        parameters, secrets, configuration)
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #4
0
def fill_disk(filter: str = None,
              duration: int = 120,
              timeout: int = 60,
              size: int = 1000,
              path: str = None,
              instance_criteria: Iterable[Mapping[str, any]] = None,
              configuration: Configuration = None,
              secrets: Secrets = None):
    """
    Fill the VMSS machine disk with random data. Similar to
    the fill_disk action of the machine.actions module.
    """
    logger.debug("Starting fill_disk: configuration='{}', filter='{}',"
                 " duration='{}', size='{}', path='{}', timeout='{}'".format(
                     configuration, filter, duration, size, path, timeout))

    vmss = fetch_vmss(filter, configuration, secrets)
    vmss_records = Records()
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            command_id, script_content = command.prepare(instance, 'fill_disk')
            fill_path = command.prepare_path(instance, path)

            parameters = {
                'command_id':
                command_id,
                'script': [script_content],
                'parameters': [{
                    'name': "duration",
                    'value': duration
                }, {
                    'name': "size",
                    'value': size
                }, {
                    'name': "path",
                    'value': fill_path
                }]
            }

            logger.debug("Filling disk of VMSS instance: '{}'".format(
                instance['name']))
            _timeout = duration + timeout
            command.run(scale_set['resourceGroup'], instance, _timeout,
                        parameters, secrets, configuration)
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #5
0
def delete_machines(filter: str = None,
                    configuration: Configuration = None,
                    secrets: Secrets = None):
    """
    Delete virtual machines at random.

    **Be aware**: Deleting a machine is an invasive action. You will not be
    able to recover the machine once you deleted it.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.

    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> delete_machines("where resourceGroup=='rg'", c, s)
    Delete all machines from the group 'rg'

    >>> delete_machines("where resourceGroup=='rg' and name='name'", c, s)
    Delete the machine from the group 'rg' having the name 'name'

    >>> delete_machines("where resourceGroup=='rg' | sample 2", c, s)
    Delete two machines at random from the group 'rg'
    """
    logger.debug("Start delete_machines: "
                 "configuration='{}', filter='{}'".format(
                     configuration, filter))

    machines = __fetch_machines(filter, configuration, secrets)
    client = __compute_mgmt_client(secrets, configuration)
    machine_records = Records()
    for m in machines:
        group = m['resourceGroup']
        name = m['name']
        logger.debug("Deleting machine: {}".format(name))
        client.virtual_machines.delete(group, name)
        machine_records.add(cleanse.machine(m))

    return machine_records.output_as_dict('resources')
Example #6
0
def start_machines(filter: str = None,
                   configuration: Configuration = None,
                   secrets: Secrets = None):
    """
    Start virtual machines at random. Thought as a rollback action.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.

    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> start_machines("where resourceGroup=='rg'", c, s)
    Start all stopped machines from the group 'rg'

    >>> start_machines("where resourceGroup=='rg' and name='name'", c, s)
    Start the stopped machine from the group 'rg' having the name 'name'

    >>> start_machines("where resourceGroup=='rg' | sample 2", c, s)
    Start two stopped machines at random from the group 'rg'
    """

    logger.debug(
        "Start start_machines: configuration='{}', filter='{}'".format(
            configuration, filter))

    machines = __fetch_machines(filter, configuration, secrets)
    client = __compute_mgmt_client(secrets, configuration)
    stopped_machines = __fetch_all_stopped_machines(client, machines)

    machine_records = Records()
    for machine in stopped_machines:
        logger.debug("Starting machine: {}".format(machine['name']))
        client.virtual_machines.start(machine['resourceGroup'],
                                      machine['name'])

        machine_records.add(cleanse.machine(machine))

    return machine_records.output_as_dict('resources')
def delete_vmss(filter: str = None,
                instance_criteria: Iterable[Mapping[str, any]] = None,
                configuration: Configuration = None,
                secrets: Secrets = None):
    """
    Delete a virtual machine scale set instance at random.

    **Be aware**: Deleting a VMSS instance is an invasive action. You will not
    be able to recover the VMSS instance once you deleted it.

     Parameters
    ----------
    filter : str
        Filter the virtual machine scale set. If the filter is omitted all
        virtual machine scale sets in the subscription will be selected as
        potential chaos candidates.
        Filtering example:
        'where resourceGroup=="myresourcegroup" and name="myresourcename"'
    """
    logger.debug(
        "Starting delete_vmss: configuration='{}', filter='{}'".format(
            configuration, filter))

    vmss = fetch_vmss(filter, configuration, secrets)
    vmss_records = Records()
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            logger.debug(
                "Deleting instance: {}".format(instance['name']))
            client = init_compute_management_client(secrets, configuration)
            client.virtual_machine_scale_set_vms.begin_delete(
                scale_set['resourceGroup'],
                scale_set['name'],
                instance['instance_id'])
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #8
0
def burn_io(filter: str = None,
            duration: int = 60,
            timeout: int = 60,
            instance_criteria: Iterable[Mapping[str, any]] = None,
            configuration: Configuration = None,
            secrets: Secrets = None):
    """
    Increases the Disk I/O operations per second of the VMSS machine.
    Similar to the burn_io action of the machine.actions module.
    """
    logger.debug(
        "Starting burn_io: configuration='{}', filter='{}', duration='{}',"
        " timeout='{}'".format(configuration, filter, duration, timeout))

    vmss = fetch_vmss(filter, configuration, secrets)
    vmss_records = Records()
    for scale_set in vmss:
        instances_records = Records()
        instances = fetch_instances(scale_set, instance_criteria,
                                    configuration, secrets)

        for instance in instances:
            command_id, script_content = command.prepare(instance, 'burn_io')
            parameters = {
                'command_id': command_id,
                'script': [script_content],
                'parameters': [{
                    'name': "duration",
                    'value': duration
                }]
            }

            logger.debug("Burning IO of VMSS instance: '{}'".format(
                instance['name']))
            _timeout = duration + timeout
            command.run(scale_set['resourceGroup'], instance, _timeout,
                        parameters, secrets, configuration)
            instances_records.add(cleanse.vmss_instance(instance))

        scale_set['virtualMachines'] = instances_records.output()
        vmss_records.add(cleanse.vmss(scale_set))

    return vmss_records.output_as_dict('resources')
Example #9
0
def stop_machines(filter: str = None,
                  configuration: Configuration = None,
                  secrets: Secrets = None):
    """
    Stop virtual machines at random.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.

    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> stop_machines("where resourceGroup=='rg'", c, s)
    Stop all machines from the group 'rg'

    >>> stop_machines("where resourceGroup=='mygroup' and name='myname'", c, s)
    Stop the machine from the group 'mygroup' having the name 'myname'

    >>> stop_machines("where resourceGroup=='mygroup' | sample 2", c, s)
    Stop two machines at random from the group 'mygroup'
    """
    logger.debug("Start stop_machines: "
                 "configuration='{}', filter='{}'".format(
                     configuration, filter))

    machines = __fetch_machines(filter, configuration, secrets)
    client = __compute_mgmt_client(secrets, configuration)

    machine_records = Records()
    for m in machines:
        group = m['resourceGroup']
        name = m['name']
        logger.debug("Stopping machine: {}".format(name))
        client.virtual_machines.power_off(group, name)
        machine_records.add(cleanse.machine(m))

    return machine_records.output_as_dict('resources')
Example #10
0
def burn_io(filter: str = None,
            duration: int = 60,
            timeout: int = 60,
            configuration: Configuration = None,
            secrets: Secrets = None):
    """
    Increases the Disk I/O operations per second of the virtual machine.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.
    duration : int, optional
        How long the burn lasts. Defaults to 60 seconds.
    timeout : int
        Additional wait time (in seconds) for filling operation to be completed
        Getting and sending data from/to Azure may take some time so it's not
        recommended to set this value to less than 30s. Defaults to 60 seconds.


    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> burn_io("where resourceGroup=='rg'", configuration=c, secrets=s)
    Increase the I/O operations per second of all machines from the group 'rg'

    >>> burn_io("where resourceGroup=='rg' and name='name'",
                    configuration=c, secrets=s)
    Increase the I/O operations per second of the machine from the group 'rg'
    having the name 'name'

    >>> burn_io("where resourceGroup=='rg' | sample 2",
                    configuration=c, secrets=s)
    Increase the I/O operations per second of two machines at random from
    the group 'rg'
    """

    msg = "Starting burn_io: configuration='{}', filter='{}', duration='{}'," \
          " timeout='{}'".format(configuration, filter, duration, timeout)
    logger.debug(msg)

    machines = __fetch_machines(filter, configuration, secrets)

    machine_records = Records()
    for machine in machines:
        command_id, script_content = command.prepare(machine, 'burn_io')

        parameters = {
            'command_id': command_id,
            'script': [script_content],
            'parameters': [{
                'name': "duration",
                'value': duration
            }]
        }

        logger.debug("Burning IO of machine: '{}'".format(machine['name']))
        _timeout = duration + timeout
        command.run(machine['resourceGroup'], machine, _timeout, parameters,
                    secrets, configuration)
        machine_records.add(cleanse.machine(machine))

    return machine_records.output_as_dict('resources')
Example #11
0
def network_latency(filter: str = None,
                    duration: int = 60,
                    delay: int = 200,
                    jitter: int = 50,
                    timeout: int = 60,
                    configuration: Configuration = None,
                    secrets: Secrets = None):
    """
    Increases the response time of the virtual machine.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.
    duration : int, optional
        How long the latency lasts. Defaults to 60 seconds.
    timeout : int
        Additional wait time (in seconds) for filling operation to be completed
        Getting and sending data from/to Azure may take some time so it's not
        recommended to set this value to less than 30s. Defaults to 60 seconds.
    delay : int
        Added delay in ms. Defaults to 200.
    jitter : int
        Variance of the delay in ms. Defaults to 50.


    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> network_latency("where resourceGroup=='rg'", configuration=c,
                    secrets=s)
    Increase the latency of all machines from the group 'rg'

    >>> network_latency("where resourceGroup=='rg' and name='name'",
                    configuration=c, secrets=s)
    Increase the latecy of the machine from the group 'rg' having the name
    'name'

    >>> network_latency("where resourceGroup=='rg' | sample 2",
                    configuration=c, secrets=s)
    Increase the latency of two machines at random from the group 'rg'
    """

    logger.debug(
        "Start network_latency: configuration='{}', filter='{}'".format(
            configuration, filter))

    machines = __fetch_machines(filter, configuration, secrets)

    machine_records = Records()
    for machine in machines:
        command_id, script_content = command \
            .prepare(machine, 'network_latency')

        logger.debug("Script content: {}".format(script_content))
        parameters = {
            'command_id':
            command_id,
            'script': [script_content],
            'parameters': [{
                'name': "duration",
                'value': duration
            }, {
                'name': "delay",
                'value': delay
            }, {
                'name': "jitter",
                'value': jitter
            }]
        }

        logger.debug("Increasing the latency of machine: {}".format(
            machine['name']))
        _timeout = duration + timeout
        command.run(machine['resourceGroup'], machine, _timeout, parameters,
                    secrets, configuration)
        machine_records.add(cleanse.machine(machine))

    return machine_records.output_as_dict('resources')
Example #12
0
def fill_disk(filter: str = None,
              duration: int = 120,
              timeout: int = 60,
              size: int = 1000,
              path: str = None,
              configuration: Configuration = None,
              secrets: Secrets = None):
    """
    Fill the disk with random data.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.
    duration : int, optional
        Lifetime of the file created. Defaults to 120 seconds.
    timeout : int
        Additional wait time (in seconds)
        for filling operation to be completed.
        Getting and sending data from/to Azure may take some time so it's not
        recommended to set this value to less than 30s. Defaults to 60 seconds.
    size : int
        Size of the file created on the disk. Defaults to 1GB.
    path : str, optional
        The absolute path to write the fill file into.
        Defaults: C:/burn for Windows clients, /root/burn for Linux clients.


    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> fill_disk("where resourceGroup=='rg'", configuration=c, secrets=s)
    Fill all machines from the group 'rg'

    >>> fill_disk("where resourceGroup=='rg' and name='name'",
                    configuration=c, secrets=s)
    Fill the machine from the group 'rg' having the name 'name'

    >>> fill_disk("where resourceGroup=='rg' | sample 2",
                    configuration=c, secrets=s)
    Fill two machines at random from the group 'rg'
    """

    msg = "Starting fill_disk: configuration='{}', filter='{}'," \
          " duration='{}', size='{}', path='{}', timeout='{}'" \
        .format(configuration, filter, duration, size, path, timeout)
    logger.debug(msg)

    machines = __fetch_machines(filter, configuration, secrets)

    machine_records = Records()
    for machine in machines:
        command_id, script_content = command.prepare(machine, 'fill_disk')
        fill_path = command.prepare_path(machine, path)

        parameters = {
            'command_id':
            command_id,
            'script': [script_content],
            'parameters': [{
                'name': "duration",
                'value': duration
            }, {
                'name': "size",
                'value': size
            }, {
                'name': "path",
                'value': fill_path
            }]
        }

        logger.debug("Filling disk of machine: {}".format(machine['name']))
        _timeout = duration + timeout
        command.run(machine['resourceGroup'], machine, _timeout, parameters,
                    secrets, configuration)
        machine_records.add(cleanse.machine(machine))

    return machine_records.output_as_dict('resources')
Example #13
0
def stress_cpu(filter: str = None,
               duration: int = 120,
               timeout: int = 60,
               configuration: Configuration = None,
               secrets: Secrets = None):
    """
    Stress CPU up to 100% at virtual machines.

    Parameters
    ----------
    filter : str, optional
        Filter the virtual machines. If the filter is omitted all machines in
        the subscription will be selected as potential chaos candidates.
    duration : int, optional
        Duration of the stress test (in seconds) that generates high CPU usage.
        Defaults to 120 seconds.
    timeout : int
        Additional wait time (in seconds) for stress operation to be completed.
        Getting and sending data from/to Azure may take some time so it's not
        recommended to set this value to less than 30s. Defaults to 60 seconds.

    Examples
    --------
    Some calling examples. Deep dive into the filter syntax:
    https://docs.microsoft.com/en-us/azure/kusto/query/

    >>> stress_cpu("where resourceGroup=='rg'", configuration=c, secrets=s)
    Stress all machines from the group 'rg'

    >>> stress_cpu("where resourceGroup=='rg' and name='name'",
                    configuration=c, secrets=s)
    Stress the machine from the group 'rg' having the name 'name'

    >>> stress_cpu("where resourceGroup=='rg' | sample 2",
                    configuration=c, secrets=s)
    Stress two machines at random from the group 'rg'
    """

    msg = "Starting stress_cpu:" \
          " configuration='{}', filter='{}', duration='{}', timeout='{}'" \
        .format(configuration, filter, duration, timeout)
    logger.debug(msg)

    machines = __fetch_machines(filter, configuration, secrets)

    machine_records = Records()
    for machine in machines:
        command_id, script_content = command \
            .prepare(machine, 'cpu_stress_test')

        parameters = {
            'command_id': command_id,
            'script': [script_content],
            'parameters': [{
                'name': "duration",
                'value': duration
            }]
        }

        logger.debug("Stressing CPU of machine: '{}'".format(machine['name']))
        _timeout = duration + timeout
        command.run(machine['resourceGroup'], machine, _timeout, parameters,
                    secrets, configuration)
        machine_records.add(cleanse.machine(machine))

    return machine_records.output_as_dict('resources')