We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
os_server_actions nova rebuild server
##### ISSUE TYPE

Feature Idea
##### COMPONENT NAME

os_server module
##### ANSIBLE VERSION

N/A
##### SUMMARY

Could it be possible to implement the nova rebuild server action in the os_server_actions module?

We use openstack in our CI pipeline, and this is far more cheaper then booting a new server every
time we test.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cloud/openstack/os_server_actions.py`
Content:
```
1 #!/usr/bin/python
2 # coding: utf-8 -*-
3 
4 # Copyright (c) 2015, Jesse Keating <jlk@derpops.bike>
5 #
6 # This module is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This software is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this software.  If not, see <http://www.gnu.org/licenses/>.
18 
19 
20 try:
21     import shade
22     from shade import meta
23     HAS_SHADE = True
24 except ImportError:
25     HAS_SHADE = False
26 
27 
28 DOCUMENTATION = '''
29 ---
30 module: os_server_actions
31 short_description: Perform actions on Compute Instances from OpenStack
32 extends_documentation_fragment: openstack
33 version_added: "2.0"
34 author: "Jesse Keating (@j2sol)"
35 description:
36    - Perform server actions on an existing compute instance from OpenStack.
37      This module does not return any data other than changed true/false.
38 options:
39    server:
40      description:
41         - Name or ID of the instance
42      required: true
43    wait:
44      description:
45         - If the module should wait for the instance action to be performed.
46      required: false
47      default: 'yes'
48    timeout:
49      description:
50         - The amount of time the module should wait for the instance to perform
51           the requested action.
52      required: false
53      default: 180
54    action:
55      description:
56        - Perform the given action. The lock and unlock actions always return
57          changed as the servers API does not provide lock status.
58      choices: [stop, start, pause, unpause, lock, unlock, suspend, resume]
59      default: present
60 requirements:
61     - "python >= 2.6"
62     - "shade"
63 '''
64 
65 EXAMPLES = '''
66 # Pauses a compute instance
67 - os_server_actions:
68        action: pause
69        auth:
70          auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0
71          username: admin
72          password: admin
73          project_name: admin
74        server: vm1
75        timeout: 200
76 '''
77 
78 _action_map = {'stop': 'SHUTOFF',
79                'start': 'ACTIVE',
80                'pause': 'PAUSED',
81                'unpause': 'ACTIVE',
82                'lock': 'ACTIVE', # API doesn't show lock/unlock status
83                'unlock': 'ACTIVE',
84                'suspend': 'SUSPENDED',
85                'resume': 'ACTIVE',}
86 
87 _admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']
88 
89 def _wait(timeout, cloud, server, action):
90     """Wait for the server to reach the desired state for the given action."""
91 
92     for count in shade._utils._iterate_timeout(
93             timeout,
94             "Timeout waiting for server to complete %s" % action):
95         try:
96             server = cloud.get_server(server.id)
97         except Exception:
98             continue
99 
100         if server.status == _action_map[action]:
101             return
102 
103         if server.status == 'ERROR':
104             module.fail_json(msg="Server reached ERROR state while attempting to %s" % action)
105 
106 def _system_state_change(action, status):
107     """Check if system state would change."""
108     if status == _action_map[action]:
109         return False
110     return True
111 
112 def main():
113     argument_spec = openstack_full_argument_spec(
114         server=dict(required=True),
115         action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',
116                                             'lock', 'unlock', 'suspend', 'resume']),
117     )
118 
119     module_kwargs = openstack_module_kwargs()
120     module = AnsibleModule(argument_spec, supports_check_mode=True, **module_kwargs)
121 
122     if not HAS_SHADE:
123         module.fail_json(msg='shade is required for this module')
124 
125     action = module.params['action']
126     wait = module.params['wait']
127     timeout = module.params['timeout']
128 
129     try:
130         if action in _admin_actions:
131             cloud = shade.operator_cloud(**module.params)
132         else:
133             cloud = shade.openstack_cloud(**module.params)
134         server = cloud.get_server(module.params['server'])
135         if not server:
136             module.fail_json(msg='Could not find server %s' % server)
137         status = server.status
138 
139         if module.check_mode:
140             module.exit_json(changed=_system_state_change(action, status))
141 
142         if action == 'stop':
143             if not _system_state_change(action, status):
144                 module.exit_json(changed=False)
145 
146             cloud.nova_client.servers.stop(server=server.id)
147             if wait:
148                 _wait(timeout, cloud, server, action)
149                 module.exit_json(changed=True)
150 
151         if action == 'start':
152             if not _system_state_change(action, status):
153                 module.exit_json(changed=False)
154 
155             cloud.nova_client.servers.start(server=server.id)
156             if wait:
157                 _wait(timeout, cloud, server, action)
158                 module.exit_json(changed=True)
159 
160         if action == 'pause':
161             if not _system_state_change(action, status):
162                 module.exit_json(changed=False)
163 
164             cloud.nova_client.servers.pause(server=server.id)
165             if wait:
166                 _wait(timeout, cloud, server, action)
167                 module.exit_json(changed=True)
168 
169         elif action == 'unpause':
170             if not _system_state_change(action, status):
171                 module.exit_json(changed=False)
172 
173             cloud.nova_client.servers.unpause(server=server.id)
174             if wait:
175                 _wait(timeout, cloud, server, action)
176             module.exit_json(changed=True)
177 
178         elif action == 'lock':
179             # lock doesn't set a state, just do it
180             cloud.nova_client.servers.lock(server=server.id)
181             module.exit_json(changed=True)
182 
183         elif action == 'unlock':
184             # unlock doesn't set a state, just do it
185             cloud.nova_client.servers.unlock(server=server.id)
186             module.exit_json(changed=True)
187 
188         elif action == 'suspend':
189             if not _system_state_change(action, status):
190                 module.exit_json(changed=False)
191 
192             cloud.nova_client.servers.suspend(server=server.id)
193             if wait:
194                 _wait(timeout, cloud, server, action)
195             module.exit_json(changed=True)
196 
197         elif action == 'resume':
198             if not _system_state_change(action, status):
199                 module.exit_json(changed=False)
200 
201             cloud.nova_client.servers.resume(server=server.id)
202             if wait:
203                 _wait(timeout, cloud, server, action)
204             module.exit_json(changed=True)
205 
206     except shade.OpenStackCloudException as e:
207         module.fail_json(msg=str(e), extra_data=e.extra_data)
208 
209 # this is magic, see lib/ansible/module_common.py
210 from ansible.module_utils.basic import *
211 from ansible.module_utils.openstack import *
212 if __name__ == '__main__':
213     main()
214
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cloud/openstack/os_server_actions.py b/cloud/openstack/os_server_actions.py
--- a/cloud/openstack/os_server_actions.py
+++ b/cloud/openstack/os_server_actions.py
@@ -35,6 +35,7 @@
 description:
    - Perform server actions on an existing compute instance from OpenStack.
      This module does not return any data other than changed true/false.
