OpenStack Mitaka Nova API 接口扩展之instance_resize
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenStack Mitaka Nova API 接口扩展之instance_resize相关的知识,希望对你有一定的参考价值。
# Mitaka NOVA API 接口开发
背景: OpenStack官方默认Resize接口支持local storage 不是很好,问题很多,因此重新定
制Resize接口,实现云主机套餐变更,比之前的接口提高了很多时间
### 配置 Resize 路由 vim /usr/lib/python2.7/site-packages/nova-13.1.0-py2.7.egg-info/entry_points.txt [nova.api.v21.extensions] instance_resize = nova.api.openstack.compute.instance_resize:InstanceResize access_ips = nova.api.openstack.compute.access_ips:AccessIPs admin_actions = nova.api.openstack.compute.admin_actions:AdminActions admin_password = nova.api.openstack.compute.admin_password:AdminPassword agents = nova.api.openstack.compute.agents:Agents aggregates = nova.api.openstack.compute.aggregates:Aggregates assisted_volume_snapshots = nova.api.openstack.compute.assisted_volume_snapshots:AssistedVolumeSnapshots attach_interfaces = nova.api.openstack.compute.attach_interfaces:AttachInterfaces availability_zone = nova.api.openstack.compute.availability_zone:AvailabilityZone baremetal_nodes = nova.api.openstack.compute.baremetal_nodes:BareMetalNodes block_device_mapping = nova.api.openstack.compute.block_device_mapping:BlockDeviceMapping cells = nova.api.openstack.compute.cells:Cells certificates = nova.api.openstack.compute.certificates:Certificates cloudpipe = nova.api.openstack.compute.cloudpipe:Cloudpipe config_drive = nova.api.openstack.compute.config_drive:ConfigDrive console_auth_tokens = nova.api.openstack.compute.console_auth_tokens:ConsoleAuthTokens console_output = nova.api.openstack.compute.console_output:ConsoleOutput
### 定制API 接口
* Mitaka 接口开发目录与Havana 版本发生变化,所有的接口放在nova/api/openstack/compute/目录中,在此目录中创建Resize 接口
# Copyright 2013 Rackspace Hosting # 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. from webob import exc from nova.api.openstack import common from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova import compute #from nova.i18n import _ from oslo_log import log as logging from nova.extend import api as extend_api from nova import utils LOG = logging.getLogger(__name__) ALIAS = "os-instance-resize" authorize = extensions.os_compute_authorizer(ALIAS) class InstanceResizeController(wsgi.Controller): def __init__(self): #super(InstanceResizeController, self).__init__() self.compute_api = compute.API(skip_policy_check=True) @wsgi.Controller.api_version("2.1", "2.20") def _get_instance(self, req, context, server_id): return common.get_instance(self.compute_api, context, server_id) @extensions.expected_errors(404) def index(self,req): """Returns the list of actions recorded for a given instance.""" context = req.environ["nova.context"] LOG.info("index.dir %s" %context) LOG.info("index.InstanceResizeController is ok") return "True" @extensions.expected_errors(404) def create(self,req,body): try: """Return data about the given instance action.""" context = req.environ["nova.context"] flavor = body[‘flavor‘] instance_uuid = body[‘instance_uuid‘] resize_api = extend_api.LocalAPI() result = resize_api.instance_resize(context,req,flavor,instance_uuid) #Reboot to instances body = {‘reboot‘: {‘type‘: ‘SOFT‘}} reboot_type = body[‘reboot‘][‘type‘].upper() instance = self._get_instance(req, context, instance_uuid) try: self.compute_api.reboot(context, instance, reboot_type) except exception.InstanceIsLocked as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, ‘reboot‘, id) LOG.info("create.InstanceResizeController is ok %s.%s.%s" % (result,flavor,instance_uuid)) return str(result ) except: return "False" LOG.error(traceback.format_exc()) @extensions.expected_errors(404) def delete(self,req): """Return data about the given instance action.""" LOG.info("delete.InstanceResizeController is ok") return "True" @extensions.expected_errors(404) def update(self,req): """Return data about the given instance action.""" LOG.info("update.InstanceResizeController is ok") return "True" @extensions.expected_errors(404) def show(self,req): """Return data about the given instance action.""" LOG.info("show.InstanceResizeController is ok") return "True" class InstanceResize(extensions.V21APIExtensionBase): """View a log of actions and events taken on an instance.""" name = "InstanceResize" alias = ALIAS version = 1 def get_resources(self): ext = extensions.ResourceExtension(ALIAS, InstanceResizeController(),) return [ext] def get_controller_extensions(self): """It‘s an abstract function V21APIExtensionBase and the extension will not be loaded without it. """ return []
### 定制extend.api
# Copyright 2012 IBM Corp. # # 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. """Handles all requests to the extend service. Compute health checks """ import os,sys,time,traceback,json from oslo_config import cfg import nova.conf from nova.extend import manager from oslo_log import log as logging from nova import utils from nova.extend import instance_resize as InstanceResize conductor_opts = [ cfg.StrOpt(‘topic‘, default=‘extend‘, help=‘the topic extend nodes listen on‘), cfg.StrOpt(‘manager‘, default=‘nova.extend.manager.ExtendManager‘, help=‘full class name for the Manager for extend‘), cfg.IntOpt(‘workers‘, help=‘Number of workers for OpenStack Extend service‘) ] extend_group = cfg.OptGroup(name=‘extend‘, title=‘exntend Options‘) CONF=nova.conf.CONF CONF.register_group(extend_group) CONF.register_opts(conductor_opts, extend_group) LOG = logging.getLogger(__name__) class LocalAPI(object): """A local version of the exten API that does compute health chekcs and virtual machine restart. """ def __init__(self): # TODO(danms): This needs to be something more generic for # other/future users of this sort of functionality. self._manager = utils.ExceptionHelper(manager.ExtendManager()) def instance_resize(self,context,req,flavor,instance_uuid): # instance resize for nova.extend.instance_resize try: resize_action = InstanceResize.InstanceResize() resize_action.work(context,req,flavor,instance_uuid) LOG.info("instance_resize.Extend.API.%s.%s" %(flavor,instance_uuid)) return True except: LOG.error(traceback.format_exc()) return False
### 定制Extend.instance_resize
#opyright 2013 Rackspace Hosting # 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 os import time import sys import nova.conf import traceback import json from oslo_log import log as logging from nova import db from nova import compute import base64 import re from oslo_config import cfg from oslo_log import log as logging import oslo_messaging as messaging from oslo_utils import strutils from oslo_utils import timeutils from oslo_utils import uuidutils import six import stevedore import webob from webob import exc from nova.api.openstack import api_version_request from nova.api.openstack import common from nova.api.openstack.compute.schemas import servers as schema_servers from nova.api.openstack.compute.views import servers as views_servers from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api import validation from nova import compute from nova.compute import flavors from nova import exception from nova.i18n import _ from nova.i18n import _LW from nova.image import glance from nova import objects from nova import utils LOG = logging.getLogger(__name__) class InstanceResize(object): def __init__(self): version = ‘v1.0‘ self.compute_api = compute.API(skip_policy_check=True) def instance_system_metadata_update_havana(self,context,req,instance_uuid,metadata,delete): metadata = db.instance_system_metadata_update(context, instance_uuid, metadata,delete) LOG.info("instance_system_metadata_update %s" %metadata) def instance_extra_update_by_uuid_mitaka(self,context,req,instance_uuid,metadata): values = {‘flavor‘:metadata} update_extra = db.instance_extra_update_by_uuid(context, instance_uuid,values) if update_extra == 1: LOG.info("instance_extra_update_by_uuid_mitaka %s update is oK" %instance_uuid ) def flavor_get_by_name_havana(self,context,req,name): # get flavor dict for db.flavor_get_by_name to havana version meta = db.flavor_get_by_name(context,name) metadata = dict() metadata[‘instance_type_memory_mb‘] = meta[‘memory_mb‘] metadata[‘instance_type_id‘] = meta[‘id‘] metadata[‘instance_type_name‘] = meta[‘name‘] metadata[‘instance_type_flavorid‘] = meta[‘flavorid‘] LOG.info(‘flavor_get_by_name metadata %s‘ %metadata) return metadata def flavor_get_by_name_mitaka(self,context,req,flavor,instance_uuid): new_meta = db.flavor_get_by_name(context,flavor) meta = db.instance_extra_get_by_instance_uuid(context,instance_uuid) # get nova.instance_extra.flavor for data json_meta = json.loads(meta[‘flavor‘]) json_meta[‘cur‘][‘nova_object.data‘] = new_meta # Time format to str stime = json_meta[‘cur‘][‘nova_object.data‘][‘created_at‘] timestamp=time.localtime(time.mktime(stime.timetuple())) ntime = time.strftime("%Y-%m-%dT%H:%M:%S",timestamp) json_meta[‘cur‘][‘nova_object.data‘][‘created_at‘] = ntime metadata = json.dumps(json_meta) LOG.info("flavor_get_by_name_mitaka.meta:%s" %metadata) return metadata def work(self,context,req,flavor,instance_uuid): LOG.info("InstanceResize.work.%s.%s"%(flavor,instance_uuid)) metadata = self.flavor_get_by_name_mitaka(context,req,flavor,instance_uuid) self.instance_extra_update_by_uuid_mitaka(context,req,instance_uuid,metadata) return True
### 接口验证测试
import os,sys,json,time,socket,traceback,urllib2,urllib def post(url,data): cmds ="""curl -d ‘{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "root", "password":"XXXXXXXXX"}}}‘ -H "Content-type: application/json" http://127.0.0.1:35357/v2.0/tokens""" info = os.popen(cmds).readline() jsondata = json.loads(info) for x,y in jsondata.items(): dat = y token_id = dat[‘token‘][‘id‘] tenant_id = dat[‘token‘][‘tenant‘][‘id‘] url = "http://127.0.0.1:8774/v2.1/%s/os-instance-resize" % tenant_id try: json_data = json.dumps(data) socket.setdefaulttimeout(5) httpsHandler = urllib2.HTTPSHandler(debuglevel = 1) opener = urllib2.build_opener(httpsHandler) urllib2.install_opener(opener) request = urllib2.Request(url, json_data) request.add_header(‘User-Agent‘,"Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20120701 Firefox/6.0.2") request.add_header(‘Content-type‘,‘application/json‘) request.add_header(‘Accept‘,‘application/json‘) request.add_header(‘charset‘,‘UTF-8‘) request.add_header(‘X-Auth-Token‘,token_id) response = urllib2.urlopen(request) #res = json.loads(response.readlines()[0]) except Exception,e: print (‘Post %s is failed \n %s‘ %(url,traceback.format_exc())) if __name__ == "__main__": url = "http://127.0.0.1:8774/v2.1/82572642-04da-44aa-a18d-4280589b7a3d/os-instance-resize" data ={"flavor":"windows-16-16G-100G","instance_uuid":"351ab096-6ab1-496c-a4d7-cc91f78c6eca"} sc = post(url,data)
### 验证接口,日志输出
python extend/token.py 2016-09-23 12:31:26.382 5642 WARNING keystonemiddleware.auth_token [-] Using the in-process token cache is deprecated as of the 4.2.0 release and may be removed in the 5.0.0 release or the ‘O‘ development cycle. The in-process cache causes inconsistent results and high memory usage. When the feature is removed the auth_token middleware will not cache tokens by default which may result in performance issues. It is recommended to use memcache for the auth_token token cache by setting the memcached_servers option.2016-09-23 12:31:27.684 5642 INFO nova.extend.instance_resize [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] InstanceResize. work.linux-16-16G-100G.82572642-04da-44aa-a18d-4280589b7a3d2016-09-23 12:31:27.703 5642 INFO nova.extend.instance_resize [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] flavor_get_by_n ame_mitaka.meta:{"new": null, "old": null, "cur": {"nova_object.version": "1.1", "nova_object.name": "Flavor", "nova_object.namespace": "nova", "nova_object.data": {"memory_mb": 16384, "flavorid": "19552bc2-de5b-442d-80c8-e54907a08cc5", "name": "linux-16-16G-100G", "deleted": 0, "created_at": "2016-09-19T06:16:16", "ephemeral_gb": 100, "updated_at": null, "disabled": false, "vcpus": 16, "root_gb": 120, "extra_specs": {}, "swap": 0, "rxtx_factor": 1.0, "is_public": true, "deleted_at": null, "vcpu_weight": null, "id": 9}}}2016-09-23 12:31:27.707 5642 INFO nova.extend.instance_resize [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] instance_extra_ update_by_uuid_mitaka 82572642-04da-44aa-a18d-4280589b7a3d update is oK2016-09-23 12:31:27.707 5642 INFO nova.extend.api [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] instance_resize.Extend.API. linux-16-16G-100G.82572642-04da-44aa-a18d-4280589b7a3d2016-09-23 12:31:27.829 5642 INFO nova.api.openstack.compute.instance_resize [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] create.InstanceResizeController is ok True.linux-16-16G-100G.82572642-04da-44aa-a18d-4280589b7a3d2016-09-23 12:31:27.830 5642 INFO nova.osapi_compute.wsgi.server [req-030508f7-6d44-4099-8884-76c1ab831f8b a6300ddcbfd24fbd8892a27d6a4f8328 7b98a7afb66542c7874ddec80b41a665 - - -] 127.0.0.1 "P OST /v2.1/7b98a7afb66542c7874ddec80b41a665/os-instance-resize HTTP/1.1" status: 200 len: 202 time: 1.4489350
本文出自 “欢迎评论,欢迎点赞” 博客,请务必保留此出处http://swq499809608.blog.51cto.com/797714/1855771
以上是关于OpenStack Mitaka Nova API 接口扩展之instance_resize的主要内容,如果未能解决你的问题,请参考以下文章
OpenStack nova M Blueprints 分析