openstack 软重启和硬重启的区别
2016-04-10 18:53
2006 查看
在openstack中重启实例有两种,分别被称为“软重启”和“硬重启”。所谓的软重启会尝试正常关机并重启实例,硬重启会直接将实例“断电”并重启。也就是说硬重启会“关闭”电源。其具体命令如下:
默认情况下,如果您通过nova重启,执行的是软重启。
如果您需要执行硬重启,添加--hard参数即可:
从命令上看,两者只是参数上有所区别,因此跟踪具体代码研究一下(对应nova代码为L版本的nova-12.0.0)。
首先找到入口的API接口函数:Nova->api->openstack->compute->servers.py
上述代码中第13行(self.compute_api.reboot(context,instance,reboot_type)),
跳转到具体实现代码:nova->compute->api.py
在compute-api的代码中,首先注意到在reboot方法上有几个装饰函数,其中的check_instance_state方法会检查当前的虚拟机是否处于如task_states.RESUMING这样的状态,如果处于的话,则提示InstanceInvalidState。也就是说
当虚拟机的任务处于(REBOOTING,REBOOT_PENDING,REBOOT_STARTED,REBOOTING_HARD,RESUMING,UNPAUSING,PAUSING,SUSPENDING)时,软硬重启都不允许。详细内容可以参看装饰函数的具体实现代码:
然后,在回来继续看compute-api中的reboot的代码,此时软重启和硬重启在条件的判断上就略有区别了。
从代码中可以看出
如果是软重启,则需要继续判断虚拟机当前是否又其他任务,如果有则抛异常。
如果操作是硬重启,则还需要更新expected_task_state的可能扩展状态(task_states.REBOOTING,task_states.REBOOT_PENDING,task_states.REBOOT_STARTED,task_states.REBOOTING_HARD,task_states.RESUMING,task_states.UNPAUSING,task_states.SUSPENDING)做标识,并传递下去。
但无论是软重启还是硬重启,都重新给虚拟机state重新赋值,并通过RPC调用reboot_instance(第44行代码)。
代码跳转至Nova->compute->manager.py(注意由于这里的代码实质上是通过RPC远程调用的,所以其实际发生作用的代码应该是对应虚拟机所在Compute节点上了)
从上述代码可知,根据软硬重启的类型不同虚拟机将置成不同的状态。完毕后依此获取块设备和网络设备信息以及虚拟机电源状态,判断电源状态是否位于RUNNING状态,如果不为RUNNING状态,则将状态职位职位RUNNING,下面继续判断状态,最终将相关信息传递给driver.reboot。
继续跟中到driver层:Nova->virt->hyper->driver.py
往下到Nova->virt->hyper->vmops.py
从上述代码我们可以看到如果是软重启的话,则将执行一个_soft_shutdown(instance)函数:
_soft_shutdown(instance)函数主要是在规定时间范围内去关闭指定的虚拟机,关闭虚拟机的核心操作为第20行(
当虚拟机关闭以后,软重启的话就直接power_on虚拟机了,所谓的power_on虚拟机,实际上主要就是设置虚拟机状态
而如果是硬重启的话,则执行
从中可以看出,硬重启则只是改变了VM的状态,少了挂载块设备一项。
默认情况下,如果您通过nova重启,执行的是软重启。
$novarebootSERVER
如果您需要执行硬重启,添加--hard参数即可:
$novareboot--hardSERVER
从命令上看,两者只是参数上有所区别,因此跟踪具体代码研究一下(对应nova代码为L版本的nova-12.0.0)。
首先找到入口的API接口函数:Nova->api->openstack->compute->servers.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @wsgi.response( 202 ) @extensions.expected_errors(( 404 , 409 )) @wsgi.action( 'reboot' ) @validation.schema(schema_servers.reboot) def _action_reboot( self ,req, id ,body): reboot_type = body[ 'reboot' ][ 'type' ].upper() context = req.environ[ 'nova.context' ] authorize(context,action = 'reboot' ) instance = self ._get_server(context,req, id ) try : self .compute_api.reboot(context,instance,reboot_type) except exception.InstanceIsLockedase: raise exc.HTTPConflict(explanation = e.format_message()) except exception.InstanceInvalidStateasstate_error: common.raise_http_conflict_for_instance_invalid_state(state_error, 'reboot' , id ) |
跳转到具体实现代码:nova->compute->api.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | @wrap_check_policy @check_instance_lock @check_instance_state(vm_state = set ( vm_states.ALLOW_SOFT_REBOOT + vm_states.ALLOW_HARD_REBOOT), task_state = [ None ,task_states.REBOOTING, task_states.REBOOT_PENDING, task_states.REBOOT_STARTED, task_states.REBOOTING_HARD, task_states.RESUMING, task_states.UNPAUSING, task_states.PAUSING, task_states.SUSPENDING]) def reboot( self ,context,instance,reboot_type): """Rebootthegiveninstance.""" if (reboot_type = = 'SOFT' and (instance.vm_state not in vm_states.ALLOW_SOFT_REBOOT)): raise exception.InstanceInvalidState( attr = 'vm_state' , instance_uuid = instance.uuid, state = instance.vm_state, method = 'softreboot' ) if reboot_type = = 'SOFT' and instance.task_state is not None : raise exception.InstanceInvalidState( attr = 'task_state' , instance_uuid = instance.uuid, state = instance.task_state, method = 'reboot' ) expected_task_state = [ None ] if reboot_type = = 'HARD' : expected_task_state.extend([task_states.REBOOTING, task_states.REBOOT_PENDING, task_states.REBOOT_STARTED, task_states.REBOOTING_HARD, task_states.RESUMING, task_states.UNPAUSING, task_states.SUSPENDING]) state = { 'SOFT' :task_states.REBOOTING, 'HARD' :task_states.REBOOTING_HARD}[reboot_type] instance.task_state = state instance.save(expected_task_state = expected_task_state) self ._record_action_start(context,instance,instance_actions.REBOOT) self .compute_rpcapi.reboot_instance(context,instance = instance, block_device_info = None , reboot_type = reboot_type) |
当虚拟机的任务处于(REBOOTING,REBOOT_PENDING,REBOOT_STARTED,REBOOTING_HARD,RESUMING,UNPAUSING,PAUSING,SUSPENDING)时,软硬重启都不允许。详细内容可以参看装饰函数的具体实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 代码位于:nova->compute->api.py def check_instance_state(vm_state = None ,task_state = ( None ,), must_have_launched = True ): """DecoratortocheckVMand/ortaskstatebeforeentrytoAPIfunctions. Iftheinstanceisinthewrongstate,orhasnotbeensuccessfully startedatleastoncethewrapperwillraiseanexception. """ if vm_state is not None and not isinstance (vm_state, set ): vm_state = set (vm_state) if task_state is not None and not isinstance (task_state, set ): task_state = set (task_state) def outer(f): @functools.wraps(f) def inner( self ,context,instance, * args, * * kw): if vm_state is not None and instance.vm_state not in vm_state: raise exception.InstanceInvalidState( attr = 'vm_state' , instance_uuid = instance.uuid, state = instance.vm_state, method = f.__name__) if (task_state is not None and instance.task_state not in task_state): (lst:判断是否能软,硬重启) raise exception.InstanceInvalidState( attr = 'task_state' , instance_uuid = instance.uuid, state = instance.task_state, method = f.__name__) if must_have_launched and not instance.launched_at: raise exception.InstanceInvalidState( attr = 'launched_at' , instance_uuid = instance.uuid, state = instance.launched_at, method = f.__name__) return f( self ,context,instance, * args, * * kw) return inner return outer |
从代码中可以看出
如果是软重启,则需要继续判断虚拟机当前是否又其他任务,如果有则抛异常。
如果操作是硬重启,则还需要更新expected_task_state的可能扩展状态(task_states.REBOOTING,task_states.REBOOT_PENDING,task_states.REBOOT_STARTED,task_states.REBOOTING_HARD,task_states.RESUMING,task_states.UNPAUSING,task_states.SUSPENDING)做标识,并传递下去。
但无论是软重启还是硬重启,都重新给虚拟机state重新赋值,并通过RPC调用reboot_instance(第44行代码)。
代码跳转至Nova->compute->manager.py(注意由于这里的代码实质上是通过RPC远程调用的,所以其实际发生作用的代码应该是对应虚拟机所在Compute节点上了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 代码位于Nova->compute->manager.py:2874行 @wrap_exception() @reverts_task_state @wrap_instance_event @wrap_instance_fault def reboot_instance( self ,context,instance,block_device_info, reboot_type): """Rebootaninstanceonthishost.""" #acknowledgetherequestmadeittothemanager if reboot_type = = "SOFT" : instance.task_state = task_states.REBOOT_PENDING expected_states = (task_states.REBOOTING, task_states.REBOOT_PENDING, task_states.REBOOT_STARTED) else : instance.task_state = task_states.REBOOT_PENDING_HARD expected_states = (task_states.REBOOTING_HARD, task_states.REBOOT_PENDING_HARD, task_states.REBOOT_STARTED_HARD) context = context.elevated() LOG.info(_LI( "Rebootinginstance" ),context = context,instance = instance) block_device_info = self ._get_instance_block_device_info(context, instance) network_info = self .network_api.get_instance_nw_info(context,instance) self ._notify_about_instance_usage(context,instance, "reboot.start" ) instance.power_state = self ._get_power_state(context,instance) instance.save(expected_task_state = expected_states) if instance.power_state! = power_state.RUNNING: state = instance.power_state running = power_state.RUNNING LOG.warning(_LW( 'tryingtorebootanon-runninginstance:' '(state:%(state)sexpected:%(running)s)' ), { 'state' :state, 'running' :running}, context = context,instance = instance) def bad_volumes_callback(bad_devices): self ._handle_bad_volumes_detached( context,instance,bad_devices,block_device_info) try : #Don'tchangeitoutofrescuemode if instance.vm_state = = vm_states.RESCUED: new_vm_state = vm_states.RESCUED else : new_vm_state = vm_states.ACTIVE new_power_state = None if reboot_type = = "SOFT" : instance.task_state = task_states.REBOOT_STARTED expected_state = task_states.REBOOT_PENDING else : instance.task_state = task_states.REBOOT_STARTED_HARD expected_state = task_states.REBOOT_PENDING_HARD instance.save(expected_task_state = expected_state) self .driver.reboot(context,instance, network_info, reboot_type, block_device_info = block_device_info, bad_volumes_callback = bad_volumes_callback) except Exceptionaserror: withexcutils.save_and_reraise_exception()asctxt: exc_info = sys.exc_info() #iftherebootfailedbuttheVMisrunningdon't #putitintoanerrorstate new_power_state = self ._get_power_state(context,instance) if new_power_state = = power_state.RUNNING: LOG.warning(_LW( 'Rebootfailedbutinstanceisrunning' ), context = context,instance = instance) compute_utils.add_instance_fault_from_exc(context, instance,error,exc_info) self ._notify_about_instance_usage(context,instance, 'reboot.error' ,fault = error) ctxt.reraise = False else : LOG.error(_LE( 'Cannotrebootinstance:%s' ),error, context = context,instance = instance) self ._set_instance_obj_error_state(context,instance) if not new_power_state: new_power_state = self ._get_power_state(context,instance) try : instance.power_state = new_power_state instance.vm_state = new_vm_state instance.task_state = None instance.save() except exception.InstanceNotFound: LOG.warning(_LW( "Instancedisappearedduringreboot" ), context = context,instance = instance) self ._notify_about_instance_usage(context,instance, "reboot.end" ) |
继续跟中到driver层:Nova->virt->hyper->driver.py
1 2 3 | def reboot( self ,context,instance,network_info,reboot_type, block_device_info = None ,bad_volumes_callback = None ): self ._vmops.reboot(instance,network_info,reboot_type) |
1 2 3 4 5 6 7 8 9 10 11 | def reboot( self ,instance,network_info,reboot_type): """Rebootthespecifiedinstance.""" LOG.debug( "Rebootinginstance" ,instance = instance) if reboot_type = = REBOOT_TYPE_SOFT: if self ._soft_shutdown(instance): self .power_on(instance) return self ._set_vm_state(instance, constants.HYPERV_VM_STATE_REBOOT) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | def _soft_shutdown( self ,instance, timeout = CONF.hyperv.wait_soft_reboot_seconds, retry_interval = SHUTDOWN_TIME_INCREMENT): """PerformasoftshutdownontheVM. (lst:软重启特有步骤,此步骤就是区别软重启和硬重启的不同之处) :return:Trueiftheinstancewasshutdownwithintimelimit, Falseotherwise. """ LOG.debug( "PerformingSoftshutdownoninstance" ,instance = instance) while timeout> 0 : #Performasoftshutdownontheinstance. #Waitmaximumtimeoutfortheinstancetobeshutdown. #Ifitwasnotshutdown,retryuntilitsucceedsoramaximumof #timewaitedisequaltotimeout. wait_time = min (retry_interval,timeout) try : LOG.debug( "Softshutdowninstance,timeoutremaining:%d" , timeout,instance = instance) self ._vmu tils.soft_shutdown_vm(instance.name) if self ._wait_for_power_off(instance.name,wait_time): LOG.info(_LI( "Softshutdownsucceeded." ), instance = instance) return True except vmutils.HyperVExceptionase: #Exceptionisraisedwhentryingtoshutdowntheinstance #whileitisstillbooting. LOG.debug( "Softshutdownfailed:%s" ,e,instance = instance) time.sleep(wait_time) timeout - = retry_interval LOG.warning(_LW( "Timedoutwhilewaitingforsoftshutdown." ), instance = instance) return False |
self
._vmu
tils.soft_shutdown_vm(instance.name)).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def soft_shutdown_vm( self ,vm_name): vm = self ._lookup_vm_check(vm_name) shutdown_component = vm.associators( wmi_result_class = self ._SHUTDOWN_COMPONENT) if not shutdown_component: #Ifnoshutdown_componentisfound,itmeanstheVMisalready #inashutdownstate. return reason = 'SoftshutdownrequestedbyOpenStackNova.' (ret_val,) = shutdown_component[ 0 ].InitiateShutdown(Force = False , Reason = reason) self .check_ret_val(ret_val, None ) |
1 2 3 4 5 6 7 8 9 | def power_on( self ,instance,block_device_info = None ): """Poweronthespecifiedinstance.""" LOG.debug( "Poweroninstance" ,instance = instance) if block_device_info: self ._volumeops.fix_instance_volume_disk_paths(instance.name, block_device_info) self ._set_vm_state(instance,constants.HYPERV_VM_STATE_ENABLED) |
_set_vm_state方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | def _set_vm_state( self ,instance,req_state): instance_name = instance.name instance_uuid = instance.uuid try : self ._vmutils.set_vm_state(instance_name,req_state) if req_state in (constants.HYPERV_VM_STATE_DISABLED, constants.HYPERV_VM_STATE_REBOOT): self ._delete_vm_console_log(instance) if req_state in (constants.HYPERV_VM_STATE_ENABLED, constants.HYPERV_VM_STATE_REBOOT): self .log_vm_serial_output(instance_name, instance_uuid) LOG.debug( "SuccessfullychangedstateofVM%(instance_name)s" "to:%(req_state)s" ,{ 'instance_name' :instance_name, 'req_state' :req_state}) except Exception: withexcutils.save_and_reraise_exception(): LOG.error(_LE( "Failedtochangevmstateof%(instance_name)s" "to%(req_state)s" ), { 'instance_name' :instance_name, 'req_state' :req_state}) |
相关文章推荐
- opencv mat 转灰度图
- Windows环境下配置Apache2.4+Tomcat7的负载均衡配置
- git入门
- hadoop修改block size,并上传文件
- 1.OSI(开放系统互连(Open System Interconnection))模型
- 关于安装centos中遇到的问题
- CentOS 6.5 编译升级内核
- opengl 简单滑动条类实现
- 进程创建监控x86
- 驱动加载监控x86
- 【OpenGL4.0】GLSL-Flat Shading平面着色
- 采用maven 对tomcat 进行自动部署
- 编译安装LAMP(一)
- Openstack学习笔记(七)-在Win环境下通过XManager(xshell)远程打开eclipse
- CentOS6.5系统双网卡绑定配置详解
- modSecurity和Naxsi哪个更适合Nginx搭建WAF
- Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序
- Linux基础09_shellscript练习
- opencv图像霍夫变化
- CentOs 安装 Redmine 部分问题解决