diff --git a/changelogs/fragments/59574-os_image_from_volume.yaml b/changelogs/fragments/59574-os_image_from_volume.yaml
new file mode 100644
index 00000000000..56c057cb3c4
--- /dev/null
+++ b/changelogs/fragments/59574-os_image_from_volume.yaml
@@ -0,0 +1,3 @@
+---
+minor_changes:
+  - os_image - add ``volume`` option to support creating an image from a volume
diff --git a/lib/ansible/modules/cloud/openstack/os_image.py b/lib/ansible/modules/cloud/openstack/os_image.py
index f103a7c0c6c..9a1d06d82ba 100644
--- a/lib/ansible/modules/cloud/openstack/os_image.py
+++ b/lib/ansible/modules/cloud/openstack/os_image.py
@@ -86,6 +86,11 @@ options:
    availability_zone:
      description:
        - Ignored. Present for backwards compatibility
+   volume:
+     version_added: "2.10"
+     description:
+       - ID of a volume to create an image from.
+       - The volume must be in AVAILABLE state.
 requirements: ["openstacksdk"]
 '''
 
@@ -109,6 +114,33 @@ EXAMPLES = '''
     properties:
       cpu_arch: x86_64
       distro: ubuntu
+
+# Create image from volume attached to an instance
+- name: create volume snapshot
+  os_volume_snapshot:
+    auth:
+      "{{ auth }}"
+    display_name: myvol_snapshot
+    volume: myvol
+    force: yes
+  register: myvol_snapshot
+
+- name: create volume from snapshot
+  os_volume:
+    auth:
+      "{{ auth }}"
+    size: "{{ myvol_snapshot.snapshot.size }}"
+    snapshot_id: "{{ myvol_snapshot.snapshot.id }}"
+    display_name: myvol_snapshot_volume
+    wait: yes
+  register: myvol_snapshot_volume
+
+- name: create image from volume snapshot
+  os_image:
+    auth:
+      "{{ auth }}"
+    volume: "{{ myvol_snapshot_volume.volume.id }}"
+    name: myvol_image
 '''
 
 from ansible.module_utils.basic import AnsibleModule
@@ -132,9 +164,13 @@ def main():
         ramdisk=dict(default=None),
         kernel=dict(default=None),
         properties=dict(type='dict', default={}),
+        volume=dict(default=None),
         state=dict(default='present', choices=['absent', 'present']),
     )
-    module_kwargs = openstack_module_kwargs()
+
+    module_kwargs = openstack_module_kwargs(
+        mutually_exclusive=[['filename', 'volume']],
+    )
     module = AnsibleModule(argument_spec, **module_kwargs)
 
     sdk, cloud = openstack_cloud_from_module(module)
@@ -162,6 +198,7 @@ def main():
                     protected=module.params['protected'],
                     min_disk=module.params['min_disk'],
                     min_ram=module.params['min_ram'],
+                    volume=module.params['volume'],
                     **kwargs
                 )
                 changed = True