Merge branch 'trunk' of https://github.com/jwk404/libcloud into jwk404-trunk
diff --git a/.asf.yaml b/.asf.yaml
index ddd6804..487c3d7 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -35,6 +35,8 @@
     squash: true
     merge: true
     rebase: false
+  autolink_jira:
+    - LIBCLOUD
   protected_branches:
     trunk:
       required_status_checks:
@@ -46,6 +48,7 @@
           - "Unit Tests (Python 3.8)"
           - "Unit Tests (Python 3.9)"
           - "Unit Tests (Python 3.10)"
+          - "Unit Tests (Python 3.11)"
           - "Run Various Lint and Other Checks (3.8)"
           - "Build and upload Documentation (3.8)"
           - "Dependency Review"
diff --git a/.bandit.yaml b/.bandit.yaml
deleted file mode 100644
index 80ddbf0..0000000
--- a/.bandit.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-exclude_dirs:
-  - .tox
-  - .git
-  - build
-  - dist
-  - venv
-  - "tests/*"
-
-skips:
-  - B411
diff --git a/.codecov.yml b/.codecov.yml
index 925a7a7..61caf6f 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -1,7 +1,3 @@
-codecov:
-  #notify:
-    #require_ci_to_pass: yes
-
 coverage:
   precision: 2         # decimal places to display: 0 <= value <= 4
   round: nearest
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 61014db..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,32 +0,0 @@
-# .coveragerc to control coverage.py
-[run]
-branch = True
-source = libcloud
-
-[report]
-# Regexes for lines to exclude from consideration
-exclude_lines =
-    # Have to re-enable the standard pragma
-    pragma: no cover
-
-    # Don't complain about missing debug-only code:
-    def __repr__
-    def __str__
-    if self\.debug
-
-    # Don't complain if tests don't hit defensive assertion code:
-    raise AssertionError
-    raise NotImplementedError
-
-    # Don't complain if non-runnable code isn't run:
-    if 0:
-    if __name__ == .__main__.:
-    __all__
-    import
-    deprecated_warning
-    in_development_warning
-
-ignore_errors = True
-
-[html]
-directory = coverage_html_report
diff --git a/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..f931fc5
--- /dev/null
+++ b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,64 @@
+name: Bug report
+description: Report a bug with pip-audit's GitHub Action
+labels: bug
+body:
+  - type: markdown
+    attributes:
+      value: >-
+        Thank you for reporting a potential bug in `gh-action-pip-audit`! Please
+        read the following carefully:
+
+
+        **IMPORTANT:** This issue tracker is for `pip-audit`'s
+        **GitHub Action**, the scaffolding that integrates `pip-audit` with your
+        CI. If the buggy behavior you are experiencing appears to be in
+        `pip-audit`, please file an issue
+        [against the `pip-audit` repo](https://github.com/pypa/pip-audit/issues/new/choose).
+
+
+        **IMPORTANT:** Please fill out every section below. Bug reports with
+        missing information will be given a lower priority or closed outright.
+
+
+        Before filing an issue, check out our
+        [troubleshooting guide](https://github.com/pypa/gh-action-pip-audit#troubleshooting) :)
+  - type: textarea
+    id: current-behavior
+    attributes:
+      label: Current behavior
+      description: >-
+        What issue are you having with the action? What were you trying to do
+        when the issue occurred?
+      placeholder: The action run succeeds when I ...
+    validations:
+      required: true
+  - type: textarea
+    id: expected-behavior
+    attributes:
+      label: Expected behavior
+      description: What should've happened instead?
+      placeholder: I expected the action run to fail.
+    validations:
+      required: true
+  - type: textarea
+    id: repro
+    attributes:
+      label: Steps to reproduce
+      description: What are the detailed steps we can follow to trigger this issue?
+      placeholder: |-
+        1. ...
+        2. ...
+        3. ...
+    validations:
+      required: true
+  - type: textarea
+    id: context
+    attributes:
+      label: Relevant context
+      description: >-
+        Please include a link to an action run, as well as any logs that you think might
+        be helpful! You can
+        [follow these instructions](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow)
+        to re-run the action with debug logging.
+    validations:
+      required: true
diff --git a/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/config.yml b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..ff27519
--- /dev/null
+++ b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,11 @@
+blank_issues_enabled: false
+contact_links:
+  - name: pip-audit's issue tracker
+    url: https://github.com/pypa/pip-audit/issues/new/choose
+    about: >-
+      You may want to file a report on pip-audit instead if your issue is not
+      directly related to this GitHub Action
+  - name: Troubleshooting guide
+    url: https://github.com/pypa/gh-action-pip-audit#troubleshooting
+    about: >-
+      Learn how to fix some common issues or enable debug logging here
diff --git a/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..c83f913
--- /dev/null
+++ b/.github/actions/gh-action-pip-audit/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,50 @@
+name: Feature request
+description: Suggest an idea for pip-audit's GitHub Action
+labels: enhancement
+body:
+  - type: markdown
+    attributes:
+      value: >-
+        Thank you for filing a feature request for `gh-action-pip-audit`! Please
+        read the following carefully:
+
+
+        **IMPORTANT:** This form is for `pip-audit`'s **GitHub Action**, the
+        scaffolding that integrates `pip-audit` with your CI. If you would like
+        a new feature in `pip-audit` itself, please go to
+        [the `pip-audit` repo](https://github.com/pypa/pip-audit/issues/new/choose).
+
+
+        **IMPORTANT:** Please fill out every required section below to the best
+        of your ability. Feature requests with missing information may be given
+        a lower priority or closed outright.
+  - type: textarea
+    id: problem
+    attributes:
+      label: Is your feature request related to a problem?
+      description: Describe how the current solution is deficient.
+      placeholder: I am frustrated when ...
+    validations:
+      required: true
+  - type: textarea
+    id: solution
+    attributes:
+      label: Describe the solution you'd like
+      description:
+      placeholder: I think gh-action-pip-audit would benefit from ...
+    validations:
+      required: true
+  - type: textarea
+    id: alternatives-considered
+    attributes:
+      label: Alternative solutions or features you've considered
+      description:
+      placeholder:
+    validations:
+      required: true
+  - type: textarea
+    id: context
+    attributes:
+      label: Additional context
+      description: Add any context or screenshots related to the feature request.
+      placeholder:
diff --git a/.github/actions/gh-action-pip-audit/.github/workflows/selftest.yml b/.github/actions/gh-action-pip-audit/.github/workflows/selftest.yml
index 8640284..261a198 100644
--- a/.github/actions/gh-action-pip-audit/.github/workflows/selftest.yml
+++ b/.github/actions/gh-action-pip-audit/.github/workflows/selftest.yml
@@ -88,3 +88,21 @@
           PIP_AUDIT_OUTPUT: "${{ steps.pip-audit.outputs.internal-be-careful-output }}"
         run: |
           grep -E 'pyyaml\s+\|\s+5.1' <<< $(base64 -d <<< "${PIP_AUDIT_OUTPUT}")
+  selftest-pipaudit-fail:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: ./
+        id: pip-audit
+        with:
+          # we do not care about pip-audit's actual output in this test, we just need a file to pass
+          # in so as to not exercise `pip list` mode.
+          inputs: ./test/empty.txt
+          # pass in a fake flag here to reliably trigger the failure we're looking for.
+          internal-be-careful-extra-flags: --not-a-real-pip-audit-flag
+          internal-be-careful-allow-failure: true
+      - name: assert expected output
+        env:
+          PIP_AUDIT_OUTPUT: "${{ steps.pip-audit.outputs.internal-be-careful-output }}"
+        run: |
+          grep 'pip-audit did not return any output' <<< $(base64 -d <<< "${PIP_AUDIT_OUTPUT}")
diff --git a/.github/actions/gh-action-pip-audit/README.md b/.github/actions/gh-action-pip-audit/README.md
index c7f790d..ff434ac 100644
--- a/.github/actions/gh-action-pip-audit/README.md
+++ b/.github/actions/gh-action-pip-audit/README.md
@@ -32,7 +32,7 @@
       - uses: actions/checkout@v3
       - name: install
         run: python -m pip install .
-      - uses: pypa/gh-action-pip-audit@v1.0.5
+      - uses: pypa/gh-action-pip-audit@v1.0.8
 ```
 
 Or, with a virtual environment:
@@ -48,7 +48,7 @@
           python -m venv env/
           source env/bin/activate
           python -m pip install .
-      - uses: pypa/gh-action-pip-audit@v1.0.5
+      - uses: pypa/gh-action-pip-audit@v1.0.8
         with:
           virtual-environment: env/
 ```
@@ -72,7 +72,7 @@
 To audit one or more requirements-style inputs:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     inputs: requirements.txt dev-requirements.txt
 ```
@@ -80,7 +80,7 @@
 To audit a project that uses `pyproject.toml` for its dependencies:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     # NOTE: this can be `.`, for the current directory
     inputs: path/to/project/
@@ -108,7 +108,7 @@
 current directory:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     virtual-environment: env/
     # Note the absence of `input:`, since we're auditing the environment.
@@ -128,7 +128,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     local: true
 ```
@@ -145,7 +145,7 @@
 To audit with OSV instead of PyPI:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     vulnerability-service: osv
 ```
@@ -160,7 +160,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     # NOTE: only works with requirements-style inputs
     inputs: requirements.txt
@@ -177,7 +177,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     # NOTE: only works with requirements-style inputs
     inputs: requirements.txt
@@ -195,7 +195,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     summary: false
   ```
@@ -214,7 +214,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     index-url: https://example.corporate.local/simple
 ```
@@ -229,7 +229,7 @@
 Example:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     extra-index-urls: |
       https://example.corporate.local/simple
@@ -246,7 +246,7 @@
 Example
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     ignore-vulns: |
       GHSA-XXXX-YYYYYY
@@ -276,29 +276,24 @@
   Example:
 
   ```yaml
-  - uses: pypa/gh-action-pip-audit@v1.0.5
+  - uses: pypa/gh-action-pip-audit@v1.0.8
     with:
       internal-be-careful-allow-failure: true
   ```
 
-  #### `internal-be-careful-debug`
+#### `internal-be-careful-extra-flags`
+**Default**: `""`
 
-  **Default**: `false`
+The `internal-be-careful-extra-flags` setting passes the specified flags
+to `pip-audit`.
 
-  The `internal-be-careful-debug` setting enables additional debug logs,
-  both within `pip-audit` itself and the action's harness code. You can
-  use it to debug troublesome configurations.
+Example:
 
-  Be mindful that `pip-audit`'s own debug logs contain HTTP requests,
-  which may or may not be sensitive in your use case.
-
-  Example:
-
-  ```yaml
-  - uses: pypa/gh-action-pip-audit@v1.0.5
-    with:
-      internal-be-careful-debug: true
-  ```
+```yaml
+- uses: pypa/gh-action-pip-audit@v1.0.8
+  with:
+    internal-be-careful-extra-flags: --not-a-real-pip-audit-flag
+```
 
 </details>
 
@@ -312,7 +307,7 @@
 `require-hashes: true`:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     inputs: requirements.txt
     require-hashes: true
@@ -321,7 +316,7 @@
 or:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     inputs: requirements.txt
     no-deps: true
@@ -342,7 +337,7 @@
 To minimize external dependencies, you can opt into a virtual environment:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     # must be populated earlier in the CI
     virtual-environment: env/
@@ -352,13 +347,19 @@
 in the virtual environment should be included:
 
 ```yaml
-- uses: pypa/gh-action-pip-audit@v1.0.5
+- uses: pypa/gh-action-pip-audit@v1.0.8
   with:
     # must be populated earlier in the CI
     virtual-environment: env/
     local: true
 ```
 
+### There's an issue with the action and I want to enable debug logging!
+
+The action prints debug information when the `ACTIONS_STEP_DEBUG` secret is set
+to `true``. You should be able to enable this behavior by
+[following these instructions](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow).
+
 ## Tips and Tricks
 
 ### Running against a pipenv project
@@ -382,7 +383,7 @@
         run: |
           pipx run pipfile-requirements Pipfile.lock > requirements.txt
 
-      - uses: pypa/gh-action-pip-audit@v1.0.5
+      - uses: pypa/gh-action-pip-audit@v1.0.8
         with:
           inputs: requirements.txt
 ```
diff --git a/.github/actions/gh-action-pip-audit/action.py b/.github/actions/gh-action-pip-audit/action.py
index 75d8d7f..dd624ad 100755
--- a/.github/actions/gh-action-pip-audit/action.py
+++ b/.github/actions/gh-action-pip-audit/action.py
@@ -18,7 +18,7 @@
 _GITHUB_STEP_SUMMARY = Path(os.getenv("GITHUB_STEP_SUMMARY")).open("a")
 _GITHUB_OUTPUT = Path(os.getenv("GITHUB_OUTPUT")).open("a")
 _RENDER_SUMMARY = os.getenv("GHA_PIP_AUDIT_SUMMARY", "true") == "true"
-_DEBUG = os.getenv("GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_DEBUG", "false") != "false"
+_DEBUG = os.getenv("RUNNER_DEBUG") is not None
 
 
 def _template(name):
@@ -33,7 +33,7 @@
 
 def _debug(msg):
     if _DEBUG:
-        print(f"\033[93mDEBUG: {msg}\033[0m", file=sys.stderr)
+        print(f"::debug::{msg}")
 
 
 def _log(msg):
@@ -64,7 +64,7 @@
     "--desc",
     # Write the output to this logfile, which we'll turn into the step summary (if configured).
     "--output=/tmp/pip-audit-output.txt",
-]
+] + os.getenv("GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_EXTRA_FLAGS").split()
 
 if _DEBUG:
     pip_audit_args.append("--verbose")
@@ -135,15 +135,19 @@
 else:
     _summary("❌ pip-audit found one or more problems")
 
-    with open("/tmp/pip-audit-output.txt", "r") as io:
-        output = io.read()
+    output = "⚠️ pip-audit did not return any output"
+    try:
+        with open("/tmp/pip-audit-output.txt", "r") as io:
+            output = io.read()
+    except OSError as ex:
+        _log(ex)
 
-        # This is really nasty: our output contains multiple lines,
-        # so we can't naively stuff it into an output.
-        print(f"output={b64encode(output.encode()).decode()}", file=_GITHUB_OUTPUT)
+    # This is really nasty: our output contains multiple lines,
+    # so we can't naively stuff it into an output.
+    print(f"output={b64encode(output.encode()).decode()}", file=_GITHUB_OUTPUT)
 
-        _log(output)
-        _summary(output)
+    _log(output)
+    _summary(output)
 
 
 _log(status.stdout)
diff --git a/.github/actions/gh-action-pip-audit/action.yml b/.github/actions/gh-action-pip-audit/action.yml
index 3574e61..39e9d3d 100644
--- a/.github/actions/gh-action-pip-audit/action.yml
+++ b/.github/actions/gh-action-pip-audit/action.yml
@@ -46,10 +46,10 @@
     description: "don't fail the job if the audit fails (default false)"
     required: false
     default: false
-  internal-be-careful-debug:
-    description: "run with debug logs (default false)"
+  internal-be-careful-extra-flags:
+    description: "extra flags to be passed in to pip-audit"
     required: false
-    default: false
+    default: ""
 outputs:
   internal-be-careful-output:
     description: "the column-formatted output from pip-audit, wrapped as base64"
@@ -83,5 +83,5 @@
         GHA_PIP_AUDIT_EXTRA_INDEX_URLS: "${{ inputs.extra-index-urls }}"
         GHA_PIP_AUDIT_IGNORE_VULNS: "${{ inputs.ignore-vulns }}"
         GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_ALLOW_FAILURE: "${{ inputs.internal-be-careful-allow-failure }}"
-        GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_DEBUG: "${{ inputs.internal-be-careful-debug }}"
+        GHA_PIP_AUDIT_INTERNAL_BE_CAREFUL_EXTRA_FLAGS: "${{ inputs.internal-be-careful-extra-flags }}"
       shell: bash
diff --git a/.github/actions/gh-action-pip-audit/requirements.txt b/.github/actions/gh-action-pip-audit/requirements.txt
index 931128f..546e8fe 100644
--- a/.github/actions/gh-action-pip-audit/requirements.txt
+++ b/.github/actions/gh-action-pip-audit/requirements.txt
@@ -1 +1 @@
-pip-audit ~= 2.0, >= 2.4.13
+pip-audit ~= 2.0, >= 2.5.6
diff --git a/.gitmodules b/.github/actions/gh-action-pip-audit/test/empty.txt
similarity index 100%
rename from .gitmodules
rename to .github/actions/gh-action-pip-audit/test/empty.txt
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4941da4..7868071 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -3,9 +3,11 @@
   - package-ecosystem: "github-actions"
     directory: "/"
     schedule:
-      interval: "daily"
+      interval: "weekly"
+    open-pull-requests-limit: 2
 
   - package-ecosystem: "pip"
     directory: "/"
     schedule:
-      interval: "daily"
+      interval: "weekly"
+    open-pull-requests-limit: 2
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 1183e7b..9f61f1b 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -16,6 +16,11 @@
   actions: write  # Needed for skip-duplicate-jobs job
   contents: read
 
+env:
+  # Needed if we want colors in pytest output without tty and script -e -c wrapper
+  PY_COLORS: "1"
+  FORCE_COLOR: "1"
+
 jobs:
   # Special job which skips duplicate jobs
   pre_job:
@@ -80,7 +85,7 @@
 
       - name: Run tox target
         run: |
-          script -e -c "tox -e integration-storage"
+          tox -e integration-storage
         env:
           AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
           AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 9d881eb..cf03c62 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -14,6 +14,11 @@
   actions: write  # Needed for skip-duplicate-jobs job
   contents: read
 
+env:
+  # Needed if we want colors in pytest output without tty and script -e -c wrapper
+  PY_COLORS: "1"
+  FORCE_COLOR: "1"
+
 jobs:
   # Special job which skips duplicate jobs
   pre_job:
@@ -54,7 +59,9 @@
           - 3.9
           - "3.10"
           - "3.11"
-          - "pypy-3.7"
+          - "3.12-dev"
+          # TODO: Investigate why it started failing with cryptic error on CI
+          #- "pypy-3.7"
         os:
           - ubuntu-latest
         include:
@@ -95,7 +102,7 @@
 
       - name: Setup Dotnet 6
         if: ${{ matrix.python_version == 'pyjion' }}
-        uses: actions/setup-dotnet@v3.0.3
+        uses: actions/setup-dotnet@v3.2.0
         with:
           dotnet-version: "6.0.100"
 
@@ -118,12 +125,12 @@
 
       - name: Run unit tests tox target
         run: |
-         script -e -c "tox -e py${{ matrix.python_version }}"
+         tox -e py${{ matrix.python_version }}
 
       - name: Run dist install checks tox target
         if: ${{ matrix.python_version != 'pypy-3.7' && matrix.python_version != 'pyjion' }}
         run: |
-         script -e -c "tox -e py${{ matrix.python_version }}-dist,py${{ matrix.python_version }}-dist-wheel"
+         tox -e py${{ matrix.python_version }}-dist,py${{ matrix.python_version }}-dist-wheel
 
   code_coverage:
     name: Generate Code Coverage
@@ -165,7 +172,13 @@
 
       - name: Run Checks
         run: |
-          script -e -c "tox -e coverage-ci"
+          tox -e coverage-ci
+
+      - name: Upload Coverage to codecov.io
+        uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
+        with:
+          fail_ci_if_error: true
+          verbose: true
 
   lint_checks:
     name: Run Various Lint and Other Checks
@@ -207,7 +220,7 @@
 
       - name: Run Checks
         run: |
-          script -e -c "tox -e black-check,isort-check,pyupgrade,checks,import-timings,lint,pylint"
+          tox -e black-check,isort-check,pyupgrade,checks,import-timings,lint,pylint
 
   build_test_docker_image:
     name: Build and Verify Docker Image
@@ -287,6 +300,7 @@
           # setuptools which we don't install or depend on directly
           ignore-vulns: |
             GHSA-r9hx-vwmv-q579
+            PYSEC-2022-43012
 
       - name: Cleanup
         run: |
@@ -302,7 +316,7 @@
 
       - name: Run Bandit Check
         run: |
-          script -e -c "tox -e bandit"
+          tox -e bandit
 
   micro-benchmarks:
     name: Micro Benchmarks
@@ -344,7 +358,7 @@
 
       - name: Run Micro Benchmarks
         run: |
-          script -e -c "tox -e micro-benchmarks"
+          tox -e micro-benchmarks
 
   docs:
     name: Build and upload Documentation
@@ -391,7 +405,7 @@
 
       - name: Build Docs
         run: |
-          script -e -c "tox -e docs-ci"
+          tox -e docs-ci
 
       - name: Trigger ReadTheDocs build
         env:
diff --git a/.pylintrc b/.pylintrc
deleted file mode 100644
index a0b4ddd..0000000
--- a/.pylintrc
+++ /dev/null
@@ -1,39 +0,0 @@
-[MASTER]
-# Add <file or directory> to the black list. It should be a base name, not a
-# path. You may set this option multiple times.
-ignore=test,constants
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-disable=redefined-builtin,too-many-arguments,too-few-public-methods,missing-docstring,invalid-name,abstract-method
-
-
-[TYPECHECK]
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=async_request,objects
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching names used for dummy variables (i.e. not used).
-dummy-variables-rgx=_|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-[FORMAT]
-max-line-length=100
-max-module-lines=1000
-indent-string='    '
diff --git a/.ratignore b/.ratignore
index 9668cf0..346a627 100644
--- a/.ratignore
+++ b/.ratignore
@@ -1,19 +1,10 @@
-RELEASING
-MANIFEST
 MANIFEST.in
 .gitignore
 tox.ini
-apidocs/
-CHANGES
-HACKING
-test/storage/fixtures/
-test/compute/fixtures/
-test/loadbalancer/fixtures/
-test/dns/fixtures/
-test/container/fixtures/
-coverage_html_report/
-.coverage
-.coveragerc
+docs/apidocs.rst
+CHANGES.rst
+.codecov.rc
+pyproject.toml
 libcloud/data/pricing.json
 libcloud/common/__init__.py
 libcloud/compute/__init__.py
@@ -21,5 +12,10 @@
 libcloud/storage/__init__.py
 libcloud/loadbalancer/__init__.py
 libcloud/dns/__init__.py
-test/storage/__init__.py
-test/pricing_test.json
+libcloud/test/storage/fixtures/
+libcloud/test/compute/fixtures/
+libcloud/test/loadbalancer/fixtures/
+libcloud/test/dns/fixtures/
+libcloud/test/container/fixtures/
+libcloud/test/storage/__init__.py
+libcloud/test/pricing_test.json
diff --git a/CHANGES.rst b/CHANGES.rst
index cce0e66..0409547 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,13 +7,22 @@
 Compute
 ~~~~~~~
 
-Remove obsolete compute driver where the provider is either dead or not
-offering those services anymore: Bluebox, bsnlcloud, Cloudwatt, Enomaly,
-ElasticHosts, ElasticStack, GoGrid, Gridspot, HostVirtual, Joyent, Med-1,
-Nephoscale, 1on1, ProfitBricks, ServerLove, SkaliCloud, Softlayer, Voxel.
+- Remove obsolete compute driver where the provider is either dead or not
+  offering those services anymore: Bluebox, bsnlcloud, Cloudwatt, Enomaly,
+  ElasticHosts, ElasticStack, GoGrid, Gridspot, HostVirtual, Joyent, Med-1,
+  Nephoscale, 1on1, ProfitBricks, ServerLove, SkaliCloud, Softlayer, Voxel.
 
-(GITHUB-1743, GITHUB-1852)
-[Anthony Monthe - @ZuluPro, Tomaz Muraus - @Kami]
+  (GITHUB-1743, GITHUB-1852)
+  [Anthony Monthe - @ZuluPro, Tomaz Muraus - @Kami]
+
+- [Outscale] Fix ``list_nodes()`` and ``list_volumes()`` method.
+  (GITHUB-1877)
+  [Matthias Gatto - @outscale-mgo]
+
+- [Azure ARM] Implement pagination in the ``list_nodes()`` method. This fixes a
+  bug which would result in sometimes not all nodes being returned.
+  (GITHUB-1824, GITHUB-1850)
+  [Jan Müller - @ojan-mue]
 
 Storage
 ~~~~~~~
@@ -32,6 +41,34 @@
   (GITHUB-1796)
   [@shengwubin]
 
+- [S3] Support all available storage classes. Previously only "standard" and
+  "reduced_redundancy" were supported.
+  (GITHUB-1875)
+  [Mohammad Aburadeh - @mohammad-aburadeh]
+
+- [CloudFiles] Fix ``get_endpoint_url()`` throwing an exception when being used
+  with ``use_internal_url=True`` argument.
+  (GITHUB-1883, GITHUB-1884)
+  [Marcus T - @llamasoft]
+
+- [CloudFiles] Update OpenStack connection handling code to only re-connect in
+  case connection details (scheme, host, port) have changed.
+
+  This should result in significant performance improvements when downloading
+  objects since the underlying HTTP connection will be properly re-used.
+  (GITHUB-1885, GITHUB-1886)
+  [Marcus T - @llamasoft]
+
+Other
+~~~~~
+
+- Move Python tooling (pytest, bandit, pylint, mypy, coverage) config options
+  from separate config files into single pyproject.yaml config files.
+
+  NOTE: This change only affects development process and nothing else.
+  (GITHUB-1901)
+  [RS Nikhil Krishna - @rsnk96]
+
 Changes in Apache Libcloud 3.7.0
 --------------------------------
 
diff --git a/MANIFEST.in b/MANIFEST.in
index cc4af03..a8ddee3 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,7 +4,7 @@
 include CHANGES.rst
 include README.rst
 include tox.ini
-include .pylintrc
+include pyproject.toml
 include requirements-tests.txt
 include requirements-lint.txt
 include libcloud/data/pricing.json
diff --git a/contrib/generate_contributor_list.py b/contrib/generate_contributor_list.py
index 520fe30..201c226 100755
--- a/contrib/generate_contributor_list.py
+++ b/contrib/generate_contributor_list.py
@@ -106,7 +106,6 @@
 
 
 def convert_to_markdown(contributors_map, include_tickets=False):
-
     # Contributors are sorted in ascending lexiographical order based on their
     # last name
     def compare(item1, item2):
diff --git a/contrib/scrape-azure-prices.py b/contrib/scrape-azure-prices.py
index 53ee06b..7c33ef5 100755
--- a/contrib/scrape-azure-prices.py
+++ b/contrib/scrape-azure-prices.py
@@ -40,7 +40,6 @@
     result = {"windows": {}, "linux": {}}
     parsed_sizes = {"lowpriority", "basic", "standard"}
     for offer, value in prices_raw["offers"].items():
-
         size_raw = offer.split("-")
         #  Servers that go by the core with global price are not yet added
         if len(size_raw) != 3 or size_raw[2] not in parsed_sizes:
diff --git a/contrib/scrape-ec2-prices.py b/contrib/scrape-ec2-prices.py
index 6a029ea..a4b6f5a 100755
--- a/contrib/scrape-ec2-prices.py
+++ b/contrib/scrape-ec2-prices.py
@@ -305,7 +305,7 @@
     """
     result = []
 
-    for (numeric, alpha, other) in RE_NUMERIC_OTHER.findall(key_value[0]):
+    for numeric, alpha, other in RE_NUMERIC_OTHER.findall(key_value[0]):
         numeric = int(numeric) if numeric else -1
         alpha = INSTANCE_SIZES.index(alpha) if alpha in INSTANCE_SIZES else alpha
         alpha = str(alpha)
diff --git a/docs/compute/_supported_methods_block_storage.rst b/docs/compute/_supported_methods_block_storage.rst
index 6621e47..c8ae023 100644
--- a/docs/compute/_supported_methods_block_storage.rst
+++ b/docs/compute/_supported_methods_block_storage.rst
@@ -1,57 +1,57 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-===================================== ============ ============= ============== ============= ============= ============== ===============
-Provider                              list volumes create volume destroy volume attach volume detach volume list snapshots create snapshot
-===================================== ============ ============= ============== ============= ============= ============== ===============
-`Abiquo`_                             no           no            no             no            no            no             no             
-`Aliyun ECS`_                         yes          yes           yes            yes           yes           yes            yes            
-`PCextreme AuroraCompute`_            yes          yes           yes            yes           yes           no             yes            
-`Azure Virtual machines`_             yes          yes           yes            yes           yes           no             yes            
-`Azure Virtual machines`_             yes          yes           yes            yes           yes           yes            yes            
-`Brightbox`_                          no           no            no             no            no            no             no             
-`Cloudscale`_                         no           no            no             no            no            no             no             
-`CloudSigma (API v2.0)`_              yes          yes           yes            yes           yes           no             no             
-`CloudStack`_                         yes          yes           yes            yes           yes           no             yes            
-`DigitalOcean`_                       yes          yes           yes            yes           yes           yes            yes            
-`DimensionData`_                      no           no            no             no            no            no             no             
-`Amazon EC2`_                         yes          yes           yes            yes           yes           yes            yes            
-`EquinixMetal`_                       yes          yes           yes            yes           yes           yes            yes            
-`Eucalyptus`_                         yes          yes           yes            yes           yes           yes            yes            
-`Exoscale`_                           yes          yes           yes            yes           yes           no             yes            
-`Gandi`_                              yes          yes           yes            yes           yes           no             no             
-`Google Compute Engine`_              yes          yes           yes            yes           yes           yes            yes            
-`GiG G8 Node Provider`_               yes          yes           yes            yes           yes           no             no             
-`Gridscale`_                          yes          yes           yes            yes           yes           yes            yes            
-`Ikoula`_                             yes          yes           yes            yes           yes           no             yes            
-`InternetSolutions`_                  no           no            no             no            no            no             no             
-`Kamatera`_                           no           no            no             no            no            no             no             
-`KTUCloud`_                           yes          yes           yes            yes           yes           no             yes            
-`kubevirt`_                           yes          yes           yes            yes           yes           no             no             
-`Libvirt`_                            no           no            no             no            no            no             no             
-`Linode`_                             yes          yes           yes            yes           yes           no             no             
-`Maxihost`_                           no           no            no             no            no            no             no             
-`Nimbus`_                             yes          yes           yes            yes           yes           yes            yes            
-`NTTAmerica`_                         no           no            no             no            no            no             no             
-`NTTC-CIS`_                           no           no            no             no            no            no             no             
-`OnApp`_                              no           no            no             no            no            no             no             
-`OpenNebula (v3.8)`_                  yes          yes           yes            yes           yes           no             no             
-`OpenStack`_                          yes          yes           yes            yes           yes           no             no             
-`Outscale API`_                       yes          yes           yes            yes           yes           yes            yes            
-`Outscale INC`_                       yes          yes           yes            yes           yes           yes            yes            
-`Outscale SAS`_                       yes          yes           yes            yes           yes           yes            yes            
-`Ovh`_                                yes          yes           yes            yes           yes           yes            yes            
-`Rackspace Cloud (Next Gen)`_         yes          yes           yes            yes           yes           yes            yes            
-`Rackspace Cloud (First Gen)`_        yes          yes           yes            yes           yes           no             no             
-`RimuHosting`_                        no           no            no             no            no            no             no             
-`Scaleway`_                           yes          yes           yes            no            no            yes            yes            
-`vCloud`_                             no           no            no             no            no            no             no             
-`Upcloud`_                            no           no            no             no            no            no             no             
-`VCL`_                                no           no            no             no            no            no             no             
-`vCloud`_                             no           no            no             no            no            no             no             
-`vps.net`_                            no           no            no             no            no            no             no             
-`VMware vSphere`_                     no           no            no             no            no            no             no             
-`Vultr`_                              yes          yes           yes            yes           yes           no             no             
-===================================== ============ ============= ============== ============= ============= ============== ===============
+============================== ============ ============= ============== ============= ============= ============== ===============
+Provider                       list volumes create volume destroy volume attach volume detach volume list snapshots create snapshot
+============================== ============ ============= ============== ============= ============= ============== ===============
+`Abiquo`_                      no           no            no             no            no            no             no             
+`Aliyun ECS`_                  yes          yes           yes            yes           yes           yes            yes            
+`PCextreme AuroraCompute`_     yes          yes           yes            yes           yes           no             yes            
+`Azure Virtual machines`_      yes          yes           yes            yes           yes           no             yes            
+`Azure Virtual machines`_      yes          yes           yes            yes           yes           yes            yes            
+`Brightbox`_                   no           no            no             no            no            no             no             
+`Cloudscale`_                  no           no            no             no            no            no             no             
+`CloudSigma (API v2.0)`_       yes          yes           yes            yes           yes           no             no             
+`CloudStack`_                  yes          yes           yes            yes           yes           no             yes            
+`DigitalOcean`_                yes          yes           yes            yes           yes           yes            yes            
+`DimensionData`_               no           no            no             no            no            no             no             
+`Amazon EC2`_                  yes          yes           yes            yes           yes           yes            yes            
+`EquinixMetal`_                yes          yes           yes            yes           yes           yes            yes            
+`Eucalyptus`_                  yes          yes           yes            yes           yes           yes            yes            
+`Exoscale`_                    yes          yes           yes            yes           yes           no             yes            
+`Gandi`_                       yes          yes           yes            yes           yes           no             no             
+`Google Compute Engine`_       yes          yes           yes            yes           yes           yes            yes            
+`GiG G8 Node Provider`_        yes          yes           yes            yes           yes           no             no             
+`Gridscale`_                   yes          yes           yes            yes           yes           yes            yes            
+`Ikoula`_                      yes          yes           yes            yes           yes           no             yes            
+`InternetSolutions`_           no           no            no             no            no            no             no             
+`Kamatera`_                    no           no            no             no            no            no             no             
+`KTUCloud`_                    yes          yes           yes            yes           yes           no             yes            
+`kubevirt`_                    yes          yes           yes            yes           yes           no             no             
+`Libvirt`_                     no           no            no             no            no            no             no             
+`Linode`_                      yes          yes           yes            yes           yes           no             no             
+`Maxihost`_                    no           no            no             no            no            no             no             
+`Nimbus`_                      yes          yes           yes            yes           yes           yes            yes            
+`NTTAmerica`_                  no           no            no             no            no            no             no             
+`NTTC-CIS`_                    no           no            no             no            no            no             no             
+`OnApp`_                       no           no            no             no            no            no             no             
+`OpenNebula (v3.8)`_           yes          yes           yes            yes           yes           no             no             
+`OpenStack`_                   yes          yes           yes            yes           yes           no             no             
+`Outscale API`_                yes          yes           yes            yes           yes           yes            yes            
+`Outscale INC`_                yes          yes           yes            yes           yes           yes            yes            
+`Outscale SAS`_                yes          yes           yes            yes           yes           yes            yes            
+`Ovh`_                         yes          yes           yes            yes           yes           yes            yes            
+`Rackspace Cloud (Next Gen)`_  yes          yes           yes            yes           yes           yes            yes            
+`Rackspace Cloud (First Gen)`_ yes          yes           yes            yes           yes           no             no             
+`RimuHosting`_                 no           no            no             no            no            no             no             
+`Scaleway`_                    yes          yes           yes            no            no            yes            yes            
+`vCloud`_                      no           no            no             no            no            no             no             
+`Upcloud`_                     no           no            no             no            no            no             no             
+`VCL`_                         no           no            no             no            no            no             no             
+`vCloud`_                      no           no            no             no            no            no             no             
+`vps.net`_                     no           no            no             no            no            no             no             
+`VMware vSphere`_              no           no            no             no            no            no             no             
+`Vultr`_                       yes          yes           yes            yes           yes           no             no             
+============================== ============ ============= ============== ============= ============= ============== ===============
 
 .. _`Abiquo`: http://www.abiquo.com/
 .. _`Aliyun ECS`: https://www.aliyun.com/product/ecs
diff --git a/docs/compute/_supported_methods_image_management.rst b/docs/compute/_supported_methods_image_management.rst
index f40cdf4..c121c6b 100644
--- a/docs/compute/_supported_methods_image_management.rst
+++ b/docs/compute/_supported_methods_image_management.rst
@@ -1,57 +1,57 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-===================================== =========== ========= ============ ============ ==========
-Provider                              list images get image create image delete image copy image
-===================================== =========== ========= ============ ============ ==========
-`Abiquo`_                             yes         no        no           no           no        
-`Aliyun ECS`_                         yes         yes       yes          yes          yes       
-`PCextreme AuroraCompute`_            yes         no        no           no           no        
-`Azure Virtual machines`_             yes         no        no           no           no        
-`Azure Virtual machines`_             yes         yes       no           no           no        
-`Brightbox`_                          yes         no        no           no           no        
-`Cloudscale`_                         yes         no        no           no           no        
-`CloudSigma (API v2.0)`_              yes         no        no           no           no        
-`CloudStack`_                         yes         no        no           no           no        
-`DigitalOcean`_                       yes         yes       yes          yes          no        
-`DimensionData`_                      yes         no        no           no           no        
-`Amazon EC2`_                         yes         yes       yes          yes          yes       
-`EquinixMetal`_                       yes         no        no           no           no        
-`Eucalyptus`_                         yes         yes       yes          yes          yes       
-`Exoscale`_                           yes         no        no           no           no        
-`Gandi`_                              yes         no        no           no           no        
-`Google Compute Engine`_              yes         no        no           no           no        
-`GiG G8 Node Provider`_               yes         no        no           no           no        
-`Gridscale`_                          yes         yes       yes          yes          no        
-`Ikoula`_                             yes         no        no           no           no        
-`InternetSolutions`_                  yes         no        no           no           no        
-`Kamatera`_                           yes         no        no           no           no        
-`KTUCloud`_                           yes         no        no           no           no        
-`kubevirt`_                           yes         no        no           no           no        
-`Libvirt`_                            no          no        no           no           no        
-`Linode`_                             yes         no        yes          yes          no        
-`Maxihost`_                           yes         no        no           no           no        
-`Nimbus`_                             yes         yes       yes          yes          yes       
-`NTTAmerica`_                         yes         no        no           no           no        
-`NTTC-CIS`_                           yes         no        no           no           no        
-`OnApp`_                              yes         no        no           no           no        
-`OpenNebula (v3.8)`_                  yes         no        no           no           no        
-`OpenStack`_                          yes         yes       no           no           no        
-`Outscale API`_                       yes         yes       yes          yes          no        
-`Outscale INC`_                       yes         yes       yes          yes          yes       
-`Outscale SAS`_                       yes         yes       yes          yes          yes       
-`Ovh`_                                yes         yes       no           no           no        
-`Rackspace Cloud (Next Gen)`_         yes         yes       yes          yes          no        
-`Rackspace Cloud (First Gen)`_        yes         yes       yes          yes          no        
-`RimuHosting`_                        yes         no        no           no           no        
-`Scaleway`_                           yes         yes       yes          yes          no        
-`vCloud`_                             yes         no        no           no           no        
-`Upcloud`_                            yes         no        no           no           no        
-`VCL`_                                yes         no        no           no           no        
-`vCloud`_                             yes         no        no           no           no        
-`vps.net`_                            yes         no        no           no           no        
-`VMware vSphere`_                     yes         no        no           no           no        
-`Vultr`_                              yes         no        no           no           no        
-===================================== =========== ========= ============ ============ ==========
+============================== =========== ========= ============ ============ ==========
+Provider                       list images get image create image delete image copy image
+============================== =========== ========= ============ ============ ==========
+`Abiquo`_                      yes         no        no           no           no        
+`Aliyun ECS`_                  yes         yes       yes          yes          yes       
+`PCextreme AuroraCompute`_     yes         no        no           no           no        
+`Azure Virtual machines`_      yes         no        no           no           no        
+`Azure Virtual machines`_      yes         yes       no           no           no        
+`Brightbox`_                   yes         no        no           no           no        
+`Cloudscale`_                  yes         no        no           no           no        
+`CloudSigma (API v2.0)`_       yes         no        no           no           no        
+`CloudStack`_                  yes         no        no           no           no        
+`DigitalOcean`_                yes         yes       yes          yes          no        
+`DimensionData`_               yes         no        no           no           no        
+`Amazon EC2`_                  yes         yes       yes          yes          yes       
+`EquinixMetal`_                yes         no        no           no           no        
+`Eucalyptus`_                  yes         yes       yes          yes          yes       
+`Exoscale`_                    yes         no        no           no           no        
+`Gandi`_                       yes         no        no           no           no        
+`Google Compute Engine`_       yes         no        no           no           no        
+`GiG G8 Node Provider`_        yes         no        no           no           no        
+`Gridscale`_                   yes         yes       yes          yes          no        
+`Ikoula`_                      yes         no        no           no           no        
+`InternetSolutions`_           yes         no        no           no           no        
+`Kamatera`_                    yes         no        no           no           no        
+`KTUCloud`_                    yes         no        no           no           no        
+`kubevirt`_                    yes         no        no           no           no        
+`Libvirt`_                     no          no        no           no           no        
+`Linode`_                      yes         no        yes          yes          no        
+`Maxihost`_                    yes         no        no           no           no        
+`Nimbus`_                      yes         yes       yes          yes          yes       
+`NTTAmerica`_                  yes         no        no           no           no        
+`NTTC-CIS`_                    yes         no        no           no           no        
+`OnApp`_                       yes         no        no           no           no        
+`OpenNebula (v3.8)`_           yes         no        no           no           no        
+`OpenStack`_                   yes         yes       no           no           no        
+`Outscale API`_                yes         yes       yes          yes          no        
+`Outscale INC`_                yes         yes       yes          yes          yes       
+`Outscale SAS`_                yes         yes       yes          yes          yes       
+`Ovh`_                         yes         yes       no           no           no        
+`Rackspace Cloud (Next Gen)`_  yes         yes       yes          yes          no        
+`Rackspace Cloud (First Gen)`_ yes         yes       yes          yes          no        
+`RimuHosting`_                 yes         no        no           no           no        
+`Scaleway`_                    yes         yes       yes          yes          no        
+`vCloud`_                      yes         no        no           no           no        
+`Upcloud`_                     yes         no        no           no           no        
+`VCL`_                         yes         no        no           no           no        
+`vCloud`_                      yes         no        no           no           no        
+`vps.net`_                     yes         no        no           no           no        
+`VMware vSphere`_              yes         no        no           no           no        
+`Vultr`_                       yes         no        no           no           no        
+============================== =========== ========= ============ ============ ==========
 
 .. _`Abiquo`: http://www.abiquo.com/
 .. _`Aliyun ECS`: https://www.aliyun.com/product/ecs
diff --git a/docs/compute/_supported_methods_key_pair_management.rst b/docs/compute/_supported_methods_key_pair_management.rst
index e663a2e..ef255a2 100644
--- a/docs/compute/_supported_methods_key_pair_management.rst
+++ b/docs/compute/_supported_methods_key_pair_management.rst
@@ -1,57 +1,57 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-===================================== ============== ============ =============== ============================= =========================== ===============
-Provider                              list key pairs get key pair create key pair import public key from string import public key from file delete key pair
-===================================== ============== ============ =============== ============================= =========================== ===============
-`Abiquo`_                             no             no           no              no                            no                          no             
-`Aliyun ECS`_                         no             no           no              no                            no                          no             
-`PCextreme AuroraCompute`_            yes            yes          yes             yes                           no                          yes            
-`Azure Virtual machines`_             no             no           no              no                            no                          no             
-`Azure Virtual machines`_             no             no           no              no                            no                          no             
-`Brightbox`_                          no             no           no              no                            no                          no             
-`Cloudscale`_                         no             no           no              no                            no                          no             
-`CloudSigma (API v2.0)`_              yes            yes          yes             yes                           no                          yes            
-`CloudStack`_                         yes            yes          yes             yes                           no                          yes            
-`DigitalOcean`_                       yes            yes          yes             no                            no                          yes            
-`DimensionData`_                      no             no           no              no                            no                          no             
-`Amazon EC2`_                         yes            yes          yes             yes                           no                          yes            
-`EquinixMetal`_                       yes            no           yes             no                            no                          yes            
-`Eucalyptus`_                         yes            yes          yes             yes                           no                          yes            
-`Exoscale`_                           yes            yes          yes             yes                           no                          yes            
-`Gandi`_                              yes            yes          no              yes                           no                          yes            
-`Google Compute Engine`_              no             no           no              no                            no                          no             
-`GiG G8 Node Provider`_               no             no           no              no                            no                          no             
-`Gridscale`_                          yes            no           no              yes                           no                          no             
-`Ikoula`_                             yes            yes          yes             yes                           no                          yes            
-`InternetSolutions`_                  no             no           no              no                            no                          no             
-`Kamatera`_                           no             no           no              no                            no                          no             
-`KTUCloud`_                           yes            yes          yes             yes                           no                          yes            
-`kubevirt`_                           no             no           no              no                            no                          no             
-`Libvirt`_                            no             no           no              no                            no                          no             
-`Linode`_                             no             no           no              no                            no                          no             
-`Maxihost`_                           yes            no           yes             no                            no                          no             
-`Nimbus`_                             yes            yes          yes             yes                           no                          yes            
-`NTTAmerica`_                         no             no           no              no                            no                          no             
-`NTTC-CIS`_                           no             no           no              no                            no                          no             
-`OnApp`_                              yes            yes          no              yes                           no                          yes            
-`OpenNebula (v3.8)`_                  no             no           no              no                            no                          no             
-`OpenStack`_                          no             no           no              no                            no                          no             
-`Outscale API`_                       yes            yes          yes             no                            no                          yes            
-`Outscale INC`_                       yes            yes          yes             yes                           no                          yes            
-`Outscale SAS`_                       yes            yes          yes             yes                           no                          yes            
-`Ovh`_                                yes            yes          no              yes                           no                          yes            
-`Rackspace Cloud (Next Gen)`_         yes            yes          yes             yes                           no                          yes            
-`Rackspace Cloud (First Gen)`_        no             no           no              no                            no                          no             
-`RimuHosting`_                        no             no           no              no                            no                          no             
-`Scaleway`_                           yes            no           no              yes                           no                          yes            
-`vCloud`_                             no             no           no              no                            no                          no             
-`Upcloud`_                            no             no           no              no                            no                          no             
-`VCL`_                                no             no           no              no                            no                          no             
-`vCloud`_                             no             no           no              no                            no                          no             
-`vps.net`_                            no             no           no              no                            no                          no             
-`VMware vSphere`_                     no             no           no              no                            no                          no             
-`Vultr`_                              yes            yes          no              yes                           no                          yes            
-===================================== ============== ============ =============== ============================= =========================== ===============
+============================== ============== ============ =============== ============================= =========================== ===============
+Provider                       list key pairs get key pair create key pair import public key from string import public key from file delete key pair
+============================== ============== ============ =============== ============================= =========================== ===============
+`Abiquo`_                      no             no           no              no                            no                          no             
+`Aliyun ECS`_                  no             no           no              no                            no                          no             
+`PCextreme AuroraCompute`_     yes            yes          yes             yes                           no                          yes            
+`Azure Virtual machines`_      no             no           no              no                            no                          no             
+`Azure Virtual machines`_      no             no           no              no                            no                          no             
+`Brightbox`_                   no             no           no              no                            no                          no             
+`Cloudscale`_                  no             no           no              no                            no                          no             
+`CloudSigma (API v2.0)`_       yes            yes          yes             yes                           no                          yes            
+`CloudStack`_                  yes            yes          yes             yes                           no                          yes            
+`DigitalOcean`_                yes            yes          yes             no                            no                          yes            
+`DimensionData`_               no             no           no              no                            no                          no             
+`Amazon EC2`_                  yes            yes          yes             yes                           no                          yes            
+`EquinixMetal`_                yes            no           yes             no                            no                          yes            
+`Eucalyptus`_                  yes            yes          yes             yes                           no                          yes            
+`Exoscale`_                    yes            yes          yes             yes                           no                          yes            
+`Gandi`_                       yes            yes          no              yes                           no                          yes            
+`Google Compute Engine`_       no             no           no              no                            no                          no             
+`GiG G8 Node Provider`_        no             no           no              no                            no                          no             
+`Gridscale`_                   yes            no           no              yes                           no                          no             
+`Ikoula`_                      yes            yes          yes             yes                           no                          yes            
+`InternetSolutions`_           no             no           no              no                            no                          no             
+`Kamatera`_                    no             no           no              no                            no                          no             
+`KTUCloud`_                    yes            yes          yes             yes                           no                          yes            
+`kubevirt`_                    no             no           no              no                            no                          no             
+`Libvirt`_                     no             no           no              no                            no                          no             
+`Linode`_                      no             no           no              no                            no                          no             
+`Maxihost`_                    yes            no           yes             no                            no                          no             
+`Nimbus`_                      yes            yes          yes             yes                           no                          yes            
+`NTTAmerica`_                  no             no           no              no                            no                          no             
+`NTTC-CIS`_                    no             no           no              no                            no                          no             
+`OnApp`_                       yes            yes          no              yes                           no                          yes            
+`OpenNebula (v3.8)`_           no             no           no              no                            no                          no             
+`OpenStack`_                   no             no           no              no                            no                          no             
+`Outscale API`_                yes            yes          yes             no                            no                          yes            
+`Outscale INC`_                yes            yes          yes             yes                           no                          yes            
+`Outscale SAS`_                yes            yes          yes             yes                           no                          yes            
+`Ovh`_                         yes            yes          no              yes                           no                          yes            
+`Rackspace Cloud (Next Gen)`_  yes            yes          yes             yes                           no                          yes            
+`Rackspace Cloud (First Gen)`_ no             no           no              no                            no                          no             
+`RimuHosting`_                 no             no           no              no                            no                          no             
+`Scaleway`_                    yes            no           no              yes                           no                          yes            
+`vCloud`_                      no             no           no              no                            no                          no             
+`Upcloud`_                     no             no           no              no                            no                          no             
+`VCL`_                         no             no           no              no                            no                          no             
+`vCloud`_                      no             no           no              no                            no                          no             
+`vps.net`_                     no             no           no              no                            no                          no             
+`VMware vSphere`_              no             no           no              no                            no                          no             
+`Vultr`_                       yes            yes          no              yes                           no                          yes            
+============================== ============== ============ =============== ============================= =========================== ===============
 
 .. _`Abiquo`: http://www.abiquo.com/
 .. _`Aliyun ECS`: https://www.aliyun.com/product/ecs
diff --git a/docs/compute/_supported_methods_main.rst b/docs/compute/_supported_methods_main.rst
index 3a84bf4..4ed5f39 100644
--- a/docs/compute/_supported_methods_main.rst
+++ b/docs/compute/_supported_methods_main.rst
@@ -1,57 +1,57 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-===================================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
-Provider                              list nodes create node reboot node destroy node start node stop node list images list sizes deploy node
-===================================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
-`Abiquo`_                             yes        yes         yes         yes          no         no        yes         yes        no         
-`Aliyun ECS`_                         yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`PCextreme AuroraCompute`_            yes        yes         yes         yes          no         no        yes         yes        yes        
-`Azure Virtual machines`_             yes        yes         yes         yes          no         no        yes         yes        yes        
-`Azure Virtual machines`_             yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Brightbox`_                          yes        yes         no          yes          no         no        yes         yes        no         
-`Cloudscale`_                         yes        yes         yes         yes          yes        yes       yes         yes        no         
-`CloudSigma (API v2.0)`_              yes        yes         yes         yes          yes        yes       yes         yes        no         
-`CloudStack`_                         yes        yes         yes         yes          no         no        yes         yes        yes        
-`DigitalOcean`_                       yes        yes         yes         yes          no         no        yes         yes        no         
-`DimensionData`_                      yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Amazon EC2`_                         yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`EquinixMetal`_                       yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Eucalyptus`_                         yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Exoscale`_                           yes        yes         yes         yes          no         no        yes         yes        yes        
-`Gandi`_                              yes        yes         yes         yes          no         no        yes         yes        no         
-`Google Compute Engine`_              yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`GiG G8 Node Provider`_               yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Gridscale`_                          yes        yes         yes         yes          yes        no        yes         no         yes        
-`Ikoula`_                             yes        yes         yes         yes          no         no        yes         yes        yes        
-`InternetSolutions`_                  yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Kamatera`_                           yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`KTUCloud`_                           yes        yes         yes         yes          no         no        yes         yes        yes        
-`kubevirt`_                           yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Libvirt`_                            yes        no          yes         yes          yes        yes       no          no         no         
-`Linode`_                             yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Maxihost`_                           yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Nimbus`_                             yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`NTTAmerica`_                         yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`NTTC-CIS`_                           yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`OnApp`_                              yes        yes         no          yes          no         no        yes         no         no         
-`OpenNebula (v3.8)`_                  yes        yes         yes         yes          no         no        yes         yes        no         
-`OpenStack`_                          yes        no          yes         yes          yes        yes       yes         yes        no         
-`Outscale API`_                       yes        yes         yes         yes          yes        yes       yes         no         no         
-`Outscale INC`_                       yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Outscale SAS`_                       yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Ovh`_                                yes        yes         no          yes          no         no        yes         yes        yes        
-`Rackspace Cloud (Next Gen)`_         yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`Rackspace Cloud (First Gen)`_        yes        yes         yes         yes          yes        yes       yes         yes        yes        
-`RimuHosting`_                        yes        yes         yes         yes          no         no        yes         yes        yes        
-`Scaleway`_                           yes        yes         yes         yes          no         no        yes         yes        no         
-`vCloud`_                             yes        yes         yes         yes          no         no        yes         yes        yes        
-`Upcloud`_                            yes        yes         yes         yes          no         no        yes         yes        yes        
-`VCL`_                                yes        yes         no          yes          no         no        yes         yes        no         
-`vCloud`_                             yes        yes         yes         yes          no         no        yes         yes        yes        
-`vps.net`_                            yes        yes         yes         yes          no         no        yes         yes        no         
-`VMware vSphere`_                     yes        yes         yes         yes          yes        yes       yes         yes        no         
-`Vultr`_                              yes        yes         yes         yes          yes        yes       yes         yes        no         
-===================================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
+============================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
+Provider                       list nodes create node reboot node destroy node start node stop node list images list sizes deploy node
+============================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
+`Abiquo`_                      yes        yes         yes         yes          no         no        yes         yes        no         
+`Aliyun ECS`_                  yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`PCextreme AuroraCompute`_     yes        yes         yes         yes          no         no        yes         yes        yes        
+`Azure Virtual machines`_      yes        yes         yes         yes          no         no        yes         yes        yes        
+`Azure Virtual machines`_      yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Brightbox`_                   yes        yes         no          yes          no         no        yes         yes        no         
+`Cloudscale`_                  yes        yes         yes         yes          yes        yes       yes         yes        no         
+`CloudSigma (API v2.0)`_       yes        yes         yes         yes          yes        yes       yes         yes        no         
+`CloudStack`_                  yes        yes         yes         yes          no         no        yes         yes        yes        
+`DigitalOcean`_                yes        yes         yes         yes          no         no        yes         yes        no         
+`DimensionData`_               yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Amazon EC2`_                  yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`EquinixMetal`_                yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Eucalyptus`_                  yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Exoscale`_                    yes        yes         yes         yes          no         no        yes         yes        yes        
+`Gandi`_                       yes        yes         yes         yes          no         no        yes         yes        no         
+`Google Compute Engine`_       yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`GiG G8 Node Provider`_        yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Gridscale`_                   yes        yes         yes         yes          yes        no        yes         no         yes        
+`Ikoula`_                      yes        yes         yes         yes          no         no        yes         yes        yes        
+`InternetSolutions`_           yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Kamatera`_                    yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`KTUCloud`_                    yes        yes         yes         yes          no         no        yes         yes        yes        
+`kubevirt`_                    yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Libvirt`_                     yes        no          yes         yes          yes        yes       no          no         no         
+`Linode`_                      yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Maxihost`_                    yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Nimbus`_                      yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`NTTAmerica`_                  yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`NTTC-CIS`_                    yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`OnApp`_                       yes        yes         no          yes          no         no        yes         no         no         
+`OpenNebula (v3.8)`_           yes        yes         yes         yes          no         no        yes         yes        no         
+`OpenStack`_                   yes        no          yes         yes          yes        yes       yes         yes        no         
+`Outscale API`_                yes        yes         yes         yes          yes        yes       yes         no         no         
+`Outscale INC`_                yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Outscale SAS`_                yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Ovh`_                         yes        yes         no          yes          no         no        yes         yes        yes        
+`Rackspace Cloud (Next Gen)`_  yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`Rackspace Cloud (First Gen)`_ yes        yes         yes         yes          yes        yes       yes         yes        yes        
+`RimuHosting`_                 yes        yes         yes         yes          no         no        yes         yes        yes        
+`Scaleway`_                    yes        yes         yes         yes          no         no        yes         yes        no         
+`vCloud`_                      yes        yes         yes         yes          no         no        yes         yes        yes        
+`Upcloud`_                     yes        yes         yes         yes          no         no        yes         yes        yes        
+`VCL`_                         yes        yes         no          yes          no         no        yes         yes        no         
+`vCloud`_                      yes        yes         yes         yes          no         no        yes         yes        yes        
+`vps.net`_                     yes        yes         yes         yes          no         no        yes         yes        no         
+`VMware vSphere`_              yes        yes         yes         yes          yes        yes       yes         yes        no         
+`Vultr`_                       yes        yes         yes         yes          yes        yes       yes         yes        no         
+============================== ========== =========== =========== ============ ========== ========= =========== ========== ===========
 
 .. _`Abiquo`: http://www.abiquo.com/
 .. _`Aliyun ECS`: https://www.aliyun.com/product/ecs
diff --git a/docs/compute/_supported_providers.rst b/docs/compute/_supported_providers.rst
index 9c05ce5..353ae00 100644
--- a/docs/compute/_supported_providers.rst
+++ b/docs/compute/_supported_providers.rst
@@ -1,57 +1,57 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-===================================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
-Provider                              Documentation                                     Provider Constant   Supported Regions                                                                                                                                                                                                                                                                                        Module                                            Class Name                          
-===================================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
-`Abiquo`_                                                                               ABIQUO              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.abiquo`            :class:`AbiquoNodeDriver`           
-`Aliyun ECS`_                         :doc:`Click </compute/drivers/aliyun_ecs>`        ALIYUN_ECS          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ecs`               :class:`ECSDriver`                  
-`PCextreme AuroraCompute`_            :doc:`Click </compute/drivers/auroracompute>`     AURORACOMPUTE       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.auroracompute`     :class:`AuroraComputeNodeDriver`    
-`Azure Virtual machines`_             :doc:`Click </compute/drivers/azure>`             AZURE               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.azure`             :class:`AzureNodeDriver`            
-`Azure Virtual machines`_             :doc:`Click </compute/drivers/azure_arm>`         AZURE_ARM           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.azure_arm`         :class:`AzureNodeDriver`            
-`Brightbox`_                                                                            BRIGHTBOX           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.brightbox`         :class:`BrightboxNodeDriver`        
-`Cloudscale`_                         :doc:`Click </compute/drivers/cloudscale>`        CLOUDSCALE          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudscale`        :class:`CloudscaleNodeDriver`       
-`CloudSigma (API v2.0)`_              :doc:`Click </compute/drivers/cloudsigma>`        CLOUDSIGMA          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudsigma`        :class:`CloudSigmaNodeDriver`       
-`CloudStack`_                         :doc:`Click </compute/drivers/cloudstack>`        CLOUDSTACK          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudstack`        :class:`CloudStackNodeDriver`       
-`DigitalOcean`_                       :doc:`Click </compute/drivers/digital_ocean>`     DIGITAL_OCEAN       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.digitalocean`      :class:`DigitalOceanNodeDriver`     
-`DimensionData`_                      :doc:`Click </compute/drivers/dimensiondata>`     DIMENSIONDATA       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.dimensiondata`     :class:`DimensionDataNodeDriver`    
-`Amazon EC2`_                         :doc:`Click </compute/drivers/ec2>`               EC2                 af-south-1, ap-east-1, ap-northeast-1, ap-northeast-2, ap-northeast-3, ap-south-1, ap-southeast-1, ap-southeast-2, ca-central-1, cn-north-1, cn-northwest-1, eu-central-1, eu-north-1, eu-south-1, eu-west-1, eu-west-2, eu-west-3, sa-east-1, us-east-1, us-east-2, us-gov-west-1, us-west-1, us-west-2 :mod:`libcloud.compute.drivers.ec2`               :class:`EC2NodeDriver`              
-`EquinixMetal`_                       :doc:`Click </compute/drivers/equinixmetal>`      EQUINIXMETAL        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.equinixmetal`      :class:`EquinixMetalNodeDriver`     
-`Eucalyptus`_                                                                           EUCALYPTUS          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`EucNodeDriver`              
-`Exoscale`_                           :doc:`Click </compute/drivers/exoscale>`          EXOSCALE            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.exoscale`          :class:`ExoscaleNodeDriver`         
-`Gandi`_                              :doc:`Click </compute/drivers/gandi>`             GANDI               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gandi`             :class:`GandiNodeDriver`            
-`Google Compute Engine`_              :doc:`Click </compute/drivers/gce>`               GCE                 single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gce`               :class:`GCENodeDriver`              
-`GiG G8 Node Provider`_                                                                 GIG_G8              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gig_g8`            :class:`G8NodeDriver`               
-`Gridscale`_                          :doc:`Click </compute/drivers/gridscale>`         GRIDSCALE           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gridscale`         :class:`GridscaleNodeDriver`        
-`Ikoula`_                             :doc:`Click </compute/drivers/ikoula>`            IKOULA              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ikoula`            :class:`IkoulaNodeDriver`           
-`InternetSolutions`_                  :doc:`Click </compute/drivers/internetsolutions>` INTERNETSOLUTIONS   single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.internetsolutions` :class:`InternetSolutionsNodeDriver`
-`Kamatera`_                           :doc:`Click </compute/drivers/kamatera>`          KAMATERA            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.kamatera`          :class:`KamateraNodeDriver`         
-`KTUCloud`_                                                                             KTUCLOUD            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ktucloud`          :class:`KTUCloudNodeDriver`         
-`kubevirt`_                                                                             KUBEVIRT            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.kubevirt`          :class:`KubeVirtNodeDriver`         
-`Libvirt`_                            :doc:`Click </compute/drivers/libvirt>`           LIBVIRT             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.libvirt_driver`    :class:`LibvirtNodeDriver`          
-`Linode`_                                                                               LINODE              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.linode`            :class:`LinodeNodeDriver`           
-`Maxihost`_                           :doc:`Click </compute/drivers/maxihost>`          MAXIHOST            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.maxihost`          :class:`MaxihostNodeDriver`         
-`Nimbus`_                             :doc:`Click </compute/drivers/nimbus>`            NIMBUS              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`NimbusNodeDriver`           
-`NTTAmerica`_                         :doc:`Click </compute/drivers/ntta>`              NTTA                single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ntta`              :class:`NTTAmericaNodeDriver`       
-`NTTC-CIS`_                           :doc:`Click </compute/drivers/nttcis>`            NTTCIS              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.nttcis`            :class:`NttCisNodeDriver`           
-`OnApp`_                              :doc:`Click </compute/drivers/onapp>`             ONAPP               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.onapp`             :class:`OnAppNodeDriver`            
-`OpenNebula (v3.8)`_                                                                    OPENNEBULA          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.opennebula`        :class:`OpenNebulaNodeDriver`       
-`OpenStack`_                          :doc:`Click </compute/drivers/openstack>`         OPENSTACK           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.openstack`         :class:`OpenStackNodeDriver`        
-`Outscale API`_                       :doc:`Click </compute/drivers/outscale>`          OUTSCALE            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.outscale`          :class:`OutscaleNodeDriver`         
-`Outscale INC`_                       :doc:`Click </compute/drivers/outscale_inc>`      OUTSCALE_INC        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`OutscaleINCNodeDriver`      
-`Outscale SAS`_                       :doc:`Click </compute/drivers/outscale_sas>`      OUTSCALE_SAS        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`OutscaleSASNodeDriver`      
-`Ovh`_                                :doc:`Click </compute/drivers/ovh>`               OVH                 ca, eu                                                                                                                                                                                                                                                                                                   :mod:`libcloud.compute.drivers.ovh`               :class:`OvhNodeDriver`              
-`Rackspace Cloud (Next Gen)`_         :doc:`Click </compute/drivers/rackspace>`         RACKSPACE           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rackspace`         :class:`RackspaceNodeDriver`        
-`Rackspace Cloud (First Gen)`_                                                          RACKSPACE_FIRST_GEN single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rackspace`         :class:`RackspaceFirstGenNodeDriver`
-`RimuHosting`_                                                                          RIMUHOSTING         single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rimuhosting`       :class:`RimuHostingNodeDriver`      
-`Scaleway`_                           :doc:`Click </compute/drivers/scaleway>`          SCALEWAY            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.scaleway`          :class:`ScalewayNodeDriver`         
-`vCloud`_                                                                               TERREMARK           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcloud`            :class:`TerremarkDriver`            
-`Upcloud`_                            :doc:`Click </compute/drivers/upcloud>`           UPCLOUD             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.upcloud`           :class:`UpcloudDriver`              
-`VCL`_                                                                                  VCL                 single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcl`               :class:`VCLNodeDriver`              
-`vCloud`_                             :doc:`Click </compute/drivers/vcloud>`            VCLOUD              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcloud`            :class:`VCloudNodeDriver`           
-`vps.net`_                                                                              VPSNET              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vpsnet`            :class:`VPSNetNodeDriver`           
-`VMware vSphere`_                     :doc:`Click </compute/drivers/vsphere>`           VSPHERE             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vsphere`           :class:`VSphereNodeDriver`          
-`Vultr`_                              :doc:`Click </compute/drivers/vultr>`             VULTR               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vultr`             :class:`VultrNodeDriver`            
-===================================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
+============================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
+Provider                       Documentation                                     Provider Constant   Supported Regions                                                                                                                                                                                                                                                                                        Module                                            Class Name                          
+============================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
+`Abiquo`_                                                                        ABIQUO              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.abiquo`            :class:`AbiquoNodeDriver`           
+`Aliyun ECS`_                  :doc:`Click </compute/drivers/aliyun_ecs>`        ALIYUN_ECS          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ecs`               :class:`ECSDriver`                  
+`PCextreme AuroraCompute`_     :doc:`Click </compute/drivers/auroracompute>`     AURORACOMPUTE       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.auroracompute`     :class:`AuroraComputeNodeDriver`    
+`Azure Virtual machines`_      :doc:`Click </compute/drivers/azure>`             AZURE               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.azure`             :class:`AzureNodeDriver`            
+`Azure Virtual machines`_      :doc:`Click </compute/drivers/azure_arm>`         AZURE_ARM           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.azure_arm`         :class:`AzureNodeDriver`            
+`Brightbox`_                                                                     BRIGHTBOX           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.brightbox`         :class:`BrightboxNodeDriver`        
+`Cloudscale`_                  :doc:`Click </compute/drivers/cloudscale>`        CLOUDSCALE          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudscale`        :class:`CloudscaleNodeDriver`       
+`CloudSigma (API v2.0)`_       :doc:`Click </compute/drivers/cloudsigma>`        CLOUDSIGMA          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudsigma`        :class:`CloudSigmaNodeDriver`       
+`CloudStack`_                  :doc:`Click </compute/drivers/cloudstack>`        CLOUDSTACK          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.cloudstack`        :class:`CloudStackNodeDriver`       
+`DigitalOcean`_                :doc:`Click </compute/drivers/digital_ocean>`     DIGITAL_OCEAN       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.digitalocean`      :class:`DigitalOceanNodeDriver`     
+`DimensionData`_               :doc:`Click </compute/drivers/dimensiondata>`     DIMENSIONDATA       single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.dimensiondata`     :class:`DimensionDataNodeDriver`    
+`Amazon EC2`_                  :doc:`Click </compute/drivers/ec2>`               EC2                 af-south-1, ap-east-1, ap-northeast-1, ap-northeast-2, ap-northeast-3, ap-south-1, ap-southeast-1, ap-southeast-2, ca-central-1, cn-north-1, cn-northwest-1, eu-central-1, eu-north-1, eu-south-1, eu-west-1, eu-west-2, eu-west-3, sa-east-1, us-east-1, us-east-2, us-gov-west-1, us-west-1, us-west-2 :mod:`libcloud.compute.drivers.ec2`               :class:`EC2NodeDriver`              
+`EquinixMetal`_                :doc:`Click </compute/drivers/equinixmetal>`      EQUINIXMETAL        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.equinixmetal`      :class:`EquinixMetalNodeDriver`     
+`Eucalyptus`_                                                                    EUCALYPTUS          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`EucNodeDriver`              
+`Exoscale`_                    :doc:`Click </compute/drivers/exoscale>`          EXOSCALE            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.exoscale`          :class:`ExoscaleNodeDriver`         
+`Gandi`_                       :doc:`Click </compute/drivers/gandi>`             GANDI               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gandi`             :class:`GandiNodeDriver`            
+`Google Compute Engine`_       :doc:`Click </compute/drivers/gce>`               GCE                 single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gce`               :class:`GCENodeDriver`              
+`GiG G8 Node Provider`_                                                          GIG_G8              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gig_g8`            :class:`G8NodeDriver`               
+`Gridscale`_                   :doc:`Click </compute/drivers/gridscale>`         GRIDSCALE           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.gridscale`         :class:`GridscaleNodeDriver`        
+`Ikoula`_                      :doc:`Click </compute/drivers/ikoula>`            IKOULA              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ikoula`            :class:`IkoulaNodeDriver`           
+`InternetSolutions`_           :doc:`Click </compute/drivers/internetsolutions>` INTERNETSOLUTIONS   single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.internetsolutions` :class:`InternetSolutionsNodeDriver`
+`Kamatera`_                    :doc:`Click </compute/drivers/kamatera>`          KAMATERA            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.kamatera`          :class:`KamateraNodeDriver`         
+`KTUCloud`_                                                                      KTUCLOUD            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ktucloud`          :class:`KTUCloudNodeDriver`         
+`kubevirt`_                                                                      KUBEVIRT            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.kubevirt`          :class:`KubeVirtNodeDriver`         
+`Libvirt`_                     :doc:`Click </compute/drivers/libvirt>`           LIBVIRT             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.libvirt_driver`    :class:`LibvirtNodeDriver`          
+`Linode`_                                                                        LINODE              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.linode`            :class:`LinodeNodeDriver`           
+`Maxihost`_                    :doc:`Click </compute/drivers/maxihost>`          MAXIHOST            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.maxihost`          :class:`MaxihostNodeDriver`         
+`Nimbus`_                      :doc:`Click </compute/drivers/nimbus>`            NIMBUS              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`NimbusNodeDriver`           
+`NTTAmerica`_                  :doc:`Click </compute/drivers/ntta>`              NTTA                single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ntta`              :class:`NTTAmericaNodeDriver`       
+`NTTC-CIS`_                    :doc:`Click </compute/drivers/nttcis>`            NTTCIS              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.nttcis`            :class:`NttCisNodeDriver`           
+`OnApp`_                       :doc:`Click </compute/drivers/onapp>`             ONAPP               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.onapp`             :class:`OnAppNodeDriver`            
+`OpenNebula (v3.8)`_                                                             OPENNEBULA          single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.opennebula`        :class:`OpenNebulaNodeDriver`       
+`OpenStack`_                   :doc:`Click </compute/drivers/openstack>`         OPENSTACK           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.openstack`         :class:`OpenStackNodeDriver`        
+`Outscale API`_                :doc:`Click </compute/drivers/outscale>`          OUTSCALE            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.outscale`          :class:`OutscaleNodeDriver`         
+`Outscale INC`_                :doc:`Click </compute/drivers/outscale_inc>`      OUTSCALE_INC        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`OutscaleINCNodeDriver`      
+`Outscale SAS`_                :doc:`Click </compute/drivers/outscale_sas>`      OUTSCALE_SAS        single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.ec2`               :class:`OutscaleSASNodeDriver`      
+`Ovh`_                         :doc:`Click </compute/drivers/ovh>`               OVH                 ca, eu                                                                                                                                                                                                                                                                                                   :mod:`libcloud.compute.drivers.ovh`               :class:`OvhNodeDriver`              
+`Rackspace Cloud (Next Gen)`_  :doc:`Click </compute/drivers/rackspace>`         RACKSPACE           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rackspace`         :class:`RackspaceNodeDriver`        
+`Rackspace Cloud (First Gen)`_                                                   RACKSPACE_FIRST_GEN single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rackspace`         :class:`RackspaceFirstGenNodeDriver`
+`RimuHosting`_                                                                   RIMUHOSTING         single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.rimuhosting`       :class:`RimuHostingNodeDriver`      
+`Scaleway`_                    :doc:`Click </compute/drivers/scaleway>`          SCALEWAY            single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.scaleway`          :class:`ScalewayNodeDriver`         
+`vCloud`_                                                                        TERREMARK           single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcloud`            :class:`TerremarkDriver`            
+`Upcloud`_                     :doc:`Click </compute/drivers/upcloud>`           UPCLOUD             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.upcloud`           :class:`UpcloudDriver`              
+`VCL`_                                                                           VCL                 single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcl`               :class:`VCLNodeDriver`              
+`vCloud`_                      :doc:`Click </compute/drivers/vcloud>`            VCLOUD              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vcloud`            :class:`VCloudNodeDriver`           
+`vps.net`_                                                                       VPSNET              single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vpsnet`            :class:`VPSNetNodeDriver`           
+`VMware vSphere`_              :doc:`Click </compute/drivers/vsphere>`           VSPHERE             single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vsphere`           :class:`VSphereNodeDriver`          
+`Vultr`_                       :doc:`Click </compute/drivers/vultr>`             VULTR               single region driver                                                                                                                                                                                                                                                                                     :mod:`libcloud.compute.drivers.vultr`             :class:`VultrNodeDriver`            
+============================== ================================================= =================== ======================================================================================================================================================================================================================================================================================================== ================================================= ====================================
 
 .. _`Abiquo`: http://www.abiquo.com/
 .. _`Aliyun ECS`: https://www.aliyun.com/product/ecs
diff --git a/docs/dns/_supported_methods.rst b/docs/dns/_supported_methods.rst
index cd296e8..168a30f 100644
--- a/docs/dns/_supported_methods.rst
+++ b/docs/dns/_supported_methods.rst
@@ -1,34 +1,34 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-=================== ========== ============ =========== =========== ============= ============= =========== =============
-Provider            list zones list records create zone update zone create record update record delete zone delete record
-=================== ========== ============ =========== =========== ============= ============= =========== =============
-`AuroraDNS`_        yes        yes          yes         no          yes           yes           yes         yes          
-`BuddyNS DNS`_      yes        no           yes         no          no            no            yes         no           
-`CloudFlare DNS`_   yes        yes          yes         yes         yes           yes           yes         yes          
-`DigitalOcean`_     yes        yes          yes         no          yes           yes           yes         yes          
-`DNSimple`_         yes        yes          yes         no          yes           yes           yes         yes          
-`DurableDNS`_       yes        yes          yes         yes         yes           yes           yes         yes          
-`Gandi DNS`_        yes        yes          yes         yes         yes           yes           yes         yes          
-`Gandi LiveDNS`_    yes        yes          yes         no          yes           yes           no          yes          
-`GoDaddy DNS`_      yes        yes          no          no          yes           yes           yes         no           
-`Google DNS`_       yes        yes          yes         no          yes           no            yes         yes          
-`Linode DNS`_       yes        yes          yes         yes         yes           yes           yes         yes          
-`Liquidweb DNS`_    yes        yes          yes         no          yes           yes           yes         yes          
-`Luadns`_           yes        yes          yes         no          yes           no            yes         yes          
-`NFSN DNS`_         no         yes          no          no          yes           no            no          yes          
-`NS1 DNS`_          yes        yes          yes         no          yes           yes           yes         yes          
-`OnApp`_            yes        yes          yes         no          yes           yes           yes         yes          
-`Point DNS`_        yes        yes          yes         yes         yes           yes           yes         yes          
-`PowerDNS`_         yes        yes          yes         no          yes           yes           yes         yes          
-`Rackspace DNS`_    yes        yes          yes         yes         yes           yes           yes         yes          
-`RcodeZero DNS`_    yes        yes          yes         yes         yes           yes           yes         yes          
-`Route53 DNS`_      yes        yes          yes         no          yes           yes           yes         yes          
-`Vultr DNS`_        yes        yes          yes         no          yes           yes           yes         yes          
-`World Wide DNS`_   yes        yes          yes         yes         yes           yes           yes         yes          
-`Zerigo DNS`_       yes        yes          yes         yes         yes           yes           yes         yes          
-`Zonomi DNS`_       yes        yes          yes         no          yes           no            yes         yes          
-=================== ========== ============ =========== =========== ============= ============= =========== =============
+================= ========== ============ =========== =========== ============= ============= =========== =============
+Provider          list zones list records create zone update zone create record update record delete zone delete record
+================= ========== ============ =========== =========== ============= ============= =========== =============
+`AuroraDNS`_      yes        yes          yes         no          yes           yes           yes         yes          
+`BuddyNS DNS`_    yes        no           yes         no          no            no            yes         no           
+`CloudFlare DNS`_ yes        yes          yes         yes         yes           yes           yes         yes          
+`DigitalOcean`_   yes        yes          yes         no          yes           yes           yes         yes          
+`DNSimple`_       yes        yes          yes         no          yes           yes           yes         yes          
+`DurableDNS`_     yes        yes          yes         yes         yes           yes           yes         yes          
+`Gandi DNS`_      yes        yes          yes         yes         yes           yes           yes         yes          
+`Gandi LiveDNS`_  yes        yes          yes         no          yes           yes           no          yes          
+`GoDaddy DNS`_    yes        yes          no          no          yes           yes           yes         no           
+`Google DNS`_     yes        yes          yes         no          yes           no            yes         yes          
+`Linode DNS`_     yes        yes          yes         yes         yes           yes           yes         yes          
+`Liquidweb DNS`_  yes        yes          yes         no          yes           yes           yes         yes          
+`Luadns`_         yes        yes          yes         no          yes           no            yes         yes          
+`NFSN DNS`_       no         yes          no          no          yes           no            no          yes          
+`NS1 DNS`_        yes        yes          yes         no          yes           yes           yes         yes          
+`OnApp`_          yes        yes          yes         no          yes           yes           yes         yes          
+`Point DNS`_      yes        yes          yes         yes         yes           yes           yes         yes          
+`PowerDNS`_       yes        yes          yes         no          yes           yes           yes         yes          
+`Rackspace DNS`_  yes        yes          yes         yes         yes           yes           yes         yes          
+`RcodeZero DNS`_  yes        yes          yes         yes         yes           yes           yes         yes          
+`Route53 DNS`_    yes        yes          yes         no          yes           yes           yes         yes          
+`Vultr DNS`_      yes        yes          yes         no          yes           yes           yes         yes          
+`World Wide DNS`_ yes        yes          yes         yes         yes           yes           yes         yes          
+`Zerigo DNS`_     yes        yes          yes         yes         yes           yes           yes         yes          
+`Zonomi DNS`_     yes        yes          yes         no          yes           no            yes         yes          
+================= ========== ============ =========== =========== ============= ============= =========== =============
 
 .. _`AuroraDNS`: https://www.pcextreme.nl/en/aurora/dns
 .. _`BuddyNS DNS`: https://www.buddyns.com
diff --git a/docs/dns/_supported_providers.rst b/docs/dns/_supported_providers.rst
index b05b9d6..39da462 100644
--- a/docs/dns/_supported_providers.rst
+++ b/docs/dns/_supported_providers.rst
@@ -1,34 +1,34 @@
 .. NOTE: This file has been generated automatically using generate_provider_feature_matrix_table.py script, don't manually edit it
 
-=================== ========================================= ================= ==================== ======================================== ==============================
-Provider            Documentation                             Provider Constant Supported Regions    Module                                   Class Name                    
-=================== ========================================= ================= ==================== ======================================== ==============================
-`AuroraDNS`_        :doc:`Click </dns/drivers/auroradns>`     AURORADNS         single region driver :mod:`libcloud.dns.drivers.auroradns`    :class:`AuroraDNSDriver`      
-`BuddyNS DNS`_      :doc:`Click </dns/drivers/buddyns>`       BUDDYNS           single region driver :mod:`libcloud.dns.drivers.buddyns`      :class:`BuddyNSDNSDriver`     
-`CloudFlare DNS`_   :doc:`Click </dns/drivers/cloudflare>`    CLOUDFLARE        single region driver :mod:`libcloud.dns.drivers.cloudflare`   :class:`CloudFlareDNSDriver`  
-`DigitalOcean`_     :doc:`Click </dns/drivers/digital_ocean>` DIGITAL_OCEAN     single region driver :mod:`libcloud.dns.drivers.digitalocean` :class:`DigitalOceanDNSDriver`
-`DNSimple`_         :doc:`Click </dns/drivers/dnsimple>`      DNSIMPLE          single region driver :mod:`libcloud.dns.drivers.dnsimple`     :class:`DNSimpleDNSDriver`    
-`DurableDNS`_       :doc:`Click </dns/drivers/durabledns>`    DURABLEDNS        single region driver :mod:`libcloud.dns.drivers.durabledns`   :class:`DurableDNSDriver`     
-`Gandi DNS`_                                                  GANDI             single region driver :mod:`libcloud.dns.drivers.gandi`        :class:`GandiDNSDriver`       
-`Gandi LiveDNS`_                                              GANDI_LIVE        single region driver :mod:`libcloud.dns.drivers.gandi_live`   :class:`GandiLiveDNSDriver`   
-`GoDaddy DNS`_      :doc:`Click </dns/drivers/godaddy>`       GODADDY           single region driver :mod:`libcloud.dns.drivers.godaddy`      :class:`GoDaddyDNSDriver`     
-`Google DNS`_       :doc:`Click </dns/drivers/google>`        GOOGLE            single region driver :mod:`libcloud.dns.drivers.google`       :class:`GoogleDNSDriver`      
-`Linode DNS`_                                                 LINODE            single region driver :mod:`libcloud.dns.drivers.linode`       :class:`LinodeDNSDriver`      
-`Liquidweb DNS`_    :doc:`Click </dns/drivers/liquidweb>`     LIQUIDWEB         single region driver :mod:`libcloud.dns.drivers.liquidweb`    :class:`LiquidWebDNSDriver`   
-`Luadns`_           :doc:`Click </dns/drivers/luadns>`        LUADNS            single region driver :mod:`libcloud.dns.drivers.luadns`       :class:`LuadnsDNSDriver`      
-`NFSN DNS`_         :doc:`Click </dns/drivers/nfsn>`          NFSN              single region driver :mod:`libcloud.dns.drivers.nfsn`         :class:`NFSNDNSDriver`        
-`NS1 DNS`_                                                    NSONE             single region driver :mod:`libcloud.dns.drivers.nsone`        :class:`NsOneDNSDriver`       
-`OnApp`_            :doc:`Click </dns/drivers/onapp>`         ONAPP             single region driver :mod:`libcloud.dns.drivers.onapp`        :class:`OnAppDNSDriver`       
-`Point DNS`_        :doc:`Click </dns/drivers/pointdns>`      POINTDNS          single region driver :mod:`libcloud.dns.drivers.pointdns`     :class:`PointDNSDriver`       
-`PowerDNS`_         :doc:`Click </dns/drivers/powerdns>`      POWERDNS          single region driver :mod:`libcloud.dns.drivers.powerdns`     :class:`PowerDNSDriver`       
-`Rackspace DNS`_                                              RACKSPACE         uk, us               :mod:`libcloud.dns.drivers.rackspace`    :class:`RackspaceDNSDriver`   
-`RcodeZero DNS`_    :doc:`Click </dns/drivers/rcodezero>`     RCODEZERO         single region driver :mod:`libcloud.dns.drivers.rcodezero`    :class:`RcodeZeroDNSDriver`   
-`Route53 DNS`_                                                ROUTE53           single region driver :mod:`libcloud.dns.drivers.route53`      :class:`Route53DNSDriver`     
-`Vultr DNS`_        :doc:`Click </dns/drivers/vultr>`         VULTR             single region driver :mod:`libcloud.dns.drivers.vultr`        :class:`VultrDNSDriver`       
-`World Wide DNS`_   :doc:`Click </dns/drivers/worldwidedns>`  WORLDWIDEDNS      single region driver :mod:`libcloud.dns.drivers.worldwidedns` :class:`WorldWideDNSDriver`   
-`Zerigo DNS`_                                                 ZERIGO            single region driver :mod:`libcloud.dns.drivers.zerigo`       :class:`ZerigoDNSDriver`      
-`Zonomi DNS`_       :doc:`Click </dns/drivers/zonomi>`        ZONOMI            single region driver :mod:`libcloud.dns.drivers.zonomi`       :class:`ZonomiDNSDriver`      
-=================== ========================================= ================= ==================== ======================================== ==============================
+================= ========================================= ================= ==================== ======================================== ==============================
+Provider          Documentation                             Provider Constant Supported Regions    Module                                   Class Name                    
+================= ========================================= ================= ==================== ======================================== ==============================
+`AuroraDNS`_      :doc:`Click </dns/drivers/auroradns>`     AURORADNS         single region driver :mod:`libcloud.dns.drivers.auroradns`    :class:`AuroraDNSDriver`      
+`BuddyNS DNS`_    :doc:`Click </dns/drivers/buddyns>`       BUDDYNS           single region driver :mod:`libcloud.dns.drivers.buddyns`      :class:`BuddyNSDNSDriver`     
+`CloudFlare DNS`_ :doc:`Click </dns/drivers/cloudflare>`    CLOUDFLARE        single region driver :mod:`libcloud.dns.drivers.cloudflare`   :class:`CloudFlareDNSDriver`  
+`DigitalOcean`_   :doc:`Click </dns/drivers/digital_ocean>` DIGITAL_OCEAN     single region driver :mod:`libcloud.dns.drivers.digitalocean` :class:`DigitalOceanDNSDriver`
+`DNSimple`_       :doc:`Click </dns/drivers/dnsimple>`      DNSIMPLE          single region driver :mod:`libcloud.dns.drivers.dnsimple`     :class:`DNSimpleDNSDriver`    
+`DurableDNS`_     :doc:`Click </dns/drivers/durabledns>`    DURABLEDNS        single region driver :mod:`libcloud.dns.drivers.durabledns`   :class:`DurableDNSDriver`     
+`Gandi DNS`_                                                GANDI             single region driver :mod:`libcloud.dns.drivers.gandi`        :class:`GandiDNSDriver`       
+`Gandi LiveDNS`_                                            GANDI_LIVE        single region driver :mod:`libcloud.dns.drivers.gandi_live`   :class:`GandiLiveDNSDriver`   
+`GoDaddy DNS`_    :doc:`Click </dns/drivers/godaddy>`       GODADDY           single region driver :mod:`libcloud.dns.drivers.godaddy`      :class:`GoDaddyDNSDriver`     
+`Google DNS`_     :doc:`Click </dns/drivers/google>`        GOOGLE            single region driver :mod:`libcloud.dns.drivers.google`       :class:`GoogleDNSDriver`      
+`Linode DNS`_                                               LINODE            single region driver :mod:`libcloud.dns.drivers.linode`       :class:`LinodeDNSDriver`      
+`Liquidweb DNS`_  :doc:`Click </dns/drivers/liquidweb>`     LIQUIDWEB         single region driver :mod:`libcloud.dns.drivers.liquidweb`    :class:`LiquidWebDNSDriver`   
+`Luadns`_         :doc:`Click </dns/drivers/luadns>`        LUADNS            single region driver :mod:`libcloud.dns.drivers.luadns`       :class:`LuadnsDNSDriver`      
+`NFSN DNS`_       :doc:`Click </dns/drivers/nfsn>`          NFSN              single region driver :mod:`libcloud.dns.drivers.nfsn`         :class:`NFSNDNSDriver`        
+`NS1 DNS`_                                                  NSONE             single region driver :mod:`libcloud.dns.drivers.nsone`        :class:`NsOneDNSDriver`       
+`OnApp`_          :doc:`Click </dns/drivers/onapp>`         ONAPP             single region driver :mod:`libcloud.dns.drivers.onapp`        :class:`OnAppDNSDriver`       
+`Point DNS`_      :doc:`Click </dns/drivers/pointdns>`      POINTDNS          single region driver :mod:`libcloud.dns.drivers.pointdns`     :class:`PointDNSDriver`       
+`PowerDNS`_       :doc:`Click </dns/drivers/powerdns>`      POWERDNS          single region driver :mod:`libcloud.dns.drivers.powerdns`     :class:`PowerDNSDriver`       
+`Rackspace DNS`_                                            RACKSPACE         uk, us               :mod:`libcloud.dns.drivers.rackspace`    :class:`RackspaceDNSDriver`   
+`RcodeZero DNS`_  :doc:`Click </dns/drivers/rcodezero>`     RCODEZERO         single region driver :mod:`libcloud.dns.drivers.rcodezero`    :class:`RcodeZeroDNSDriver`   
+`Route53 DNS`_                                              ROUTE53           single region driver :mod:`libcloud.dns.drivers.route53`      :class:`Route53DNSDriver`     
+`Vultr DNS`_      :doc:`Click </dns/drivers/vultr>`         VULTR             single region driver :mod:`libcloud.dns.drivers.vultr`        :class:`VultrDNSDriver`       
+`World Wide DNS`_ :doc:`Click </dns/drivers/worldwidedns>`  WORLDWIDEDNS      single region driver :mod:`libcloud.dns.drivers.worldwidedns` :class:`WorldWideDNSDriver`   
+`Zerigo DNS`_                                               ZERIGO            single region driver :mod:`libcloud.dns.drivers.zerigo`       :class:`ZerigoDNSDriver`      
+`Zonomi DNS`_     :doc:`Click </dns/drivers/zonomi>`        ZONOMI            single region driver :mod:`libcloud.dns.drivers.zonomi`       :class:`ZonomiDNSDriver`      
+================= ========================================= ================= ==================== ======================================== ==============================
 
 .. _`AuroraDNS`: https://www.pcextreme.nl/en/aurora/dns
 .. _`BuddyNS DNS`: https://www.buddyns.com
diff --git a/docs/examples/container/lxd/example_lxd.py b/docs/examples/container/lxd/example_lxd.py
index 7b8d1bf..55932af 100644
--- a/docs/examples/container/lxd/example_lxd.py
+++ b/docs/examples/container/lxd/example_lxd.py
@@ -123,7 +123,6 @@
 
 
 def work_with_images():
-
     print("Working with images...")
 
     # LXD host change accordingly
diff --git a/libcloud/backup/drivers/dimensiondata.py b/libcloud/backup/drivers/dimensiondata.py
index f7d0f1e..4ea7750 100644
--- a/libcloud/backup/drivers/dimensiondata.py
+++ b/libcloud/backup/drivers/dimensiondata.py
@@ -63,7 +63,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS and host is None:
             raise ValueError("Invalid region: %s, no host specified" % (region))
         if region is not None:
diff --git a/libcloud/common/aliyun.py b/libcloud/common/aliyun.py
index 84ff648..2414432 100644
--- a/libcloud/common/aliyun.py
+++ b/libcloud/common/aliyun.py
@@ -167,7 +167,6 @@
 
 
 class SignedAliyunConnection(AliyunConnection):
-
     api_version = None
 
     def __init__(
diff --git a/libcloud/common/azure.py b/libcloud/common/azure.py
index 99cff66..cce42df 100644
--- a/libcloud/common/azure.py
+++ b/libcloud/common/azure.py
@@ -191,7 +191,6 @@
         retry_failed=None,
         *kwargs,
     ):
-
         # Log in again if the token has expired or is going to expire soon
         # (next 5 minutes).
         if (time.time() + 300) >= int(self.expires_on):
diff --git a/libcloud/common/azure_arm.py b/libcloud/common/azure_arm.py
index 8f849c1..b8caf3a 100644
--- a/libcloud/common/azure_arm.py
+++ b/libcloud/common/azure_arm.py
@@ -209,7 +209,6 @@
         return super().connect(**kwargs)
 
     def request(self, action, params=None, data=None, headers=None, method="GET", raw=False):
-
         # Log in again if the token has expired or is going to expire soon
         # (next 5 minutes).
         if (time.time() + 300) >= int(self.expires_on):
diff --git a/libcloud/common/durabledns.py b/libcloud/common/durabledns.py
index ff6b74a..1516409 100644
--- a/libcloud/common/durabledns.py
+++ b/libcloud/common/durabledns.py
@@ -160,7 +160,6 @@
 
 
 class DurableResponse(XmlResponse):
-
     errors = []  # type: List[Dict]
     objects = []  # type: List[Dict]
 
diff --git a/libcloud/common/google.py b/libcloud/common/google.py
index aa79859..1869e2e 100644
--- a/libcloud/common/google.py
+++ b/libcloud/common/google.py
@@ -499,7 +499,6 @@
         access_code = None
 
         class AccessCodeReceiver(BaseHTTPRequestHandler):
-
             # noinspection PyMethodParameters,PyPep8Naming
             def do_GET(self_):  # pylint: disable=no-self-argument
                 query = urlparse.urlparse(self_.path).query
diff --git a/libcloud/common/gridscale.py b/libcloud/common/gridscale.py
index 5582221..1c808f5 100644
--- a/libcloud/common/gridscale.py
+++ b/libcloud/common/gridscale.py
@@ -96,7 +96,6 @@
         return r
 
     def get_poll_request_kwargs(self, response, context, request_kwargs):
-
         endpoint_url = "requests/{}".format(response.object["request_uuid"])
         kwargs = {"action": endpoint_url}
         return kwargs
diff --git a/libcloud/common/kubernetes.py b/libcloud/common/kubernetes.py
index 465af7d..f4fadf6 100644
--- a/libcloud/common/kubernetes.py
+++ b/libcloud/common/kubernetes.py
@@ -62,7 +62,6 @@
 
 
 class KubernetesResponse(JsonResponse):
-
     valid_response_codes = [
         httplib.OK,
         httplib.ACCEPTED,
@@ -93,7 +92,6 @@
         cert_file=None,
         **kwargs,
     ):
-
         super().__init__(
             key_file=key_file,
             cert_file=cert_file,
diff --git a/libcloud/common/nttcis.py b/libcloud/common/nttcis.py
index 9519b8c..5d36dfa 100644
--- a/libcloud/common/nttcis.py
+++ b/libcloud/common/nttcis.py
@@ -2293,7 +2293,6 @@
                 # It is possible to have duplicate element tags.
                 # If so, convert to a dict of lists
                 if element.tag.split("}")[1] in self:
-
                     if isinstance(self[element.tag.split("}")[1]], list):
                         self[element.tag.split("}")[1]].append(dict(element.items()))
                     else:
diff --git a/libcloud/common/openstack.py b/libcloud/common/openstack.py
index de0c99e..960b759 100644
--- a/libcloud/common/openstack.py
+++ b/libcloud/common/openstack.py
@@ -357,9 +357,14 @@
         return super().morph_action_hook(action)
 
     def _set_up_connection_info(self, url):
+        prev_conn = (self.host, self.port, self.secure)
         result = self._tuple_from_url(url)
         (self.host, self.port, self.secure, self.request_path) = result
-        self.connect()
+        new_conn = (self.host, self.port, self.secure)
+        if new_conn != prev_conn:
+            # We only call connect in case connection details have changed - this way we correctly
+            # re-use connection in case nothing has changed
+            self.connect()
 
     def _populate_hosts_and_request_paths(self):
         """
diff --git a/libcloud/common/types.py b/libcloud/common/types.py
index c5b1732..673e0d9 100644
--- a/libcloud/common/types.py
+++ b/libcloud/common/types.py
@@ -89,7 +89,7 @@
     """The base class for other libcloud exceptions"""
 
     def __init__(self, value, driver=None):
-        # type: (str, BaseDriver) -> None
+        # type: (str, Optional[BaseDriver]) -> None
         super().__init__(value)
         self.value = value
         self.driver = driver
diff --git a/libcloud/common/vultr.py b/libcloud/common/vultr.py
index 10f86dc..0415715 100644
--- a/libcloud/common/vultr.py
+++ b/libcloud/common/vultr.py
@@ -38,7 +38,6 @@
 
 
 class VultrResponse(JsonResponse):
-
     objects = None
     error_dict = {}  # type: Dict[str, str]
     errors = None
@@ -55,7 +54,6 @@
     }
 
     def __init__(self, response, connection):
-
         self.errors = []
         super().__init__(response=response, connection=connection)
         self.objects, self.errors = self.parse_body_and_errors()
@@ -90,7 +88,6 @@
         return VultrException(error["ERRORCODE"], error["ERRORMESSAGE"])
 
     def success(self):
-
         return len(self.errors) == 0
 
 
diff --git a/libcloud/common/xmlrpc.py b/libcloud/common/xmlrpc.py
index 278fc40..e22d913 100644
--- a/libcloud/common/xmlrpc.py
+++ b/libcloud/common/xmlrpc.py
@@ -53,7 +53,6 @@
 
 
 class XMLRPCResponse(ErrorCodeMixin, Response):
-
     defaultExceptionCls = Exception  # type: Type[Exception]
 
     def success(self):
diff --git a/libcloud/compute/base.py b/libcloud/compute/base.py
index ac22a2d..7ec7772 100644
--- a/libcloud/compute/base.py
+++ b/libcloud/compute/base.py
@@ -118,8 +118,8 @@
     Mixin class for get_uuid function.
     """
 
-    def __init__(self):
-        self._uuid = None  # type: str
+    def __init__(self) -> None:
+        self._uuid = None  # type: Optional[str]
 
     def get_uuid(self):
         """
@@ -208,10 +208,10 @@
         public_ips,  # type: List[str]
         private_ips,  # type: List[str]
         driver,
-        size=None,  # type: NodeSize
-        image=None,  # type: NodeImage
-        extra=None,  # type: dict
-        created_at=None,  # type: datetime.datetime
+        size=None,  # type: Optional[NodeSize]
+        image=None,  # type: Optional[NodeImage]
+        extra=None,  # type: Optional[dict]
+        created_at=None,  # type: Optional[datetime.datetime]
     ):
         """
         :param id: Node ID.
@@ -500,7 +500,7 @@
         image_id,  # type: str
         state,  # type: NodeImageMemberState
         driver,  # type: NodeDriver
-        created=None,  # type: datetime.datetime
+        created=None,  # type: Optional[datetime.datetime]
         extra=None,  # type: Optional[dict]
     ):
         """
@@ -755,10 +755,10 @@
         self,
         id,  # type: str
         driver,  # type: NodeDriver
-        size=None,  # type: int
+        size=None,  # type: Optional[int]
         extra=None,  # type: Optional[Dict]
         created=None,  # type: Optional[datetime.datetime]
-        state=None,  # type: StorageVolumeState
+        state=None,  # type: Optional[StorageVolumeState]
         name=None,  # type: Optional[str]
     ):
         # type: (...) -> None
@@ -935,7 +935,7 @@
         size,  # type: NodeSize
         image,  # type: NodeImage
         location=None,  # type: Optional[NodeLocation]
-        auth=None,  # type: T_Auth
+        auth=None,  # type: Optional[T_Auth]
     ):
         # type: (...) -> Node
         """
@@ -1028,11 +1028,11 @@
         ssh_timeout=10,  # type: int
         ssh_key=None,  # type: Optional[T_Ssh_key]
         ssh_key_password=None,  # type: Optional[str]
-        auth=None,  # type: T_Auth
+        auth=None,  # type: Optional[T_Auth]
         timeout=SSH_CONNECT_TIMEOUT,  # type: int
         max_tries=3,  # type: int
         ssh_interface="public_ips",  # type: str
-        at_exit_func=None,  # type: Callable
+        at_exit_func=None,  # type: Optional[Callable]
         wait_period=5,  # type: int
         **create_node_kwargs,
     ):
diff --git a/libcloud/compute/drivers/azure.py b/libcloud/compute/drivers/azure.py
index 364e0c7..b5c29a1 100644
--- a/libcloud/compute/drivers/azure.py
+++ b/libcloud/compute/drivers/azure.py
@@ -664,7 +664,6 @@
             )
 
             if self._is_storage_service_unique(service_name=ex_storage_service_name):
-
                 self._create_storage_account(
                     service_name=ex_storage_service_name,
                     location=_storage_location.service_location,
@@ -888,7 +887,6 @@
         return result
 
     def ex_set_instance_endpoints(self, node, endpoints, ex_deployment_slot="Production"):
-
         """
         For example::
 
@@ -1895,7 +1893,6 @@
         affinity_group,
         extended_properties=None,
     ):
-
         return AzureXmlSerializer.doc_from_data(
             "CreateStorageServiceInput",
             [
@@ -2249,7 +2246,6 @@
                 or endpoint.load_balancer_probe.port
                 or endpoint.load_balancer_probe.protocol
             ):
-
                 load_balancer_probe = ET.Element("LoadBalancerProbe")
                 input_endpoint.append(load_balancer_probe)
                 AzureXmlSerializer.data_to_xml(
@@ -2295,7 +2291,6 @@
         system_configuration_set,
         xml,
     ):
-
         AzureXmlSerializer.data_to_xml([("RoleName", role_name)], xml)
         AzureXmlSerializer.data_to_xml([("RoleType", role_type)], xml)
 
@@ -2396,7 +2391,6 @@
         vm_image_name,
         role_size,
     ):
-
         doc = AzureXmlSerializer.doc_from_xml("PersistentVMRole")
         AzureXmlSerializer.role_to_xml(
             availability_set_name,
@@ -2459,7 +2453,6 @@
         virtual_network_name,
         vm_image_name,
     ):
-
         doc = AzureXmlSerializer.doc_from_xml("Deployment")
         AzureXmlSerializer.data_to_xml([("Name", deployment_name)], doc)
         AzureXmlSerializer.data_to_xml([("DeploymentSlot", deployment_slot)], doc)
@@ -2560,7 +2553,6 @@
 
     @staticmethod
     def extended_properties_dict_to_xml_fragment(extended_properties):
-
         if extended_properties is not None and len(extended_properties) > 0:
             xml = ET.Element("ExtendedProperties")
             for key, val in extended_properties.items():
@@ -2595,7 +2587,6 @@
 
 
 class WindowsAzureDataTypedList(WindowsAzureData):
-
     list_type = None
     xml_element_name = None
 
diff --git a/libcloud/compute/drivers/azure_arm.py b/libcloud/compute/drivers/azure_arm.py
index bb99926..432ccf3 100644
--- a/libcloud/compute/drivers/azure_arm.py
+++ b/libcloud/compute/drivers/azure_arm.py
@@ -25,7 +25,7 @@
 import binascii
 
 from libcloud.utils import iso8601
-from libcloud.utils.py3 import basestring
+from libcloud.utils.py3 import parse_qs, urlparse, basestring
 from libcloud.common.types import LibcloudError
 from libcloud.compute.base import (
     Node,
@@ -64,6 +64,13 @@
 VM_EXTENSION_API_VERSION = "2015-06-15"
 VM_SIZE_API_VERSION = "2015-06-15"  # this API is deprecated
 
+# If pagination code in the list_nodes() method has still not completed after this mount of
+# seconds, we will break early from while True loop to avoid infinite loop under edge conditions.
+# Keep in mind that we want this timeout relatively high since each `_to_node()` method call which
+# is called for each node can result in additional HTTP requests (to retrieve power state, nics,
+# etc).
+LIST_NODES_PAGINATION_TIMEOUT = 300
+
 
 class AzureImage(NodeImage):
     """Represents a Marketplace node image that an Azure VM can boot from."""
@@ -456,8 +463,10 @@
 
         :return:  list of node objects
         :rtype: ``list`` of :class:`.Node`
-        """
 
+        NOTE: With the default arguments, the function may result in M * (1 + (N * 3)) HTTP
+        requests where M is number of API pages and N is number of nodes returned per page.
+        """
         if ex_resource_group:
             action = (
                 "/subscriptions/%s/resourceGroups/%s/"
@@ -468,11 +477,25 @@
             action = "/subscriptions/%s/providers/Microsoft.Compute/" "virtualMachines" % (
                 self.subscription_id
             )
-        r = self.connection.request(action, params={"api-version": VM_API_VERSION})
-        return [
-            self._to_node(n, fetch_nic=ex_fetch_nic, fetch_power_state=ex_fetch_power_state)
-            for n in r.object["value"]
-        ]
+        params = {"api-version": VM_API_VERSION}
+
+        now_ts = int(time.time())
+        deadline_ts = now_ts + LIST_NODES_PAGINATION_TIMEOUT
+
+        nodes = []
+        while time.time() < deadline_ts:
+            r = self.connection.request(action, params=params)
+            nodes.extend(
+                self._to_node(n, fetch_nic=ex_fetch_nic, fetch_power_state=ex_fetch_power_state)
+                for n in r.object["value"]
+            )
+            if not r.object.get("nextLink"):
+                # No next page
+                break
+            parsed_next_link = urlparse.urlparse(r.object["nextLink"])
+            params.update({k: v[0] for k, v in parse_qs(parsed_next_link.query).items()})
+            action = parsed_next_link.path
+        return nodes
 
     def create_node(
         self,
diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py
index e6c6b34..b92895d 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -44,7 +44,6 @@
     try:
         return int(value)
     except ValueError as e:
-
         if str(value).lower() == "unlimited":
             return -1
 
@@ -467,7 +466,6 @@
         start_port=None,
         end_port=None,
     ):
-
         """
         A Firewall rule.
 
@@ -530,7 +528,6 @@
         start_port=None,
         end_port=None,
     ):
-
         """
         A egress firewall rule.
 
@@ -1383,7 +1380,6 @@
         imgs = self._sync_request(command="listTemplates", params=args, method="GET")
         images = []
         for img in imgs.get("template", []):
-
             extra = {
                 "hypervisor": img["hypervisor"],
                 "format": img["format"],
@@ -2114,7 +2110,6 @@
 
         networks = []
         for vpc in vpcs:
-
             networks.append(
                 CloudStackVPC(
                     vpc["name"],
@@ -2146,7 +2141,6 @@
 
         routers = []
         for router in rts:
-
             routers.append(
                 CloudStackRouter(
                     router["id"],
@@ -4206,7 +4200,6 @@
         return True
 
     def ex_detach_nic_from_node(self, nic, node):
-
         """
         Remove Nic from a VM
 
diff --git a/libcloud/compute/drivers/dimensiondata.py b/libcloud/compute/drivers/dimensiondata.py
index dca4b18..1d0148a 100644
--- a/libcloud/compute/drivers/dimensiondata.py
+++ b/libcloud/compute/drivers/dimensiondata.py
@@ -120,7 +120,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS and host is None:
             raise ValueError("Invalid region: %s, no host specified" % (region))
         if region is not None:
@@ -2723,7 +2722,6 @@
         value_required=None,
         display_on_report=None,
     ):
-
         """
         Modify a specific tag key
 
@@ -3720,7 +3718,6 @@
         ex_tagid_value_pairs=None,
         ex_tagname_value_pairs=None,
     ):
-
         """
         This MCP 2.0 only function deploys a new Cloud Server from a
         CloudControl compatible Server Image, which does not utilize
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 9a3e2ea..506e6f6 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -3048,7 +3048,6 @@
         try:
             results.append(self.connection.request(self.path, params=params.copy()).object)
         except Exception as e:
-
             if e.args[0].find("InvalidPermission.Duplicate") == -1:
                 raise e
         return results
@@ -3346,7 +3345,6 @@
         for node_id in node_instance_ids:
             nodes_elastic_ip_mappings.setdefault(node_id, [])
             for addr in self._to_addresses(result, only_associated):
-
                 instance_id = addr.instance_id
 
                 if node_id == instance_id:
@@ -4397,7 +4395,6 @@
         ]
 
     def _to_image(self, element):
-
         id = findtext(element=element, xpath="imageId", namespace=NAMESPACE)
         name = findtext(element=element, xpath="name", namespace=NAMESPACE)
 
@@ -4410,7 +4407,6 @@
             xpath="billingProducts/item/billingProduct",
             namespace=NAMESPACE,
         ):
-
             billing_products.append(p.text)
 
         # Get our tags
@@ -4764,7 +4760,6 @@
         for item in findall(
             element=element, xpath="privateIpAddressesSet/item", namespace=NAMESPACE
         ):
-
             priv_ips.append(
                 {
                     "private_ip": findtext(
@@ -5968,7 +5963,6 @@
         return is_truncated, quota
 
     def _to_product_type(self, elem):
-
         productTypeId = findtext(element=elem, xpath="productTypeId", namespace=OUTSCALE_NAMESPACE)
         description = findtext(element=elem, xpath="description", namespace=OUTSCALE_NAMESPACE)
 
@@ -6001,7 +5995,6 @@
         return product_type
 
     def _to_product_types(self, elem):
-
         product_types = []
         for product_types_item in findall(
             element=elem, xpath="productTypeSet/item", namespace=OUTSCALE_NAMESPACE
@@ -6044,7 +6037,6 @@
         return product_types
 
     def _to_instance_types(self, elem):
-
         instance_types = []
         for instance_types_item in findall(
             element=elem, xpath="instanceTypeSet/item", namespace=OUTSCALE_NAMESPACE
diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py
index c8a140a..49b50c2 100644
--- a/libcloud/compute/drivers/gce.py
+++ b/libcloud/compute/drivers/gce.py
@@ -496,7 +496,6 @@
         capacity_scaler=1,
         description=None,
     ):
-
         if isinstance(instance_group, GCEInstanceGroup):
             self.instance_group = instance_group
         elif isinstance(instance_group, GCEInstanceGroupManager):
diff --git a/libcloud/compute/drivers/gridscale.py b/libcloud/compute/drivers/gridscale.py
index 479ea0b..c68c482 100644
--- a/libcloud/compute/drivers/gridscale.py
+++ b/libcloud/compute/drivers/gridscale.py
@@ -650,7 +650,6 @@
             return True
 
         else:
-
             return False
 
     def import_key_pair_from_string(self, name, key_material):
diff --git a/libcloud/compute/drivers/internetsolutions.py b/libcloud/compute/drivers/internetsolutions.py
index b668f8e..32cc424 100644
--- a/libcloud/compute/drivers/internetsolutions.py
+++ b/libcloud/compute/drivers/internetsolutions.py
@@ -47,7 +47,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS:
             raise ValueError("Invalid region: %s" % (region))
 
diff --git a/libcloud/compute/drivers/kubevirt.py b/libcloud/compute/drivers/kubevirt.py
index e5f8b4a..a76293d 100644
--- a/libcloud/compute/drivers/kubevirt.py
+++ b/libcloud/compute/drivers/kubevirt.py
@@ -438,7 +438,6 @@
         data = json.dumps(vm)
         req = KUBEVIRT_URL + "namespaces/" + namespace + "/virtualmachines/"
         try:
-
             self.connection.request(req, method=method, data=data)
 
         except Exception:
@@ -486,7 +485,6 @@
         return namespaces
 
     def list_sizes(self, location=None):
-
         namespace = ""
         if location:
             namespace = location.name
@@ -678,7 +676,6 @@
             raise
         if result.object["status"]["phase"] != "Bound":
             for _ in range(3):
-
                 req = ROOT_URL + "namespaces/" + namespace + "/persistentvolumeclaims/" + name
                 try:
                     result = self.connection.request(req).object
@@ -861,7 +858,6 @@
             raise
 
     def ex_list_persistent_volume_claims(self, namespace="default"):
-
         pvc_req = ROOT_URL + "namespaces/" + namespace + "/persistentvolumeclaims"
         try:
             result = self.connection.request(pvc_req).object
@@ -871,7 +867,6 @@
         return pvcs
 
     def ex_list_storage_classes(self):
-
         # sc = storage class
         sc_req = "/apis/storage.k8s.io/v1/storageclasses"
         try:
@@ -940,7 +935,6 @@
             if "memory" in vm["spec"]["template"]["spec"]["domain"]["resources"]["limits"]:
                 memory = vm["spec"]["template"]["spec"]["domain"]["resources"]["limits"]["memory"]
         elif vm["spec"]["template"]["spec"]["domain"]["resources"].get("requests", None):
-
             if vm["spec"]["template"]["spec"]["domain"]["resources"]["requests"].get(
                 "memory", None
             ):
diff --git a/libcloud/compute/drivers/linode.py b/libcloud/compute/drivers/linode.py
index 2df7000..50f2fef 100644
--- a/libcloud/compute/drivers/linode.py
+++ b/libcloud/compute/drivers/linode.py
@@ -799,7 +799,6 @@
 
 
 class LinodeNodeDriverV4(LinodeNodeDriver):
-
     connectionCls = LinodeConnectionV4
     _linode_disk_filesystems = LINODE_DISK_FILESYSTEMS_V4
 
diff --git a/libcloud/compute/drivers/ntta.py b/libcloud/compute/drivers/ntta.py
index 04de2cc..f47d2fc 100644
--- a/libcloud/compute/drivers/ntta.py
+++ b/libcloud/compute/drivers/ntta.py
@@ -47,7 +47,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS:
             raise ValueError("Invalid region: %s" % (region))
 
diff --git a/libcloud/compute/drivers/nttcis.py b/libcloud/compute/drivers/nttcis.py
index 040e468..a0d8286 100644
--- a/libcloud/compute/drivers/nttcis.py
+++ b/libcloud/compute/drivers/nttcis.py
@@ -123,7 +123,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS and host is None:
             raise ValueError("Invalid region: %s, no host specified" % (region))
         if region is not None:
@@ -3256,7 +3255,6 @@
         value_required=None,
         display_on_report=None,
     ):
-
         """
         Modify a specific tag key
 
@@ -4282,7 +4280,6 @@
         ex_tagid_value_pairs=None,
         ex_tagname_value_pairs=None,
     ):
-
         """
         This MCP 2.0 only function deploys a new Cloud Server from a
         CloudControl compatible Server Image, which does not utilize
diff --git a/libcloud/compute/drivers/outscale.py b/libcloud/compute/drivers/outscale.py
index 8b7b737..ea8eb76 100644
--- a/libcloud/compute/drivers/outscale.py
+++ b/libcloud/compute/drivers/outscale.py
@@ -7743,22 +7743,25 @@
         )
 
     def _to_volumes(self, volumes):
-        return [self._to_volumes(volume) for volume in volumes]
+        return [self._to_volume(volume) for volume in volumes]
 
     def _to_node(self, vm):
         name = ""
         private_ips = []
+        if "PrivateIp" in vm:
+            private_ips = [vm["PrivateIp"]]
+        public_ips = []
+        if "PublicIp" in vm:
+            public_ips = [vm["PublicIp"]]
         for tag in vm["Tags"]:
             if tag["Key"] == "Name":
                 name = tag["Value"]
-        if "Nics" in vm:
-            private_ips = vm["Nics"]["PrivateIps"]
 
         return Node(
             id=vm["VmId"],
             name=name,
             state=self.NODE_STATE[vm["State"]],
-            public_ips=[],
+            public_ips=public_ips,
             private_ips=private_ips,
             driver=self,
             extra=vm,
diff --git a/libcloud/compute/drivers/vsphere.py b/libcloud/compute/drivers/vsphere.py
index 692248a..3c4e457 100644
--- a/libcloud/compute/drivers/vsphere.py
+++ b/libcloud/compute/drivers/vsphere.py
@@ -1200,7 +1200,6 @@
     ]
 
     def __init__(self, key, secret=None, secure=True, host=None, port=443, ca_cert=None):
-
         if not key or not secret:
             raise InvalidCredsError("Please provide both username " "(key) and password (secret).")
         super().__init__(key=key, secure=secure, host=host, port=port)
@@ -1550,7 +1549,6 @@
         ex_filter_datacenters=None,
         ex_filter_connection_states=None,
     ):
-
         kwargs = {
             "filter.folders": ex_filter_folders,
             "filter.names": ex_filter_names,
@@ -1782,7 +1780,6 @@
         return images
 
     def ex_list_networks(self):
-
         request = "/rest/vcenter/network"
         response = self._request(request).object["value"]
         networks = []
@@ -1950,7 +1947,6 @@
             )
 
         elif image.extra["type"] == "vm-template":
-
             tp_request = "/rest/vcenter/vm-template/library-items/" + image.id
             template = self._request(tp_request).object["value"]
             spec = {}
diff --git a/libcloud/container/base.py b/libcloud/container/base.py
index 1ec7148..b684a6d 100644
--- a/libcloud/container/base.py
+++ b/libcloud/container/base.py
@@ -41,8 +41,8 @@
         state,  # type: ContainerState
         ip_addresses,  # type: List[str]
         driver,  # type: ContainerDriver
-        extra=None,  # type: dict
-        created_at=None,  # type: str
+        extra=None,  # type: Optional[dict]
+        created_at=None,  # type: Optional[str]
     ):
         """
         :param id: Container id.
@@ -112,7 +112,7 @@
         path,  # type: str
         version,  # type: str
         driver,  # type: ContainerDriver
-        extra=None,  # type: dict
+        extra=None,  # type: Optional[dict]
     ):
         """
         :param id: Container Image id.
@@ -164,7 +164,7 @@
         id,  # type: str
         name,  # type: str
         driver,  # type: ContainerDriver
-        extra=None,  # type: dict
+        extra=None,  # type: Optional[dict]
     ):
         """
         :param id: Container Image id.
diff --git a/libcloud/container/drivers/docker.py b/libcloud/container/drivers/docker.py
index a202c4e..4f64176 100644
--- a/libcloud/container/drivers/docker.py
+++ b/libcloud/container/drivers/docker.py
@@ -41,7 +41,6 @@
 
 
 class DockerResponse(JsonResponse):
-
     valid_response_codes = [
         httplib.OK,
         httplib.ACCEPTED,
@@ -102,7 +101,6 @@
 
 
 class DockerConnection(ConnectionUserAndKey):
-
     responseCls = DockerResponse
     timeout = 60
 
@@ -120,7 +118,6 @@
 
 
 class DockertlsConnection(KeyCertificateConnection):
-
     responseCls = DockerResponse
 
     def __init__(
@@ -134,7 +131,6 @@
         cert_file="",
         **kwargs,
     ):
-
         super().__init__(
             key_file=key_file,
             cert_file=cert_file,
@@ -167,7 +163,6 @@
             self.cert_file = cert_file
 
     def add_default_headers(self, headers):
-
         headers["Content-Type"] = "application/json"
         return headers
 
diff --git a/libcloud/container/drivers/lxd.py b/libcloud/container/drivers/lxd.py
index 3841d31..46e3c33 100644
--- a/libcloud/container/drivers/lxd.py
+++ b/libcloud/container/drivers/lxd.py
@@ -158,7 +158,6 @@
     """
 
     def __init__(self, name, driver, used_by, config, managed):
-
         # the name of the storage pool
         self.name = name
 
@@ -216,7 +215,6 @@
 
     @classmethod
     def build_from_response(cls, metadata):
-
         server_info = LXDServerInfo()
         server_info.api_extensions = metadata.get("api_extensions", None)
         server_info.api_status = metadata.get("api_status", None)
@@ -228,7 +226,6 @@
         return server_info
 
     def __init__(self):
-
         # List of API extensions added after
         # the API was marked stable
         self.api_extensions = None
@@ -278,7 +275,6 @@
     ]
 
     def parse_body(self):
-
         if len(self.body) == 0 and not self.parse_zero_length_body:
             return self.body
 
@@ -334,7 +330,6 @@
 
 
 class LXDtlsConnection(KeyCertificateConnection):
-
     responseCls = LXDResponse
 
     def __init__(
@@ -350,7 +345,6 @@
         certificate_validator=None,
         **kwargs,
     ):
-
         if certificate_validator is not None:
             certificate_validator(key_file=key_file, cert_file=cert_file)
         else:
@@ -419,9 +413,7 @@
         ca_cert=None,
         certificate_validator=check_certificates,
     ):
-
         if key_file:
-
             if not cert_file:
                 # LXD tls authentication-
                 # We pass two files, a key_file with the
@@ -467,7 +459,6 @@
         self.version = self._get_api_version()
 
     def build_operation_websocket_url(self, uuid, w_secret):
-
         uri = "wss://%s:%s/%s/operations/%s/" "websocket?secret=%s" % (
             self.connection.host,
             self.connection.port,
@@ -524,7 +515,6 @@
         ex_instance_type=None,
         ex_timeout=default_time_out,
     ):
-
         """
         Create a new container
         Authentication: trusted
@@ -579,7 +569,6 @@
             parameters = json.loads(parameters)
 
             if parameters["source"].get("mode", None) == "pull":
-
                 try:
                     # this means the image must be downloaded
                     image = self.install_image(path=None, ex_timeout=ex_timeout, **parameters)
@@ -623,7 +612,6 @@
         return container
 
     def get_container(self, id, ex_get_ip_addr=True):
-
         """
         Get a container by ID
 
@@ -748,7 +736,6 @@
         )
 
     def ex_freeze_container(self, container, ex_timeout=default_time_out):
-
         """
         Set the given container into a freeze state
 
@@ -770,7 +757,6 @@
         )
 
     def ex_unfreeze_container(self, container, ex_timeout=default_time_out):
-
         """
         Set the given container into  unfreeze state
 
@@ -819,14 +805,12 @@
             raise self._get_lxd_api_exception_for_error(err)
 
         try:
-
             # wait until the timeout...but util getting here the operation
             # may have finished already
             id = response_dict["metadata"]["id"]
             req = "/{}/operations/{}/wait?timeout={}".format(self.version, id, ex_timeout)
             response = self.connection.request(req)
         except BaseHTTPError as err:
-
             lxd_exception = self._get_lxd_api_exception_for_error(err)
             # if not found assume the operation completed
             if lxd_exception.message != "not found":
@@ -952,7 +936,6 @@
             )
 
         elif input["wait-for-websocket"] is True and input["interactive"] is True:
-
             return LXDContainerExecuteResult(
                 uuid=uuid,
                 secret_0=fds["0"],
@@ -964,7 +947,6 @@
             )
 
         elif input["interactive"] is False and input["record-output"] is True:
-
             output = response_dict["metadata"]["metadata"]["output"]
             result = response_dict["metadata"]["metadata"]["result"]
             return LXDContainerExecuteResult(
@@ -978,7 +960,6 @@
             )
 
         else:
-
             result = response_dict["metadata"]["metadata"]["result"]
             return LXDContainerExecuteResult(
                 uuid=uuid,
@@ -1054,7 +1035,6 @@
         return self._to_image(metadata=response_dict["metadata"])
 
     def install_image(self, path, ex_timeout=default_time_out, **ex_img_data):
-
         """
         Install a container image from a remote path. Not that the
         path currently is not used. Image data should be provided
@@ -1101,14 +1081,12 @@
         assert_response(response_dict=response_dict, status_code=100)
 
         try:
-
             # wait until the timeout...but until getting here the operation
             # may have finished already
             id = response_dict["metadata"]["id"]
             req = "/{}/operations/{}/wait?timeout={}".format(self.version, id, ex_timeout)
             response = self.connection.request(req)
         except BaseHTTPError as err:
-
             lxd_exception = self._get_lxd_api_exception_for_error(err)
             # if not found assume the operation completed
             if lxd_exception.message != "not found":
@@ -1234,7 +1212,6 @@
         return self._to_storage_pool(data=response_dict["metadata"])
 
     def ex_create_storage_pool(self, definition):
-
         """
         Create a storage_pool from definition.
 
@@ -1338,7 +1315,6 @@
             type = volume[-2]
 
             if not detailed:
-
                 metadata = {
                     "config": {"size": None},
                     "name": name,
@@ -1393,7 +1369,6 @@
         pools = response_dict["metadata"]
 
         for pool in pools:
-
             pool_id = pool.split("/")[-1]
 
             volumes = self.ex_list_storage_pool_volumes(pool_id=pool_id)
@@ -1405,7 +1380,6 @@
         return None
 
     def create_volume(self, pool_id, definition, **kwargs):
-
         """
         Create a new storage volume on a given storage pool
         Operation: sync or async (when copying an existing volume)
@@ -1460,14 +1434,12 @@
         assert_response(response_dict=response_dict, status_code=100)
 
         try:
-
             # wait until the timeout...but util getting here the operation
             # may have finished already
             oid = response_dict["metadata"]["id"]
             req = "/{}/operations/{}/wait?timeout={}".format(self.version, oid, ex_timeout)
             response = self.connection.request(req)
         except BaseHTTPError as err:
-
             lxd_exception = self._get_lxd_api_exception_for_error(err)
             # if not found assume the operation completed
             if lxd_exception.message != "not found":
@@ -1517,7 +1489,6 @@
         """
 
         try:
-
             req = "/{}/storage-pools/{}/volumes/{}/{}".format(
                 self.version,
                 pool_id,
diff --git a/libcloud/container/drivers/rancher.py b/libcloud/container/drivers/rancher.py
index 8bf423d..1e68d5f 100644
--- a/libcloud/container/drivers/rancher.py
+++ b/libcloud/container/drivers/rancher.py
@@ -66,7 +66,6 @@
 
 
 class RancherConnection(ConnectionUserAndKey):
-
     responseCls = RancherResponse
     timeout = 30
 
diff --git a/libcloud/dns/base.py b/libcloud/dns/base.py
index a358b92..f878447 100644
--- a/libcloud/dns/base.py
+++ b/libcloud/dns/base.py
@@ -36,7 +36,7 @@
         type,  # type: str
         ttl,  # type: int
         driver,  # type: DNSDriver
-        extra=None,  # type: dict
+        extra=None,  # type: Optional[dict]
     ):
         """
         :param id: Zone id.
@@ -116,8 +116,8 @@
         data,  # type: str
         zone,  # type: Zone
         driver,  # type: DNSDriver
-        ttl=None,  # type: int
-        extra=None,  # type: dict
+        ttl=None,  # type: Optional[int]
+        extra=None,  # type: Optional[dict]
     ):
         """
         :param id: Record id
diff --git a/libcloud/dns/drivers/cloudflare.py b/libcloud/dns/drivers/cloudflare.py
index 12d2db5..7cf02eb 100644
--- a/libcloud/dns/drivers/cloudflare.py
+++ b/libcloud/dns/drivers/cloudflare.py
@@ -200,7 +200,6 @@
     MEMBERSHIPS_PAGE_SIZE = 50
 
     def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs):
-
         if secret is None:
             self.connectionCls = TokenDNSConnection
 
diff --git a/libcloud/dns/drivers/linode.py b/libcloud/dns/drivers/linode.py
index 45d7480..b2f609f 100644
--- a/libcloud/dns/drivers/linode.py
+++ b/libcloud/dns/drivers/linode.py
@@ -87,7 +87,6 @@
         api_version=DEFAULT_API_VERSION,
         **kwargs,
     ):
-
         if cls is LinodeDNSDriver:
             if api_version == "3.0":
                 cls = LinodeDNSDriverV3
diff --git a/libcloud/dns/drivers/vultr.py b/libcloud/dns/drivers/vultr.py
index e147f59..bdff9bd 100644
--- a/libcloud/dns/drivers/vultr.py
+++ b/libcloud/dns/drivers/vultr.py
@@ -93,7 +93,6 @@
 
 
 class VultrDNSDriverV1(VultrDNSDriver):
-
     connectionCls = VultrDNSConnection
 
     RECORD_TYPE_MAP = {
diff --git a/libcloud/loadbalancer/drivers/alb.py b/libcloud/loadbalancer/drivers/alb.py
index 34286f4..8ab3ea4 100644
--- a/libcloud/loadbalancer/drivers/alb.py
+++ b/libcloud/loadbalancer/drivers/alb.py
@@ -68,7 +68,6 @@
         balancers=[],
         members=[],
     ):
-
         self.id = target_group_id
         self.name = name
         self.protocol = protocol
@@ -135,7 +134,6 @@
         ssl_certificate="",
         rules=[],
     ):
-
         self.id = listener_id
         self.protocol = protocol
         self.port = port
@@ -186,7 +184,6 @@
         conditions={},
         listener=None,
     ):
-
         self.id = rule_id
         self.is_default = is_default
         self.priority = priority
@@ -882,7 +879,6 @@
         ]
 
     def _to_target_group(self, el):
-
         target_group = ALBTargetGroup(
             target_group_id=findtext(element=el, xpath="TargetGroupArn", namespace=NS),
             name=findtext(element=el, xpath="TargetGroupName", namespace=NS),
diff --git a/libcloud/loadbalancer/drivers/dimensiondata.py b/libcloud/loadbalancer/drivers/dimensiondata.py
index 6ff379f..11644d4 100644
--- a/libcloud/loadbalancer/drivers/dimensiondata.py
+++ b/libcloud/loadbalancer/drivers/dimensiondata.py
@@ -78,7 +78,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in API_ENDPOINTS and host is None:
             raise ValueError("Invalid region: %s, no host specified" % (region))
         if region is not None:
diff --git a/libcloud/loadbalancer/drivers/gce.py b/libcloud/loadbalancer/drivers/gce.py
index 1351119..9fa5eec 100644
--- a/libcloud/loadbalancer/drivers/gce.py
+++ b/libcloud/loadbalancer/drivers/gce.py
@@ -36,7 +36,6 @@
     _VALUE_TO_ALGORITHM_MAP = {"RANDOM": Algorithm.RANDOM}
 
     def __init__(self, *args, **kwargs):
-
         if kwargs.get("gce_driver"):
             self.gce = kwargs["gce_driver"]
         else:
diff --git a/libcloud/loadbalancer/drivers/nttcis.py b/libcloud/loadbalancer/drivers/nttcis.py
index 9f66042..ecd1499 100644
--- a/libcloud/loadbalancer/drivers/nttcis.py
+++ b/libcloud/loadbalancer/drivers/nttcis.py
@@ -82,7 +82,6 @@
         region=DEFAULT_REGION,
         **kwargs,
     ):
-
         self.network_domain_id = network_domain_id
 
         if region not in API_ENDPOINTS and host is None:
diff --git a/libcloud/pricing.py b/libcloud/pricing.py
index 836cc5d..496eccb 100644
--- a/libcloud/pricing.py
+++ b/libcloud/pricing.py
@@ -193,7 +193,6 @@
 
 
 def get_image_price(driver_name, image_name, size_name=None, cores=1):
-
     # for now only images of GCE have pricing data
     if driver_name == "gce_images":
         return _get_gce_image_price(image_name=image_name, size_name=size_name, cores=cores)
@@ -221,6 +220,7 @@
     :rtype: ``float``
     :return: Image price
     """
+
     # helper function to get image family for gce images
     def _get_gce_image_family(image_name):
         image_family = None
diff --git a/libcloud/storage/drivers/azure_blobs.py b/libcloud/storage/drivers/azure_blobs.py
index 763cbb8..1fafbe9 100644
--- a/libcloud/storage/drivers/azure_blobs.py
+++ b/libcloud/storage/drivers/azure_blobs.py
@@ -1221,7 +1221,6 @@
         file_path,
         headers,
     ):
-
         headers = headers or {}
         lease.update_headers(headers)
 
diff --git a/libcloud/storage/drivers/backblaze_b2.py b/libcloud/storage/drivers/backblaze_b2.py
index 25b45f3..3ea8311 100644
--- a/libcloud/storage/drivers/backblaze_b2.py
+++ b/libcloud/storage/drivers/backblaze_b2.py
@@ -554,7 +554,6 @@
     def _perform_upload(
         self, data, container, object_name, extra=None, verify_hash=True, headers=None
     ):
-
         if isinstance(data, str):
             data = bytearray(data)
 
diff --git a/libcloud/storage/drivers/cloudfiles.py b/libcloud/storage/drivers/cloudfiles.py
index 9f749b4..c126c11 100644
--- a/libcloud/storage/drivers/cloudfiles.py
+++ b/libcloud/storage/drivers/cloudfiles.py
@@ -192,23 +192,19 @@
     def get_endpoint(self):
         region = self._ex_force_service_region.upper()
 
-        if self.use_internal_url:
-            endpoint_type = "internal"
-        else:
-            endpoint_type = "external"
-
         if "2.0" in self._auth_version:
             ep = self.service_catalog.get_endpoint(
                 service_type="object-store",
                 name="cloudFiles",
                 region=region,
-                endpoint_type=endpoint_type,
+                endpoint_type="internal" if self.use_internal_url else "external",
             )
             cdn_ep = self.service_catalog.get_endpoint(
                 service_type="rax:object-cdn",
                 name="cloudFilesCDN",
                 region=region,
-                endpoint_type=endpoint_type,
+                # Cloud Files has no concept of an "internal" CDN.
+                endpoint_type="external",
             )
         else:
             raise LibcloudError('Auth version "%s" not supported' % (self._auth_version))
diff --git a/libcloud/storage/drivers/digitalocean_spaces.py b/libcloud/storage/drivers/digitalocean_spaces.py
index f898fe9..5e0bc7b 100644
--- a/libcloud/storage/drivers/digitalocean_spaces.py
+++ b/libcloud/storage/drivers/digitalocean_spaces.py
@@ -49,7 +49,6 @@
         backoff=None,
         **kwargs,
     ):
-
         super().__init__(
             user_id,
             key,
@@ -82,7 +81,6 @@
         backoff=None,
         **kwargs,
     ):
-
         super().__init__(
             user_id,
             key,
@@ -115,7 +113,6 @@
         region=DO_SPACES_DEFAULT_REGION,
         **kwargs,
     ):
-
         if region not in DO_SPACES_HOSTS_BY_REGION:
             raise LibcloudError("Unknown region (%s)" % (region), driver=self)
 
diff --git a/libcloud/storage/drivers/minio.py b/libcloud/storage/drivers/minio.py
index 0d42931..a1bafdd 100644
--- a/libcloud/storage/drivers/minio.py
+++ b/libcloud/storage/drivers/minio.py
@@ -39,7 +39,6 @@
         backoff=None,
         **kwargs,
     ):
-
         super().__init__(
             user_id,
             key,
diff --git a/libcloud/storage/drivers/oss.py b/libcloud/storage/drivers/oss.py
index a3aa4b4..b43cdaa 100644
--- a/libcloud/storage/drivers/oss.py
+++ b/libcloud/storage/drivers/oss.py
@@ -545,7 +545,6 @@
             body = response.parse_body()
             # pylint: disable=maybe-no-member
             for node in body.findall(fixxpath(xpath="Upload", namespace=self.namespace)):
-
                 key = finder(node, "Key")
                 upload_id = finder(node, "UploadId")
                 initiated = finder(node, "Initiated")
@@ -884,7 +883,7 @@
 
         root = Element("CompleteMultipartUpload")
 
-        for (count, etag) in chunks:
+        for count, etag in chunks:
             part = SubElement(root, "Part")
             part_no = SubElement(part, "PartNumber")
             part_no.text = str(count)
diff --git a/libcloud/storage/drivers/rgw.py b/libcloud/storage/drivers/rgw.py
index 088c988..ba8caed 100644
--- a/libcloud/storage/drivers/rgw.py
+++ b/libcloud/storage/drivers/rgw.py
@@ -56,7 +56,6 @@
         backoff=None,
         **kwargs,
     ):
-
         super().__init__(
             user_id,
             key,
@@ -89,7 +88,6 @@
         backoff=None,
         **kwargs,
     ):
-
         super().__init__(
             user_id,
             key,
@@ -120,7 +118,6 @@
         region=S3_RGW_DEFAULT_REGION,
         **kwargs,
     ):
-
         if host is None:
             raise LibcloudError("host required", driver=self)
 
diff --git a/libcloud/storage/drivers/s3.py b/libcloud/storage/drivers/s3.py
index 31ef851..a46a7bd 100644
--- a/libcloud/storage/drivers/s3.py
+++ b/libcloud/storage/drivers/s3.py
@@ -725,7 +725,7 @@
         """
         root = Element("CompleteMultipartUpload")
 
-        for (count, etag) in chunks:
+        for count, etag in chunks:
             part = SubElement(root, "Part")
             part_no = SubElement(part, "PartNumber")
             part_no.text = str(count)
@@ -1107,7 +1107,16 @@
         """
         headers = {}
         storage_class = storage_class or "standard"
-        if storage_class not in ["standard", "reduced_redundancy"]:
+        if storage_class not in [
+            "standard",
+            "reduced_redundancy",
+            "standard_ia",
+            "onezone_ia",
+            "intelligent_tiering",
+            "glacier",
+            "deep_archive",
+            "glacier_ir",
+        ]:
             raise ValueError("Invalid storage class value: %s" % (storage_class))
 
         key = self.http_vendor_prefix + "-storage-class"
diff --git a/libcloud/test/backup/test_dimensiondata_v2_3.py b/libcloud/test/backup/test_dimensiondata_v2_3.py
index eb666cf..46110ed 100644
--- a/libcloud/test/backup/test_dimensiondata_v2_3.py
+++ b/libcloud/test/backup/test_dimensiondata_v2_3.py
@@ -303,7 +303,6 @@
 
 
 class DimensionDataMockHttp(MockHttp):
-
     fixtures = BackupFileFixtures("dimensiondata")
 
     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
diff --git a/libcloud/test/backup/test_dimensiondata_v2_4.py b/libcloud/test/backup/test_dimensiondata_v2_4.py
index 939a6b5..2156c42 100644
--- a/libcloud/test/backup/test_dimensiondata_v2_4.py
+++ b/libcloud/test/backup/test_dimensiondata_v2_4.py
@@ -303,7 +303,6 @@
 

 

 class DimensionDataMockHttp(MockHttp):

-

     fixtures = BackupFileFixtures("dimensiondata")

 

     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):

diff --git a/libcloud/test/common/test_cloudstack.py b/libcloud/test/common/test_cloudstack.py
index 631680b..ad49df9 100644
--- a/libcloud/test/common/test_cloudstack.py
+++ b/libcloud/test/common/test_cloudstack.py
@@ -117,7 +117,6 @@
 
 
 class CloudStackMockHttp(MockHttp, unittest.TestCase):
-
     ERROR_TEXT = "ERROR TEXT"
 
     def _response(self, status, result, response):
diff --git a/libcloud/test/common/test_google.py b/libcloud/test/common/test_google.py
index 0b4250c..4303f44 100644
--- a/libcloud/test/common/test_google.py
+++ b/libcloud/test/common/test_google.py
@@ -357,7 +357,6 @@
 
 
 class GoogleOAuth2CredentialTest(GoogleTestCase):
-
     _ia_get_code_patcher = mock.patch(
         "libcloud.common.google.GoogleInstalledAppAuthConnection.get_code",
         return_value=1234,
diff --git a/libcloud/test/common/test_openstack.py b/libcloud/test/common/test_openstack.py
index e10a7a1..2bfeb76 100644
--- a/libcloud/test/common/test_openstack.py
+++ b/libcloud/test/common/test_openstack.py
@@ -76,6 +76,47 @@
             raw=False,
         )
 
+    @patch("libcloud.test.common.test_openstack.OpenStackBaseConnection.connect", Mock())
+    def test_connection_is_reused_when_details_dont_change(self):
+        url = "https://example.com"
+
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 1)
+
+        for index in range(0, 10):
+            self.connection._set_up_connection_info(url=url)
+            self.assertEqual(self.connection.connect.call_count, 1)
+
+    @patch("libcloud.test.common.test_openstack.OpenStackBaseConnection.connect", Mock())
+    def test_connection_is_not_reused_when_details_change(self):
+        url = "https://example.com"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 1)
+
+        url = "https://example.com"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 1)
+
+        url = "https://example.com:80"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 2)
+
+        url = "http://example.com:80"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 3)
+
+        url = "http://exxample.com:80"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 4)
+
+        url = "http://exxample.com:81"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 5)
+
+        url = "http://exxample.com:81"
+        self.connection._set_up_connection_info(url=url)
+        self.assertEqual(self.connection.connect.call_count, 5)
+
 
 if __name__ == "__main__":
     sys.exit(unittest.main())
diff --git a/libcloud/test/common/test_openstack_identity.py b/libcloud/test/common/test_openstack_identity.py
index f8545a3..8f6b550 100644
--- a/libcloud/test/common/test_openstack_identity.py
+++ b/libcloud/test/common/test_openstack_identity.py
@@ -98,8 +98,8 @@
         user_id = OPENSTACK_PARAMS[0]
         key = OPENSTACK_PARAMS[1]
 
-        for (auth_version, mock_http_class, kwargs) in tuples:
-            for (url, url_path) in auth_urls:
+        for auth_version, mock_http_class, kwargs in tuples:
+            for url, url_path in auth_urls:
                 connection = self._get_mock_connection(
                     mock_http_class=mock_http_class, auth_url=url
                 )
@@ -167,7 +167,7 @@
         user_id = OPENSTACK_PARAMS[0]
         key = OPENSTACK_PARAMS[1]
 
-        for (auth_version, mock_http_class, kwargs) in tuples:
+        for auth_version, mock_http_class, kwargs in tuples:
             connection = self._get_mock_connection(mock_http_class=mock_http_class)
             auth_url = connection.auth_url
 
@@ -313,7 +313,7 @@
         user_id = OPENSTACK_PARAMS[0]
         key = OPENSTACK_PARAMS[1]
 
-        for (auth_version, mock_http_class, kwargs) in tuples:
+        for auth_version, mock_http_class, kwargs in tuples:
             mock_http_class.type = None
             connection = self._get_mock_connection(mock_http_class=mock_http_class)
             auth_url = connection.auth_url
diff --git a/libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token_PAGINATION_INFINITE_LOOP.json b/libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token_PAGINATION_INFINITE_LOOP.json
new file mode 100644
index 0000000..b9702f2
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_77777777_7777_7777_7777_777777777777_oauth2_token_PAGINATION_INFINITE_LOOP.json
@@ -0,0 +1 @@
+{"expires_in":"3600","token_type":"Bearer","expires_on":"1111111111","not_before":"1111111111","resource":"https://management.core.windows.net/","access_token":"3333333333333333333333333333333333333333333333333333333"}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.json b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.json
index 019c5c7..4c40f57 100644
--- a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.json
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines.json
@@ -52,5 +52,6 @@
       "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-1",
       "name": "test-node-1"
     }
-  ]
+  ],
+  "nextLink": "https://management.azure.com:443/subscriptions/99999999-9999-9999-9999-999999999999/providers/Microsoft.Compute/virtualMachines?api-version=2021-11-01&$skiptoken=1!/Subscriptions/99999999-9999-9999-9999-999999999999/ResourceGroups/000000/VMs/DDFEBF64-E92B-4A50-9949-6E44BFC61D4G"
 }
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_1.json b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_1.json
new file mode 100644
index 0000000..1b63cd9
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_1.json
@@ -0,0 +1,56 @@
+{
+  "value": [
+    {
+      "properties": {
+        "vmId": "DDFEBF64-E92B-4A50-9949-6E44BFC61D4G",
+        "additionalCapabilities": {
+          "ultraSSDEnabled": "False",
+          "hibernationEnabled": "False"
+        },
+        "hardwareProfile": {
+          "vmSize": "Standard_A1"
+        },
+        "storageProfile": {
+          "imageReference": {
+            "publisher": "OpenLogic",
+            "offer": "CentOS",
+            "sku": "7.3",
+            "version": "latest"
+          },
+          "osDisk": {
+            "osType": "Linux",
+            "name": "test-node-disk-1",
+            "createOption": "FromImage",
+            "caching": "ReadWrite",
+            "managedDisk": {
+              "storageAccountType": "Standard_LRS",
+              "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-node-disk-2"
+            }
+          },
+          "dataDisks": []
+        },
+        "osProfile": {
+          "computerName": "test-node-2",
+          "adminUsername": "user",
+          "linuxConfiguration": {
+            "disablePasswordAuthentication": false
+          },
+          "secrets": []
+        },
+        "networkProfile": {
+          "networkInterfaces": [
+            {
+              "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-2-nic"
+            }
+          ]
+        },
+        "provisioningState": "Running"
+      },
+      "type": "Microsoft.Compute/virtualMachines",
+      "location": "eastus",
+      "tags": {},
+      "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-2",
+      "name": "test-node-2"
+    }
+  ]
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_PAGINATION_INFINITE_LOOP.json b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_PAGINATION_INFINITE_LOOP.json
new file mode 100644
index 0000000..8c9e913
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_providers_Microsoft_Compute_virtualMachines_PAGINATION_INFINITE_LOOP.json
@@ -0,0 +1,53 @@
+{
+  "value": [
+    {
+      "properties": {
+        "vmId": "CCEEBF63-E92B-4A50-9949-6E44BFC61D3F",
+        "additionalCapabilities": {
+          "ultraSSDEnabled": "False",
+          "hibernationEnabled": "False"
+        },
+        "hardwareProfile": {
+          "vmSize": "Standard_A1"
+        },
+        "storageProfile": {
+          "imageReference": {
+            "publisher": "OpenLogic",
+            "offer": "CentOS",
+            "sku": "7.3",
+            "version": "latest"
+          },
+          "osDisk": {
+            "osType": "Linux",
+            "name": "test-node-disk-1",
+            "createOption": "FromImage",
+            "caching": "ReadWrite",
+            "managedDisk": {
+              "storageAccountType": "Standard_LRS",
+              "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/disks/test-node-disk-1"
+            }
+          },
+          "dataDisks": []
+        },
+        "osProfile": {
+          "computerName": "test-node-1",
+          "adminUsername": "user",
+          "linuxConfiguration": {
+            "disablePasswordAuthentication": false
+          },
+          "secrets": []
+        },
+        "networkProfile": {
+          "networkInterfaces": []
+        },
+        "provisioningState": "Running"
+      },
+      "type": "Microsoft.Compute/virtualMachines",
+      "location": "eastus",
+      "tags": {},
+      "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-1",
+      "name": "test-node-1"
+    }
+  ],
+  "nextLink": "https://management.azure.com:443/subscriptions/99999999-9999-9999-9999-999999999999/providers/Microsoft.Compute/virtualMachines?api-version=2021-11-01&$skiptoken=1!/Subscriptions/99999999-9999-9999-9999-999999999999/ResourceGroups/000000/VMs/DDFEBF64-E92B-4A50-9949-6E44BFC61D4G"
+}
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_2_InstanceView.json b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_2_InstanceView.json
new file mode 100644
index 0000000..0ac000f
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Compute_virtualMachines_test_node_2_InstanceView.json
@@ -0,0 +1,27 @@
+{
+  "vmAgent": {
+    "vmAgentVersion": "2.2.5",
+    "statuses": [
+      {
+        "code": "ProvisioningState/succeeded",
+        "level": "Info",
+        "displayStatus": "Ready",
+        "message": "Guest Agent is running",
+        "time": "2017-03-09T15:11:03+00:00"
+      }
+    ],
+    "extensionHandlers": []
+  },
+  "statuses": [
+    {
+      "code": "ProvisioningState/updating",
+      "level": "Info",
+      "displayStatus": "Updating"
+    },
+    {
+      "code": "PowerState/running",
+      "level": "Info",
+      "displayStatus": "VM running"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Network_networkInterfaces_test_node_2_nic.json b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Network_networkInterfaces_test_node_2_nic.json
new file mode 100644
index 0000000..868bb53
--- /dev/null
+++ b/libcloud/test/compute/fixtures/azure_arm/_subscriptions_99999999_resourceGroups_000000_providers_Microsoft_Network_networkInterfaces_test_node_2_nic.json
@@ -0,0 +1,38 @@
+{
+  "name": "test-node-2-nic",
+  "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-2-nic",
+  "etag": "W/\"5E19562E-8E84-493D-A29E-A84F5AC21D77\"",
+  "location": "eastus",
+  "tags": {},
+  "properties": {
+    "provisioningState": "Succeeded",
+    "resourceGuid": "AD512C3D-9A7B-4012-8C5D-227A9EA5E6F5",
+    "ipConfigurations": [
+      {
+        "name": "myip1",
+        "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/networkInterfaces/test-node-2-nic/ipConfigurations/myip2",
+        "etag": "W/\"5E19562E-8E84-493D-A29E-A84F5AC21D77\"",
+        "properties": {
+          "provisioningState": "Succeeded",
+          "privateIPAddress": "10.0.0.2",
+          "privateIPAllocationMethod": "Dynamic",
+          "subnet": {
+            "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Network/virtualNetworks/000000/subnets/000000"
+          },
+          "primary": true
+        }
+      }
+    ],
+    "dnsSettings": {
+      "dnsServers": [],
+      "appliedDnsServers": []
+    },
+    "macAddress": "11-11-11-11-11-11",
+    "enableIPForwarding": false,
+    "primary": true,
+    "virtualMachine": {
+      "id": "/subscriptions/99999999-9999-9999-9999-999999999999/resourceGroups/000000/providers/Microsoft.Compute/virtualMachines/test-node-2"
+    }
+  },
+  "type": "Microsoft.Network/networkInterfaces"
+}
\ No newline at end of file
diff --git a/libcloud/test/compute/test_abiquo.py b/libcloud/test/compute/test_abiquo.py
index 3734633..13ae1b8 100644
--- a/libcloud/test/compute/test_abiquo.py
+++ b/libcloud/test/compute/test_abiquo.py
@@ -415,7 +415,6 @@
     def _api_cloud_virtualdatacenters_4_virtualappliances_6_virtualmachines_3_tasks_b44fe278_6b0f_4dfb_be81_7c03006a93cb(
         self, method, url, body, headers
     ):
-
         if headers["Authorization"] == "Basic dGVuOnNoaW4=":
             # User 'ten:shin' failed task
             response = self.fixtures.load("vdc_4_vapp_6_vm_3_deploy_task_failed.xml")
diff --git a/libcloud/test/compute/test_azure.py b/libcloud/test/compute/test_azure.py
index 5d50b8d..b42507c 100644
--- a/libcloud/test/compute/test_azure.py
+++ b/libcloud/test/compute/test_azure.py
@@ -118,7 +118,6 @@
             self.driver.list_nodes(ex_cloud_service_name="dcoddkinztest04")
 
     def test_restart_node_success(self):
-
         node = Node(
             id="dc03",
             name="dc03",
@@ -137,7 +136,6 @@
 
     #  simulating attempting to reboot a node that is already rebooting
     def test_restart_node_fail_no_deployment(self):
-
         node = Node(
             id="dc03",
             name="dc03",
@@ -155,7 +153,6 @@
             )
 
     def test_restart_node_fail_no_cloud_service(self):
-
         node = Node(
             id="dc03",
             name="dc03",
@@ -173,7 +170,6 @@
             )
 
     def test_restart_node_fail_node_not_found(self):
-
         node = Node(
             id="dc13",
             name="dc13",
@@ -191,7 +187,6 @@
         self.assertFalse(result)
 
     def test_destroy_node_success_single_node_in_cloud_service(self):
-
         node = Node(
             id="oddkinz1",
             name="oddkinz1",
@@ -207,7 +202,6 @@
         self.assertTrue(result)
 
     def test_destroy_node_success_multiple_nodes_in_cloud_service(self):
-
         node = Node(
             id="oddkinz1",
             name="oddkinz1",
@@ -223,7 +217,6 @@
         self.assertTrue(result)
 
     def test_destroy_node_fail_node_does_not_exist(self):
-
         node = Node(
             id="oddkinz2",
             name="oddkinz2",
@@ -241,7 +234,6 @@
             )
 
     def test_destroy_node_success_cloud_service_not_found(self):
-
         node = Node(
             id="cloudredis",
             name="cloudredis",
@@ -354,7 +346,6 @@
 
 
 class AzureMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("azure")
 
     def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_oddkinz1_deploymentslots_Production(
@@ -584,7 +575,6 @@
     def _3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production(
         self, method, url, body, headers
     ):
-
         if method == "GET":
             body = self.fixtures.load(
                 "_3761b98b_673d_526c_8d55_fee918758e6e_services_hostedservices_testdcabc2_deploymentslots_Production.xml"
@@ -601,7 +591,6 @@
     def _3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3(
         self, method, url, body, headers
     ):
-
         if method == "GET":
             body = self.fixtures.load(
                 "_3761b98b_673d_526c_8d55_fee918758e6e_operations_acc33f6756cda6fd96826394fce4c9f3.xml"
diff --git a/libcloud/test/compute/test_azure_arm.py b/libcloud/test/compute/test_azure_arm.py
index 85b320d..b81fb24 100644
--- a/libcloud/test/compute/test_azure_arm.py
+++ b/libcloud/test/compute/test_azure_arm.py
@@ -20,7 +20,7 @@
 from unittest import mock
 
 from libcloud.test import MockHttp, LibcloudTestCase, unittest
-from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import httplib, parse_qs, urlparse, urlunquote
 from libcloud.common.types import LibcloudError
 from libcloud.compute.base import NodeSize, NodeLocation, StorageVolume, VolumeSnapshot
 from libcloud.compute.types import Provider, NodeState, StorageVolumeState, VolumeSnapshotState
@@ -36,13 +36,13 @@
 
 
 class AzureNodeDriverTests(LibcloudTestCase):
-
     TENANT_ID = "77777777-7777-7777-7777-777777777777"
     SUBSCRIPTION_ID = "99999999"
     APPLICATION_ID = "55555555-5555-5555-5555-555555555555"
     APPLICATION_PASS = "p4ssw0rd"
 
     def setUp(self):
+        AzureMockHttp.type = None
         Azure = get_driver(Provider.AZURE_ARM)
         Azure.connectionCls.conn_class = AzureMockHttp
         self.driver = Azure(
@@ -445,29 +445,51 @@
     def test_list_nodes(self, fps_mock):
         nodes = self.driver.list_nodes()
 
-        self.assertEqual(len(nodes), 1)
+        self.assertEqual(len(nodes), 2)
 
         self.assertEqual(nodes[0].name, "test-node-1")
         self.assertEqual(nodes[0].state, NodeState.UPDATING)
         self.assertEqual(nodes[0].private_ips, ["10.0.0.1"])
         self.assertEqual(nodes[0].public_ips, [])
 
+        self.assertEqual(nodes[1].name, "test-node-2")
+        self.assertEqual(nodes[1].state, NodeState.UPDATING)
+        self.assertEqual(nodes[1].private_ips, ["10.0.0.2"])
+        self.assertEqual(nodes[1].public_ips, [])
+
         fps_mock.assert_called()
 
     @mock.patch(
+        "libcloud.compute.drivers.azure_arm.AzureNodeDriver._fetch_power_state",
+        return_value=NodeState.UPDATING,
+    )
+    @mock.patch("libcloud.compute.drivers.azure_arm.LIST_NODES_PAGINATION_TIMEOUT", 1)
+    def test_list_nodes_pagination_timeout_reached(self, fps_mock):
+        # Verify we don't end up in an infinite loop in case server returns a bad response or
+        # similar
+        AzureMockHttp.type = "PAGINATION_INFINITE_LOOP"
+        nodes = self.driver.list_nodes()
+        self.assertTrue(len(nodes) >= 1)
+
+    @mock.patch(
         "libcloud.compute.drivers.azure_arm.AzureNodeDriver" "._fetch_power_state",
         return_value=NodeState.UPDATING,
     )
     def test_list_nodes__no_fetch_power_state(self, fps_mock):
         nodes = self.driver.list_nodes(ex_fetch_power_state=False)
 
-        self.assertEqual(len(nodes), 1)
+        self.assertEqual(len(nodes), 2)
 
         self.assertEqual(nodes[0].name, "test-node-1")
         self.assertNotEqual(nodes[0].state, NodeState.UPDATING)
         self.assertEqual(nodes[0].private_ips, ["10.0.0.1"])
         self.assertEqual(nodes[0].public_ips, [])
 
+        self.assertEqual(nodes[1].name, "test-node-2")
+        self.assertNotEqual(nodes[1].state, NodeState.UPDATING)
+        self.assertEqual(nodes[1].private_ips, ["10.0.0.2"])
+        self.assertEqual(nodes[1].public_ips, [])
+
         fps_mock.assert_not_called()
 
     def test_create_volume(self):
@@ -677,7 +699,6 @@
         self.assertTrue(isinstance(snaps[3].created, datetime))
 
     def test_list_snapshots_in_resource_group(self):
-
         snaps = self.driver.list_snapshots(ex_resource_group="111111")
         self.assertEqual(len(snaps), 2)
 
@@ -815,6 +836,11 @@
                 "99999999_9999_9999_9999_999999999999",
                 AzureNodeDriverTests.SUBSCRIPTION_ID,
             )
+            unquoted_url = urlunquote(url)
+            if "$skiptoken=" in unquoted_url and self.type != "PAGINATION_INFINITE_LOOP":
+                parsed_url = urlparse.urlparse(unquoted_url)
+                params = parse_qs(parsed_url.query)
+                file_name += "_" + params["$skiptoken"][0].split("!")[0]
             fixture = self.fixtures.load(file_name + ".json")
 
             if method in ("POST", "PUT"):
diff --git a/libcloud/test/compute/test_cloudsigma_v1_0.py b/libcloud/test/compute/test_cloudsigma_v1_0.py
index d0c3b4d..a0deb3a 100644
--- a/libcloud/test/compute/test_cloudsigma_v1_0.py
+++ b/libcloud/test/compute/test_cloudsigma_v1_0.py
@@ -152,24 +152,19 @@
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_start(self, method, url, body, headers):
-
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_stop(self, method, url, body, headers):
-
         return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
 
     def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_destroy(self, method, url, body, headers):
-
         return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.NO_CONTENT])
 
     def _drives_d18119ce_7afa_474a_9242_e0384b160220_clone(self, method, url, body, headers):
-
         body = self.fixtures.load("drives_clone.txt")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _drives_a814def5_1789_49a0_bf88_7abe7bb1682a_info(self, method, url, body, headers):
-
         body = self.fixtures.load("drives_single_info.txt")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
@@ -197,11 +192,9 @@
         return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
 
     def _drives_d18119ce_7afa_474a_9242_e0384b160220_destroy(self, method, url, body, headers):
-
         return (httplib.NO_CONTENT, body, {}, httplib.responses[httplib.OK])
 
     def _servers_62fe7cde_4fb9_4c63_bd8c_e757930066a0_set(self, method, url, body, headers):
-
         body = self.fixtures.load("servers_set.txt")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index 469e969..6f9907d 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -341,7 +341,6 @@
         self.assertEqual(network.extra["project_id"], fixture_network["projectid"])
 
     def test_ex_delete_network(self):
-
         network = self.driver.ex_list_networks()[0]
 
         result = self.driver.ex_delete_network(network=network)
@@ -364,7 +363,6 @@
             self.assertEqual(nic.mac_address, fixture_nic[i]["macaddress"])
 
     def test_ex_add_nic_to_node(self):
-
         vm = self.driver.list_nodes()[0]
         network = self.driver.ex_list_networks()[0]
         ip = "10.1.4.123"
@@ -373,7 +371,6 @@
         self.assertTrue(result)
 
     def test_ex_remove_nic_from_node(self):
-
         vm = self.driver.list_nodes()[0]
         nic = self.driver.ex_list_nics(node=vm)[0]
 
@@ -436,7 +433,6 @@
         self.assertEqual(vpc.id, fixture_vpc["id"])
 
     def test_ex_delete_vpc(self):
-
         vpc = self.driver.ex_list_vpcs()[0]
 
         result = self.driver.ex_delete_vpc(vpc=vpc)
diff --git a/libcloud/test/compute/test_dimensiondata_v2_3.py b/libcloud/test/compute/test_dimensiondata_v2_3.py
index c0befbe..0113de5 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_3.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_3.py
@@ -2198,7 +2198,6 @@
 
 
 class DimensionDataMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("dimensiondata")
 
     def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usage(
@@ -3472,7 +3471,6 @@
     def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "createPortList":
             raise InvalidRequestError(request.tag)
@@ -3499,7 +3497,6 @@
     def _caas_2_3_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "editPortList":
             raise InvalidRequestError(request.tag)
diff --git a/libcloud/test/compute/test_dimensiondata_v2_4.py b/libcloud/test/compute/test_dimensiondata_v2_4.py
index f26cea5..ec4c2b3 100644
--- a/libcloud/test/compute/test_dimensiondata_v2_4.py
+++ b/libcloud/test/compute/test_dimensiondata_v2_4.py
@@ -2294,7 +2294,6 @@
 
 
 class DimensionDataMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("dimensiondata")
 
     def _oec_0_9_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_report_usage(
@@ -3572,7 +3571,6 @@
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "createPortList":
             raise InvalidRequestError(request.tag)
@@ -3599,7 +3597,6 @@
     def _caas_2_4_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "editPortList":
             raise InvalidRequestError(request.tag)
diff --git a/libcloud/test/compute/test_gandi.py b/libcloud/test/compute/test_gandi.py
index f21eab8..19b9832 100644
--- a/libcloud/test/compute/test_gandi.py
+++ b/libcloud/test/compute/test_gandi.py
@@ -28,7 +28,6 @@
 
 
 class GandiTests(unittest.TestCase):
-
     node_name = "test2"
 
     def setUp(self):
@@ -212,7 +211,6 @@
 
 
 class GandiMockHttp(BaseGandiMockHttp):
-
     fixtures = ComputeFileFixtures("gandi")
 
     def _xmlrpc__hosting_datacenter_list(self, method, url, body, headers):
diff --git a/libcloud/test/compute/test_kamatera.py b/libcloud/test/compute/test_kamatera.py
index a42e8e1..ee16fb3 100644
--- a/libcloud/test/compute/test_kamatera.py
+++ b/libcloud/test/compute/test_kamatera.py
@@ -209,7 +209,6 @@
 
 
 class KamateraMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("kamatera")
 
     def _service_server(self, method, url, body, headers):
diff --git a/libcloud/test/compute/test_kubevirt.py b/libcloud/test/compute/test_kubevirt.py
index e5afafa..0d89fac 100644
--- a/libcloud/test/compute/test_kubevirt.py
+++ b/libcloud/test/compute/test_kubevirt.py
@@ -24,7 +24,6 @@
 
 
 class KubeVirtTestCase(unittest.TestCase, KubernetesAuthTestCaseMixin):
-
     driver_cls = KubeVirtNodeDriver
     fixtures = ComputeFileFixtures("kubevirt")
 
@@ -84,7 +83,6 @@
 
 
 class KubeVirtMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("kubevirt")
 
     def _api_v1_namespaces(self, method, url, body, headers):
@@ -199,7 +197,6 @@
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _api_v1_namespaces_default_pods(self, method, url, body, headers):
-
         if method == "GET":
             body = self.fixtures.load("get_pods.json")
         else:
diff --git a/libcloud/test/compute/test_nttcis.py b/libcloud/test/compute/test_nttcis.py
index ff45d08..2a46477 100644
--- a/libcloud/test/compute/test_nttcis.py
+++ b/libcloud/test/compute/test_nttcis.py
@@ -2107,7 +2107,6 @@
 
 
 class NttCisMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("nttcis")
 
     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
@@ -3263,7 +3262,6 @@
     def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_createPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "createPortList":
             raise InvalidRequestError(request.tag)
@@ -3290,7 +3288,6 @@
     def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_network_editPortList(
         self, method, url, body, headers
     ):
-
         request = ET.fromstring(body)
         if request.tag != "{urn:didata.com:api:cloud:types}" "editPortList":
             raise InvalidRequestError(request.tag)
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index b683249..e8bf332 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -722,7 +722,6 @@
         return (httplib.NO_CONTENT, "", {}, httplib.responses[httplib.NO_CONTENT])
 
     def _v1_0_slug_shared_ip_groups(self, method, url, body, headers):
-
         fixture = (
             "v1_slug_shared_ip_group.xml" if method == "POST" else "v1_slug_shared_ip_groups.xml"
         )
@@ -1102,7 +1101,6 @@
         self.assertEqual(sizes[0].vcpus, 8)
 
     def test_list_sizes_with_specified_pricing(self):
-
         pricing = {str(i): i * 5.0 for i in range(1, 9)}
 
         set_pricing(driver_type="compute", driver_name=self.driver.api_name, pricing=pricing)
diff --git a/libcloud/test/compute/test_rackspace.py b/libcloud/test/compute/test_rackspace.py
index 24b0a67..1a05b5a 100644
--- a/libcloud/test/compute/test_rackspace.py
+++ b/libcloud/test/compute/test_rackspace.py
@@ -164,7 +164,6 @@
 
 
 class RackspaceNovaDfwTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
@@ -174,7 +173,6 @@
 
 
 class RackspaceNovaOrdTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
@@ -184,7 +182,6 @@
 
 
 class RackspaceNovaIadTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
@@ -194,7 +191,6 @@
 
 
 class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
@@ -207,7 +203,6 @@
 
 
 class RackspaceNovaSydTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
@@ -217,7 +212,6 @@
 
 
 class RackspaceNovaHkgTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
-
     driver_klass = RackspaceNodeDriver
     driver_type = RackspaceNodeDriver
     driver_args = RACKSPACE_NOVA_PARAMS
diff --git a/libcloud/test/compute/test_rimuhosting.py b/libcloud/test/compute/test_rimuhosting.py
index 82f1237..3af9fdd 100644
--- a/libcloud/test/compute/test_rimuhosting.py
+++ b/libcloud/test/compute/test_rimuhosting.py
@@ -72,7 +72,6 @@
 
 
 class RimuHostingMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("rimuhosting")
 
     def _r_orders(self, method, url, body, headers):
diff --git a/libcloud/test/compute/test_vcloud.py b/libcloud/test/compute/test_vcloud.py
index 3df531e..981f788 100644
--- a/libcloud/test/compute/test_vcloud.py
+++ b/libcloud/test/compute/test_vcloud.py
@@ -636,7 +636,13 @@
     def test_change_vm_script_text_and_file_logic(self, _):
         assertion_error = False
 
-        for (vm_script_file, vm_script_text, open_succeeds, open_call_count, returned_early,) in (
+        for (
+            vm_script_file,
+            vm_script_text,
+            open_succeeds,
+            open_call_count,
+            returned_early,
+        ) in (
             (None, None, True, 0, True),
             (None, None, False, 0, True),
             (None, "script text", True, 0, False),
@@ -994,7 +1000,6 @@
 
 
 class TerremarkMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("terremark")
 
     def _api_v0_8_login(self, method, url, body, headers):
@@ -1072,7 +1077,6 @@
 
 
 class VCloud_1_5_MockHttp(MockHttp, unittest.TestCase):
-
     fixtures = ComputeFileFixtures("vcloud_1_5")
 
     def request(self, method, url, body=None, headers=None, raw=False, stream=False):
diff --git a/libcloud/test/compute/test_vsphere.py b/libcloud/test/compute/test_vsphere.py
index c2593d3..c328a98 100644
--- a/libcloud/test/compute/test_vsphere.py
+++ b/libcloud/test/compute/test_vsphere.py
@@ -22,7 +22,6 @@
 
 
 class KubeVirtTestCase(unittest.TestCase):
-
     driver_cls = VSphere_REST_NodeDriver
     fixtures = ComputeFileFixtures("vsphere")
 
@@ -68,7 +67,6 @@
 
 
 class VSphereMockHttp(MockHttp):
-
     fixtures = ComputeFileFixtures("vsphere")
 
     def _rest_com_vmware_cis_session(self, method, url, body, headers):
diff --git a/libcloud/test/container/test_lxd.py b/libcloud/test/container/test_lxd.py
index 5b5300b..a9a437c 100644
--- a/libcloud/test/container/test_lxd.py
+++ b/libcloud/test/container/test_lxd.py
@@ -201,7 +201,6 @@
         )
 
     def _linux_124_containers(self, method, url, body, headers):
-
         if method == "GET":
             return (
                 httplib.OK,
@@ -228,7 +227,6 @@
         )
 
     def _linux_124_containers_second_lxd_container(self, method, url, body, headers):
-
         if method == "PUT" or method == "DELETE":
             json = self.fixtures.load("linux_124/background_op.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
@@ -241,7 +239,6 @@
             )
 
     def _linux_124_containers_first_lxd_container_state(self, method, url, body, headers):
-
         if method == "PUT" or method == "DELETE":
             json = self.fixtures.load("linux_124/background_op.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
@@ -250,7 +247,6 @@
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
 
     def _linux_124_containers_second_lxd_container_state(self, method, url, body, headers):
-
         if method == "PUT" or method == "DELETE":
             json = self.fixtures.load("linux_124/background_op.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
@@ -267,13 +263,11 @@
         )
 
     def _linux_124_storage_pools(self, method, url, body, header):
-
         if method == "GET":
             json = self.fixtures.load("linux_124/storage_pools.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
 
     def _linux_124_storage_pools_pool1(self, method, url, body, header):
-
         if method == "GET":
             json = self.fixtures.load("linux_124/storage_pool_1.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
@@ -286,7 +280,6 @@
             )
 
     def _linux_124_storage_pools_pool2(self, method, url, body, header):
-
         if method == "GET":
             json = self.fixtures.load("linux_124/storage_pool_2.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
@@ -299,7 +292,6 @@
             )
 
     def _linux_124_storage_pools_pool3(self, method, url, body, header):
-
         if method == "GET":
             json = self.fixtures.load("linux_124/no_meta_pool.json")
             return (httplib.OK, json, {}, httplib.responses[httplib.OK])
diff --git a/libcloud/test/dns/test_liquidweb.py b/libcloud/test/dns/test_liquidweb.py
index 1e7e3e4..a0135f1 100644
--- a/libcloud/test/dns/test_liquidweb.py
+++ b/libcloud/test/dns/test_liquidweb.py
@@ -330,7 +330,6 @@
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _v1_Network_DNS_Record_update(self, method, url, body, headers):
-
         body = self.fixtures.load("update_record.json")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
diff --git a/libcloud/test/dns/test_luadns.py b/libcloud/test/dns/test_luadns.py
index 97406d2..cc6cb94 100644
--- a/libcloud/test/dns/test_luadns.py
+++ b/libcloud/test/dns/test_luadns.py
@@ -278,7 +278,6 @@
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
 
     def _v1_zones_31_GET_RECORD_RECORD_DOES_NOT_EXIST(self, method, url, body, headers):
-
         body = self.fixtures.load("get_zone.json")
 
         return httplib.OK, body, {}, httplib.responses[httplib.OK]
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
index 7a2b436..5cdc2b2 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_3.py
@@ -490,7 +490,6 @@
 
 
 class DimensionDataMockHttp(MockHttp):
-
     fixtures = LoadBalancerFileFixtures("dimensiondata")
 
     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
diff --git a/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
index ab3347a..e8f02cc 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata_v2_4.py
@@ -490,7 +490,6 @@
 
 
 class DimensionDataMockHttp(MockHttp):
-
     fixtures = LoadBalancerFileFixtures("dimensiondata")
 
     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
diff --git a/libcloud/test/loadbalancer/test_nttcis.py b/libcloud/test/loadbalancer/test_nttcis.py
index 78b1f01..bdcfc5b 100644
--- a/libcloud/test/loadbalancer/test_nttcis.py
+++ b/libcloud/test/loadbalancer/test_nttcis.py
@@ -628,7 +628,6 @@
 
 
 class NttCisMockHttp(MockHttp):
-
     fixtures = LoadBalancerFileFixtures("nttcis")
 
     def _oec_0_9_myaccount_UNAUTHORIZED(self, method, url, body, headers):
@@ -737,7 +736,6 @@
     def _caas_2_7_8a8f6abc_2745_4d8a_9cbc_8dabe5a7d0e4_networkDomainVip_node(
         self, method, url, body, headers
     ):
-
         body = self.fixtures.load("networkDomainVip_node.xml")
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
diff --git a/libcloud/test/loadbalancer/test_rackspace.py b/libcloud/test/loadbalancer/test_rackspace.py
index 4bc86fa..cf4923d 100644
--- a/libcloud/test/loadbalancer/test_rackspace.py
+++ b/libcloud/test/loadbalancer/test_rackspace.py
@@ -1344,7 +1344,6 @@
 
             return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED])
         elif method == "POST":
-
             json_body = json.loads(body)
             access_list = json_body["accessList"]
             self.assertEqual("ALLOW", access_list[0]["type"])
diff --git a/libcloud/test/storage/test_azure_blobs.py b/libcloud/test/storage/test_azure_blobs.py
index 1e6d70e..a67e7dd 100644
--- a/libcloud/test/storage/test_azure_blobs.py
+++ b/libcloud/test/storage/test_azure_blobs.py
@@ -44,7 +44,6 @@
 
 
 class AzureBlobsMockHttp(BaseRangeDownloadMockHttp, unittest.TestCase):
-
     fixtures = StorageFileFixtures("azure_blobs")
     base_headers = {}
 
diff --git a/libcloud/test/storage/test_base.py b/libcloud/test/storage/test_base.py
index 41db0c4..e9dc72c 100644
--- a/libcloud/test/storage/test_base.py
+++ b/libcloud/test/storage/test_base.py
@@ -52,7 +52,6 @@
         self.driver1.strict_mode = False
 
     def test__upload_object_iterator_must_have_next_method(self):
-
         valid_iterators = [BytesIO(b("134")), StringIO("bar")]
         invalid_iterators = ["foobar", "", False, True, 1, object()]
 
diff --git a/libcloud/test/storage/test_cloudfiles.py b/libcloud/test/storage/test_cloudfiles.py
index 2134062..df4a73e 100644
--- a/libcloud/test/storage/test_cloudfiles.py
+++ b/libcloud/test/storage/test_cloudfiles.py
@@ -123,6 +123,14 @@
         )
         self.driver.connection.cdn_request = False
 
+    def test_get_endpoint_internalurl(self):
+        self.driver.connection.use_internal_url = True
+        url = (
+            "https://snet-storage101.%s1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111"
+            % (self.region)
+        )
+        self.assertEqual(url, self.driver.connection.get_endpoint())
+
     def test_list_containers(self):
         CloudFilesMockHttp.type = "EMPTY"
         containers = self.driver.list_containers()
@@ -801,7 +809,6 @@
         expected_headers.update(cors_headers)
 
         def intercept_request(request_path, method=None, data=None, headers=None, raw=True):
-
             # What we're actually testing
             self.assertDictEqual(expected_headers, headers)
 
@@ -841,7 +848,6 @@
 
     @unittest.skip("Skipping as chunking is disabled in 2.0rc1")
     def test_upload_object_via_stream_chunked_encoding(self):
-
         # Create enough bytes it should get split into two chunks
         bytes_blob = "".join(["\0" for _ in range(CHUNK_SIZE + 1)])
         hex_chunk_size = ("%X" % CHUNK_SIZE).encode("utf8")
@@ -1055,7 +1061,6 @@
 
 
 class CloudFilesMockHttp(BaseRangeDownloadMockHttp, unittest.TestCase):
-
     fixtures = StorageFileFixtures("cloudfiles")
     base_headers = {"content-type": "application/json; charset=UTF-8"}
 
@@ -1255,7 +1260,6 @@
         return (status_code, body, headers, httplib.responses[httplib.OK])
 
     def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS(self, method, url, body, headers):
-
         if method == "DELETE":
             # test_ex_purge_from_cdn
             headers = self.base_headers
@@ -1265,7 +1269,6 @@
     def _v1_MossoCloudFS_foo_bar_container_object_PURGE_SUCCESS_EMAIL(
         self, method, url, body, headers
     ):
-
         if method == "DELETE":
             # test_ex_purge_from_cdn_with_email
             self.assertEqual(headers["X-Purge-Email"], "test@test.com")
@@ -1274,7 +1277,6 @@
         return (status_code, body, headers, httplib.responses[httplib.OK])
 
     def _v1_MossoCloudFS_foo_bar_container_NOT_FOUND(self, method, url, body, headers):
-
         if method == "DELETE":
             # test_delete_container_not_found
             body = self.fixtures.load("list_container_objects_empty.json")
@@ -1283,7 +1285,6 @@
         return (status_code, body, headers, httplib.responses[httplib.OK])
 
     def _v1_MossoCloudFS_foo_bar_container_NOT_EMPTY(self, method, url, body, headers):
-
         if method == "DELETE":
             # test_delete_container_not_empty
             body = self.fixtures.load("list_container_objects_empty.json")
@@ -1292,7 +1293,6 @@
         return (status_code, body, headers, httplib.responses[httplib.OK])
 
     def _v1_MossoCloudFS_foo_bar_container_foo_bar_object(self, method, url, body, headers):
-
         if method == "DELETE":
             # test_delete_object_success
             body = self.fixtures.load("list_container_objects_empty.json")
@@ -1398,7 +1398,6 @@
     def _v1_MossoCloudFS_foo_bar_container_foo_test_stream_data_seek(
         self, method, url, body, headers
     ):
-
         # test_upload_object_via_stream_stream_seek_at_end
         hasher = hashlib.md5()
         hasher.update(b"123456789")
diff --git a/libcloud/test/storage/test_oss.py b/libcloud/test/storage/test_oss.py
index 66394d4..3debf9d 100644
--- a/libcloud/test/storage/test_oss.py
+++ b/libcloud/test/storage/test_oss.py
@@ -76,7 +76,6 @@
 
 
 class OSSMockHttp(MockHttp, unittest.TestCase):
-
     fixtures = StorageFileFixtures("oss")
     base_headers = {}
 
diff --git a/libcloud/test/storage/test_s3.py b/libcloud/test/storage/test_s3.py
index e5ea383..46aa60a 100644
--- a/libcloud/test/storage/test_s3.py
+++ b/libcloud/test/storage/test_s3.py
@@ -51,7 +51,6 @@
 
 
 class S3MockHttp(BaseRangeDownloadMockHttp, unittest.TestCase):
-
     fixtures = StorageFileFixtures("s3")
     base_headers = {}
 
@@ -1088,6 +1087,28 @@
         self.assertEqual(obj.name, object_name)
         self.assertEqual(obj.size, 3)
 
+    def test_upload_small_object_with_glacier_ir(self):
+        if self.driver.supports_s3_multipart_upload:
+            self.mock_response_klass.type = "MULTIPART"
+        else:
+            self.mock_response_klass.type = None
+
+        container = Container(name="foo_bar_container", extra={}, driver=self.driver)
+        object_name = "foo_test_stream_data"
+        storage_class = "glacier_ir"
+        iterator = BytesIO(b("234"))
+        extra = {"content_type": "text/plain"}
+        obj = self.driver.upload_object_via_stream(
+            container=container,
+            object_name=object_name,
+            iterator=iterator,
+            extra=extra,
+            ex_storage_class=storage_class,
+        )
+
+        self.assertEqual(obj.name, object_name)
+        self.assertEqual(obj.size, 3)
+
     def test_upload_big_object_via_stream(self):
         if self.driver.supports_s3_multipart_upload:
             self.mock_response_klass.type = "MULTIPART"
diff --git a/libcloud/test/test_utils.py b/libcloud/test/test_utils.py
index 69d3705..49a4805 100644
--- a/libcloud/test/test_utils.py
+++ b/libcloud/test/test_utils.py
@@ -479,7 +479,6 @@
 
 
 class TestPublicKeyUtils(unittest.TestCase):
-
     PUBKEY = (
         "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOfbWSXOlqvYjZmRO84/lIoV4gvuX+"
         "P1lLg50MMg6jZjLZIlYY081XPRmuom0xY0+BO++J2KgLl7gxJ6xMsKK2VQ+TakdfAH20"
diff --git a/libcloud/utils/decorators.py b/libcloud/utils/decorators.py
index 847933f..1538e32 100644
--- a/libcloud/utils/decorators.py
+++ b/libcloud/utils/decorators.py
@@ -34,7 +34,6 @@
         try:
             return func(*args, **kwargs)
         except Exception as e:
-
             if isinstance(e, LibcloudError):
                 raise e
 
diff --git a/mypy.ini b/mypy.ini
deleted file mode 100644
index bc5ffe3..0000000
--- a/mypy.ini
+++ /dev/null
@@ -1,46 +0,0 @@
-[mypy]
-python_version = 3.7
-platform = linux
-show_error_context = True
-show_column_numbers = True
-# This Package contains generated Protobuf files
-#mypy_path = ../common/:common/
-
-# List of ignore files for packages and libraries which don't have type hints
-[mypy-lxml.*]
-ignore_missing_imports = True
-
-[mypy-xml.dom.*]
-ignore_missing_imports = True
-
-[mypy-xmlrpc.*]
-ignore_missing_imports = True
-
-[mypy-paramiko.*]
-ignore_missing_imports = True
-
-[mypy-cryptography.*]
-ignore_missing_imports = True
-
-[mypy-lockfile.*]
-ignore_missing_imports = True
-
-# Ignored local modules
-[mypy-libcloud.utils.py3]
-ignore_errors = True
-
-# NOTE: Fixing drivers will take a while
-[mypy-libcloud.compute.drivers.*]
-ignore_errors = True
-
-# NOTE: Fixing drivers will take a while
-[mypy-libcloud.storage.drivers.*]
-ignore_errors = True
-
-# NOTE: Fixing drivers will take a while
-[mypy-libcloud.dns.drivers.*]
-ignore_errors = True
-
-# NOTE: Fixing drivers will take a while
-[mypy-libcloud.container.drivers.*]
-ignore_errors = True
diff --git a/pyproject.toml b/pyproject.toml
index 7a2fe8b..6c510ca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,17 +1,22 @@
+[build-system]
+requires = ["setuptools~=66.1", "wheel~=0.37.1"]
+build-backend = "setuptools.build_meta"
+
 [tool.black]
 line_length = 100
 target_version = ['py37', 'py38', 'py39', 'py310']
 include = '\.pyi?$'
 extended_exclude = '''
 (
-  /(
-    | \.git
-    | \.virtualenv
-    | __pycache__
-  )/
+    /(
+        | \.git
+        | \.virtualenv
+        | __pycache__
+    )/
 )
 '''
 
+
 [tool.isort]
 profile = "black"
 multi_line_output = 3
@@ -19,3 +24,96 @@
 src_paths = ["libcloud", "contrib", "docs", "demos", "pylint_plugins", "integration"]
 skip_glob = [".venv/*", ".tox/*", ".github/actions/*"]
 length_sort = true
+
+
+[tool.pytest.ini_options]
+# Set options for pytest
+python_classes = "*Test"
+testpaths = "libcloud/test"
+# Show slowest 10 tests in the output
+addopts = "--durations=10"
+# Ignore UserWarning's
+filterwarnings = ["ignore::UserWarning"]
+
+
+[tool.bandit]
+exclude_dirs = [".tox", ".git", "build", "dist", "venv", "tests/*"]
+skips = ["B411"]
+
+
+[tool.pylint.MASTER]
+ignore = "test,constants"
+persistent = "yes"
+load-plugins = ""
+
+[tool.pylint.'MESSAGES CONTROL']
+disable = "redefined-builtin,too-many-arguments,too-few-public-methods,missing-docstring,invalid-name,abstract-method"
+
+[tool.pylint.TYPECHECK]
+generated-members = "async_request,objects"
+
+[tool.pylint.VARIABLES]
+init-import = "no"
+dummy-variables-rgx = "_|dummy"
+additional-builtins = ""
+
+[tool.pylint.FORMAT]
+max-line-length = 100
+max-module-lines = 1000
+indent-string = "    "
+
+
+[tool.mypy]
+python_version = 3.7
+platform = "linux"
+show_error_context = true
+show_column_numbers = true
+
+[[tool.mypy.overrides]]
+module = [
+    "lxml",
+    "xml.dom",
+    "xmlrpc.*",
+    "paramiko.*",
+    "cryptography.*",
+    "lockfile.*",
+]
+ignore_missing_imports = true
+
+[[tool.mypy.overrides]]
+module = [
+    "libcloud.utils.py3",
+    "libcloud.compute.drivers.*",
+    "libcloud.storage.drivers.*",
+    "libcloud.dns.drivers.*",
+    "libcloud.container.drivers.*",
+]
+ignore_errors = true
+
+[tool.coverage.run]
+branch = true
+source = ["libcloud"]
+
+[tool.coverage.report]
+exclude_lines = [
+    # Have to re-enable the standard pragma
+    "pragma: no cover",
+    # Don't complain about missing debug-only code:
+    "def __repr__",
+    "def __str__",
+    "if self\\.debug",
+    # Don't complain if tests don't hit defensive assertion code:
+    "raise AssertionError",
+    "raise NotImplementedError",
+    # Don't complain if non-runnable code isn't run:
+    "if 0:",
+    "if __name__ == .__main__.:",
+    "__all__",
+    "import",
+    "deprecated_warning",
+    "in_development_warning",
+]
+ignore_errors = true
+
+[tool.coverage.html]
+directory = "coverage_html_report"
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index cdecf53..0000000
--- a/pytest.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[pytest]
-python_classes=*Test
-testpaths=libcloud/test
-# Show slowest 10 tests in the output
-addopts = --durations=10
-# Ignore UserWarning's
-filterwarnings =
-    ignore::UserWarning
diff --git a/requirements-docs.txt b/requirements-docs.txt
index 01227da..7b7ec59 100644
--- a/requirements-docs.txt
+++ b/requirements-docs.txt
@@ -1,3 +1,3 @@
-rstcheck==6.1.1; python_version >= '3.7'
+rstcheck==6.1.2; python_version >= '3.7'
 fasteners
 sphinx==6.1.3
diff --git a/requirements-lint.txt b/requirements-lint.txt
index 8cd7452..b018032 100644
--- a/requirements-lint.txt
+++ b/requirements-lint.txt
@@ -1,12 +1,12 @@
 pep8==1.7.1
 flake8==5.0.4
-astroid==2.13.3; python_version >= '3.8'
-pylint==2.15.10; python_version >= '3.8'
-bandit==1.7.4; python_version >= '3.7'
-black==22.12.0; python_version >= '3.6' and implementation_name == "cpython"
+astroid==2.15.6; python_version >= '3.8'
+pylint==2.17.5; python_version >= '3.8'
+bandit[toml]==1.7.4; python_version >= '3.7'
+black==23.7.0; python_version >= '3.7' and implementation_name == "cpython"
 isort[pyproject]==5.12.0; python_version >= '3.8'
 pyupgrade==3.3.1
-rstcheck==6.1.1; python_version >= '3.7'
+rstcheck==6.1.2; python_version >= '3.7'
 
 requests>=2.27.1
-paramiko==3.0.0; platform_python_implementation != 'PyPy'
+paramiko==3.3.1; platform_python_implementation != 'PyPy'
diff --git a/requirements-mypy.txt b/requirements-mypy.txt
index ab556f4..9ca1dcc 100644
--- a/requirements-mypy.txt
+++ b/requirements-mypy.txt
@@ -1,6 +1,6 @@
 typing
 # Mypy requires typed-ast, which is broken on PyPy 3.7 (could work in PyPy 3.8).
-mypy==0.982; implementation_name == "cpython"
+mypy==1.4.1; implementation_name == "cpython"
 types-simplejson
 types-certifi
 types-requests
diff --git a/requirements-tests.txt b/requirements-tests.txt
index e9e8c07..9f1d56a 100644
--- a/requirements-tests.txt
+++ b/requirements-tests.txt
@@ -1,19 +1,18 @@
-codecov==2.1.12
-coverage==7.1.0; python_version >= '3.8'
-requests>=2.27.1
-requests_mock==1.10.0
-pytest==7.2.1
-pytest-xdist==3.1.0
+coverage[toml]==7.2.7; python_version >= '3.8'
+requests>=2.31.0
+requests_mock==1.11.0
+pytest==7.4.0
+pytest-xdist==3.3.1
 pytest-timeout==2.1.0
 pytest-benchmark[histogram]==4.0.0
-cryptography==39.0.0
+cryptography==41.0.2
 
 # NOTE: Only needed by nttcis loadbalancer driver
-pyopenssl==23.0.0
+pyopenssl==23.2.0
 
 more-itertools==9.0.0
 
 # Required by subset of tests
 fasteners
-paramiko==3.0.0; platform_python_implementation != 'PyPy'
+paramiko==3.3.1; platform_python_implementation != 'PyPy'
 libvirt-python==9.0.0
diff --git a/setup.py b/setup.py
index cd96eaa..10b3d46 100644
--- a/setup.py
+++ b/setup.py
@@ -321,6 +321,7 @@
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
         "Programming Language :: Python :: Implementation :: CPython",
         "Programming Language :: Python :: Implementation :: PyPy",
     ],
diff --git a/tox.ini b/tox.ini
index efdf9ec..4d3affb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -19,6 +19,7 @@
     /bin/bash
     scripts/*.sh
 basepython =
+    py3.12-dev: python3.12
     pypypy3: pypy3
     pypypy3.7: pypy3.7
     pypypy-3.7: pypy3.7
@@ -38,7 +39,7 @@
 # python setup.py test
 # for pytest-xdist, we want to distribute tests by file aka --dist loadfile
 commands = cp libcloud/test/secrets.py-dist libcloud/test/secrets.py
-           pytest -rsx -vvv --capture=tee-sys -o log_cli=True --durations=10 --timeout=15 -n auto --dist loadfile --ignore libcloud/test/benchmarks/ --ignore-glob "*test_list_objects_filtering_performance*"
+           pytest --color=yes -rsx -vvv --capture=tee-sys -o log_cli=True --durations=10 --timeout=15 -n auto --dist loadfile --ignore libcloud/test/benchmarks/ --ignore-glob "*test_list_objects_filtering_performance*"
 
 [testenv:py3.6-dist]
 # Verify library installs without any dependencies when using python setup.py
@@ -235,16 +236,16 @@
     PYTHONPATH={toxinidir}
 deps =
     -r{toxinidir}/requirements-lint.txt
-commands = pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/common/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/compute/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/container/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/backup/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/dns/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/storage/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc libcloud/utils/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc demos/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc contrib/
-           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./.pylintrc pylint_plugins/
+commands = pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/common/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/compute/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/container/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/backup/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/dns/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/storage/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml libcloud/utils/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml demos/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml contrib/
+           pylint -E --load-plugins=pylint_plugins.driver_class --rcfile=./pyproject.toml pylint_plugins/
 
 [testenv:lint]
 deps =
@@ -264,7 +265,7 @@
 [testenv:bandit]
 deps =
     -r{toxinidir}/requirements-lint.txt
-commands = bandit --configfile .bandit.yaml -lll -r libcloud/
+commands = bandit --configfile pyproject.toml -lll -r libcloud/
 
 [testenv:black]
 deps =
@@ -319,7 +320,7 @@
 deps =
     -r{toxinidir}/requirements-tests.txt
     -r{toxinidir}/integration/storage/requirements.txt
-commands = pytest -rsx -vvv --capture=tee-sys -o log_cli=True --durations=10 integration/storage
+commands = pytest --color=yes -rsx -vvv --capture=tee-sys -o log_cli=True --durations=10 integration/storage
 
 [testenv:coverage]
 deps =
@@ -341,7 +342,7 @@
   CRYPTOGRAPHY_ALLOW_OPENSSL_102=1
 commands = cp libcloud/test/secrets.py-dist libcloud/test/secrets.py
            coverage run --source=libcloud setup.py test
-           codecov
+           coverage xml
 
 [testenv:isort]
 deps =
@@ -386,8 +387,8 @@
 [testenv:micro-benchmarks]
 commands =
     cp libcloud/test/secrets.py-dist libcloud/test/secrets.py
-    pytest -s -v --timeout 60 --benchmark-only --benchmark-name=short --benchmark-columns=min,max,mean,stddev,median,ops,rounds --benchmark-histogram=benchmark_histograms/benchmark  --benchmark-group-by=group,param:sort_objects libcloud/test/benchmarks/test_list_objects_filtering_performance.py
-    pytest -s -v --timeout 60 --benchmark-only --benchmark-name=short --benchmark-columns=min,max,mean,stddev,median,ops,rounds --benchmark-histogram=benchmark_histograms/benchmark --benchmark-group-by=group,func,param:read_in_chunks_func libcloud/test/benchmarks/test_read_in_chunks.py
+    pytest --color=yes -s -v --timeout 60 --benchmark-only --benchmark-name=short --benchmark-columns=min,max,mean,stddev,median,ops,rounds --benchmark-histogram=benchmark_histograms/benchmark  --benchmark-group-by=group,param:sort_objects libcloud/test/benchmarks/test_list_objects_filtering_performance.py
+    pytest --color=yes -s -v --timeout 60 --benchmark-only --benchmark-name=short --benchmark-columns=min,max,mean,stddev,median,ops,rounds --benchmark-histogram=benchmark_histograms/benchmark --benchmark-group-by=group,func,param:read_in_chunks_func libcloud/test/benchmarks/test_read_in_chunks.py
 
 [testenv:import-timings]
 setenv =