diff --git a/bindep.txt b/bindep.txt
new file mode 100644
index 0000000..17575d9
--- /dev/null
+++ b/bindep.txt
@@ -0,0 +1,4 @@
+libffi-dev [platform:dpkg]
+libpq-dev [platform:dpkg]
+libxml2-dev [platform:dpkg]
+libxslt1-dev [platform:dpkg]
diff --git a/charmcraft.yaml b/charmcraft.yaml
index 03d2d1d..51fdc6f 100644
--- a/charmcraft.yaml
+++ b/charmcraft.yaml
@@ -14,24 +14,40 @@ parts:
       apt-get install ca-certificates -y
       tox -e build-reactive
     override-stage: |
-      echo "Copying charm to staging area: $CHARMCRAFT_STAGE"
-      NAME=$(ls $CHARMCRAFT_PART_BUILD/build/builds)
-      cp -r $CHARMCRAFT_PART_BUILD/build/builds/$NAME/* $CHARMCRAFT_STAGE/
+      echo "Copying charm to staging area: $CRAFT_STAGE"
+      NAME=$(ls $CRAFT_PART_BUILD/build/builds)
+      cp -r $CRAFT_PART_BUILD/build/builds/$NAME/* $CRAFT_STAGE/
     override-prime: |
       # For some reason, the normal priming chokes on the fact that there's a
       # hooks directory.
-      cp -r $CHARMCRAFT_STAGE/* .
+      cp -r $CRAFT_STAGE/* .
+      # Charmcraft looks for this specific entry point.
+      mkdir -p src
+      touch src/charm.py
+      chmod +x src/charm.py
 
 bases:
-  - build-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures:
-          - amd64
-    run-on:
-      - name: ubuntu
-        channel: "20.04"
-        architectures: [amd64, s390x, ppc64el, arm64]
-      - name: ubuntu
-        channel: "22.04"
-        architectures: [amd64, s390x, ppc64el, arm64]
+  - name: ubuntu
+    channel: "20.04"
+    architectures: [amd64]
+  - name: ubuntu
+    channel: "20.04"
+    architectures: [arm64]
+  - name: ubuntu
+    channel: "20.04"
+    architectures: [ppc64el]
+  - name: ubuntu
+    channel: "20.04"
+    architectures: [s390x]
+  - name: ubuntu
+    channel: "22.04"
+    architectures: [amd64]
+  - name: ubuntu
+    channel: "22.04"
+    architectures: [arm64]
+  - name: ubuntu
+    channel: "22.04"
+    architectures: [ppc64el]
+  - name: ubuntu
+    channel: "22.04"
+    architectures: [s390x]
diff --git a/osci.yaml b/osci.yaml
index bcbb193..2ad430f 100644
--- a/osci.yaml
+++ b/osci.yaml
@@ -8,3 +8,4 @@
       needs_charm_build: true
       charm_build_name: keystone-saml-mellon
       build_type: charmcraft
+      charmcraft_channel: 2.0/stable
diff --git a/src/tests/bundles/focal-xena.yaml b/src/tests/bundles/focal-xena.yaml
index 5097c3b..931ef59 100644
--- a/src/tests/bundles/focal-xena.yaml
+++ b/src/tests/bundles/focal-xena.yaml
@@ -193,8 +193,7 @@ applications:
     channel: latest/edge
 
   keystone-saml-mellon1:
-    series: focal
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-20.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp1'
@@ -214,7 +213,7 @@ applications:
 
   keystone-saml-mellon2:
     series: focal
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-20.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp2'
diff --git a/src/tests/bundles/focal-yoga.yaml b/src/tests/bundles/focal-yoga.yaml
index c49a56f..66df4a1 100644
--- a/src/tests/bundles/focal-yoga.yaml
+++ b/src/tests/bundles/focal-yoga.yaml
@@ -193,8 +193,7 @@ applications:
     channel: latest/edge
 
   keystone-saml-mellon1:
-    series: focal
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-20.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp1'
@@ -214,7 +213,7 @@ applications:
 
   keystone-saml-mellon2:
     series: focal
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-20.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp2'
diff --git a/src/tests/bundles/impish-xena.yaml b/src/tests/bundles/impish-xena.yaml
deleted file mode 100644
index 35667f3..0000000
--- a/src/tests/bundles/impish-xena.yaml
+++ /dev/null
@@ -1,411 +0,0 @@
-variables:
-  openstack-origin: &openstack-origin distro
-
-local_overlay_enabled: False
-
-series: impish
-
-comment:
-- 'machines section to decide order of deployment. database sooner = faster'
-machines:
-  '0':
-    constraints: mem=3072M
-  '1':
-    constraints: mem=3072M
-  '2':
-    constraints: mem=3072M
-  '3':
-  '4':
-  '5':
-  '6':
-  '7':
-  '8':
-  '9':
-  '10':
-  '11':
-  '12':
-  '13':
-  '14':
-  '15':
-  '16':
-  '17':
-  '18':
-
-applications:
-
-  keystone-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  neutron-api-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  glance-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  openstack-dashboard-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  nova-cloud-controller-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  cinder-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  vault-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-  placement-mysql-router:
-    charm: ch:mysql-router
-    channel: latest/edge
-
-  mysql-innodb-cluster:
-    charm: ch:mysql-innodb-cluster
-    num_units: 3
-    options:
-      source: *openstack-origin
-    to:
-      - '0'
-      - '1'
-      - '2'
-    channel: latest/edge
-
-  cinder:
-    num_units: 1
-    charm: ch:cinder
-    options:
-      openstack-origin: *openstack-origin
-      glance-api-version: 2
-      block-device: None
-    to:
-      - '3'
-    channel: latest/edge
-
-  glance:
-    charm: ch:glance
-    num_units: 1
-    options:
-      openstack-origin: *openstack-origin
-    to:
-      - '4'
-    channel: latest/edge
-
-  keystone:
-    charm: ch:keystone
-    num_units: 3
-    options:
-      openstack-origin: *openstack-origin
-      token-provider: 'fernet'
-    to:
-      - '5'
-      - '6'
-      - '7'
-    channel: latest/edge
-
-  neutron-api:
-    charm: ch:neutron-api
-    num_units: 1
-    options:
-      openstack-origin: *openstack-origin
-      manage-neutron-plugin-legacy-mode: true
-      flat-network-providers: physnet1
-      neutron-security-groups: true
-    to:
-      - '8'
-    channel: latest/edge
-
-  neutron-gateway:
-    charm: ch:neutron-gateway
-    num_units: 1
-    options:
-      openstack-origin: *openstack-origin
-      bridge-mappings: physnet1:br-ex
-    to:
-      - '9'
-    channel: latest/edge
-
-  neutron-openvswitch:
-    charm: ch:neutron-openvswitch
-    num_units: 0
-    channel: latest/edge
-
-  nova-cloud-controller:
-    charm: ch:nova-cloud-controller
-    num_units: 1
-    options:
-      openstack-origin: *openstack-origin
-      network-manager: Neutron
-    to:
-      - '10'
-    channel: latest/edge
-
-  nova-compute:
-    charm: ch:nova-compute
-    num_units: 2
-    options:
-      openstack-origin: *openstack-origin
-      config-flags: default_ephemeral_format=ext4
-      enable-live-migration: true
-      enable-resize: true
-      migration-auth-type: ssh
-    to:
-      - '11'
-      - '12'
-    channel: latest/edge
-
-  ntp:
-    charm: cs:ntp
-    series: focal
-    num_units: 0
-
-  openstack-dashboard:
-    charm: ch:openstack-dashboard
-    num_units: 3
-    options:
-      openstack-origin: *openstack-origin
-    to:
-      - '13'
-      - '14'
-      - '15'
-    channel: latest/edge
-
-  rabbitmq-server:
-    charm: ch:rabbitmq-server
-    num_units: 1
-    options:
-      source: *openstack-origin
-    to:
-      - '16'
-    channel: latest/edge
-
-  vault:
-    num_units: 1
-    charm: ch:vault
-    to:
-      - '17'
-    channel: latest/edge
-
-  placement:
-    charm: ch:placement
-    num_units: 1
-    options:
-      openstack-origin: *openstack-origin
-    to:
-      - '18'
-    channel: latest/edge
-
-  keystone-saml-mellon1:
-    series: groovy
-    charm: ../../../keystone-saml-mellon.charm
-    num_units: 0
-    options:
-      idp-name: 'test-saml-idp1'
-      protocol-name: 'mapped'
-      user-facing-name: "Test SAML IDP #1"
-      subject-confirmation-data-address-check: False
-      nameid-formats: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
-
-  test-saml-idp1:
-    charm: ch:ionutbalutoiu-test-saml-idp
-    num_units: 1
-    series: focal
-    options:
-      idp-name: 'test-saml-idp1'
-      protocol-name: 'mapped'
-      auth-user-name: 'user1'
-      auth-user-password: 'userpass1'
-
-  keystone-saml-mellon2:
-    series: groovy
-    charm: ../../../keystone-saml-mellon.charm
-    num_units: 0
-    options:
-      idp-name: 'test-saml-idp2'
-      protocol-name: 'mapped'
-      user-facing-name: "Test SAML IDP #2"
-      subject-confirmation-data-address-check: False
-      nameid-formats: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
-
-  test-saml-idp2:
-    charm: ch:ionutbalutoiu-test-saml-idp
-    num_units: 1
-    series: focal
-    options:
-      idp-name: 'test-saml-idp2'
-      protocol-name: 'mapped'
-      auth-user-name: 'user2'
-      auth-user-password: 'userpass2'
-
-  keystone-hacluster:
-    charm: ch:hacluster
-    num_units: 0
-    options:
-      corosync_transport: unicast
-      cluster_count: 3
-    channel: latest/edge
-
-  openstack-dashboard-hacluster:
-    charm: ch:hacluster
-    num_units: 0
-    options:
-      corosync_transport: unicast
-      cluster_count: 3
-    channel: latest/edge
-
-relations:
-
-  - - 'nova-compute:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'neutron-gateway:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'keystone:shared-db'
-    - 'keystone-mysql-router:shared-db'
-  - - 'keystone-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'nova-cloud-controller:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'glance:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'neutron-api:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'neutron-openvswitch:neutron-plugin-api'
-    - 'neutron-api:neutron-plugin-api'
-
-  - - 'neutron-api:shared-db'
-    - 'neutron-api-mysql-router:shared-db'
-  - - 'neutron-api-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'neutron-api:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'neutron-gateway:neutron-plugin-api'
-    - 'neutron-api:neutron-plugin-api'
-
-  - - 'glance:shared-db'
-    - 'glance-mysql-router:shared-db'
-  - - 'glance-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'glance:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'nova-cloud-controller:image-service'
-    - 'glance:image-service'
-
-  - - 'nova-compute:image-service'
-    - 'glance:image-service'
-
-  - - 'nova-cloud-controller:cloud-compute'
-    - 'nova-compute:cloud-compute'
-
-  - - 'nova-cloud-controller:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'nova-cloud-controller:quantum-network-service'
-    - 'neutron-gateway:quantum-network-service'
-
-  - - 'nova-compute:neutron-plugin'
-    - 'neutron-openvswitch:neutron-plugin'
-
-  - - 'neutron-openvswitch:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'openstack-dashboard:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'openstack-dashboard:shared-db'
-    - 'openstack-dashboard-mysql-router:shared-db'
-  - - 'openstack-dashboard-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'nova-cloud-controller:shared-db'
-    - 'nova-cloud-controller-mysql-router:shared-db'
-  - - 'nova-cloud-controller-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'nova-cloud-controller:neutron-api'
-    - 'neutron-api:neutron-api'
-
-  - - 'cinder:image-service'
-    - 'glance:image-service'
-
-  - - 'cinder:amqp'
-    - 'rabbitmq-server:amqp'
-
-  - - 'cinder:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'cinder:cinder-volume-service'
-    - 'nova-cloud-controller:cinder-volume-service'
-
-  - - 'cinder:shared-db'
-    - 'cinder-mysql-router:shared-db'
-  - - 'cinder-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'ntp:juju-info'
-    - 'nova-compute:juju-info'
-
-  - - 'ntp:juju-info'
-    - 'neutron-gateway:juju-info'
-
-  - - 'keystone'
-    - 'keystone-saml-mellon1'
-  - - 'keystone'
-    - 'keystone-saml-mellon2'
-
-  - - 'vault:shared-db'
-    - 'vault-mysql-router:shared-db'
-  - - 'vault-mysql-router:db-router'
-    - 'mysql-innodb-cluster:db-router'
-
-  - - 'vault:certificates'
-    - 'keystone:certificates'
-
-  - - 'vault:certificates'
-    - 'glance:certificates'
-
-  - - 'vault:certificates'
-    - 'openstack-dashboard:certificates'
-
-  - - 'openstack-dashboard'
-    - 'keystone-saml-mellon1'
-  - - 'openstack-dashboard'
-    - 'keystone-saml-mellon2'
-
-  - - 'keystone:websso-trusted-dashboard'
-    - 'openstack-dashboard:websso-trusted-dashboard'
-
-  - - 'vault:certificates'
-    - 'cinder:certificates'
-
-  - - 'vault:certificates'
-    - 'neutron-api:certificates'
-
-  - - 'vault:certificates'
-    - 'nova-cloud-controller:certificates'
-
-  - - 'placement:identity-service'
-    - 'keystone:identity-service'
-
-  - - 'placement:placement'
-    - 'nova-cloud-controller:placement'
-
-  - - 'vault:certificates'
-    - 'placement:certificates'
-
-  - - "placement:shared-db"
-    - "placement-mysql-router:shared-db"
-  - - "placement-mysql-router:db-router"
-    - "mysql-innodb-cluster:db-router"
-
-  - - "keystone:ha"
-    - "keystone-hacluster:ha"
-  - - "openstack-dashboard:ha"
-    - "openstack-dashboard-hacluster:ha"
diff --git a/src/tests/bundles/jammy-yoga.yaml b/src/tests/bundles/jammy-yoga.yaml
index 74d9c94..54ba627 100644
--- a/src/tests/bundles/jammy-yoga.yaml
+++ b/src/tests/bundles/jammy-yoga.yaml
@@ -194,8 +194,7 @@ applications:
     channel: latest/edge
 
   keystone-saml-mellon1:
-    series: groovy
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-22.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp1'
@@ -216,7 +215,7 @@ applications:
 
   keystone-saml-mellon2:
     series: groovy
-    charm: ../../../keystone-saml-mellon.charm
+    charm: ../../../keystone-saml-mellon_ubuntu-22.04-amd64.charm
     num_units: 0
     options:
       idp-name: 'test-saml-idp2'
diff --git a/src/tests/bundles/overlays/bionic-ha.yaml.j2 b/src/tests/bundles/overlays/bionic-ha.yaml.j2
deleted file mode 100644
index a64eb24..0000000
--- a/src/tests/bundles/overlays/bionic-ha.yaml.j2
+++ /dev/null
@@ -1,28 +0,0 @@
-relations:
-- - keystone
-  - keystone-hacluster
-- - openstack-dashboard
-  - openstack-dashboard-hacluster
-applications:
-  keystone:
-    num_units: 3
-    options:
-      vip: {{ OS_VIP00 }}
-  openstack-dashboard:
-    num_units: 3
-    options:
-      vip: {{ OS_VIP01 }}
-  keystone-hacluster:
-    charm: ch:hacluster
-    num_units: 0
-    options:
-      corosync_transport: unicast
-      cluster_count: 3
-    channel: latest/edge
-  openstack-dashboard-hacluster:
-    charm: ch:hacluster
-    num_units: 0
-    options:
-      corosync_transport: unicast
-      cluster_count: 3
-    channel: latest/edge
diff --git a/src/tests/bundles/overlays/bionic-queens.yaml.j2 b/src/tests/bundles/overlays/bionic-queens.yaml.j2
deleted file mode 120000
index 7d609fa..0000000
--- a/src/tests/bundles/overlays/bionic-queens.yaml.j2
+++ /dev/null
@@ -1 +0,0 @@
-bionic-ha.yaml.j2
\ No newline at end of file
diff --git a/src/tests/bundles/overlays/bionic-stein.yaml.j2 b/src/tests/bundles/overlays/bionic-stein.yaml.j2
deleted file mode 120000
index 7d609fa..0000000
--- a/src/tests/bundles/overlays/bionic-stein.yaml.j2
+++ /dev/null
@@ -1 +0,0 @@
-bionic-ha.yaml.j2
\ No newline at end of file
diff --git a/src/tests/bundles/overlays/bionic-ussuri.yaml.j2 b/src/tests/bundles/overlays/bionic-ussuri.yaml.j2
deleted file mode 120000
index 9280f58..0000000
--- a/src/tests/bundles/overlays/bionic-ussuri.yaml.j2
+++ /dev/null
@@ -1 +0,0 @@
-ha.yaml.j2
\ No newline at end of file
diff --git a/src/tests/bundles/overlays/hirsute-wallaby.yaml.j2 b/src/tests/bundles/overlays/hirsute-wallaby.yaml.j2
deleted file mode 120000
index 9280f58..0000000
--- a/src/tests/bundles/overlays/hirsute-wallaby.yaml.j2
+++ /dev/null
@@ -1 +0,0 @@
-ha.yaml.j2
\ No newline at end of file
diff --git a/src/tests/bundles/overlays/impish-xena.yaml.j2 b/src/tests/bundles/overlays/impish-xena.yaml.j2
deleted file mode 120000
index 9280f58..0000000
--- a/src/tests/bundles/overlays/impish-xena.yaml.j2
+++ /dev/null
@@ -1 +0,0 @@
-ha.yaml.j2
\ No newline at end of file
diff --git a/src/tests/tests.yaml b/src/tests/tests.yaml
index 9b88f7f..d27b47c 100644
--- a/src/tests/tests.yaml
+++ b/src/tests/tests.yaml
@@ -5,7 +5,6 @@ smoke_bundles:
 
 gate_bundles:
 - focal-xena
-- impish-xena
 
 dev_bundles:
 - focal-yoga
@@ -55,5 +54,4 @@ target_deploy_status:
 
 tests_options:
   force_deploy:
-    - impish-xena
     - jammy-yoga
diff --git a/tox.ini b/tox.ini
index e22fe48..e649e6a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,18 +11,6 @@ envlist = pep8,py3
 sitepackages = False
 # NOTE: Avoid false positives by not skipping missing interpreters.
 skip_missing_interpreters = False
-# NOTES:
-# * We avoid the new dependency resolver by pinning pip < 20.3, see
-#   https://github.com/pypa/pip/issues/9187
-# * Pinning dependencies requires tox >= 3.2.0, see
-#   https://tox.readthedocs.io/en/latest/config.html#conf-requires
-# * It is also necessary to pin virtualenv as a newer virtualenv would still
-#   lead to fetching the latest pip in the func* tox targets, see
-#   https://stackoverflow.com/a/38133283
-requires =
-  pip < 20.3
-  virtualenv < 20.0
-  setuptools<50.0.0
 
 # NOTE: https://wiki.canonical.com/engineering/OpenStack/InstallLatestToxOnOsci
 minversion = 3.18.0
@@ -41,7 +29,6 @@ allowlist_externals =
     charmcraft
     bash
     tox
-    rename.sh
 deps =
     -r{toxinidir}/requirements.txt
 
@@ -50,13 +37,12 @@ basepython = python3
 deps = -r{toxinidir}/build-requirements.txt
 commands =
     charmcraft clean
-    charmcraft -v build
-    {toxinidir}/rename.sh
+    charmcraft -v pack
 
 [testenv:build-reactive]
 basepython = python3
 commands =
-    charm-build --log-level DEBUG --use-lock-file-branches -o {toxinidir}/build/builds src {posargs}
+    charm-build --log-level DEBUG --use-lock-file-branches --binary-wheels-from-source -o {toxinidir}/build/builds src {posargs}
 
 [testenv:add-build-lock-file]
 basepython = python3
@@ -91,7 +77,7 @@ commands = stestr run --slowest {posargs}
 [testenv:pep8]
 basepython = python3
 deps = flake8==3.9.2
-       charm-tools==2.8.3
+       git+https://github.com/juju/charm-tools.git
 commands = flake8 {posargs} src unit_tests
 
 [testenv:func-target]