You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调整带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。


具体改造步骤

一、前端改造:替换按钮与交互逻辑

  1. 修改按钮文本与事件
    找到页面上的「添加计划」按钮,把文字改成「开机」,把点击事件从打开计划弹窗改成调用新的一键开机API。
    示例Vue模板代码:
<!-- 原来的按钮 -->
<button @click="openScheduleModal" class="button is-primary">添加计划</button>

<!-- 改造后的按钮 -->
<button @click="startVmAutoStop" class="button is-success" :disabled="vmState === 'running'">
  {{ vmState === 'running' ? '运行中' : '开机(8小时后自动关机)' }}
</button>
  1. 新增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;
  }
}
  1. 状态提示优化
    点击开机后,可以在VM卡片上添加临时提示:已启动,将在8小时后自动关机,提升用户体验。

二、后端改造:新增一键开机API与临时关机计划

核心思路

点击开机时,API完成两个动作:

  1. 立即启动目标VM
  2. 给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()

测试验证

  1. 前端点击「开机」按钮,检查VM是否成功启动
  2. 查看Azure Portal中VM的标签,确认存在一次性的关机Cron计划
  3. 等待8小时后,检查VM是否自动关机,标签是否被清除
  4. 测试边界场景:VM已在运行时点击按钮,API应返回友好提示

备注:内容来源于stack exchange,提问作者Michael Shepard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:20:13