diff --git a/ci/roles/server/defaults/main.yaml b/ci/roles/server/defaults/main.yaml
index e3bd5f33..0b0f2769 100644
--- a/ci/roles/server/defaults/main.yaml
+++ b/ci/roles/server/defaults/main.yaml
@@ -1,5 +1,8 @@
 server_network: private
 server_name: ansible_server
+server_alt_network: private_alt
+server_alt_subnet: subnet_alt
+server_alt_name: ansible_server_alt
 flavor: m1.tiny
 floating_ip_pool_name: public
 boot_volume_size: 5
diff --git a/ci/roles/server/tasks/server_actions.yml b/ci/roles/server/tasks/server_actions.yml
index ede97a9c..7d0d33a1 100644
--- a/ci/roles/server/tasks/server_actions.yml
+++ b/ci/roles/server/tasks/server_actions.yml
@@ -518,3 +518,95 @@
     that:
       - info24.openstack_servers.0.status == 'ACTIVE'
       - server is not changed
+
+- name: Create network for alternate server
+  openstack.cloud.network:
+    cloud: "{{ cloud_alt }}"
+    name: "{{ server_alt_network }}"
+    state: present
+
+- name: Create subnet for alternate server
+  openstack.cloud.subnet:
+    cloud: "{{ cloud_alt }}"
+    network_name: "{{ server_alt_network }}"
+    name: "{{ server_alt_subnet }}"
+    state: present
+    cidr: 192.168.0.0/24
+
+- name: Create server in alternate project
+  openstack.cloud.server:
+     cloud: "{{ cloud_alt }}"
+     state: present
+     name: "{{ server_alt_name }}"
+     image: "{{ image }}"
+     flavor: "{{ flavor }}"
+     network: "{{ server_alt_network }}"
+     auto_floating_ip: false
+     wait: true
+  register: server_alt
+
+- name: Get info about server in alternate project
+  openstack.cloud.server_info:
+    cloud: "{{ cloud_alt }}"
+    server: "{{ server_alt_name }}"
+  register: info25
+
+- name: Ensure status for server in alternate project is ACTIVE
+  assert:
+    that:
+      - info25.openstack_servers.0.status == 'ACTIVE'
+
+- name: Try to stop server in alternate project
+  openstack.cloud.server_action:
+    cloud: "{{ cloud }}"
+    server: "{{ server_alt_name }}"
+    action: stop
+    wait: true
+  ignore_errors: true
+  register: server_alt
+
+- name: Ensure server was not stopped
+  assert:
+    that:
+      - server_alt is failed
+      - server_alt.msg == "Could not find server {{ server_alt_name }}"
+
+- name: Stop server in alternate project with all_projects=true
+  openstack.cloud.server_action:
+    cloud: "{{ cloud }}"
+    server: "{{ server_alt_name }}"
+    action: stop
+    wait: true
+    all_projects: True
+  register: server_alt
+
+- name: Get info about server in alternate project
+  openstack.cloud.server_info:
+    cloud: "{{ cloud_alt }}"
+    server: "{{ server_alt_name }}"
+  register: info26
+
+- name: Ensure status for server is SHUTOFF
+  assert:
+    that:
+      - info26.openstack_servers.0.status == 'SHUTOFF'
+      - server_alt is changed
+
+- name: Delete server in alternate project
+  openstack.cloud.server:
+     cloud: "{{ cloud_alt }}"
+     state: absent
+     name: "{{ server_alt_name }}"
+     wait: true
+
+- name: Delete subnet for alternate server
+  openstack.cloud.subnet:
+    cloud: "{{ cloud_alt }}"
+    name: "{{ server_alt_subnet }}"
+    state: absent
+
+- name: Delete network for alternate server
+  openstack.cloud.network:
+    cloud: "{{ cloud_alt }}"
+    name: "{{ server_alt_network }}"
+    state: absent
diff --git a/ci/run-ansible-tests-collection.sh b/ci/run-ansible-tests-collection.sh
index 32a2894a..31003ab3 100644
--- a/ci/run-ansible-tests-collection.sh
+++ b/ci/run-ansible-tests-collection.sh
@@ -6,20 +6,22 @@
 #
 #    tox -e ansible [TAG ...]
 # or
-#    tox -e ansible -- -c cloudX [TAG ...]
+#    tox -e ansible -- -c cloudX -u cloudY [TAG ...]
 # or to use the development version of Ansible:
