| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- // Copyright 2019 Yunion
- //
- // 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.
- package tools
- import (
- "context"
- "encoding/json"
- "fmt"
- "strconv"
- "github.com/mark3labs/mcp-go/mcp"
- "yunion.io/x/log"
- "yunion.io/x/onecloud/pkg/mcp-server/adapters"
- "yunion.io/x/onecloud/pkg/mcp-server/models"
- )
- // CloudpodsServerStartTool 用于启动指定的Cloudpods虚拟机实例
- type CloudpodsServerStartTool struct {
- adapter *adapters.CloudpodsAdapter
- }
- // NewCloudpodsServerStartTool 创建一个新的CloudpodsServerStartTool实例
- func NewCloudpodsServerStartTool(adapter *adapters.CloudpodsAdapter) *CloudpodsServerStartTool {
- return &CloudpodsServerStartTool{
- adapter: adapter,
- }
- }
- // GetTool 返回启动虚拟机工具的定义,包括参数和描述
- func (c *CloudpodsServerStartTool) GetTool() mcp.Tool {
- return mcp.NewTool(
- "cloudpods_start_server",
- mcp.WithDescription("启动指定的Cloudpods虚拟机实例"),
- mcp.WithString("server_id", mcp.Required(), mcp.Description("虚拟机ID")),
- mcp.WithString("auto_prepaid", mcp.Description("按量机器自动转换为包年包月,默认为false")),
- mcp.WithString("qemu_version", mcp.Description("指定启动虚拟机的Qemu版本,可选值:2.12.1, 4.2.0,仅适用于KVM虚拟机")),
- mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
- mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
- )
- }
- // Handle 处理启动虚拟机的请求,调用适配器执行启动操作并返回结果
- func (c *CloudpodsServerStartTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- // 从请求中获取必需的 server_id 参数
- serverID, err := req.RequireString("server_id")
- if err != nil {
- return nil, err
- }
- // 解析 auto_prepaid 参数,决定是否自动转换为包年包月
- autoPrepaid := false
- if autoPrepaidStr := req.GetString("auto_prepaid", "false"); autoPrepaidStr == "true" {
- autoPrepaid = true
- }
- // 获取 qemu_version 参数,用于指定启动虚拟机的 Qemu 版本
- qemuVersion := req.GetString("qemu_version", "")
- // 构造启动虚拟机的请求参数
- startReq := models.ServerStartRequest{
- AutoPrepaid: autoPrepaid,
- QemuVersion: qemuVersion,
- }
- // 获取认证所需的 access key 和 secret key
- ak := req.GetString("ak", "")
- sk := req.GetString("sk", "")
- // 调用适配器的 StartServer 方法执行启动操作
- response, err := c.adapter.StartServer(ctx, serverID, startReq, ak, sk)
- if err != nil {
- log.Errorf("Fail to start server: %s", err)
- return nil, fmt.Errorf("fail to start server: %w", err)
- }
- // 构造返回结果,包含任务ID、成功状态和状态信息
- result := map[string]interface{}{
- "server_id": serverID,
- "operation": "start",
- "task_id": response.TaskId,
- "success": response.Success,
- "status": response.Status,
- }
- // 如果有错误信息,则添加到结果中
- if response.Error != "" {
- result["error"] = response.Error
- }
- // 将结果序列化为 JSON 格式
- resultJSON, err := json.MarshalIndent(result, "", " ")
- if err != nil {
- return nil, fmt.Errorf("序列化结果失败: %w", err)
- }
- // 返回序列化后的结果
- return mcp.NewToolResultText(string(resultJSON)), nil
- }
- // GetName 返回启动虚拟机工具的名称
- func (c *CloudpodsServerStartTool) GetName() string {
- return "cloudpods_start_server"
- }
- // CloudpodsServerStopTool 用于停止指定的Cloudpods虚拟机实例
- type CloudpodsServerStopTool struct {
- adapter *adapters.CloudpodsAdapter
- }
- // NewCloudpodsServerStopTool 创建一个新的CloudpodsServerStopTool实例
- func NewCloudpodsServerStopTool(adapter *adapters.CloudpodsAdapter) *CloudpodsServerStopTool {
- return &CloudpodsServerStopTool{
- adapter: adapter,
- }
- }
- // GetTool 返回停止虚拟机工具的定义,包括参数和描述
- func (c *CloudpodsServerStopTool) GetTool() mcp.Tool {
- return mcp.NewTool(
- "cloudpods_stop_server",
- mcp.WithDescription("停止指定的Cloudpods虚拟机实例"),
- mcp.WithString("server_id", mcp.Required(), mcp.Description("虚拟机ID")),
- mcp.WithString("is_force", mcp.Description("是否强制停止,默认为false")),
- mcp.WithString("stop_charging", mcp.Description("是否关机停止计费,默认为false")),
- mcp.WithString("timeout_secs", mcp.Description("关机等待时间,如果是强制关机,则等待时间为0,如果不设置,默认为30秒")),
- mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
- mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
- )
- }
- // Handle 处理停止虚拟机的请求,调用适配器执行停止操作并返回结果
- func (c *CloudpodsServerStopTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- // 从请求中获取必需的 server_id 参数
- serverID, err := req.RequireString("server_id")
- if err != nil {
- return nil, err
- }
- // 解析 is_force 参数,决定是否强制停止虚拟机
- isForce := false
- if isForceStr := req.GetString("is_force", "false"); isForceStr == "true" {
- isForce = true
- }
- // 解析 stop_charging 参数,决定是否停止计费
- stopCharging := false
- if stopChargingStr := req.GetString("stop_charging", "false"); stopChargingStr == "true" {
- stopCharging = true
- }
- // 解析 timeout_secs 参数,设置停止操作的超时时间
- timeoutSecs := int64(0)
- if timeoutSecsStr := req.GetString("timeout_secs", ""); timeoutSecsStr != "" {
- if parsed, err := strconv.ParseInt(timeoutSecsStr, 10, 64); err == nil && parsed > 0 {
- timeoutSecs = parsed
- }
- }
- // 构造停止虚拟机的请求参数
- stopReq := models.ServerStopRequest{
- IsForce: isForce,
- StopCharging: stopCharging,
- TimeoutSecs: timeoutSecs,
- }
- // 获取认证所需的 access key 和 secret key
- ak := req.GetString("ak", "")
- sk := req.GetString("sk", "")
- // 调用适配器的 StopServer 方法执行停止操作
- response, err := c.adapter.StopServer(ctx, serverID, stopReq, ak, sk)
- if err != nil {
- log.Errorf("Fail to stop server: %s", err)
- return nil, fmt.Errorf("fail to stop server: %w", err)
- }
- // 构造返回结果,包含任务ID、成功状态和状态信息
- result := map[string]interface{}{
- "server_id": serverID,
- "operation": "stop",
- "task_id": response.TaskId,
- "success": response.Success,
- "status": response.Status,
- }
- // 如果有错误信息,则添加到结果中
- if response.Error != "" {
- result["error"] = response.Error
- }
- // 将结果序列化为 JSON 格式
- resultJSON, err := json.MarshalIndent(result, "", " ")
- if err != nil {
- return nil, fmt.Errorf("序列化结果失败: %w", err)
- }
- // 返回序列化后的结果
- return mcp.NewToolResultText(string(resultJSON)), nil
- }
- // GetName 返回停止虚拟机工具的名称
- func (c *CloudpodsServerStopTool) GetName() string {
- return "cloudpods_stop_server"
- }
- // CloudpodsServerRestartTool 用于重启指定的Cloudpods虚拟机实例
- type CloudpodsServerRestartTool struct {
- adapter *adapters.CloudpodsAdapter
- }
- // NewCloudpodsServerRestartTool 创建一个新的CloudpodsServerRestartTool实例
- func NewCloudpodsServerRestartTool(adapter *adapters.CloudpodsAdapter) *CloudpodsServerRestartTool {
- return &CloudpodsServerRestartTool{
- adapter: adapter,
- }
- }
- // GetTool 返回重启虚拟机工具的定义,包括参数和描述
- func (c *CloudpodsServerRestartTool) GetTool() mcp.Tool {
- return mcp.NewTool(
- "cloudpods_restart_server",
- mcp.WithDescription("重启指定的Cloudpods虚拟机实例"),
- mcp.WithString("server_id", mcp.Required(), mcp.Description("虚拟机ID")),
- mcp.WithString("is_force", mcp.Description("是否强制重启,默认为false")),
- mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
- mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
- )
- }
- // Handle 处理重启虚拟机的请求,调用适配器执行重启操作并返回结果
- func (c *CloudpodsServerRestartTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- // 从请求中获取必需的 server_id 参数
- serverID, err := req.RequireString("server_id")
- if err != nil {
- return nil, err
- }
- // 解析 is_force 参数,决定是否强制重启虚拟机
- isForce := false
- if isForceStr := req.GetString("is_force", "false"); isForceStr == "true" {
- isForce = true
- }
- // 构造重启虚拟机的请求参数
- restartReq := models.ServerRestartRequest{
- IsForce: isForce,
- }
- // 获取认证所需的 access key 和 secret key
- ak := req.GetString("ak", "")
- sk := req.GetString("sk", "")
- // 调用适配器的 RestartServer 方法执行重启操作
- response, err := c.adapter.RestartServer(ctx, serverID, restartReq, ak, sk)
- if err != nil {
- log.Errorf("Fail to query restart server: %s", err)
- return nil, fmt.Errorf("fail to restart server: %w", err)
- }
- // 构造返回结果,包含任务ID、成功状态和状态信息
- result := map[string]interface{}{
- "server_id": serverID,
- "operation": "restart",
- "task_id": response.TaskId,
- "success": response.Success,
- "status": response.Status,
- }
- // 如果有错误信息,则添加到结果中
- if response.Error != "" {
- result["error"] = response.Error
- }
- // 将结果序列化为 JSON 格式
- resultJSON, err := json.MarshalIndent(result, "", " ")
- if err != nil {
- return nil, fmt.Errorf("序列化结果失败: %w", err)
- }
- // 返回序列化后的结果
- return mcp.NewToolResultText(string(resultJSON)), nil
- }
- // GetName 返回重启虚拟机工具的名称
- func (c *CloudpodsServerRestartTool) GetName() string {
- return "cloudpods_restart_server"
- }
- // CloudpodsServerResetPasswordTool 用于重置指定Cloudpods虚拟机的登录密码
- type CloudpodsServerResetPasswordTool struct {
- adapter *adapters.CloudpodsAdapter
- }
- // NewCloudpodsServerResetPasswordTool 创建一个新的CloudpodsServerResetPasswordTool实例
- func NewCloudpodsServerResetPasswordTool(adapter *adapters.CloudpodsAdapter) *CloudpodsServerResetPasswordTool {
- return &CloudpodsServerResetPasswordTool{
- adapter: adapter,
- }
- }
- // GetTool 返回重置虚拟机密码工具的定义,包括参数和描述
- func (c *CloudpodsServerResetPasswordTool) GetTool() mcp.Tool {
- return mcp.NewTool(
- "cloudpods_reset_server_password",
- mcp.WithDescription("重置指定Cloudpods虚拟机的登录密码"),
- mcp.WithString("server_id", mcp.Required(), mcp.Description("虚拟机ID")),
- mcp.WithString("password", mcp.Required(), mcp.Description("新密码,长度8-30个字符")),
- mcp.WithString("reset_password", mcp.Description("是否重置密码,默认为true")),
- mcp.WithString("auto_start", mcp.Description("重置后是否自动启动,默认为true")),
- mcp.WithString("username", mcp.Description("用户名,可选,默认为空")),
- mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
- mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
- )
- }
- // Handle 处理重置虚拟机密码的请求,调用适配器执行密码重置操作并返回结果
- func (c *CloudpodsServerResetPasswordTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- // 从请求中获取必需的 server_id 参数
- serverID, err := req.RequireString("server_id")
- if err != nil {
- return nil, err
- }
- // 从请求中获取必需的 password 参数,并验证其长度
- password, err := req.RequireString("password")
- if err != nil {
- return nil, err
- }
- if len(password) < 8 || len(password) > 30 {
- return nil, fmt.Errorf("密码长度必须在8-30个字符之间")
- }
- // 解析 reset_password 参数,决定是否重置密码
- resetPassword := true
- if resetPasswordStr := req.GetString("reset_password", "true"); resetPasswordStr == "false" {
- resetPassword = false
- }
- // 解析 auto_start 参数,决定重置密码后是否自动启动虚拟机
- autoStart := true
- if autoStartStr := req.GetString("auto_start", "true"); autoStartStr == "false" {
- autoStart = false
- }
- // 获取 username 参数,可选
- username := req.GetString("username", "")
- // 构造重置虚拟机密码的请求参数
- resetPasswordReq := models.ServerResetPasswordRequest{
- Password: password,
- ResetPassword: resetPassword,
- AutoStart: autoStart,
- Username: username,
- }
- // 获取认证所需的 access key 和 secret key
- ak := req.GetString("ak", "")
- sk := req.GetString("sk", "")
- // 调用适配器的 ResetServerPassword 方法执行密码重置操作
- response, err := c.adapter.ResetServerPassword(ctx, serverID, resetPasswordReq, ak, sk)
- if err != nil {
- log.Errorf("Fail to reset server password: %s", err)
- return nil, fmt.Errorf("fail to reset server password: %w", err)
- }
- // 构造返回结果,包含任务ID、成功状态和状态信息
- result := map[string]interface{}{
- "server_id": serverID,
- "operation": "reset-password",
- "task_id": response.TaskId,
- "success": response.Success,
- "status": response.Status,
- }
- // 如果有错误信息,则添加到结果中
- if response.Error != "" {
- result["error"] = response.Error
- }
- // 将结果序列化为 JSON 格式
- resultJSON, err := json.MarshalIndent(result, "", " ")
- if err != nil {
- return nil, fmt.Errorf("序列化结果失败: %w", err)
- }
- // 返回序列化后的结果
- return mcp.NewToolResultText(string(resultJSON)), nil
- }
- // GetName 返回重置虚拟机密码工具的名称
- func (c *CloudpodsServerResetPasswordTool) GetName() string {
- return "cloudpods_reset_server_password"
- }
- // CloudpodsServerDeleteTool 用于删除指定的Cloudpods虚拟机实例
- type CloudpodsServerDeleteTool struct {
- adapter *adapters.CloudpodsAdapter
- }
- // NewCloudpodsServerDeleteTool 创建一个新的CloudpodsServerDeleteTool实例
- func NewCloudpodsServerDeleteTool(adapter *adapters.CloudpodsAdapter) *CloudpodsServerDeleteTool {
- return &CloudpodsServerDeleteTool{
- adapter: adapter,
- }
- }
- // GetTool 返回删除虚拟机工具的定义,包括参数和描述
- func (c *CloudpodsServerDeleteTool) GetTool() mcp.Tool {
- return mcp.NewTool(
- "cloudpods_delete_server",
- mcp.WithDescription("删除指定的Cloudpods虚拟机实例"),
- mcp.WithString("server_id", mcp.Required(), mcp.Description("虚拟机ID")),
- mcp.WithString("override_pending_delete", mcp.Description("是否强制删除(包括在回收站中的实例),默认为false")),
- mcp.WithString("purge", mcp.Description("是否仅删除本地资源,默认为false")),
- mcp.WithString("delete_snapshots", mcp.Description("是否删除快照,默认为false")),
- mcp.WithString("delete_eip", mcp.Description("是否删除关联的EIP,默认为false")),
- mcp.WithString("delete_disks", mcp.Description("是否删除关联的数据盘,默认为false")),
- mcp.WithString("ak", mcp.Description("用户登录cloudpods后获取的access key")),
- mcp.WithString("sk", mcp.Description("用户登录cloudpods后获取的secret key")),
- )
- }
- // Handle 处理删除虚拟机的请求,调用适配器执行删除操作并返回结果
- func (c *CloudpodsServerDeleteTool) Handle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- // 从请求中获取必需的 server_id 参数
- serverID, err := req.RequireString("server_id")
- if err != nil {
- return nil, err
- }
- // 解析 override_pending_delete 参数,决定是否强制删除(包括在回收站中的实例)
- overridePendingDelete := false
- if overrideStr := req.GetString("override_pending_delete", "false"); overrideStr == "true" {
- overridePendingDelete = true
- }
- // 解析 purge 参数,决定是否仅删除本地资源
- purge := false
- if purgeStr := req.GetString("purge", "false"); purgeStr == "true" {
- purge = true
- }
- // 解析 delete_snapshots 参数,决定是否删除快照
- deleteSnapshots := false
- if deleteSnapshotsStr := req.GetString("delete_snapshots", "false"); deleteSnapshotsStr == "true" {
- deleteSnapshots = true
- }
- // 解析 delete_eip 参数,决定是否删除关联的EIP
- deleteEip := false
- if deleteEipStr := req.GetString("delete_eip", "false"); deleteEipStr == "true" {
- deleteEip = true
- }
- // 解析 delete_disks 参数,决定是否删除关联的数据盘
- deleteDisks := false
- if deleteDisksStr := req.GetString("delete_disks", "false"); deleteDisksStr == "true" {
- deleteDisks = true
- }
- // 构造删除虚拟机的请求参数
- deleteReq := models.ServerDeleteRequest{
- OverridePendingDelete: overridePendingDelete,
- Purge: purge,
- DeleteSnapshots: deleteSnapshots,
- DeleteEip: deleteEip,
- DeleteDisks: deleteDisks,
- }
- // 获取认证所需的 access key 和 secret key
- ak := req.GetString("ak", "")
- sk := req.GetString("sk", "")
- // 调用适配器的 DeleteServer 方法执行删除操作
- response, err := c.adapter.DeleteServer(ctx, serverID, deleteReq, ak, sk)
- if err != nil {
- log.Errorf("Fail to delete server: %s", err)
- return nil, fmt.Errorf("fail to delete server: %w", err)
- }
- // 构造返回结果,包含任务ID、成功状态和状态信息
- result := map[string]interface{}{
- "server_id": serverID,
- "operation": "delete",
- "task_id": response.TaskId,
- "success": response.Success,
- "status": response.Status,
- }
- // 如果有错误信息,则添加到结果中
- if response.Error != "" {
- result["error"] = response.Error
- }
- // 将结果序列化为 JSON 格式
- resultJSON, err := json.MarshalIndent(result, "", " ")
- if err != nil {
- return nil, fmt.Errorf("序列化结果失败: %w", err)
- }
- // 返回序列化后的结果
- return mcp.NewToolResultText(string(resultJSON)), nil
- }
- // GetName 返回删除虚拟机工具的名称
- func (c *CloudpodsServerDeleteTool) GetName() string {
- return "cloudpods_delete_server"
- }
|