调整带Vue前端的Azure VM电源管理Python应用
调整带Vue前端的Azure VM电源管理Python应用
我现在要改造Dev环境里的Azure Function App,原来的功能是给VM设置重复的开关机周计划,现在想把界面上的「添加计划」按钮改成「开机」——点击之后直接启动目标VM,并且自动在8小时后关机。后端用Python的Azure Functions实现,前端是Vue+JS+Bulma的栈。
现有核心代码分析
1. 后端核心逻辑
- SetSchedule函数:通过
api/scheduleAPI接收前端的计划参数,生成Cron格式的开关机计划,写入VM的标签中 - StartStop定时函数:每5分钟轮询所有VM,读取标签里的Cron计划,判断是否需要执行开关机操作
2. 前端Vue组件
原来点击「添加计划」会弹出一个设置时间、星期的Vue弹窗,用来提交计划参数给SetSchedule API。
具体改造步骤
一、前端改造:替换按钮与交互逻辑
- 修改按钮文本与事件
找到页面上的「添加计划」按钮,把文字改成「开机」,把点击事件从打开计划弹窗改成调用新的一键开机API。
示例Vue模板代码:
<!-- 原来的按钮 --> <button @click="openScheduleModal" class="button is-primary">添加计划</button> <!-- 改造后的按钮 --> <button @click="startVmAutoStop" class="button is-success" :disabled="vmState === 'running'"> {{ vmState === 'running' ? '运行中' : '开机(8小时后自动关机)' }} </button>
- 新增API调用逻辑
在Vue组件的methods里添加一键开机的请求函数:
async startVmAutoStop() { this.formDisabled = true; try { const res = await fetch('/api/start-vm-auto-stop', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: this.vmData.id }) }); if (res.ok) { const data = await res.json(); this.$notify.success(`VM已启动,将在${new Date(data.auto_stop_time).toLocaleString()}自动关机`); // 更新本地VM状态为运行中 this.vmData.state = 'running'; } else { this.$notify.error('开机失败,请稍后重试'); } } catch (err) { console.error(err); this.$notify.error('请求出错'); } finally { this.formDisabled = false; } }
- 状态提示优化
点击开机后,可以在VM卡片上添加临时提示:已启动,将在8小时后自动关机,提升用户体验。
二、后端改造:新增一键开机API与临时关机计划
核心思路
点击开机时,API完成两个动作:
- 立即启动目标VM
- 给VM设置仅执行一次的关机计划(当前时间+8小时),写入VM标签,由原有的StartStop定时函数触发关机
1. 新增一键开机API
在现有的schedule_bp蓝图中添加新的路由:
from azure.identity import DefaultAzureCredential from azure.mgmt.compute import ComputeManagementClient import json import logging import utilities import datetime import azure.functions as func schedule_bp = func.Blueprint() # ... 保留原来的generateCronSchedule、SetSchedule函数 ... @schedule_bp.function_name(name="StartVmAutoStop") @schedule_bp.route(route="api/start-vm-auto-stop", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS) def start_vm_auto_stop(req: func.HttpRequest) -> func.HttpResponse: try: req_body = json.loads(req.get_body()) vm_id = req_body.get("id") if not vm_id: return func.HttpResponse("请求缺少VM ID参数", status_code=400) # 解析VM的订阅ID、资源组、名称 vm_parts = vm_id.split("/") subscription_id = vm_parts[2] resource_group = vm_parts[4] vm_name = vm_parts[8] # 初始化Azure Compute客户端 credential = DefaultAzureCredential(exclude_environment_credential=True) compute_client = ComputeManagementClient(credential, subscription_id) # 1. 立即启动VM logging.info(f"开始启动VM: {vm_name}") start_op = compute_client.virtual_machines.begin_start( resource_group_name=resource_group, vm_name=vm_name ) start_op.wait() logging.info(f"VM {vm_name}启动成功") # 2. 计算8小时后的关机时间,生成一次性Cron计划 current_time = datetime.datetime.now() stop_time = current_time + datetime.timedelta(hours=8) # 生成仅执行一次的Cron表达式:分 时 日 月 * stop_cron = f"{stop_time.minute} {stop_time.hour} {stop_time.day} {stop_time.month} *" # 3. 更新VM标签:设置关机计划,清空启动计划(避免冲突) vm_instance = compute_client.virtual_machines.get(resource_group, vm_name) tags = vm_instance.tags or {} tags[utilities.STOPSCHEDULETAG] = stop_cron tags.pop(utilities.STARTSCHEDULETAG, None) # 移除重复的启动计划 update_tags_op = compute_client.virtual_machines.begin_create_or_update( resource_group_name=resource_group, vm_name=vm_name, parameters={"location": vm_instance.location, "tags": tags} ) update_tags_op.wait() logging.info(f"已为VM {vm_name}设置8小时后关机计划: {stop_cron}") # 返回成功响应 return func.HttpResponse(json.dumps({ "status": "success", "vm_name": vm_name, "auto_stop_time": stop_time.isoformat() }), mimetype="application/json") except Exception as e: logging.error(f"一键开机逻辑出错: {str(e)}") return func.HttpResponse(f"服务内部错误: {str(e)}", status_code=500)
2. 优化StartStop函数:执行关机后自动清除计划标签
为了避免过期的Cron计划残留,在StartStop函数执行关机后,自动移除VM的STOPSCHEDULETAG标签:
# 在StartStop函数中,执行关机操作的代码块后添加 if vm_state == "running": logging.info(f"[{vm.name}]: 执行关机...") stop_op = utilities.set_vm_state('stopped', vm, compute_client) events.append(stop_op) # 关机后清除计划标签 stop_op.wait() tags = vm.tags or {} tags.pop(utilities.STOPSCHEDULETAG, None) compute_client.virtual_machines.begin_create_or_update( resource_group_name=resource_group, vm_name=vm.name, parameters={"location": vm.location, "tags": tags} ).wait()
测试验证
- 前端点击「开机」按钮,检查VM是否成功启动
- 查看Azure Portal中VM的标签,确认存在一次性的关机Cron计划
- 等待8小时后,检查VM是否自动关机,标签是否被清除
- 测试边界场景:VM已在运行时点击按钮,API应返回友好提示
备注:内容来源于stack exchange,提问作者Michael Shepard
相关产品推荐
相关产品推荐

