API for shelving
Adds new 'shelve', 'shelveOffload'/'shelve_offload'(V3), and 'unshelve' actions to the API. Exposes the functionality already provided in the compute api. Part of bp shelve-instance Co-author: Dan Smith <danms@us.ibm.com> (Instance objects) Change-Id: Idd485b591730c6ac025ee57a1242afdd02191b2f
This commit is contained in:
		@@ -512,6 +512,14 @@
 | 
				
			|||||||
            "namespace": "http://docs.openstack.org/compute/ext/extended_services/api/v2",
 | 
					            "namespace": "http://docs.openstack.org/compute/ext/extended_services/api/v2",
 | 
				
			||||||
            "updated": "2013-05-17T00:00:00-00:00"
 | 
					            "updated": "2013-05-17T00:00:00-00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "alias": "os-shelve",
 | 
				
			||||||
 | 
					            "description": "Instance shelve mode.",
 | 
				
			||||||
 | 
					            "links": [],
 | 
				
			||||||
 | 
					            "name": "Shelve",
 | 
				
			||||||
 | 
					            "namespace": "http://docs.openstack.org/compute/ext/shelve/api/v1.1",
 | 
				
			||||||
 | 
					            "updated": "2013-04-06T00:00:00+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "alias": "os-simple-tenant-usage",
 | 
					            "alias": "os-simple-tenant-usage",
 | 
				
			||||||
            "description": "Simple tenant usage extension.",
 | 
					            "description": "Simple tenant usage extension.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -210,6 +210,9 @@
 | 
				
			|||||||
  <extension alias="os-extended-services" updated="2013-05-17T00:00:00-00:00" namespace="http://docs.openstack.org/compute/ext/extended_services/api/v2" name="ExtendedServices">
 | 
					  <extension alias="os-extended-services" updated="2013-05-17T00:00:00-00:00" namespace="http://docs.openstack.org/compute/ext/extended_services/api/v2" name="ExtendedServices">
 | 
				
			||||||
    <description>Extended services support.</description>
 | 
					    <description>Extended services support.</description>
 | 
				
			||||||
  </extension>
 | 
					  </extension>
 | 
				
			||||||
 | 
					  <extension alias="os-shelve" updated="2013-04-06T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/shelve/api/v1.1" name="Shelve">
 | 
				
			||||||
 | 
					    <description>Instance shelve mode.</description>
 | 
				
			||||||
 | 
					  </extension>
 | 
				
			||||||
  <extension alias="os-simple-tenant-usage" updated="2011-08-19T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1" name="SimpleTenantUsage">
 | 
					  <extension alias="os-simple-tenant-usage" updated="2011-08-19T00:00:00+00:00" namespace="http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1" name="SimpleTenantUsage">
 | 
				
			||||||
    <description>Simple tenant usage extension.</description>
 | 
					    <description>Simple tenant usage extension.</description>
 | 
				
			||||||
  </extension>
 | 
					  </extension>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								doc/api_samples/os-shelve/os-shelve.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								doc/api_samples/os-shelve/os-shelve.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "shelve": null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2
									
								
								doc/api_samples/os-shelve/os-shelve.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								doc/api_samples/os-shelve/os-shelve.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					    <shelve/>
 | 
				
			||||||
							
								
								
									
										16
									
								
								doc/api_samples/os-shelve/server-post-req.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								doc/api_samples/os-shelve/server-post-req.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "server" : {
 | 
				
			||||||
 | 
					        "name" : "new-server-test",
 | 
				
			||||||
 | 
					        "imageRef" : "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b",
 | 
				
			||||||
 | 
					        "flavorRef" : "http://openstack.example.com/openstack/flavors/1",
 | 
				
			||||||
 | 
					        "metadata" : {
 | 
				
			||||||
 | 
					            "My Server Name" : "Apache1"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "personality" : [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "path" : "/etc/banner.txt",
 | 
				
			||||||
 | 
					                "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								doc/api_samples/os-shelve/server-post-req.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								doc/api_samples/os-shelve/server-post-req.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" flavorRef="http://openstack.example.com/openstack/flavors/1" name="new-server-test">
 | 
				
			||||||
 | 
					  <metadata>
 | 
				
			||||||
 | 
					    <meta key="My Server Name">Apache1</meta>
 | 
				
			||||||
 | 
					  </metadata>
 | 
				
			||||||
 | 
					  <personality>
 | 
				
			||||||
 | 
					    <file path="/etc/banner.txt">
 | 
				
			||||||
 | 
					        ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
 | 
				
			||||||
 | 
					        dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
 | 
				
			||||||
 | 
					        IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
 | 
				
			||||||
 | 
					        c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
 | 
				
			||||||
 | 
					        QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
 | 
				
			||||||
 | 
					        ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
 | 
				
			||||||
 | 
					        dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
 | 
				
			||||||
 | 
					        c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
 | 
				
			||||||
 | 
					        b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
 | 
				
			||||||
 | 
					    </file>
 | 
				
			||||||
 | 
					  </personality>
 | 
				
			||||||
 | 
					</server>
 | 
				
			||||||
							
								
								
									
										16
									
								
								doc/api_samples/os-shelve/server-post-resp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								doc/api_samples/os-shelve/server-post-resp.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "server": {
 | 
				
			||||||
 | 
					        "adminPass": "bGZzzzeaSp9z",
 | 
				
			||||||
 | 
					        "id": "9582b762-0964-4509-8fff-0146c02abe31",
 | 
				
			||||||
 | 
					        "links": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "href": "http://openstack.example.com/v2/openstack/servers/9582b762-0964-4509-8fff-0146c02abe31",
 | 
				
			||||||
 | 
					                "rel": "self"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "href": "http://openstack.example.com/openstack/servers/9582b762-0964-4509-8fff-0146c02abe31",
 | 
				
			||||||
 | 
					                "rel": "bookmark"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								doc/api_samples/os-shelve/server-post-resp.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								doc/api_samples/os-shelve/server-post-resp.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version='1.0' encoding='UTF-8'?>
 | 
				
			||||||
 | 
					<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="380d8ce9-bd82-4182-b643-b72232cd11d0" adminPass="LePA926cLP3R">
 | 
				
			||||||
 | 
					  <metadata/>
 | 
				
			||||||
 | 
					  <atom:link href="http://openstack.example.com/v2/openstack/servers/380d8ce9-bd82-4182-b643-b72232cd11d0" rel="self"/>
 | 
				
			||||||
 | 
					  <atom:link href="http://openstack.example.com/openstack/servers/380d8ce9-bd82-4182-b643-b72232cd11d0" rel="bookmark"/>
 | 
				
			||||||
 | 
					</server>
 | 
				
			||||||
@@ -162,10 +162,16 @@
 | 
				
			|||||||
    "compute_extension:services": "rule:admin_api",
 | 
					    "compute_extension:services": "rule:admin_api",
 | 
				
			||||||
    "compute_extension:v3:os-services": "rule:admin_api",
 | 
					    "compute_extension:v3:os-services": "rule:admin_api",
 | 
				
			||||||
    "compute_extension:v3:servers:discoverable": "",
 | 
					    "compute_extension:v3:servers:discoverable": "",
 | 
				
			||||||
 | 
					    "compute_extension:shelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:shelveOffload": "rule:admin_api",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:shelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:shelve_offload": "rule:admin_api",
 | 
				
			||||||
    "compute_extension:simple_tenant_usage:show": "rule:admin_or_owner",
 | 
					    "compute_extension:simple_tenant_usage:show": "rule:admin_or_owner",
 | 
				
			||||||
    "compute_extension:v3:os-simple-tenant-usage:show": "rule:admin_or_owner",
 | 
					    "compute_extension:v3:os-simple-tenant-usage:show": "rule:admin_or_owner",
 | 
				
			||||||
    "compute_extension:simple_tenant_usage:list": "rule:admin_api",
 | 
					    "compute_extension:simple_tenant_usage:list": "rule:admin_api",
 | 
				
			||||||
    "compute_extension:v3:os-simple-tenant-usage:list": "rule:admin_api",
 | 
					    "compute_extension:v3:os-simple-tenant-usage:list": "rule:admin_api",
 | 
				
			||||||
 | 
					    "compute_extension:unshelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:unshelve": "",
 | 
				
			||||||
    "compute_extension:users": "rule:admin_api",
 | 
					    "compute_extension:users": "rule:admin_api",
 | 
				
			||||||
    "compute_extension:virtual_interfaces": "",
 | 
					    "compute_extension:virtual_interfaces": "",
 | 
				
			||||||
    "compute_extension:virtual_storage_arrays": "",
 | 
					    "compute_extension:virtual_storage_arrays": "",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,6 +103,12 @@ _STATE_MAP = {
 | 
				
			|||||||
    vm_states.SOFT_DELETED: {
 | 
					    vm_states.SOFT_DELETED: {
 | 
				
			||||||
        'default': 'DELETED',
 | 
					        'default': 'DELETED',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    vm_states.SHELVED: {
 | 
				
			||||||
 | 
					        'default': 'SHELVED',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    vm_states.SHELVED_OFFLOADED: {
 | 
				
			||||||
 | 
					        'default': 'SHELVED_OFFLOADED',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										100
									
								
								nova/api/openstack/compute/contrib/shelve.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								nova/api/openstack/compute/contrib/shelve.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					#   Copyright 2013 Rackspace Hosting
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
				
			||||||
 | 
					#   not use this file except in compliance with the License. You may obtain
 | 
				
			||||||
 | 
					#   a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
				
			||||||
 | 
					#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
				
			||||||
 | 
					#   License for the specific language governing permissions and limitations
 | 
				
			||||||
 | 
					#   under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""The shelved mode extension."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import webob
 | 
				
			||||||
 | 
					from webob import exc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from nova.api.openstack import common
 | 
				
			||||||
 | 
					from nova.api.openstack import extensions as exts
 | 
				
			||||||
 | 
					from nova.api.openstack import wsgi
 | 
				
			||||||
 | 
					from nova import compute
 | 
				
			||||||
 | 
					from nova import exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auth_shelve = exts.extension_authorizer('compute', 'shelve')
 | 
				
			||||||
 | 
					auth_shelve_offload = exts.extension_authorizer('compute', 'shelveOffload')
 | 
				
			||||||
 | 
					auth_unshelve = exts.extension_authorizer('compute', 'unshelve')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShelveController(wsgi.Controller):
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super(ShelveController, self).__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.compute_api = compute.API()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_instance(self, context, instance_id):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return self.compute_api.get(context, instance_id,
 | 
				
			||||||
 | 
					                                        want_objects=True)
 | 
				
			||||||
 | 
					        except exception.InstanceNotFound:
 | 
				
			||||||
 | 
					            msg = _("Server not found")
 | 
				
			||||||
 | 
					            raise exc.HTTPNotFound(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('shelve')
 | 
				
			||||||
 | 
					    def _shelve(self, req, id, body):
 | 
				
			||||||
 | 
					        """Move an instance into shelved mode."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_shelve(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.shelve(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                                  'shelve')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('shelveOffload')
 | 
				
			||||||
 | 
					    def _shelve_offload(self, req, id, body):
 | 
				
			||||||
 | 
					        """Force removal of a shelved instance from the compute node."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_shelve_offload(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.shelve_offload(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                              'shelveOffload')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('unshelve')
 | 
				
			||||||
 | 
					    def _unshelve(self, req, id, body):
 | 
				
			||||||
 | 
					        """Restore an instance from shelved mode."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_unshelve(context)
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.unshelve(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                                  'unshelve')
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Shelve(exts.ExtensionDescriptor):
 | 
				
			||||||
 | 
					    """Instance shelve mode."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = "Shelve"
 | 
				
			||||||
 | 
					    alias = "os-shelve"
 | 
				
			||||||
 | 
					    namespace = "http://docs.openstack.org/compute/ext/shelve/api/v1.1"
 | 
				
			||||||
 | 
					    updated = "2013-04-06T00:00:00+00:00"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_controller_extensions(self):
 | 
				
			||||||
 | 
					        controller = ShelveController()
 | 
				
			||||||
 | 
					        extension = exts.ControllerExtension(self, 'servers', controller)
 | 
				
			||||||
 | 
					        return [extension]
 | 
				
			||||||
							
								
								
									
										105
									
								
								nova/api/openstack/compute/plugins/v3/shelve.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								nova/api/openstack/compute/plugins/v3/shelve.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					#   Copyright 2013 Rackspace Hosting
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
				
			||||||
 | 
					#   not use this file except in compliance with the License. You may obtain
 | 
				
			||||||
 | 
					#   a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
				
			||||||
 | 
					#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
				
			||||||
 | 
					#   License for the specific language governing permissions and limitations
 | 
				
			||||||
 | 
					#   under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""The shelved mode extension."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import webob
 | 
				
			||||||
 | 
					from webob import exc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from nova.api.openstack import common
 | 
				
			||||||
 | 
					from nova.api.openstack import extensions as exts
 | 
				
			||||||
 | 
					from nova.api.openstack import wsgi
 | 
				
			||||||
 | 
					from nova import compute
 | 
				
			||||||
 | 
					from nova import exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALIAS = 'os-shelve'
 | 
				
			||||||
 | 
					auth_shelve = exts.extension_authorizer('compute', 'v3:%s:shelve' % ALIAS)
 | 
				
			||||||
 | 
					auth_shelve_offload = exts.extension_authorizer('compute',
 | 
				
			||||||
 | 
					                                                'v3:%s:shelve_offload' % ALIAS)
 | 
				
			||||||
 | 
					auth_unshelve = exts.extension_authorizer('compute', 'v3:%s:unshelve' % ALIAS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShelveController(wsgi.Controller):
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super(ShelveController, self).__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.compute_api = compute.API()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_instance(self, context, instance_id):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            return self.compute_api.get(context, instance_id,
 | 
				
			||||||
 | 
					                                        want_objects=True)
 | 
				
			||||||
 | 
					        except exception.InstanceNotFound:
 | 
				
			||||||
 | 
					            msg = _("Server not found")
 | 
				
			||||||
 | 
					            raise exc.HTTPNotFound(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('shelve')
 | 
				
			||||||
 | 
					    def _shelve(self, req, id, body):
 | 
				
			||||||
 | 
					        """Move an instance into shelved mode."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_shelve(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.shelve(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                                  'shelve')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('shelve_offload')
 | 
				
			||||||
 | 
					    def _shelve_offload(self, req, id, body):
 | 
				
			||||||
 | 
					        """Force removal of a shelved instance from the compute node."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_shelve_offload(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.shelve_offload(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                              'shelve_offload')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @wsgi.action('unshelve')
 | 
				
			||||||
 | 
					    def _unshelve(self, req, id, body):
 | 
				
			||||||
 | 
					        """Restore an instance from shelved mode."""
 | 
				
			||||||
 | 
					        context = req.environ["nova.context"]
 | 
				
			||||||
 | 
					        auth_unshelve(context)
 | 
				
			||||||
 | 
					        instance = self._get_instance(context, id)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.compute_api.unshelve(context, instance)
 | 
				
			||||||
 | 
					        except exception.InstanceInvalidState as state_error:
 | 
				
			||||||
 | 
					            common.raise_http_conflict_for_instance_invalid_state(state_error,
 | 
				
			||||||
 | 
					                                                                  'unshelve')
 | 
				
			||||||
 | 
					        return webob.Response(status_int=202)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Shelve(exts.V3APIExtensionBase):
 | 
				
			||||||
 | 
					    """Instance shelve mode."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = "Shelve"
 | 
				
			||||||
 | 
					    alias = ALIAS
 | 
				
			||||||
 | 
					    namespace = "http://docs.openstack.org/compute/ext/shelve/api/v3"
 | 
				
			||||||
 | 
					    version = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_controller_extensions(self):
 | 
				
			||||||
 | 
					        controller = ShelveController()
 | 
				
			||||||
 | 
					        extension = exts.ControllerExtension(self, 'servers', controller)
 | 
				
			||||||
 | 
					        return [extension]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_resources(self):
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
							
								
								
									
										107
									
								
								nova/tests/api/openstack/compute/contrib/test_shelve.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								nova/tests/api/openstack/compute/contrib/test_shelve.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					# All Rights Reserved.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
				
			||||||
 | 
					#    not use this file except in compliance with the License. You may obtain
 | 
				
			||||||
 | 
					#    a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#         http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
				
			||||||
 | 
					#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
				
			||||||
 | 
					#    License for the specific language governing permissions and limitations
 | 
				
			||||||
 | 
					#    under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from nova.api.openstack.compute.contrib import shelve
 | 
				
			||||||
 | 
					from nova import db
 | 
				
			||||||
 | 
					from nova import exception
 | 
				
			||||||
 | 
					from nova.openstack.common import policy
 | 
				
			||||||
 | 
					from nova import test
 | 
				
			||||||
 | 
					from nova.tests.api.openstack import fakes
 | 
				
			||||||
 | 
					from nova.tests import fake_instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShelvePolicyTest(test.TestCase):
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        super(ShelvePolicyTest, self).setUp()
 | 
				
			||||||
 | 
					        self.controller = shelve.ShelveController()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve_restricted_by_role(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute_extension:shelve':
 | 
				
			||||||
 | 
					                              policy.parse_rule('role:admin')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized, self.controller._shelve,
 | 
				
			||||||
 | 
					                req, str(uuid.uuid4()), {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve_allowed(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute:get': policy.parse_rule(''),
 | 
				
			||||||
 | 
					                              'compute_extension:shelve':
 | 
				
			||||||
 | 
					                              policy.parse_rule('')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def fake_instance_get_by_uuid(context, instance_id,
 | 
				
			||||||
 | 
					                                      columns_to_join=None):
 | 
				
			||||||
 | 
					            return fake_instance.fake_db_instance(
 | 
				
			||||||
 | 
					                **{'name': 'fake', 'project_id': '%s_unequal' %
 | 
				
			||||||
 | 
					                       context.project_id})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized, self.controller._shelve,
 | 
				
			||||||
 | 
					                req, str(uuid.uuid4()), {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_unshelve_restricted_by_role(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute_extension:unshelve':
 | 
				
			||||||
 | 
					                              policy.parse_rule('role:admin')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized, self.controller._unshelve,
 | 
				
			||||||
 | 
					                req, str(uuid.uuid4()), {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_unshelve_allowed(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute:get': policy.parse_rule(''),
 | 
				
			||||||
 | 
					                              'compute_extension:unshelve':
 | 
				
			||||||
 | 
					                              policy.parse_rule('')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def fake_instance_get_by_uuid(context, instance_id,
 | 
				
			||||||
 | 
					                                      columns_to_join=None):
 | 
				
			||||||
 | 
					            return fake_instance.fake_db_instance(
 | 
				
			||||||
 | 
					                **{'name': 'fake', 'project_id': '%s_unequal' %
 | 
				
			||||||
 | 
					                       context.project_id})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized, self.controller._unshelve,
 | 
				
			||||||
 | 
					                req, str(uuid.uuid4()), {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve_offload_restricted_by_role(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute_extension:shelveOffload':
 | 
				
			||||||
 | 
					                              policy.parse_rule('role:admin')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized,
 | 
				
			||||||
 | 
					                self.controller._shelve_offload, req, str(uuid.uuid4()), {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve_offload_allowed(self):
 | 
				
			||||||
 | 
					        rules = policy.Rules({'compute:get': policy.parse_rule(''),
 | 
				
			||||||
 | 
					                              'compute_extension:shelveOffload':
 | 
				
			||||||
 | 
					                              policy.parse_rule('')})
 | 
				
			||||||
 | 
					        policy.set_rules(rules)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def fake_instance_get_by_uuid(context, instance_id,
 | 
				
			||||||
 | 
					                                      columns_to_join=None):
 | 
				
			||||||
 | 
					            return fake_instance.fake_db_instance(
 | 
				
			||||||
 | 
					                **{'name': 'fake', 'project_id': '%s_unequal' %
 | 
				
			||||||
 | 
					                       context.project_id})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid)
 | 
				
			||||||
 | 
					        req = fakes.HTTPRequest.blank('/v2/123/servers/12/os-shelve')
 | 
				
			||||||
 | 
					        self.assertRaises(exception.NotAuthorized,
 | 
				
			||||||
 | 
					                self.controller._shelve_offload, req, str(uuid.uuid4()), {})
 | 
				
			||||||
@@ -238,10 +238,16 @@ policy_data = """
 | 
				
			|||||||
    "compute_extension:server_usage": "",
 | 
					    "compute_extension:server_usage": "",
 | 
				
			||||||
    "compute_extension:services": "",
 | 
					    "compute_extension:services": "",
 | 
				
			||||||
    "compute_extension:v3:os-services": "",
 | 
					    "compute_extension:v3:os-services": "",
 | 
				
			||||||
 | 
					    "compute_extension:shelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:shelveOffload": "",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:shelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:shelve_offload": "",
 | 
				
			||||||
    "compute_extension:simple_tenant_usage:show": "",
 | 
					    "compute_extension:simple_tenant_usage:show": "",
 | 
				
			||||||
    "compute_extension:v3:os-simple-tenant-usage:show": "",
 | 
					    "compute_extension:v3:os-simple-tenant-usage:show": "",
 | 
				
			||||||
    "compute_extension:simple_tenant_usage:list": "",
 | 
					    "compute_extension:simple_tenant_usage:list": "",
 | 
				
			||||||
    "compute_extension:v3:os-simple-tenant-usage:list": "",
 | 
					    "compute_extension:v3:os-simple-tenant-usage:list": "",
 | 
				
			||||||
 | 
					    "compute_extension:unshelve": "",
 | 
				
			||||||
 | 
					    "compute_extension:v3:os-shelve:unshelve": "",
 | 
				
			||||||
    "compute_extension:users": "",
 | 
					    "compute_extension:users": "",
 | 
				
			||||||
    "compute_extension:virtual_interfaces": "",
 | 
					    "compute_extension:virtual_interfaces": "",
 | 
				
			||||||
    "compute_extension:virtual_storage_arrays": "",
 | 
					    "compute_extension:virtual_storage_arrays": "",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -512,6 +512,14 @@
 | 
				
			|||||||
            "namespace": "http://docs.openstack.org/compute/ext/servers/api/v1.1",
 | 
					            "namespace": "http://docs.openstack.org/compute/ext/servers/api/v1.1",
 | 
				
			||||||
            "updated": "%(timestamp)s"
 | 
					            "updated": "%(timestamp)s"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "alias": "os-shelve",
 | 
				
			||||||
 | 
					            "description": "%(text)s",
 | 
				
			||||||
 | 
					            "links": [],
 | 
				
			||||||
 | 
					            "name": "Shelve",
 | 
				
			||||||
 | 
					            "namespace": "http://docs.openstack.org/compute/ext/shelve/api/v1.1",
 | 
				
			||||||
 | 
					            "updated": "%(timestamp)s"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "alias": "os-simple-tenant-usage",
 | 
					            "alias": "os-simple-tenant-usage",
 | 
				
			||||||
            "description": "%(text)s",
 | 
					            "description": "%(text)s",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -192,6 +192,9 @@
 | 
				
			|||||||
  <extension alias="os-server-start-stop" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/servers/api/v1.1" name="ServerStartStop">
 | 
					  <extension alias="os-server-start-stop" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/servers/api/v1.1" name="ServerStartStop">
 | 
				
			||||||
    <description>%(text)s</description>
 | 
					    <description>%(text)s</description>
 | 
				
			||||||
  </extension>
 | 
					  </extension>
 | 
				
			||||||
 | 
					  <extension alias="os-shelve" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/shelve/api/v1.1" name="Shelve">
 | 
				
			||||||
 | 
					    <description>%(text)s</description>
 | 
				
			||||||
 | 
					  </extension>
 | 
				
			||||||
  <extension alias="os-simple-tenant-usage" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1" name="SimpleTenantUsage">
 | 
					  <extension alias="os-simple-tenant-usage" updated="%(timestamp)s" namespace="http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1" name="SimpleTenantUsage">
 | 
				
			||||||
    <description>%(text)s</description>
 | 
					    <description>%(text)s</description>
 | 
				
			||||||
  </extension>
 | 
					  </extension>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "%(action)s": null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					    <%(action)s/>
 | 
				
			||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "server" : {
 | 
				
			||||||
 | 
					        "name" : "new-server-test",
 | 
				
			||||||
 | 
					        "imageRef" : "%(host)s/openstack/images/%(image_id)s",
 | 
				
			||||||
 | 
					        "flavorRef" : "%(host)s/openstack/flavors/1",
 | 
				
			||||||
 | 
					        "metadata" : {
 | 
				
			||||||
 | 
					            "My Server Name" : "Apache1"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "personality" : [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "path" : "/etc/banner.txt",
 | 
				
			||||||
 | 
					                "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="%(host)s/openstack/images/%(image_id)s" flavorRef="%(host)s/openstack/flavors/1" name="new-server-test">
 | 
				
			||||||
 | 
					  <metadata>
 | 
				
			||||||
 | 
					    <meta key="My Server Name">Apache1</meta>
 | 
				
			||||||
 | 
					  </metadata>
 | 
				
			||||||
 | 
					  <personality>
 | 
				
			||||||
 | 
					    <file path="/etc/banner.txt">
 | 
				
			||||||
 | 
					        ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp
 | 
				
			||||||
 | 
					        dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k
 | 
				
			||||||
 | 
					        IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs
 | 
				
			||||||
 | 
					        c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g
 | 
				
			||||||
 | 
					        QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo
 | 
				
			||||||
 | 
					        ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv
 | 
				
			||||||
 | 
					        dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy
 | 
				
			||||||
 | 
					        c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6
 | 
				
			||||||
 | 
					        b25zLiINCg0KLVJpY2hhcmQgQmFjaA==
 | 
				
			||||||
 | 
					    </file>
 | 
				
			||||||
 | 
					  </personality>
 | 
				
			||||||
 | 
					</server>
 | 
				
			||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "server": {
 | 
				
			||||||
 | 
					        "adminPass": "%(password)s",
 | 
				
			||||||
 | 
					        "id": "%(id)s",
 | 
				
			||||||
 | 
					        "links": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "href": "%(host)s/v2/openstack/servers/%(uuid)s",
 | 
				
			||||||
 | 
					                "rel": "self"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "href": "%(host)s/openstack/servers/%(uuid)s",
 | 
				
			||||||
 | 
					                "rel": "bookmark"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<?xml version='1.0' encoding='UTF-8'?>
 | 
				
			||||||
 | 
					<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="%(id)s" adminPass="%(password)s">
 | 
				
			||||||
 | 
					  <metadata/>
 | 
				
			||||||
 | 
					  <atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/>
 | 
				
			||||||
 | 
					  <atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/>
 | 
				
			||||||
 | 
					</server>
 | 
				
			||||||
@@ -1522,6 +1522,40 @@ class RescueXmlTest(RescueJsonTest):
 | 
				
			|||||||
    ctype = 'xml'
 | 
					    ctype = 'xml'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShelveJsonTest(ServersSampleBase):
 | 
				
			||||||
 | 
					    extension_name = "nova.api.openstack.compute.contrib.shelve.Shelve"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setUp(self):
 | 
				
			||||||
 | 
					        super(ShelveJsonTest, self).setUp()
 | 
				
			||||||
 | 
					        # Don't offload instance, so we can test the offload call.
 | 
				
			||||||
 | 
					        CONF.shelved_offload_time = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _test_server_action(self, uuid, action):
 | 
				
			||||||
 | 
					        response = self._do_post('servers/%s/action' % uuid,
 | 
				
			||||||
 | 
					                                 'os-shelve',
 | 
				
			||||||
 | 
					                                 {'action': action})
 | 
				
			||||||
 | 
					        self.assertEqual(response.status, 202)
 | 
				
			||||||
 | 
					        self.assertEqual(response.read(), "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve(self):
 | 
				
			||||||
 | 
					        uuid = self._post_server()
 | 
				
			||||||
 | 
					        self._test_server_action(uuid, 'shelve')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_shelve_offload(self):
 | 
				
			||||||
 | 
					        uuid = self._post_server()
 | 
				
			||||||
 | 
					        self._test_server_action(uuid, 'shelve')
 | 
				
			||||||
 | 
					        self._test_server_action(uuid, 'shelveOffload')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_unshelve(self):
 | 
				
			||||||
 | 
					        uuid = self._post_server()
 | 
				
			||||||
 | 
					        self._test_server_action(uuid, 'shelve')
 | 
				
			||||||
 | 
					        self._test_server_action(uuid, 'unshelve')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ShelveXmlTest(ShelveJsonTest):
 | 
				
			||||||
 | 
					    ctype = 'xml'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class VirtualInterfacesJsonTest(ServersSampleBase):
 | 
					class VirtualInterfacesJsonTest(ServersSampleBase):
 | 
				
			||||||
    extension_name = ("nova.api.openstack.compute.contrib"
 | 
					    extension_name = ("nova.api.openstack.compute.contrib"
 | 
				
			||||||
                     ".virtual_interfaces.Virtual_interfaces")
 | 
					                     ".virtual_interfaces.Virtual_interfaces")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user