+     When I(action) is 'rebuild', then I(image) parameter is required.
 options:
    server:
      description:
@@ -55,8 +56,14 @@
      description:
        - Perform the given action. The lock and unlock actions always return
          changed as the servers API does not provide lock status.
-     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume]
+     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume,
+               rebuild]
      default: present
+   image:
+     description:
+       - Image the server should be rebuilt with
+     default: null
+     version_added: "2.3"
 requirements:
     - "python >= 2.6"
     - "shade"
@@ -82,7 +89,8 @@
                'lock': 'ACTIVE', # API doesn't show lock/unlock status
                'unlock': 'ACTIVE',
                'suspend': 'SUSPENDED',
-               'resume': 'ACTIVE',}
+               'resume': 'ACTIVE',
+               'rebuild': 'ACTIVE'}
 
 _admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']
 
@@ -113,11 +121,15 @@
     argument_spec = openstack_full_argument_spec(
         server=dict(required=True),
         action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',
-                                            'lock', 'unlock', 'suspend', 'resume']),
+                                            'lock', 'unlock', 'suspend', 'resume',
+                                            'rebuild']),
+        image=dict(required=False),
     )
 
     module_kwargs = openstack_module_kwargs()
-    module = AnsibleModule(argument_spec, supports_check_mode=True, **module_kwargs)
+    module = AnsibleModule(argument_spec, supports_check_mode=True,
+                           required_if=[('action', 'rebuild', ['image'])],
+                           **module_kwargs)
 
     if not HAS_SHADE:
         module.fail_json(msg='shade is required for this module')
