23
23
from nova .api .openstack import wsgi
24
24
from nova .api import validation
25
25
from nova .compute import api as compute
26
+ from nova .compute import vm_states
26
27
import nova .conf
27
28
from nova import exception
28
29
from nova .i18n import _
30
+ from nova import objects
29
31
from nova .policies import evacuate as evac_policies
30
32
from nova import utils
31
33
32
34
CONF = nova .conf .CONF
33
35
34
36
LOG = logging .getLogger (__name__ )
35
37
38
+ MIN_VER_NOVA_COMPUTE_EVACUATE_STOPPED = 62
39
+
36
40
37
41
class EvacuateController (wsgi .Controller ):
38
42
def __init__ (self ):
@@ -77,7 +81,8 @@ def _get_password_v214(self, req, evacuate_body):
77
81
@validation .schema (evacuate .evacuate , "2.0" , "2.13" )
78
82
@validation .schema (evacuate .evacuate_v214 , "2.14" , "2.28" )
79
83
@validation .schema (evacuate .evacuate_v2_29 , "2.29" , "2.67" )
80
- @validation .schema (evacuate .evacuate_v2_68 , "2.68" )
84
+ @validation .schema (evacuate .evacuate_v2_68 , "2.68" , "2.94" )
85
+ @validation .schema (evacuate .evacuate_v2_95 , "2.95" )
81
86
def _evacuate (self , req , id , body ):
82
87
"""Permit admins to evacuate a server from a failed host
83
88
to a new one.
@@ -92,6 +97,19 @@ def _evacuate(self, req, id, body):
92
97
host = evacuate_body .get ("host" )
93
98
force = None
94
99
100
+ target_state = None
101
+ if api_version_request .is_supported (req , min_version = '2.95' ):
102
+ min_ver = objects .service .get_minimum_version_all_cells (
103
+ context , ['nova-compute' ])
104
+ if min_ver < MIN_VER_NOVA_COMPUTE_EVACUATE_STOPPED :
105
+ raise exception .NotSupportedComputeForEvacuateV295 (
106
+ {'currently' : min_ver ,
107
+ 'expected' : MIN_VER_NOVA_COMPUTE_EVACUATE_STOPPED })
108
+ # Starts to 2.95 any evacuated instances will be stopped at
109
+ # destination. Previously an active or stopped instance would have
110
+ # kept its state.
111
+ target_state = vm_states .STOPPED
112
+
95
113
on_shared_storage = self ._get_on_shared_storage (req , evacuate_body )
96
114
97
115
if api_version_request .is_supported (req , min_version = '2.29' ):
@@ -120,7 +138,8 @@ def _evacuate(self, req, id, body):
120
138
121
139
try :
122
140
self .compute_api .evacuate (context , instance , host ,
123
- on_shared_storage , password , force )
141
+ on_shared_storage , password , force ,
142
+ target_state )
124
143
except exception .InstanceInvalidState as state_error :
125
144
common .raise_http_conflict_for_instance_invalid_state (state_error ,
126
145
'evacuate' , id )
@@ -130,6 +149,8 @@ def _evacuate(self, req, id, body):
130
149
exception .ExtendedResourceRequestOldCompute ,
131
150
) as e :
132
151
raise exc .HTTPBadRequest (explanation = e .format_message ())
152
+ except exception .UnsupportedRPCVersion as e :
153
+ raise exc .HTTPConflict (explanation = e .format_message ())
133
154
134
155
if (not api_version_request .is_supported (req , min_version = '2.14' ) and
135
156
CONF .api .enable_instance_password ):
0 commit comments