diff --git a/README-CN.md b/README-CN.md index 1e9d5a1d8cc..04f7418c423 100644 --- a/README-CN.md +++ b/README-CN.md @@ -95,4 +95,4 @@ Apache license 2.0,详情请看 [LICENSE](./LICENSE)。 ## AI生成文档 -[DeepWiki](https://deepwiki.com/yunionio/cloudpods) 提供了对本项目代码详细和全面的AI解读,可以参考。 +[DeepWiki](https://deepwiki.com/yunionio/cloudpods) 和 [Zread](https://zread.ai/yunionio/cloudpods) 提供了对本项目代码详细和全面的AI解读,可以参考。 diff --git a/README.md b/README.md index 0c1336cd726..47f7816480f 100644 --- a/README.md +++ b/README.md @@ -96,5 +96,5 @@ Apache License 2.0. See [LICENSE](./LICENSE). ## AI-generated doc -[DeepWiki](https://deepwiki.com/yunionio/cloudpods) provides an amazing AI-generated doc of this project, you may refer to it for more detailed and comprehensive understanding of codes. +[DeepWiki](https://deepwiki.com/yunionio/cloudpods) and [Zread](https://zread.ai/yunionio/cloudpods) provide AI-generated docs of this project, you may refer to them for more detailed and comprehensive understanding of codes. diff --git a/pkg/apis/cloudprovider/doc.go b/pkg/apis/cloudprovider/doc.go index b617c8ad6df..eafecb981d6 100644 --- a/pkg/apis/cloudprovider/doc.go +++ b/pkg/apis/cloudprovider/doc.go @@ -15,18 +15,6 @@ //go:build !ignore_autogenerated // +build !ignore_autogenerated -// 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. - // Code generated by swagger-gen. DO NOT EDIT. // Cloudprovider API diff --git a/pkg/apis/compute/api.go b/pkg/apis/compute/api.go index cf899fbf949..abfa8953c51 100644 --- a/pkg/apis/compute/api.go +++ b/pkg/apis/compute/api.go @@ -462,6 +462,56 @@ type DeployConfig struct { Content string `json:"content"` } +// ServerCreate输入参数主要检查规则如下: +// 1. 调用内部的 validateCreateData 方法对输入参数进行详细校验,包括镜像、磁盘、网络、主机名等基础信息的合法性和完整性。 +// validateCreateData 详细校验规则: +// 基础参数校验: +// - 元数据条目不能超过20个 +// - 实例快照和备份ID的有效性校验,保留用户输入的CPU、内存和实例类型配置 +// - 密码强度校验,登录账户长度不超过32字符且格式合法 +// - 实例组存在性校验,支持通过ID或名称指定 +// +// 镜像和磁盘校验: +// - 检查所有磁盘镜像是否为虚拟机镜像的一部分 +// - 非容器虚拟机必须提供启动磁盘或光驱 +// - 系统磁盘不支持ISO镜像格式,需使用cdrom参数 +// - 启动索引唯一性校验,避免重复 +// - UEFI支持校验:ARM架构默认支持UEFI,UEFI镜像必须使用UEFI启动模式 +// - 加密密钥与镜像加密密钥一致性校验 +// +// 资源配置校验: +// - SKU配置校验,验证SKU存在性并从SKU获取内存和CPU配置 +// - 内存和CPU配置合法性校验,内存不能为0,CPU默认为1 +// - 根磁盘校验:NVMe设备不能作为根磁盘 +// - 存储类型和大小校验,确保系统磁盘不小于最小值 +// +// 网络配置校验: +// - 网络配置解析和合法性验证 +// - 默认网关唯一性校验,确保只有一个默认网关 +// - 自动设置默认网关(优先选择出口网络) +// +// 隔离设备校验: +// - GPU设备校验:NVIDIA vGPU数量不能超过1个,且不能与其他GPU同时使用 +// - 备份虚拟机不支持隔离设备 +// +// 安全组校验: +// - 根据虚拟化类型限制安全组数量 +// - ESXi不支持安全组 +// +// 计费配置校验: +// - 预付费资源类型不能创建预付费服务器 +// - 计费周期合法性校验 +// - 虚拟化类型对计费方式的支持性校验 +// +// 其他校验: +// - 用户数据格式校验(根据操作系统类型) +// - 策略定义验证 +// - 主机名格式校验 +// - 云提供商和区域信息推断 +// +// 2. 若校验通过,且实例不是系统虚拟机(IsSystem 字段为 nil 或 false),则会进一步检查配额(checkCreateQuota),确保资源配额充足。 +// 3. 若上述校验均通过,则返回格式化后的参数 JSON 对象。 +// 该方法确保了虚拟机实例创建时的参数符合平台要求,避免因参数错误导致的创建失败。 type ServerCreateInput struct { apis.VirtualResourceCreateInput DeletePreventableCreateInput diff --git a/pkg/apis/compute/zz_generated.model.go b/pkg/apis/compute/zz_generated.model.go index 0f31609d540..963dc34d7fa 100644 --- a/pkg/apis/compute/zz_generated.model.go +++ b/pkg/apis/compute/zz_generated.model.go @@ -54,6 +54,20 @@ type SAccessGroupRule struct { UserAccessType string `json:"user_access_type"` } +// SAiGateway is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SAiGateway. +type SAiGateway struct { + apis.SVirtualResourceBase + apis.SExternalizedResourceBase + SManagedResourceBase + Authentication bool `json:"authentication"` + CacheInvalidateOnUpdate bool `json:"cache_invalidate_on_update"` + CacheTTL int `json:"cache_ttl"` + CollectLogs bool `json:"collect_logs"` + RateLimitingInterval int `json:"rate_limiting_interval"` + RateLimitingLimit int `json:"rate_limiting_limit"` + RateLimitingTechnique string `json:"rate_limiting_technique"` +} + // SApp is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SApp. type SApp struct { apis.SVirtualResourceBase @@ -110,8 +124,10 @@ type SBillingResourceBase struct { // 计费类型, 按量、包年包月 // example: postpaid BillingType string `json:"billing_type"` - // 过期时间 + // 包年包月到期时间 ExpiredAt time.Time `json:"expired_at"` + // 到期释放时间 + ReleaseAt time.Time `json:"release_at"` // 计费周期 BillingCycle string `json:"billing_cycle"` // 是否自动续费 @@ -172,6 +188,16 @@ type SCDNDomain struct { Referer *cloudprovider.SCDNReferer `json:"referer"` // 浏览器缓存配置 MaxAge *cloudprovider.SCDNMaxAge `json:"max_age"` + // 是否启用DNSSEC + DNSSECEnabled bool `json:"dnssec_enabled"` + // SSL加密模式 + SSLSetting string `json:"ssl_setting"` + // 是否启用HTTPS重写 + HTTPSRewrites bool `json:"https_rewrites"` + // 缓存级别 + CacheLevel string `json:"cache_level"` + // 浏览器缓存TTL + BrowserCacheTTL int `json:"browser_cache_ttl"` } // SCachedimage is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCachedimage. @@ -627,8 +653,11 @@ type SDnsZone struct { apis.SEnabledResourceBase apis.SExternalizedResourceBase SManagedResourceBase - ZoneType string `json:"zone_type"` - ProductType string `json:"product_type"` + NameServers *SNameServers `json:"name_servers"` + OriginalNameServers *SNameServers `json:"original_name_servers"` + ZoneType string `json:"zone_type"` + Registrar string `json:"registrar"` + ProductType string `json:"product_type"` } // SDnsZoneResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SDnsZoneResourceBase. @@ -909,7 +938,7 @@ type SExternalProject struct { // 优先级,同一个本地项目映射多个云上项目,优先级高的优先选择 // 数值越高,优先级越大 Priority int `json:"priority"` - // swagger:ignore + // swagger: ignore // 将在3.12之后版本移除 CloudaccountId string `json:"cloudaccount_id"` } @@ -1156,6 +1185,8 @@ type SGuestnetwork struct { TeamWith string `json:"team_with"` // IPv4映射地址,当子网属于私有云vpc的时候分配,用于访问外网 MappedIpAddr string `json:"mapped_ip_addr"` + // IPv6映射地址,当子网属于私有云vpc的时候分配,用于访问外网 + MappedIp6Addr string `json:"mapped_ip6_addr"` // 网卡关联的Eip实例 EipId string `json:"eip_id"` // 是否为缺省路由 @@ -1257,6 +1288,8 @@ type SHost struct { BootMode string `json:"boot_mode"` // IPv4地址,作为私有云vpc访问外网时的网关 OvnMappedIpAddr string `json:"ovn_mapped_ip_addr"` + // IPv6地址,作为私有云vpc访问外网时的网关 + OvnMappedIp6Addr string `json:"ovn_mapped_ip6_addr"` // UEFI详情 UefiInfo jsonutils.JSONObject `json:"uefi_info"` // 公网Ip地址 @@ -1311,6 +1344,8 @@ type SHostnetwork struct { NetworkId string `json:"network_id"` // IP地址 IpAddr string `json:"ip_addr"` + // IPv6地址 + Ip6Addr string `json:"ip6_addr"` // MAC地址 MacAddr string `json:"mac_addr"` // VLAN @@ -1499,6 +1534,10 @@ type SIsolatedDevice struct { CardPath string `json:"card_path"` // GPU render path, like /dev/dri/renderDX RenderPath string `json:"render_path"` + // Nvidia GPU index + Index int `json:"index"` + // Nvidia GPU minor number, parsing from /proc/driver/nvidia/gpus/*/information + DeviceMinor int `json:"device_minor"` // Is vgpu physical funcion, That means it cannot be attached to guest // VGPUPhysicalFunction bool `nullable:"true" default:"false" list:"domain" create:"domain_optional"` // nvidia vgpu config @@ -1766,7 +1805,9 @@ type SLoadbalancerBackendGroup struct { apis.SStatusStandaloneResourceBase apis.SExternalizedResourceBase SLoadbalancerResourceBase - Type string `json:"type"` + LoadbalancerHealthCheckId string `json:"loadbalancer_health_check_id"` + Scheduler string `json:"scheduler"` + Type string `json:"type"` } // SLoadbalancerBackendgroupResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerBackendgroupResourceBase. @@ -1815,35 +1856,39 @@ type SLoadbalancerClusterResourceBase struct { // SLoadbalancerHTTPListener is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerHTTPListener. type SLoadbalancerHTTPListener struct { - StickySession string `json:"sticky_session"` // 会话保持开启状态 on|off - StickySessionType string `json:"sticky_session_type"` + StickySession string `json:"sticky_session"` // Cookie处理方式 insert(植入cookie)|server(重写cookie) - StickySessionCookie string `json:"sticky_session_cookie"` + StickySessionType string `json:"sticky_session_type"` // Cookie名称 - StickySessionCookieTimeout int `json:"sticky_session_cookie_timeout"` - XForwardedFor bool `json:"xforwarded_for"` + StickySessionCookie string `json:"sticky_session_cookie"` + // 会话超时时间 + StickySessionCookieTimeout int `json:"sticky_session_cookie_timeout"` // 获取客户端真实IP + XForwardedFor bool `json:"xforwarded_for"` + // Gzip数据压缩 Gzip bool `json:"gzip"` } // SLoadbalancerHTTPRateLimiter is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerHTTPRateLimiter. type SLoadbalancerHTTPRateLimiter struct { - HTTPRequestRate int `json:"http_request_rate"` // 限定监听接收请示速率 + HTTPRequestRate int `json:"http_request_rate"` + // 源IP监听请求最大速率 HTTPRequestRatePerSrc int `json:"http_request_rate_per_src"` } // SLoadbalancerHTTPRedirect is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerHTTPRedirect. type SLoadbalancerHTTPRedirect struct { - Redirect string `json:"redirect"` // 跳转类型 - RedirectCode int `json:"redirect_code"` + Redirect string `json:"redirect"` // 跳转HTTP code - RedirectScheme string `json:"redirect_scheme"` + RedirectCode int `json:"redirect_code"` // 跳转uri scheme - RedirectHost string `json:"redirect_host"` + RedirectScheme string `json:"redirect_scheme"` // 跳转时变更Host + RedirectHost string `json:"redirect_host"` + // 跳转时变更Path RedirectPath string `json:"redirect_path"` } @@ -1856,23 +1901,40 @@ type SLoadbalancerHTTPSListener struct { // SLoadbalancerHealthCheck is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerHealthCheck. type SLoadbalancerHealthCheck struct { - HealthCheck string `json:"health_check"` + apis.SVirtualResourceBase + apis.SExternalizedResourceBase + SManagedResourceBase + SCloudregionResourceBase + SLoadbalancerHealthChecker +} + +// SLoadbalancerHealthChecker is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SLoadbalancerHealthChecker. +type SLoadbalancerHealthChecker struct { // 健康检查开启状态 on|off - HealthCheckType string `json:"health_check_type"` - HealthCheckDomain string `json:"health_check_domain"` + HealthCheck string `json:"health_check"` + // 健康检查协议 HTTP|TCP + HealthCheckType string `json:"health_check_type"` // 健康检查域名 yunion.cn - HealthCheckURI string `json:"health_check_uri"` + HealthCheckDomain string `json:"health_check_domain"` // 健康检查路径 / + HealthCheckURI string `json:"health_check_uri"` + // HTTP正常状态码 http_2xx,http_3xx HealthCheckHttpCode string `json:"health_check_http_code"` - HealthCheckRise int `json:"health_check_rise"` + // 健康检查方法 GET|POST|HEAD + HealthCheckMethod string `json:"health_check_method"` + // 健康检查端口 80 + HealthCheckPort int `json:"health_check_port"` // 健康检查健康阈值 3秒 - HealthCheckFall int `json:"health_check_fall"` + HealthCheckRise int `json:"health_check_rise"` // 健康检查不健康阈值 15秒 - HealthCheckTimeout int `json:"health_check_timeout"` + HealthCheckFall int `json:"health_check_fall"` // 健康检查超时时间 10秒 - HealthCheckInterval int `json:"health_check_interval"` - HealthCheckReq string `json:"health_check_req"` + HealthCheckTimeout int `json:"health_check_timeout"` + // 健康检查间隔时间 5秒 + HealthCheckInterval int `json:"health_check_interval"` // UDP监听健康检查的请求串 + HealthCheckReq string `json:"health_check_req"` + // UDP监听健康检查的响应串 HealthCheckExp string `json:"health_check_exp"` } @@ -1881,18 +1943,19 @@ type SLoadbalancerListener struct { apis.SStatusStandaloneResourceBase apis.SExternalizedResourceBase SLoadbalancerResourceBase - ListenerType string `json:"listener_type"` - ListenerPort int `json:"listener_port"` - BackendGroupId string `json:"backend_group_id"` - BackendServerPort int `json:"backend_server_port"` - Scheduler string `json:"scheduler"` - SendProxy string `json:"send_proxy"` - ClientRequestTimeout int `json:"client_request_timeout"` + ListenerType string `json:"listener_type"` + ListenerPort int `json:"listener_port"` + BackendGroupId string `json:"backend_group_id"` + BackendServerPort int `json:"backend_server_port"` + Scheduler string `json:"scheduler"` + SendProxy string `json:"send_proxy"` // 连接请求超时时间 - ClientIdleTimeout int `json:"client_idle_timeout"` + ClientRequestTimeout int `json:"client_request_timeout"` // 连接空闲超时时间 - BackendConnectTimeout int `json:"backend_connect_timeout"` + ClientIdleTimeout int `json:"client_idle_timeout"` // 后端连接超时时间 + BackendConnectTimeout int `json:"backend_connect_timeout"` + // 后端连接空闲时间 BackendIdleTimeout int `json:"backend_idle_timeout"` AclStatus string `json:"acl_status"` AclType string `json:"acl_type"` @@ -1902,7 +1965,7 @@ type SLoadbalancerListener struct { SLoadbalancerUDPListener SLoadbalancerHTTPListener SLoadbalancerHTTPSListener - SLoadbalancerHealthCheck + SLoadbalancerHealthChecker SLoadbalancerHTTPRateLimiter SLoadbalancerHTTPRedirect } @@ -1917,14 +1980,20 @@ type SLoadbalancerListenerResourceBase struct { type SLoadbalancerListenerRule struct { apis.SStatusStandaloneResourceBase apis.SExternalizedResourceBase + SLoadbalancerCertificateResourceBase SLoadbalancerListenerResourceBase // 默认转发策略,目前只有aws用到其它云都是false - IsDefault bool `json:"is_default"` + IsDefault bool `json:"is_default"` + // 默认后端服务器组 BackendGroupId string `json:"backend_group_id"` - Domain string `json:"domain"` - Path string `json:"path"` - Condition string `json:"condition"` - SLoadbalancerHealthCheck + // 后端服务器组列表 + BackendGroups *ListenerRuleBackendGroups `json:"backend_groups"` + // 域名 + Domain string `json:"domain"` + Path string `json:"path"` + Condition string `json:"condition"` + RedirectPool *ListenerRuleRedirectPool `json:"redirect_pool"` + SLoadbalancerHealthChecker // 目前只有腾讯云HTTP、HTTPS类型的健康检查是和规则绑定的。 SLoadbalancerHTTPRateLimiter SLoadbalancerHTTPRedirect @@ -2217,10 +2286,7 @@ type SNetwork struct { GuestIp6Mask byte `json:"guest_ip6_mask"` // IPv6网关 GuestGateway6 string `json:"guest_gateway6"` - // IPv6域名服务器 - GuestDns6 string `json:"guest_dns6"` - GuestDomain6 string `json:"guest_domain6"` - VlanId int `json:"vlan_id"` + VlanId int `json:"vlan_id"` // 服务器类型 // example: server ServerType string `json:"server_type"` @@ -2394,6 +2460,7 @@ type SSSLCertificate struct { apis.SVirtualResourceBase apis.SExternalizedResourceBase SManagedResourceBase + SDnsZoneResourceBase SDeletePreventableResourceBase Sans string `json:"sans"` StartDate time.Time `json:"start_date"` @@ -2401,7 +2468,6 @@ type SSSLCertificate struct { Common string `json:"common"` Country string `json:"country"` Issuer string `json:"issuer"` - Expired bool `json:"expired"` IsUpload bool `json:"is_upload"` EndDate time.Time `json:"end_date"` Fingerprint string `json:"fingerprint"` @@ -2666,7 +2732,12 @@ type SSnapshotPolicy struct { apis.SExternalizedResourceBase SManagedResourceBase SCloudregionResourceBase + // 快照保留天数 RetentionDays int `json:"retention_days"` + // 快照保留数量, 优先级高于 RetentionDays, 且仅对本地IDC资源有效 + RetentionCount int `json:"retention_count"` + // 快照类型, 目前支持 disk, server + Type string `json:"type"` // 1~7, 1 is Monday RepeatWeekdays []int `json:"repeat_weekdays"` // 0~23 @@ -2680,6 +2751,14 @@ type SSnapshotPolicyDisk struct { SDiskResourceBase } +// SSnapshotPolicyResource is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SSnapshotPolicyResource. +type SSnapshotPolicyResource struct { + apis.SResourceBase + SnapshotpolicyId string `json:"snapshotpolicy_id"` + ResourceId string `json:"resource_id"` + ResourceType string `json:"resource_type"` +} + // SStorage is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SStorage. type SStorage struct { apis.SEnabledStatusInfrasResourceBase @@ -2878,7 +2957,7 @@ type SWafRegexSet struct { // SWafRule is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SWafRule. type SWafRule struct { - apis.SStatusStandaloneResourceBase + apis.SEnabledStatusStandaloneResourceBase apis.SExternalizedResourceBase // 规则优先级 Priority int `json:"priority"` @@ -2886,6 +2965,12 @@ type SWafRule struct { Action *cloudprovider.DefaultAction `json:"action"` // 条件 StatementConditon string `json:"statement_conditon"` + // 条件表达式 + Expression string `json:"expression"` + // 规则类型 + Type string `json:"type"` + // 规则配置 + Config jsonutils.JSONObject `json:"config"` // 规则组的id WafRuleGroupId string `json:"waf_rule_group_id"` // 所属waf实例id diff --git a/pkg/apis/monitor/zz_generated.model.go b/pkg/apis/monitor/zz_generated.model.go index 937d8869f2d..2495840a548 100644 --- a/pkg/apis/monitor/zz_generated.model.go +++ b/pkg/apis/monitor/zz_generated.model.go @@ -60,14 +60,6 @@ type SAlertDashBoard struct { Refresh string `json:"refresh"` } -// SAlertDashboardPanel is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertDashboardPanel. -type SAlertDashboardPanel struct { - apis.SVirtualJointResourceBase - DashboardId string `json:"dashboard_id"` - PanelId string `json:"panel_id"` - Index int `json:"index"` -} - // SAlertPanel is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SAlertPanel. type SAlertPanel struct { apis.SStatusStandaloneResourceBase @@ -127,11 +119,6 @@ type SDataSource struct { IsDefault *bool `json:"is_default,omitempty"` } -// SMeterAlert is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SMeterAlert. -type SMeterAlert struct { - SV1Alert -} - // SMetric is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SMetric. type SMetric struct { apis.SVirtualJointResourceBase @@ -215,8 +202,3 @@ type SNotification struct { Settings jsonutils.JSONObject `json:"settings"` LastSendNotification time.Time `json:"last_send_notification"` } - -// SV1Alert is an autogenerated struct via yunion.io/x/onecloud/pkg/monitor/models.SV1Alert. -type SV1Alert struct { - SAlert -} diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index f0ca0bdf151..d33c9ce41ee 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1616,6 +1616,9 @@ func (manager *SGuestManager) ExpandBatchCreateData( return input, nil } +// validateCreateData 是虚拟机创建参数的核心校验方法,执行全面的参数验证和规范化处理 +// 该方法确保所有输入参数符合平台要求,为虚拟机创建提供可靠的数据基础 +// 校验过程包括:基础参数验证、资源配置校验、网络配置校验、安全配置校验等 func (manager *SGuestManager) validateCreateData( ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*api.ServerCreateInput, error) { @@ -1625,10 +1628,12 @@ func (manager *SGuestManager) validateCreateData( return nil, err } + // 元数据条目数量限制:不能超过20个 if len(input.Metadata) > 20 { return nil, httperrors.NewInputParameterError("metdata must less then 20") } + // 实例快照处理:解析快照信息并保留用户输入的资源配置 if len(input.InstanceSnapshotId) > 0 { inputMem := input.VmemSize inputCpu := input.VcpuCount @@ -1637,7 +1642,7 @@ func (manager *SGuestManager) validateCreateData( if err != nil { return nil, err } - // keep input cpu mem flavor + // 保留用户输入的CPU、内存和实例类型配置 if inputMem > 0 { input.VmemSize = inputMem } @@ -1672,6 +1677,7 @@ func (manager *SGuestManager) validateCreateData( resetPassword = *input.ResetPassword } + // 密码强度校验:如果提供了密码,必须通过密码强度验证 passwd := input.Password if len(passwd) > 0 { err = seclib2.ValidatePassword(passwd) @@ -1682,6 +1688,7 @@ func (manager *SGuestManager) validateCreateData( input.ResetPassword = &resetPassword } + // 登录账户校验:长度限制和格式验证 if resetPassword && len(input.LoginAccount) > 0 { if len(input.LoginAccount) > 32 { return nil, httperrors.NewInputParameterError("login_account is longer than 32 chars") @@ -1691,7 +1698,7 @@ func (manager *SGuestManager) validateCreateData( } } - // check group + // 实例组校验:验证所有指定的实例组是否存在,支持ID或名称指定 if input.InstanceGroupIds != nil && len(input.InstanceGroupIds) != 0 { newGroupIds := make([]string, len(input.InstanceGroupIds)) for index, id := range input.InstanceGroupIds { @@ -1701,11 +1708,11 @@ func (manager *SGuestManager) validateCreateData( } newGroupIds[index] = model.GetId() } - // list of id or name ==> ids + // 统一转换为ID格式 input.InstanceGroupIds = newGroupIds } - // check that all image of disk is the part of guest imgae, if use guest image to create guest + // 镜像完整性校验:检查所有磁盘镜像是否为虚拟机镜像的一部分 err = manager.checkGuestImage(ctx, input) if err != nil { return nil, errors.Wrap(err, "checkGuestImage") @@ -1743,6 +1750,7 @@ func (manager *SGuestManager) validateCreateData( // var rootStorageType string var osProf osprofile.SOSProfile hypervisor = input.Hypervisor + // 启动磁盘校验:非容器虚拟机必须提供启动磁盘或光驱 if hypervisor != api.HYPERVISOR_POD { if len(input.Disks) == 0 && input.Cdrom == "" { return nil, httperrors.NewInputParameterError("No bootable disk information provided") @@ -1761,6 +1769,7 @@ func (manager *SGuestManager) validateCreateData( imgEncryptKeyId = diskConfig.ImageEncryptKeyId imgProperties = diskConfig.ImageProperties imageDiskFormat = imgProperties[imageapi.IMAGE_DISK_FORMAT] + // 系统磁盘格式校验:不支持ISO镜像格式,需使用cdrom参数 if imgProperties[imageapi.IMAGE_DISK_FORMAT] == "iso" { return nil, httperrors.NewInputParameterError("System disk does not support iso image, please consider using cdrom parameter") } @@ -1778,7 +1787,7 @@ func (manager *SGuestManager) validateCreateData( } } - // check boot indexes + // 启动索引唯一性校验:使用位图确保启动索引不重复 bm := bitmap.NewBitMap(128) if input.CdromBootIndex != nil && *input.CdromBootIndex >= 0 { bm.Set(int64(*input.CdromBootIndex)) @@ -1807,6 +1816,7 @@ func (manager *SGuestManager) validateCreateData( support := true imgSupportUEFI = &support } + // UEFI支持校验:UEFI镜像必须使用UEFI启动模式,非UEFI镜像不能使用UEFI启动模式 switch { case imgSupportUEFI != nil && *imgSupportUEFI: if len(input.Bios) == 0 { @@ -1815,7 +1825,7 @@ func (manager *SGuestManager) validateCreateData( return nil, httperrors.NewInputParameterError("UEFI image requires UEFI boot mode") } default: - // not UEFI image + // 非UEFI镜像 if input.Bios == "UEFI" && len(imgProperties) != 0 { return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image") } @@ -1847,6 +1857,7 @@ func (manager *SGuestManager) validateCreateData( if input.EncryptKeyId == nil && len(imgEncryptKeyId) > 0 { input.EncryptKeyId = &imgEncryptKeyId } + // 加密配置校验:验证加密资源配置和密钥一致性 if input.EncryptKeyId != nil || input.EncryptKeyNew != nil { input.EncryptedResourceCreateInput, err = manager.SEncryptedResourceManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EncryptedResourceCreateInput) if err != nil { @@ -1900,7 +1911,7 @@ func (manager *SGuestManager) validateCreateData( return nil, err } if hypervisor != api.HYPERVISOR_POD { - // support sku here + // SKU配置校验:验证SKU存在性并从SKU获取资源配置 var sku *SServerSku skuName := input.InstanceType if len(skuName) > 0 { @@ -1913,6 +1924,7 @@ func (manager *SGuestManager) validateCreateData( input.VmemSize = sku.MemorySizeMB input.VcpuCount = sku.CpuCoreCount } else { + // 内存和CPU配置合法性校验 vmemSize, vcpuCount, err := ValidateMemCpuData(input.VmemSize, input.VcpuCount, input.Hypervisor, input.Provider) if err != nil { return nil, err @@ -1955,8 +1967,9 @@ func (manager *SGuestManager) validateCreateData( if err != nil { return nil, httperrors.NewGeneralError(err) // should no error } - // validate root disk config + // 根磁盘配置校验 { + // NVMe设备不能作为根磁盘 if rootDiskConfig.NVMEDevice != nil { return nil, httperrors.NewBadRequestError("NVMe device can't assign as root disk") } @@ -2023,6 +2036,7 @@ func (manager *SGuestManager) validateCreateData( input.Disks[i+1] = diskConfig } + // 计费配置校验:预付费资源类型冲突检查 if len(input.Duration) > 0 { if input.ResourceType == api.HostResourceTypePrepaidRecycle { return nil, httperrors.NewConflictError("cannot create prepaid server on prepaid resource type") @@ -2054,7 +2068,7 @@ func (manager *SGuestManager) validateCreateData( } } - // HACK: if input networks is empty, add one random network config + // 网络配置默认处理:如果没有指定网络,添加一个默认网络配置 if len(input.Networks) == 0 { input.Networks = append(input.Networks, &api.NetworkConfig{Exit: false}) } @@ -2099,14 +2113,14 @@ func (manager *SGuestManager) validateCreateData( } input.Networks[idx] = netConfig } - // check default gateway + // 默认网关校验:确保只有一个默认网关,优先选择出口网络 if defaultGwCnt == 0 { defIdx := 0 if firstExit >= 0 { - // there is a exit network, make it the default + // 存在出口网络时,将其设为默认网关 defIdx = firstExit } - // make the first nic as default + // 将第一个网卡设为默认网关 input.Networks[defIdx].IsDefault = true } else if defaultGwCnt > 1 { return nil, errors.Wrapf(httperrors.ErrInputParameter, "more than 1 nic(%d) assigned as default gateway", defaultGwCnt) @@ -2128,6 +2142,7 @@ func (manager *SGuestManager) validateCreateData( input.IsolatedDevices[idx] = devConfig } + // GPU设备校验:NVIDIA vGPU数量限制和兼容性检查 nvidiaVgpuCnt := 0 gpuCnt := 0 for i := 0; i < len(input.IsolatedDevices); i++ { @@ -2138,9 +2153,11 @@ func (manager *SGuestManager) validateCreateData( } } + // NVIDIA vGPU数量不能超过1个 if nvidiaVgpuCnt > 1 { return nil, httperrors.NewBadRequestError("Nvidia vgpu count exceed > 1") } + // NVIDIA vGPU不能与其他GPU同时使用 if nvidiaVgpuCnt > 0 && gpuCnt > 0 { return nil, httperrors.NewBadRequestError("Nvidia vgpu can't passthrough with other gpus") } @@ -2178,8 +2195,9 @@ func (manager *SGuestManager) validateCreateData( input.SecgroupId = options.Options.GetDefaultSecurityGroupId(hypervisor) } + // 安全组数量限制:根据虚拟化类型限制安全组数量 maxSecgrpCount := driver.GetMaxSecurityGroupCount() - if maxSecgrpCount == 0 { //esxi 不支持安全组 + if maxSecgrpCount == 0 { // ESXi不支持安全组 input.SecgroupId = "" input.Secgroups = []string{} } else if len(input.Secgroups)+1 > maxSecgrpCount { @@ -2218,11 +2236,12 @@ func (manager *SGuestManager) validateCreateData( return nil, err } - // validate UserData + // 用户数据格式校验:根据操作系统类型验证用户数据格式 if err := userdata.ValidateUserdata(input.UserData, input.OsType); err != nil { return nil, httperrors.NewInputParameterError("Invalid userdata: %v", err) } + // 策略定义验证:确保所有相关的策略定义有效 err = manager.ValidatePolicyDefinitions(ctx, userCred, ownerId, query, input) if err != nil { return nil, err