@@ -125,6 +137,7 @@
     action = module.params['action']
     wait = module.params['wait']
     timeout = module.params['timeout']
+    image = module.params['image']
 
     try:
         if action in _admin_actions:
@@ -203,6 +216,18 @@
                 _wait(timeout, cloud, server, action)
             module.exit_json(changed=True)
 
+        elif action == 'rebuild':
+            image = cloud.get_image(image)
+
+            if image is None:
+                module.fail_json(msg="Image does not exist")
+
+            # rebuild doesn't set a state, just do it
+            cloud.nova_client.servers.rebuild(server=server.id, image=image.id)
+            if wait:
+                _wait(timeout, cloud, server, action)
+            module.exit_json(changed=True)
+
     except shade.OpenStackCloudException as e:
         module.fail_json(msg=str(e), extra_data=e.extra_data)

{"golden_diff": "diff --git a/cloud/openstack/os_server_actions.py b/cloud/openstack/os_server_actions.py\n--- a/cloud/openstack/os_server_actions.py\n+++ b/cloud/openstack/os_server_actions.py\n@@ -35,6 +35,7 @@\n description:\n    - Perform server actions on an existing compute instance from OpenStack.\n      This module does not return any data other than changed true/false.\n+     When I(action) is 'rebuild', then I(image) parameter is required.\n options:\n    server:\n      description:\n@@ -55,8 +56,14 @@\n      description:\n        - Perform the given action. The lock and unlock actions always return\n          changed as the servers API does not provide lock status.\n-     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume]\n+     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume,\n+               rebuild]\n      default: present\n+   image:\n+     description:\n+       - Image the server should be rebuilt with\n+     default: null\n+     version_added: \"2.3\"\n requirements:\n     - \"python >= 2.6\"\n     - \"shade\"\n@@ -82,7 +89,8 @@\n                'lock': 'ACTIVE', # API doesn't show lock/unlock status\n                'unlock': 'ACTIVE',\n                'suspend': 'SUSPENDED',\n-               'resume': 'ACTIVE',}\n+               'resume': 'ACTIVE',\n+               'rebuild': 'ACTIVE'}\n \n _admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']\n \n@@ -113,11 +121,15 @@\n     argument_spec = openstack_full_argument_spec(\n         server=dict(required=True),\n         action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',\n-                                            'lock', 'unlock', 'suspend', 'resume']),\n+                                            'lock', 'unlock', 'suspend', 'resume',\n+                                            'rebuild']),\n+        image=dict(required=False),\n     )\n \n     module_kwargs = openstack_module_kwargs()\n-    module = AnsibleModule(argument_spec, supports_check_mode=True, **module_kwargs)\n+    module = AnsibleModule(argument_spec, supports_check_mode=True,\n+                           required_if=[('action', 'rebuild', ['image'])],\n+                           **module_kwargs)\n \n     if not HAS_SHADE:\n         module.fail_json(msg='shade is required for this module')\n@@ -125,6 +137,7 @@\n     action = module.params['action']\n     wait = module.params['wait']\n     timeout = module.params['timeout']\n+    image = module.params['image']\n \n     try:\n         if action in _admin_actions:\n@@ -203,6 +216,18 @@\n                 _wait(timeout, cloud, server, action)\n             module.exit_json(changed=True)\n \n+        elif action == 'rebuild':\n+            image = cloud.get_image(image)\n+\n+            if image is None:\n+                module.fail_json(msg=\"Image does not exist\")\n+\n+            # rebuild doesn't set a state, just do it\n+            cloud.nova_client.servers.rebuild(server=server.id, image=image.id)\n+            if wait:\n+                _wait(timeout, cloud, server, action)\n+            module.exit_json(changed=True)\n+\n     except shade.OpenStackCloudException as e:\n         module.fail_json(msg=str(e), extra_data=e.extra_data)\n", "issue": "os_server_actions nova rebuild server\n##### ISSUE TYPE\n\nFeature Idea\n##### COMPONENT NAME\n\nos_server module\n##### ANSIBLE VERSION\n\nN/A\n##### SUMMARY\n\nCould it be possible to implement the nova rebuild server action in the os_server_actions module?\n\nWe use openstack in our CI pipeline, and this is far more cheaper then booting a new server every\ntime we test.\n\n", "before_files": [{"content": "#!/usr/bin/python\n# coding: utf-8 -*-\n\n# Copyright (c) 2015, Jesse Keating <jlk@derpops.bike>\n#\n# This module is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This software is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this software.  If not, see <http://www.gnu.org/licenses/>.\n\n\ntry:\n    import shade\n    from shade import meta\n    HAS_SHADE = True\nexcept ImportError:\n    HAS_SHADE = False\n\n\nDOCUMENTATION = '''\n---\nmodule: os_server_actions\nshort_description: Perform actions on Compute Instances from OpenStack\nextends_documentation_fragment: openstack\nversion_added: \"2.0\"\nauthor: \"Jesse Keating (@j2sol)\"\ndescription:\n   - Perform server actions on an existing compute instance from OpenStack.\n     This module does not return any data other than changed true/false.\noptions:\n   server:\n     description:\n        - Name or ID of the instance\n     required: true\n   wait:\n     description:\n        - If the module should wait for the instance action to be performed.\n     required: false\n     default: 'yes'\n   timeout:\n     description:\n        - The amount of time the module should wait for the instance to perform\n          the requested action.\n     required: false\n     default: 180\n   action:\n     description:\n       - Perform the given action. The lock and unlock actions always return\n         changed as the servers API does not provide lock status.\n     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume]\n     default: present\nrequirements:\n    - \"python >= 2.6\"\n    - \"shade\"\n'''\n\nEXAMPLES = '''\n# Pauses a compute instance\n- os_server_actions:\n       action: pause\n       auth:\n         auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0\n         username: admin\n         password: admin\n         project_name: admin\n       server: vm1\n       timeout: 200\n'''\n\n_action_map = {'stop': 'SHUTOFF',\n               'start': 'ACTIVE',\n               'pause': 'PAUSED',\n               'unpause': 'ACTIVE',\n               'lock': 'ACTIVE', # API doesn't show lock/unlock status\n               'unlock': 'ACTIVE',\n               'suspend': 'SUSPENDED',\n               'resume': 'ACTIVE',}\n\n_admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']\n\ndef _wait(timeout, cloud, server, action):\n    \"\"\"Wait for the server to reach the desired state for the given action.\"\"\"\n\n    for count in shade._utils._iterate_timeout(\n            timeout,\n            \"Timeout waiting for server to complete %s\" % action):\n        try:\n            server = cloud.get_server(server.id)\n        except Exception:\n            continue\n\n        if server.status == _action_map[action]:\n            return\n\n        if server.status == 'ERROR':\n            module.fail_json(msg=\"Server reached ERROR state while attempting to %s\" % action)\n\ndef _system_state_change(action, status):\n    \"\"\"Check if system state would change.\"\"\"\n    if status == _action_map[action]:\n        return False\n    return True\n\ndef main():\n    argument_spec = openstack_full_argument_spec(\n        server=dict(required=True),\n        action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',\n                                            'lock', 'unlock', 'suspend', 'resume']),\n    )\n\n    module_kwargs = openstack_module_kwargs()\n    module = AnsibleModule(argument_spec, supports_check_mode=True, **module_kwargs)\n\n    if not HAS_SHADE:\n        module.fail_json(msg='shade is required for this module')\n\n    action = module.params['action']\n    wait = module.params['wait']\n    timeout = module.params['timeout']\n\n    try:\n        if action in _admin_actions:\n            cloud = shade.operator_cloud(**module.params)\n        else:\n            cloud = shade.openstack_cloud(**module.params)\n        server = cloud.get_server(module.params['server'])\n        if not server:\n            module.fail_json(msg='Could not find server %s' % server)\n        status = server.status\n\n        if module.check_mode:\n            module.exit_json(changed=_system_state_change(action, status))\n\n        if action == 'stop':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.stop(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        if action == 'start':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.start(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        if action == 'pause':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.pause(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        elif action == 'unpause':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.unpause(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n        elif action == 'lock':\n            # lock doesn't set a state, just do it\n            cloud.nova_client.servers.lock(server=server.id)\n            module.exit_json(changed=True)\n\n        elif action == 'unlock':\n            # unlock doesn't set a state, just do it\n            cloud.nova_client.servers.unlock(server=server.id)\n            module.exit_json(changed=True)\n\n        elif action == 'suspend':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.suspend(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n        elif action == 'resume':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.resume(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n    except shade.OpenStackCloudException as e:\n        module.fail_json(msg=str(e), extra_data=e.extra_data)\n\n# this is magic, see lib/ansible/module_common.py\nfrom ansible.module_utils.basic import *\nfrom ansible.module_utils.openstack import *\nif __name__ == '__main__':\n    main()\n", "path": "cloud/openstack/os_server_actions.py"}], "after_files": [{"content": "#!/usr/bin/python\n# coding: utf-8 -*-\n\n# Copyright (c) 2015, Jesse Keating <jlk@derpops.bike>\n#\n# This module is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This software is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this software.  If not, see <http://www.gnu.org/licenses/>.\n\n\ntry:\n    import shade\n    from shade import meta\n    HAS_SHADE = True\nexcept ImportError:\n    HAS_SHADE = False\n\n\nDOCUMENTATION = '''\n---\nmodule: os_server_actions\nshort_description: Perform actions on Compute Instances from OpenStack\nextends_documentation_fragment: openstack\nversion_added: \"2.0\"\nauthor: \"Jesse Keating (@j2sol)\"\ndescription:\n   - Perform server actions on an existing compute instance from OpenStack.\n     This module does not return any data other than changed true/false.\n     When I(action) is 'rebuild', then I(image) parameter is required.\noptions:\n   server:\n     description:\n        - Name or ID of the instance\n     required: true\n   wait:\n     description:\n        - If the module should wait for the instance action to be performed.\n     required: false\n     default: 'yes'\n   timeout:\n     description:\n        - The amount of time the module should wait for the instance to perform\n          the requested action.\n     required: false\n     default: 180\n   action:\n     description:\n       - Perform the given action. The lock and unlock actions always return\n         changed as the servers API does not provide lock status.\n     choices: [stop, start, pause, unpause, lock, unlock, suspend, resume,\n               rebuild]\n     default: present\n   image:\n     description:\n       - Image the server should be rebuilt with\n     default: null\n     version_added: \"2.3\"\nrequirements:\n    - \"python >= 2.6\"\n    - \"shade\"\n'''\n\nEXAMPLES = '''\n# Pauses a compute instance\n- os_server_actions:\n       action: pause\n       auth:\n         auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0\n         username: admin\n         password: admin\n         project_name: admin\n       server: vm1\n       timeout: 200\n'''\n\n_action_map = {'stop': 'SHUTOFF',\n               'start': 'ACTIVE',\n               'pause': 'PAUSED',\n               'unpause': 'ACTIVE',\n               'lock': 'ACTIVE', # API doesn't show lock/unlock status\n               'unlock': 'ACTIVE',\n               'suspend': 'SUSPENDED',\n               'resume': 'ACTIVE',\n               'rebuild': 'ACTIVE'}\n\n_admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock']\n\ndef _wait(timeout, cloud, server, action):\n    \"\"\"Wait for the server to reach the desired state for the given action.\"\"\"\n\n    for count in shade._utils._iterate_timeout(\n            timeout,\n            \"Timeout waiting for server to complete %s\" % action):\n        try:\n            server = cloud.get_server(server.id)\n        except Exception:\n            continue\n\n        if server.status == _action_map[action]:\n            return\n\n        if server.status == 'ERROR':\n            module.fail_json(msg=\"Server reached ERROR state while attempting to %s\" % action)\n\ndef _system_state_change(action, status):\n    \"\"\"Check if system state would change.\"\"\"\n    if status == _action_map[action]:\n        return False\n    return True\n\ndef main():\n    argument_spec = openstack_full_argument_spec(\n        server=dict(required=True),\n        action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',\n                                            'lock', 'unlock', 'suspend', 'resume',\n                                            'rebuild']),\n        image=dict(required=False),\n    )\n\n    module_kwargs = openstack_module_kwargs()\n    module = AnsibleModule(argument_spec, supports_check_mode=True,\n                           required_if=[('action', 'rebuild', ['image'])],\n                           **module_kwargs)\n\n    if not HAS_SHADE:\n        module.fail_json(msg='shade is required for this module')\n\n    action = module.params['action']\n    wait = module.params['wait']\n    timeout = module.params['timeout']\n    image = module.params['image']\n\n    try:\n        if action in _admin_actions:\n            cloud = shade.operator_cloud(**module.params)\n        else:\n            cloud = shade.openstack_cloud(**module.params)\n        server = cloud.get_server(module.params['server'])\n        if not server:\n            module.fail_json(msg='Could not find server %s' % server)\n        status = server.status\n\n        if module.check_mode:\n            module.exit_json(changed=_system_state_change(action, status))\n\n        if action == 'stop':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.stop(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        if action == 'start':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.start(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        if action == 'pause':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.pause(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n                module.exit_json(changed=True)\n\n        elif action == 'unpause':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.unpause(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n        elif action == 'lock':\n            # lock doesn't set a state, just do it\n            cloud.nova_client.servers.lock(server=server.id)\n            module.exit_json(changed=True)\n\n        elif action == 'unlock':\n            # unlock doesn't set a state, just do it\n            cloud.nova_client.servers.unlock(server=server.id)\n            module.exit_json(changed=True)\n\n        elif action == 'suspend':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.suspend(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n        elif action == 'resume':\n            if not _system_state_change(action, status):\n                module.exit_json(changed=False)\n\n            cloud.nova_client.servers.resume(server=server.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n        elif action == 'rebuild':\n            image = cloud.get_image(image)\n\n            if image is None:\n                module.fail_json(msg=\"Image does not exist\")\n\n            # rebuild doesn't set a state, just do it\n            cloud.nova_client.servers.rebuild(server=server.id, image=image.id)\n            if wait:\n                _wait(timeout, cloud, server, action)\n            module.exit_json(changed=True)\n\n    except shade.OpenStackCloudException as e:\n        module.fail_json(msg=str(e), extra_data=e.extra_data)\n\n# this is magic, see lib/ansible/module_common.py\nfrom ansible.module_utils.basic import *\nfrom ansible.module_utils.openstack import *\nif __name__ == '__main__':\n    main()\n", "path": "cloud/openstack/os_server_actions.py"}]}