-#    tox -e ansible -- -d -c cloudX [TAG ...]
+#    tox -e ansible -- -d -c cloudX -u cloudY [TAG ...]
 #
 # USAGE:
-#    run-ansible-tests.sh -e ENVDIR [-d] [-c CLOUD] [TAG ...]
+#    run-ansible-tests.sh -e ENVDIR [-d] [-c CLOUD] [-u CLOUD_ALT] [TAG ...]
 #
 # PARAMETERS:
-#    -d         Use Ansible source repo development branch.
-#    -e ENVDIR  Directory of the tox environment to use for testing.
-#    -c CLOUD   Name of the cloud to use for testing.
-#               Defaults to "devstack-admin".
-#    [TAG ...]  Optional list of space-separated tags to control which
-#               modules are tested.
+#    -d            Use Ansible source repo development branch.
+#    -e ENVDIR     Directory of the tox environment to use for testing.
+#    -c CLOUD      Name of the cloud to use for testing.
+#                  Defaults to "devstack-admin".
+#    -u CLOUD_ALT  Name of another cloud to use for testing.
+#                  Defaults to "devstack-alt".
+#    [TAG ...]     Optional list of space-separated tags to control which
+#                  modules are tested.
 #
 # EXAMPLES:
 #    # Run all Ansible tests
@@ -31,14 +33,16 @@
 set -ex
 
 CLOUD="devstack-admin"
+CLOUD_ALT="devstack-alt"
 ENVDIR=
 USE_DEV=0
 
-while getopts "c:de:" opt
+while getopts "c:de:u:" opt
 do
     case $opt in
     d) USE_DEV=1 ;;
     c) CLOUD=${OPTARG} ;;
+    u) CLOUD_ALT=${OPTARG} ;;
     e) ENVDIR=${OPTARG} ;;
     ?) echo "Invalid option: -${OPTARG}"
        exit 1;;
@@ -134,6 +138,6 @@ pushd ci/
 set -o pipefail
 ANSIBLE_COLLECTIONS_PATHS=$TEST_COLLECTIONS_PATHS ansible-playbook \
     -vvv ./run-collection.yml \
-    -e "sdk_version=${SDK_VER} cloud=${CLOUD} image=${IMAGE} ${ANSIBLE_VARS}" \
+    -e "sdk_version=${SDK_VER} cloud=${CLOUD} cloud_alt=${CLOUD_ALT} image=${IMAGE} ${ANSIBLE_VARS}" \
     ${tag_opt} 2>&1 | sudo tee /opt/stack/logs/test_output.log
 popd
diff --git a/plugins/modules/server_action.py b/plugins/modules/server_action.py
index 747278bc..341ff374 100644
--- a/plugins/modules/server_action.py
+++ b/plugins/modules/server_action.py
@@ -46,6 +46,12 @@ options:
         description:
         - Admin password for server to rebuild
         type: str
+    all_projects:
+        description:
+        - Whether to search for server in all projects or just the current
+          auth scoped project.
+        type: bool
+        default: 'no'
 
 requirements:
     - "python >= 3.6"
@@ -120,6 +126,7 @@ class ServerActionModule(OpenStackModule):
                              'rebuild', 'shelve', 'shelve_offload', 'unshelve']),
         image=dict(required=False, type='str'),
         admin_password=dict(required=False, type='str', no_log=True),
+        all_projects=dict(required=False, type='bool', default=False),
     )
     module_kwargs = dict(
         required_if=[('action', 'rebuild', ['image'])],
@@ -137,7 +144,10 @@ class ServerActionModule(OpenStackModule):
 
     def _preliminary_checks(self):
         # Using Munch object for getting information about a server
-        os_server = self.conn.get_server(self.params['server'])
+        os_server = self.conn.get_server(
+            self.params['server'],
+            all_projects=self.params['all_projects'],
+        )
         if not os_server:
             self.fail_json(msg='Could not find server %s' % self.params['server'])
         # check mode
@@ -193,8 +203,9 @@ class ServerActionModule(OpenStackModule):
 
     def _wait(self, os_server):
         """Wait for the server to reach the desired state for the given action."""
-        # Using Server object for wait_for_server function
-        server = self.conn.compute.find_server(self.params['server'])
+        # The wait_for_server function needs a Server object instead of the
+        # Munch object returned by self.conn.get_server
+        server = self.conn.compute.get_server(os_server['id'])
         states = _action_map[self.params['action']]
 
         try: