diff --git a/cmd/climc/shell/keypairs.go b/cmd/climc/shell/keypairs.go index c22f7a3ba1..130e651940 100644 --- a/cmd/climc/shell/keypairs.go +++ b/cmd/climc/shell/keypairs.go @@ -51,9 +51,10 @@ func init() { }) type KeypairCreate struct { - NAME string `help:"Name of keypair to be created"` - Scheme string `help:"Scheme of keypair, default is RSA" choices:"RSA|DSA" default:"RSA"` - Desc string `help:"Short description of keypair"` + NAME string `help:"Name of keypair to be created"` + Scheme string `help:"Scheme of keypair, default is RSA" choices:"RSA" default:"RSA"` + PublicKey string `help:"Publickey of keypair"` + Desc string `help:"Short description of keypair"` } R(&KeypairCreate{}, "keypair-create", "Create a new keypair", func(s *mcclient.ClientSession, args *KeypairCreate) error { @@ -63,6 +64,10 @@ func init() { params.Add(jsonutils.NewString(args.Scheme), "scheme") } + if len(args.PublicKey) > 0 { + params.Add(jsonutils.NewString(args.PublicKey), "public_key") + } + if len(args.Desc) > 0 { params.Add(jsonutils.NewString(args.Desc), "description") } diff --git a/pkg/apis/compute/api.go b/pkg/apis/compute/api.go index fa644da27a..2db5b05180 100644 --- a/pkg/apis/compute/api.go +++ b/pkg/apis/compute/api.go @@ -31,14 +31,36 @@ type SchedtagConfig struct { type NetworkConfig struct { apis.Meta - Index int `json:"index"` - Network string `json:"network"` - Wire string `json:"wire"` - Exit bool `json:"exit"` - Private bool `json:"private"` - Mac string `json:"mac"` - Address string `json:"address"` + // 网卡序号, 从0开始 + // required: true + Index int `json:"index"` + + // 子网名称或ID + // required: true + Network string `json:"network"` + + // swagger:ignore + Wire string `json:"wire"` + + // 内网地址 + Exit bool `json:"exit"` + Private bool `json:"private"` + + // 网卡MAC地址 + // requried: false + Mac string `json:"mac"` + + // 子网内的IPv4地址, 若不指定会安装子网的地址分配策略分配一个IP地址 + // required: false + Address string `json:"address"` + + // 子网内的IPv6地址 + // required: false + // swagger:ignore Address6 string `json:"address6"` + + // 驱动方式 + // 若指定镜像的网络驱动方式,此参数会被覆盖 Driver string `json:"driver"` BwLimit int `json:"bw_limit"` Vip bool `json:"vip"` @@ -53,7 +75,10 @@ type NetworkConfig struct { StandbyPortCount int `json:"standby_port_count"` StandbyAddrCount int `json:"standby_addr_count"` - Project string `json:"project_id"` + // swagger:ignore + Project string `json:"project_id"` + + // swagger:ignore Domain string `json:"domain_id"` Ifname string `json:"ifname"` Schedtags []*SchedtagConfig `json:"schedtags"` @@ -62,24 +87,114 @@ type NetworkConfig struct { type DiskConfig struct { apis.Meta - Index int `json:"index"` // -1 means not attach to any guests - ImageId string `json:"image_id"` - SnapshotId string `json:"snapshot_id"` - DiskType string `json:"disk_type"` - Schedtags []*SchedtagConfig `json:"schedtags"` + // 挂载到虚拟机的磁盘顺序, -1代表不挂载任何虚拟机 + // default: -1 + Index int `json:"index"` - SizeMb int `json:"size"` - Fs string `json:"fs"` - Format string `json:"format"` - Driver string `json:"driver"` - Cache string `json:"cache"` - Mountpoint string `json:"mountpoint"` - Backend string `json:"backend"` // stroageType - Medium string `json:"medium"` + // 镜像ID,通过镜像创建磁盘,创建虚拟机时第一块磁盘需要指定此参数 + // required: false + ImageId string `json:"image_id"` + + // 快照ID,通过快照创建磁盘,此参数必须加上 'snapshot-' 前缀 + // example: snapshot-3140cecb-ccc4-4865-abae-3a5ba8c69d9b + // requried: false + SnapshotId string `json:"snapshot_id"` + + // 磁盘类型 + // enum: sys, data, swap + DiskType string `json:"disk_type"` + + Schedtags []*SchedtagConfig `json:"schedtags"` + + // 磁盘大小,单位Mb + // 若创建裸金属服务器是, -1代表自动向后扩展存储 + // requried:true + SizeMb int `json:"size"` + + // 文件系统,仅kvm支持自动格式化磁盘,私有云和公有云此参数不会生效 + // enum: swap, ext2, ext3, ext4, xfs, ntfs, fat, hfsplus + // requried: false + Fs string `json:"fs"` + + // 磁盘存储格式 + // enum: qcow2, raw, docker, iso, vmdk, vmdkflatver1, vmdkflatver2, vmdkflat, vmdksparse, vmdksparsever1, vmdksparsever2, vmdksepsparse vhd + // requried: false + Format string `json:"format"` + + // 磁盘驱动方式 + // enum: virtio, ide, scsi, sata, pvscsi + // requried: false + Driver string `json:"driver"` + + // 磁盘缓存模式 + // enum: writeback, none, writethrough + // requried: false + Cache string `json:"cache"` + + // 挂载点,必须以 '/' 开头,例如 /opt 仅KVM此参数有效 + // requried: false + Mountpoint string `json:"mountpoint"` + + //后端存储类型,若指定了存储ID,此参数会根据存储设置,若不指定,则作为调度的一个参考 + // + // + // + //| 平台 | 存储类型 | 中文 | 数据盘 | 系统盘 | 可否扩容 | 可否单独创建 | 扩容步长 | 说明 | + //| ---- | ---- | ---- | ----- | ----- | ------- | ----------- | ------- | ----- | + //| Esxi |local |本地盘 |1-500GB |30~500GB | 是 | 否 | 1G | | + //| Esxi |nas |NAS盘 |30-3072GB |30~500GB | 是 | 否 | 1G | | + //| Esxi |vsan |VSAN盘 |30-3072GB |30~500GB | 是 | 否 | 1G | | + //| KVM |local |本地盘盘 |1-500GB |30~500GB | 是 | 否 | 1G | | + //| KVM |rbd |云硬盘 |1-3072GB |30~500GB | 是 | 是 | 1G | | + //| Azure |standard_lrs |标准 HDD |1-4095GB |30~4095GB | 是 | 是 | 1G | | + //| Azure |standardssd_lrs |标准 SSD |1-4095GB |30~4095GB | 是 | 是 | 1G | | + //| Azure |premium_lrs |高级SSD |1-4095GB |30~4095GB | 是 | 是 | 1G | | + //| AWS |gp2 |通用型SSD |1-16384GB |20~16384GB | 是 | 是 | 1G | | + //| AWS |io1 |预配置 IOPS SSD|4-16384GB |20-16384GB | 是 | 是 | 1G | | + //| AWS |st1 |吞吐优化HDD |500-16384GB |不支持 | 是 | 是 | 1G | | + //| AWS |sc1 |Cold HDD |500-16384GB |不支持 | 是 | 是 | 1G | | + //| AWS |standard |磁介质 |1-1024GB |20-1024GB | 是 | 是 | 1G | | + //| 腾讯云 |cloud_ssd |SSD云硬盘 |10-16000GB |50~500GB | 是 | 是 | 10G | | + //| 腾讯云 |cloud_basic |普通云硬盘 |10-16000GB |50~500GB | 是 | 是 | 10G | | + //| 腾讯云 |cloud_preium |高性能云硬盘 |10-16000GB |50~1024GB | 是 | 是 | 10G | | + //| 腾讯云 |local_basic |普通本地盘 |10-1600GB |不支持 | 否 | 否 | | | + //| 腾讯云 |local_ssd |SSD本地盘 |10-7000GB |部分区域套餐支持 | 否 | 否 | | | + //| 腾讯云 |local_pro |HDD本地盘 |跟随套餐 |部分区域套餐支持 | 否 | 否 | | | + //| 华为云或天翼云 |SSD |超高IO云硬盘 |10-32768GB |40~1024GB | 是 | 是 | 1G | | + //| 华为云或天翼云 |SAS |高IO云硬盘 |10-32768GB |40~1024GB | 是 | 是 | 1G | | + //| 华为云或天翼云 |SATA |普通IO云硬盘 |10-32768GB |40~1024GB | 是 | 是 | 1G | | + //| OpenStack |nova |nova |不支持 |30-500GB | 否 | 否 | | | + //| OpenStack |自定义 |... |无限制 |无限制 | 是 | 是 | 1G | | + //| Ucloud |CLOUD_NORMAL |普通云盘 |20-8000GB |不支持 | 是 | 是 | 1G | | + //| Ucloud |CLOUD_SSD |SSD云盘 |20-4000GB |20-500GB | 是 | 是 | 1G | | + //| Ucloud |LOCAL_NORMAL |普通本地盘 | | | 是 | 是 | 1G | | + //| Ucloud |LOCAL_SSD |SSD本地盘 | | | 是 | 是 | 1G | | + //| Ucloud |EXCLUSIVE_LOCAL_DISK |独享本地盘 | | | 是 | 是 | 1G | | + //| ZStack |localstorage |本地盘 | | | 是 | 是 | 1G | | + //| ZStack |ceph |云硬盘 | | | 是 | 是 | 1G | | + //| Google |local-ssd |本地SSD暂存盘 |375GB |不支持 | 否 | 否 | | 跟随实例创建,一次最多添加8个 | + //| Google |pd-standard |标准永久性磁盘 |10-65536GB |10-65536GB | 是 | 是 | 1G | | + //| Google |pd-ssd |SSD永久性磁盘 |10-65536GB |10-65536GB | 是 | 是 | 1G | | + Backend string `json:"backend"` + + //介质类型 + //rotate: 机械盘 + //ssd: 固态硬盘 + //hybird: 混合盘 + //emum: [rotate, ssd, hybrid] + //default: hybird + Medium string `json:"medium"` + + //swagger:ignore ImageProperties map[string]string `json:"image_properties"` + //存储ID, 指定存储后,磁盘会在此存储上创建 + //存储列表可以参数 storage 列表API + //required: false Storage string `json:"storage_id"` - DiskId string `json:"disk_id"` + + //swagger:ignore + DiskId string `json:"disk_id"` } type IsolatedDeviceConfig struct { @@ -110,26 +225,84 @@ type BaremetalDiskConfig struct { } type ServerConfigs struct { - // prefer options - PreferRegion string `json:"prefer_region_id"` - PreferZone string `json:"prefer_zone_id"` - PreferWire string `json:"prefer_wire_id"` - PreferHost string `json:"prefer_host_id"` + // 调度到指定区域,优先级低于prefer_zone_id + PreferRegion string `json:"prefer_region_id"` + + // 调度到指定可用区,优先级低于prefer_host_id + PreferZone string `json:"prefer_zone_id"` + + // 调度使用指定二层网络, 优先级低于prefer_host_id + PreferWire string `json:"prefer_wire_id"` + + // 调度使用指定宿主机 + PreferHost string `json:"prefer_host_id"` + + // 主机高可用时,将备机调度到指定宿主机, 此参数仅对KVM生效 PreferBackupHost string `json:"prefer_backup_host"` + // 虚拟化技术或平台 + // + // + // + // |hypervisor | 技术或平台 | + // |------- | ---------- | + // |kvm | 本地私有云 | + // |esxi | VMWare | + // |baremetal | 裸金属 | + // |aliyun | 阿里云 | + // |aws | 亚马逊 | + // |qcloud | 腾讯云 | + // |azure | 微软云 | + // |huawei | 华为云 | + // |openstack | OpenStack | + // |ucloud | Ucloud | + // |zstack | ZStack | + // |google | 谷歌云 | + // |ctyun | 天翼云 | + // default: kvm Hypervisor string `json:"hypervisor"` - // ResourceType "shared|prepaid|dedicated"` + + // 包年包月资源池 + // swagger:ignore + // emum: shared, prepaid, dedicated ResourceType string `json:"resource_type"` + + // 套餐名称, 此参数优先级高于vcpu_count和vmem_size + // 套餐可以通过 serverskus 列表获取 + // esxi, openstack, zstack等私有云都统一使用provider为OneCloud的套餐 + // 公有云使用各自的套餐 InstanceType string `json:"instance_type"` - Backup bool `json:"backup"` - Count int `json:"count"` - Disks []*DiskConfig `json:"disks"` - Networks []*NetworkConfig `json:"nets"` - Schedtags []*SchedtagConfig `json:"schedtags"` - IsolatedDevices []*IsolatedDeviceConfig `json:"isolated_devices"` - BaremetalDiskConfigs []*BaremetalDiskConfig `json:"baremetal_disk_configs"` + // 虚拟机高可用(创建备机) + // default: false + // requried: false + Backup bool `json:"backup"` + // 创建虚拟机数量 + // default: 1 + Count int `json:"count"` + + // 磁盘列表,第一块磁盘为系统盘,需要指定image_id + // 若指定主机快照,此参数可以为空 + // required: true + Disks []*DiskConfig `json:"disks"` + + // 指定主机网络 + // required: false + Networks []*NetworkConfig `json:"nets"` + + // 调度标签 + // required: false + Schedtags []*SchedtagConfig `json:"schedtags"` + + // 透传设备列表 + // required: false + IsolatedDevices []*IsolatedDeviceConfig `json:"isolated_devices"` + + // 裸金属磁盘配置列表 + BaremetalDiskConfigs []*BaremetalDiskConfig `json:"baremetal_disk_configs"` + + // 主机组列表, 参数可以是主机组名称或ID,建议使用ID InstanceGroupIds []string `json:"groups"` // DEPRECATE @@ -159,47 +332,136 @@ type ServerCreateInput struct { *ServerConfigs - VmemSize int `json:"vmem_size"` - VcpuCount int `json:"vcpu_count"` - UserData string `json:"user_data"` - Metadata map[string]string `json:"__meta__"` + // 虚拟机内存大小,单位Mb,若未指定instance_type,此参数为必传项 + VmemSize int `json:"vmem_size"` + // 虚拟机Cpu大小,若未指定instance_type,此参数为必传项 + // default: 1 + VcpuCount int `json:"vcpu_count"` + + // 用户自定义启动脚本 + // required: false + UserData string `json:"user_data"` + + // 秘钥对Id + // required: false KeypairId string `json:"keypair_id"` - Password string `json:"password"` - Cdrom string `json:"cdrom"` - Vga string `json:"vga"` - Vdi string `json:"vdi"` - Bios string `json:"bios"` - // Description string `json:"description"` - BootOrder string `json:"boot_order"` - EnableCloudInit bool `json:"enable_cloud_init"` - ResetPassword *bool `json:"reset_password"` - // DisableDelete *bool `json:"disable_delete"` - ShutdownBehavior string `json:"shutdown_behavior"` - AutoStart bool `json:"auto_start"` - DeployConfigs []*DeployConfig `json:"deploy_configs"` - // IsSystem bool `json:"is_system"` - Duration string `json:"duration"` - AutoPrepaidRecycle bool `json:"auto_prepaid_recycle,omitfalse"` - SecgroupId string `json:"secgrp_id"` - EipBw int `json:"eip_bw,omitzero"` - EipChargeType string `json:"eip_charge_type,omitempty"` - Eip string `json:"eip,omitempty"` - InstanceSnapshotId string `json:"instance_snapshot_id,omitempty"` - Secgroups []string `json:"secgroups"` + // 密码 + // 要求: 密码长度 >= 20, 至少包含一个数字一个小写字母一个大小字母及特殊字符~`!@#$%^&*()-_=+[]{}|:';\",./<>?中的一个 + // requried: false + Password string `json:"password"` + + // 使用ISO光盘启动, 仅KVM平台支持 + // required: false + Cdrom string `json:"cdrom"` + + // enum: cirros, vmware, qxl, std + // default: std + Vga string `json:"vga"` + + // 远程连接协议 + // enum: vnc, spice + // default: vnc + Vdi string `json:"vdi"` + + // BIOS类型, 若镜像是Windows,并且支持UEFI,则自动会设置为UEFI + // emulate: BIOS, UEFI + Bios string `json:"bios"` + + // 启动顺序 + // c: cdrome + // d: disk + // n: network + // example: cnd + // default: cdn + BootOrder string `json:"boot_order"` + + // 启用cloud-init,需要镜像装有cloud-init服务 + // default: false + EnableCloudInit bool `json:"enable_cloud_init"` + + // 随机密码, 若指定password参数,此参数不生效 + // 若值为false并且password为空,则表示保留镜像密码 + ResetPassword *bool `json:"reset_password"` + + // 关机后执行的操作 + // terminate: 关机后自动删除 + // emum: stop, terminate + // default: stop + ShutdownBehavior string `json:"shutdown_behavior"` + + // 创建后自动启动 + // 部分云创建后会自动启动例如: 腾讯云, AWS, OpenStack, ZStack, Ucloud, Huawei, Azure, 天翼云 + // default: false + AutoStart bool `json:"auto_start"` + DeployConfigs []*DeployConfig `json:"deploy_configs"` + + // 包年包月时长 + // + // + // |平台 |是否支持 | + // |---- |------- | + // |KVM |否 | + // |ESxi |否 | + // |OpenStack |否 | + // |ZStack |否 | + // |Google |否 | + // |Azure |否 | + // |AWS |否 | + // |腾讯云 |是 | + // |Aliyun |是 | + // |Ucloud |是 | + // |Huawei |是 | + // |天翼云 |是 | + Duration string `json:"duration"` + + // swagger:ignore + AutoPrepaidRecycle bool `json:"auto_prepaid_recycle,omitfalse"` + + // 安全组Id, 此参数会和secgroups参数合并 + SecgroupId string `json:"secgrp_id"` + + // 弹性公网IP带宽 + // 指定此参数后会创建新的弹性公网IP并绑定到新建的虚拟机 + // 私有云不支持此参数 + EipBw int `json:"eip_bw,omitzero"` + + // 弹性公网IP计费类型 + EipChargeType string `json:"eip_charge_type,omitempty"` + + // 弹性公网IP名称或ID + // 绑定已有弹性公网IP, 此参数会限制虚拟机再谈下公网IP所在的区域创建 + // required: false + Eip string `json:"eip,omitempty"` + + // 使用主机快照创建虚拟机, 主机快照不会重置密码及秘钥信息 + // 使用主机快照创建的虚拟机将沿用之前的密码秘钥及安全组信息 + // required: false + InstanceSnapshotId string `json:"instance_snapshot_id,omitempty"` + + // 安全组Id列表 + Secgroups []string `json:"secgroups"` + + // swagger:ignore OsType string `json:"os_type"` - // Fill by server - OsProfile jsonutils.JSONObject `json:"__os_profile__"` - BillingType string `json:"billing_type"` - BillingCycle string `json:"billing_cycle"` - // DEPRECATE or not used fields + // swagger:ignore + OsProfile jsonutils.JSONObject `json:"__os_profile__"` + // swagger:ignore + BillingType string `json:"billing_type"` + // swagger:ignore + BillingCycle string `json:"billing_cycle"` + + // DEPRECATE + // 此参数等同于 hypervisor=baremetal Baremetal bool `json:"baremetal"` // Used to store BaremetalConvertHypervisorTaskId ParentTaskId string `json:"__parent_task_id,omitempty"` - // default stroage type if host is given + + // 指定系统盘默认存储类型, 如果指定宿主机 + // swagger:ignore DefaultStorageType string `json:"default_storage_type,omitempty"` // Guest Image ID diff --git a/pkg/apis/compute/cloudaccount.go b/pkg/apis/compute/cloudaccount.go index 066b60a7c8..a2d7968724 100644 --- a/pkg/apis/compute/cloudaccount.go +++ b/pkg/apis/compute/cloudaccount.go @@ -26,17 +26,58 @@ import ( type CloudaccountCreateInput struct { apis.EnabledStatusStandaloneResourceCreateInput - Provider string - AccountId string - Brand string - IsPublicCloud bool - IsOnPremise bool - Tenant string - TenantId string - EnableAutoSync bool - SyncIntervalSeconds int - AutoCreateProject bool - Options *jsonutils.JSONObject + // 指定云平台 + // Qcloud: 腾讯云 + // Ctyun: 天翼云 + // enum: VMware, Aliyun, Qcloud, Azure, Aws, Huawei, OpenStack, Ucloud, ZStack, Google, Ctyun + Provider string `json:"provider"` + // swagger:ignore + AccountId string + + // 指定云平台品牌, 此参数默认和provider相同 + // requried: false + // + // + // + // | provider | 支持的参数 | + // | -------- | ---------- | + // | VMware | VMware | + // | Aliyun | Aliyun | + // | Qcloud | Qcloud | + // | Azure | Azure | + // | Aws | Aws | + // | Huawei | Huawei | + // | OpenStack | OpenStack | + // | Ucloud | Ucloud | + // | ZStack | ZStack, DStack | + // | Google | Google | + // | Ctyun | Ctyun | + Brand string `json:"brand"` + + // swagger:ignore + IsPublicCloud bool + // swagger:ignore + IsOnPremise bool + + // 指定云账号所属的项目 + Tenant string `json:"tenant"` + + // swagger:ignore + TenantId string + + // 启用自动同步 + // default: false + EnableAutoSync bool `json:"enable_auto_sync"` + + // 自动同步间隔时间 + SyncIntervalSeconds int `json:"sync_interval_seconds"` + + // 自动根据云上项目或订阅创建本地项目 + // default: false + AutoCreateProject bool `json:"auto_create_project"` + + // 额外信息,例如账单的access key + Options *jsonutils.JSONObject `json:"options"` cloudprovider.SCloudaccount cloudprovider.SCloudaccountCredential diff --git a/pkg/apis/compute/dbinstance.go b/pkg/apis/compute/dbinstance.go index ca00853a09..320238b75a 100644 --- a/pkg/apis/compute/dbinstance.go +++ b/pkg/apis/compute/dbinstance.go @@ -16,38 +16,131 @@ package compute import "yunion.io/x/onecloud/pkg/apis" -type SDBInstanceCreateInput struct { - apis.Meta +type DBInstanceCreateInput struct { + apis.VirtualResourceCreateInput + DeletePreventableCreateInput - Name string - Description string - DisableDelete *bool - NetworkId string - Address string - MasterInstanceId string - SecgroupId string - Zone1 string - Zone2 string - Zone3 string - ZoneId string - CloudregionId string - Cloudregion string - VpcId string - ManagerId string + // Ip子网名称或Id,建议使用Id + // required: true + Network string `json:"network"` + // swagger:ignore + NetworkId string + + // Ip子网内的地址,不填则按照ip子网的地址分配策略分配一个ip + // required: false + Address string `json:"address"` + + // rds实例名称或Id,建议使用Id + // 创建只读实例时此参数必传 + MasterInstance string `json:"master_instance"` + // swagger:ignore + MasterInstanceId string + + // 安全组名称或Id + // default: default + Secgroup string `json:"secgroup"` + // swagger:ignore + SecgroupId string + + // 主可用区名称或Id, 此参数从指定的套餐所在的可用区获取 + Zone1 string `json:"zone1"` + + // 次可用区名称或Id, 此参数从指定的套餐所在的可用区获取 + Zone2 string `json:"zone2"` + + // 三节点可用区名称或Id,, 此参数从指定的套餐所在的可用区获取 + Zone3 string `json:"zone3"` + + // swagger:ignore + ZoneId string + + // 区域名称或Id,建议使用Id + // swagger:ignore + Cloudregion string `json:"cloudregion"` + + // swagger:ignore + CloudregionId string + + // swagger:ignore + VpcId string + + // swagger:ignore + ManagerId string + + // swagger:ignore NetworkExternalId string - BillingType string - BillingCycle string - InstanceType string - Engine string - EngineVersion string - Category string - StorageType string - DiskSizeGB int - Password string - VcpuCount int - VmemSizeMb int - Provider string + // 包年包月时间周期 + Duration string `json:"duration"` + + // swagger:ignore + BillingType string + // swagger:ignore + BillingCycle string + + // 套餐名称, 若此参数不填, 则必须有vmem_size_mb及vcpu_count参数 + // 套餐列表可以通过 dbinstancesku 获取 + InstanceType string `json:"instance_type"` + + // rds引擎 + // enum: MySQL, SQLServer, PostgreSQL, MariaDB, Oracle, PPAS + // required: true + Engine string `json:"instance_type"` + + // rds引擎版本 + // 根据各个引擎版本各不相同 + // required: true + EngineVersion string `json:"engine_version"` + + // rds类型 + // + // + // + // | 平台 | 支持类型 | + // | ----- | ------ | + // | 华为云 |ha, single, replica| + // | 阿里云 |basic, high_availability, always_on, finance| + // 翻译: + // basic: 基础版 + // high_availability: 高可用 + // always_on: 集群版 + // finance: 金融版, 三节点 + // ha: 高可用 + // single: 单机 + // replica: 只读 + // required: true + Category string `json:"category"` + + // rds存储类型 + // + // + // + // | 平台 | 支持类型 | + // | 华为云 |SSD, SAS, SATA| + // | 阿里云 |local_ssd, cloud_essd, cloud_ssd| + // required: true + StorageType string `json:"storage_type"` + + // rds存储大小 + // 可参考rds套餐的大小范围和步长情况 + // required: true + DiskSizeGB int `json:"disk_size_gb"` + + // rds初始化密码 + // 阿里云不需要此参数 + // 华为云会默认创建一个用户,若不传此参数, 则为随机密码 + Password string `json:"password"` + + // rds实例cpu大小 + // 若指定实例套餐,此参数将根据套餐设置 + VcpuCount int `json:"vcpu_count"` + + // rds实例内存大小 + // 若指定实例套餐,此参数将根据套餐设置 + VmemSizeMb int `json:"vmem_size_mb"` + + // swagger:ignore + Provider string } type SDBInstanceChangeConfigInput struct { diff --git a/pkg/apis/compute/dbinstance_account.go b/pkg/apis/compute/dbinstance_account.go index abe1fe5b0b..2781ba8e06 100644 --- a/pkg/apis/compute/dbinstance_account.go +++ b/pkg/apis/compute/dbinstance_account.go @@ -17,21 +17,53 @@ package compute import "yunion.io/x/onecloud/pkg/apis" type SDBInstanceAccountPrivilege struct { - Database string + // 数据库名称或Id + // required: true + Database string `json:"database"` + // swagger:ignore DBInstancedatabaseId string - Privilege string + + // 权限类型 + // + // + // + // | 平台 |Rds引擎 | 支持类型 | + // | ---- |------- | -------- | + // | Aliyun |MySQL, MariaBD | rw, r, ddl, dml | + // | Aliyun |SQLServer | rw, r, owner | + // | Huawei |MySQL, MariaDB | rw, r | + // 同一平台不同的rds类型支持的权限不尽相同 + // required: true + Privilege string `json:"privilege"` } -type SDBInstanceAccountCreateInput struct { - apis.Meta +type DBInstanceAccountCreateInput struct { + apis.StatusStandaloneResourceCreateInput + // rds实例名称或Id,建议使用Id + // + // + // + // | 平台 |支持Rds引擎 | + // | ---- |------- | + // | Aliyun |MySQL, MariaBD, SQLServer | + // | 华为云 |MySQL, MariaBD | + // required: true + // 阿里云SQL Server 2017集群版不支持创建账号 + // 实例状态必须是运行中 + DBInstance string `json:"dbinstance"` + // swagger:ignore DBInstanceId string `json:"dbinstance_id"` - Name string - Description string - Password string - Privileges []SDBInstanceAccountPrivilege + + // 账号密码,若不指定,则会随机生成 + // required: false + Password string `json:"password"` + + // 账号权限 + // required: false + Privileges []SDBInstanceAccountPrivilege `json:"privileges"` } type SDBInstanceSetPrivilegesInput struct { - Privileges []SDBInstanceAccountPrivilege + Privileges []SDBInstanceAccountPrivilege `json:"privileges"` } diff --git a/pkg/apis/compute/dbinstance_backup.go b/pkg/apis/compute/dbinstance_backup.go index 4374e3893a..8f122ddfdc 100644 --- a/pkg/apis/compute/dbinstance_backup.go +++ b/pkg/apis/compute/dbinstance_backup.go @@ -16,17 +16,29 @@ package compute import "yunion.io/x/onecloud/pkg/apis" -type SDBInstanceBackupCreateInput struct { - apis.Meta +type DBInstanceBackupCreateInput struct { + apis.VirtualResourceCreateInput - DBInstanceId string `json:"dbinstance_id"` - Name string - Description string - DBNames string - Databases []string - Engine string + // Rds实例名称或Id, 建议使用Id + // required: true + DBInstance string `json:"dbinstance"` + // swagger:ignore + DBInstanceId string `json:"dbinstance_id"` + + // 需要备份的Rds数据库列表 + // required: false + Databases []string `json:"databases"` + // swagger:ignore + DBNames string + + // swagger:ignore + Engine string + // swagger:ignore EngineVersion string + // swagger:ignore CloudregionId string - BackupMode string - ManagerId string + // swagger:ignore + BackupMode string + // swagger:ignore + ManagerId string } diff --git a/pkg/apis/compute/dbinstance_database.go b/pkg/apis/compute/dbinstance_database.go index 863fb0b09a..b7d0a93d5d 100644 --- a/pkg/apis/compute/dbinstance_database.go +++ b/pkg/apis/compute/dbinstance_database.go @@ -17,18 +17,46 @@ package compute import "yunion.io/x/onecloud/pkg/apis" type SDBInstanceDatabasePrivilege struct { - Account string + // 数据库账号名称或Id + // required: true + Account string `json:"account"` + // swagger:ignore DBInstanceaccountId string - Privilege string + // 权限 + // | 平台 |Rds引擎 | 支持类型 | + // | ---- |------- | -------- | + // | Aliyun |MySQL, MariaBD | rw, r, ddl, dml | + // | Aliyun |SQLServer | rw, r, owner | + // | Huawei |MySQL, MariaDB | rw, r | + // 同一平台不同的rds类型支持的权限不尽相同 + // required: true + Privilege string `json:"privilege"` } -type SDBInstanceDatabaseCreateInput struct { - apis.Meta +type DBInstanceDatabaseCreateInput struct { + apis.StatusStandaloneResourceCreateInput - DBInstanceId string `json:"dbinstance_id"` - CharacterSet string - Name string - Description string - Accounts []SDBInstanceDatabasePrivilege - DBInstanceaccountId string + // rds实例名称或Id,建议使用Id + // + // + // + // | 平台 |支持Rds引擎 | + // | ---- |------- | + // | Aliyun |MySQL, MariaBD, SQLServer | + // | 华为云 |MySQL, MariaBD | + // required: true + // 阿里云SQL Server 2017集群版不支持创建数据库 + // 阿里云只读实例不支持创建数据库 + // 实例状态必须是运行中 + DBInstance string `json:"dbinstance"` + // swagger:ignore + DBInstanceId string `json:"dbinstance_id"` + + // 数据库字符集 + // required: true + CharacterSet string `json:"character_set"` + + // 赋予账号权限 + // required: false + Accounts []SDBInstanceDatabasePrivilege `json:"accounts"` } diff --git a/pkg/apis/compute/disk.go b/pkg/apis/compute/disk.go index cd5df60d39..52afc67277 100644 --- a/pkg/apis/compute/disk.go +++ b/pkg/apis/compute/disk.go @@ -23,15 +23,25 @@ type DiskCreateInput struct { *DiskConfig - // prefer options + // 此参数仅适用于未指定storage时进行调度到指定区域创建磁盘 + // required: false PreferRegion string `json:"prefer_region_id"` - PreferZone string `json:"prefer_zone_id"` - PreferWire string `json:"prefer_wire_id"` - PreferHost string `json:"prefer_host_id"` + // 此参数仅适用于未指定storage时进行调度到指定可用区区创建磁盘 + // required: false + PreferZone string `json:"prefer_zone_id"` + + // swagger:ignore + PreferWire string `json:"prefer_wire_id"` + + // 此参数仅适用于未指定storage时进行调度到指定可用区区创建磁盘 + // required: false + PreferHost string `json:"prefer_host_id"` + + // 此参数仅适用于未指定storage时进行调度到指定平台创建磁盘 + // default: kvm + // enum: kvm, openstack, esxi, aliyun, aws, qcloud, azure, huawei, openstack, ucloud, zstack google, ctyun Hypervisor string `json:"hypervisor"` - // Project string `json:"project"` - // Domain string `json:"domain_id"` } // ToServerCreateInput used by disk schedule diff --git a/pkg/apis/compute/elasticip.go b/pkg/apis/compute/elasticip.go new file mode 100644 index 0000000000..33e9c19301 --- /dev/null +++ b/pkg/apis/compute/elasticip.go @@ -0,0 +1,69 @@ +// 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 compute + +import "yunion.io/x/onecloud/pkg/apis" + +type SElasticipCreateInput struct { + apis.VirtualResourceCreateInput + + // 区域名称或Id, 建议使用Id + // 在指定区域内创建弹性公网ip + Cloudregion string `json:"cloudregion"` + + // swagger:ignore + Region string + // swagger:ignore + RegionId string + // swagger:ignore + CloudregionId string + + // 子订阅Id, 建议使用Id + // 使用指定子订阅创建弹性公网ip + // 弹性公网ip和虚拟机在同一区域同一子订阅底下,才可以进行绑定操作 + Cloudprovider string `json:"cloudprovider"` + // swagger:ignore + Manager string + // swagger:ignore + ManagerId string + + // 计费类型: 流量或带宽 + // + // + // + // | 平台 | 支持类型 | + // | --- | -------- | + // |Aliyun | traffic, bandwidth | + // |腾讯云 | traffic | + // |Azure | traffic | + // |Google | traffic, bandwidth | + // |Ucloud | traffic | + // |Aws | traffic | + // |华为云 | traffic, bandwidth | + // |天翼云 | traffic, bandwidth | + // |KVM | 不支持创建 | + // |VMware | 不支持创建 | + // |ZStack | traffic | + // |OpenStack | traffic | + // default: traffic + // enum: traffic, bandwidth + ChargeType string `json:"charge_type"` + + // 子网名称或Id + // 私有云创建此参数必传,例如Openstack, ZStack + Network string `json:"network"` + // swagger:ignore + NetworkId string +} diff --git a/pkg/apis/compute/input.go b/pkg/apis/compute/input.go index 8d25947ac9..1cf2248c09 100644 --- a/pkg/apis/compute/input.go +++ b/pkg/apis/compute/input.go @@ -25,5 +25,7 @@ type ManagedResourceCreateInput struct { } type DeletePreventableCreateInput struct { + //删除保护,创建的资源默认不允许删除 + //default: true DisableDelete *bool `json:"disable_delete"` } diff --git a/pkg/apis/compute/keypair.go b/pkg/apis/compute/keypair.go new file mode 100644 index 0000000000..ef4836e73a --- /dev/null +++ b/pkg/apis/compute/keypair.go @@ -0,0 +1,42 @@ +// 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 compute + +import "yunion.io/x/onecloud/pkg/apis" + +var KEYPAIR_SCHEMAS = []string{ + KEYPAIRE_SCHEME_RSA, +} + +type KeypairCreateInput struct { + apis.StandaloneResourceCreateInput + + // 公钥内容,若为空则自动生成公钥 + PublicKey string `json:"public_key"` + + // swagger:ignore + PrivateKey string + + // swagger:ignore + Fingerprint string + + // swagger:ignore + OwnerId string + + // 秘钥类型 + // enum: RSA + // default: RSA + Scheme string `json:"scheme"` +} diff --git a/pkg/apis/compute/keypair_const.go b/pkg/apis/compute/keypair_const.go new file mode 100644 index 0000000000..79e5a786f5 --- /dev/null +++ b/pkg/apis/compute/keypair_const.go @@ -0,0 +1,20 @@ +// 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 compute + +const ( + KEYPAIRE_SCHEME_RSA = "RSA" + KEYPAIRE_SCHEME_DSA = "DSA" +) diff --git a/pkg/apis/compute/schedtag.go b/pkg/apis/compute/schedtag.go index d9446c28b9..a20446a569 100644 --- a/pkg/apis/compute/schedtag.go +++ b/pkg/apis/compute/schedtag.go @@ -20,3 +20,21 @@ type SchedtagShortDescDetails struct { *apis.StandaloneResourceShortDescDetail Default string `json:"default"` } + +type ScopedResourceCreateInput struct { + Scope string `json:"scope"` +} + +type SchedtagCreateInput struct { + apis.StandaloneResourceCreateInput + ScopedResourceCreateInput + + // 动态标签策略 + // enum: exclude, prefer, avoid + DefaultStrategy string `json:"default_strategy"` + + // 资源类型 + // enum: servers, hosts, ..... + // default: hosts + ResourceType string `json:"resource_type"` +} diff --git a/pkg/apis/compute/secgroup.go b/pkg/apis/compute/secgroup.go index a0a29dd24e..b12a8d1ad6 100644 --- a/pkg/apis/compute/secgroup.go +++ b/pkg/apis/compute/secgroup.go @@ -28,17 +28,69 @@ import ( type SSecgroupRuleCreateInput struct { apis.ResourceBaseCreateInput - Priority int - Protocol string - Ports string - PortStart int - PortEnd int - Direction string - CIDR string - Action string - Description string - Secgroup string - SecgroupId string + // 优先级, 数字越大优先级越高 + // minimum: 1 + // maximum: 100 + // required: true + Priority int `json:"priority"` + + // 协议 + // required: true + // + // + // + // | protocol | name | + // | -------- | ---- | + // | any | 所有协议| + // | tcp | TCP | + // | icmp | ICMP | + // | udp | UDP | + // enum: any, tcp, udp, icmp + Protocol string `json:"protocol"` + + // 端口列表, 参数为空代表任意端口 + // 此参数仅对protocol是tcp, udp时生效 + // 支持格式: + // | 格式类型 | 举例 | + // | -------- | ---- | + // | 单端口 | 22 | + // | 端口范围 | 100-200 | + // | 不连续端口| 80,443 | + // requried: false + Ports string `json:"ports"` + + // swagger:ignore + PortStart int + // swagger:ignore + PortEnd int + + // 方向 + // enum: in, out + // required: true + Direction string `json:"direction"` + + // ip或cidr地址 + // example: 192.168.222.121 + CIDR string `json:"cidr"` + + // 行为 + // deny: 拒绝 + // allow: 允许 + // enum: deny, allow + // required: true + Action string `json:"action"` + + // 规则描述信息 + // requried: false + // example: test to create rule + Description string `json:"description"` + + // 仅单独创建安全组规则时需要指定安全组 + // required: true + Secgroup string `json:"secgroup"` + + // swagger:ignore + SecgroupId string } func (input *SSecgroupRuleCreateInput) Check() error { @@ -73,6 +125,8 @@ func (input *SSecgroupRuleCreateInput) Check() error { type SSecgroupCreateInput struct { apis.SharableVirtualResourceCreateInput + // 规则列表 + // required: false Rules []SSecgroupRuleCreateInput `json:"rules"` } diff --git a/pkg/apis/compute/serversku.go b/pkg/apis/compute/serversku.go new file mode 100644 index 0000000000..d16bad57f5 --- /dev/null +++ b/pkg/apis/compute/serversku.go @@ -0,0 +1,130 @@ +// 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 compute + +import "yunion.io/x/onecloud/pkg/apis" + +type ServerSkuCreateInput struct { + apis.StatusStandaloneResourceCreateInput + + // 区域名称或Id,建议使用Id + // default: default + Cloudregion string `json:"cloudregion"` + // swagger:ignore + CloudregionId string + + // 可用区名称或Id, 建议使用Id + // required: false + Zone string `json:"zone"` + // swagger:ignore + ZoneId string + + // 是否启用 + // default: true + Enabled *bool `json:"enabled"` + + // swagger:ignore + InstanceTypeFamily string + + // 套餐类型 + // + // + // + // | instance_type_category | 说明 | + // | ----- | --- | + // |general_purpose |通用型 | + // |burstable |突发性能型 | + // |compute_optimized |计算优化型 | + // |memory_optimized |内存优化型 | + // |storage_optimized |存储IO优化型 | + // |hardware_accelerated |硬件加速型 | + // |high_storage |高存储型 | + // |high_memory |高内存型 | + // default: general_purpose + InstanceTypeCategory string `json:"instance_type_category"` + + // swagger:ignore + LocalCategory string + + // 预付费状态 + // default: available + PrepaidStatus string `json:"prepaid_status"` + // 后付费状态 + // default: available + PostpaidStatus string `json:"postpaid_status"` + + // Cpu核数 + // minimum: 1 + // maximum: 256 + // required: true + CpuCoreCount int64 `json:"cpu_core_count"` + + // 内存大小 + // minimum: 512 + // maximum: 524288 + // required: true + MemorySizeMB int64 `json:"memory_size_mb"` + + // swagger:ignore + OsName string + + // swagger:ignore + SysDiskResizable *bool + + // swagger:ignore + SysDiskType string + + // swagger:ignore + SysDiskMinSizeGB int + + // swagger:ignore + SysDiskMaxSizeGB int + + // swagger:ignore + AttachedDiskType string + + // swagger:ignore + AttachedDiskSizeGB int + + // swagger:ignore + AttachedDiskCount int + + // swagger:ignore + DataDiskTypes string + + // swagger:ignore + DataDiskMaxCount int + + // swagger:ignore + NicType string + + // swagger:ignore + NicMaxCount int + + // swagger:ignore + GpuAttachable *bool + + // swagger:ignore + GpuSpec string + + // swagger:ignore + GpuCount int + + // swagger:ignore + GpuMaxCount int + + // swagger:ignore + Provider string +} diff --git a/pkg/apis/compute/sku_const.go b/pkg/apis/compute/sku_const.go index 37a2203179..76c468478d 100644 --- a/pkg/apis/compute/sku_const.go +++ b/pkg/apis/compute/sku_const.go @@ -14,8 +14,6 @@ package compute -import "yunion.io/x/onecloud/pkg/util/choices" - const ( SkuCategoryGeneralPurpose = "general_purpose" // 通用型 SkuCategoryBurstable = "burstable" // 突发性能型 @@ -49,7 +47,7 @@ var InstanceFamilies = map[string]string{ SkuCategoryHighMemory: "hr1", } -var SKU_FAMILIES = choices.NewChoices( +var SKU_FAMILIES = []string{ SkuCategoryGeneralPurpose, SkuCategoryBurstable, SkuCategoryComputeOptimized, @@ -58,4 +56,4 @@ var SKU_FAMILIES = choices.NewChoices( SkuCategoryHardwareAccelerated, SkuCategoryHighStorage, SkuCategoryHighMemory, -) +} diff --git a/pkg/apis/compute/snapshot.go b/pkg/apis/compute/snapshot.go index f5484384a6..d2e08c9dcf 100644 --- a/pkg/apis/compute/snapshot.go +++ b/pkg/apis/compute/snapshot.go @@ -16,22 +16,31 @@ package compute import "yunion.io/x/onecloud/pkg/apis" -type SSnapshotCreateInput struct { - apis.Meta +type SnapshotCreateInput struct { + apis.VirtualResourceCreateInput - Name string `json:"name"` - Description string `json:"description"` - - Disk string `json:"disk"` - DiskId string `json:"disk_id"` - StorageId string `json:"storage_id"` - CreatedBy string `json:"created_by"` - Location string `json:"location"` - Size int `json:"size"` - DiskType string `json:"disk_type"` + // 磁盘名称或Id,建议使用Id + // 目前仅VMware平台不支持创建快照,其余平台磁盘均支持创建快照 + // required: true + Disk string `json:"disk"` + // swagger:ignore + DiskId string `json:"disk_id"` + // swagger:ignore + StorageId string `json:"storage_id"` + // swagger:ignore + CreatedBy string `json:"created_by"` + // swagger:ignore + Location string `json:"location"` + // swagger:ignore + Size int `json:"size"` + // swagger:ignore + DiskType string `json:"disk_type"` + // swagger:ignore CloudregionId string `json:"cloudregion_id"` - OutOfChain bool `json:"out_of_chain"` - ManagerId string `json:"manager_id"` + // swagger:ignore + OutOfChain bool `json:"out_of_chain"` + // swagger:ignore + ManagerId string `json:"manager_id"` } type SSnapshotPolicyCreateInput struct { diff --git a/pkg/apis/compute/storage.go b/pkg/apis/compute/storage.go new file mode 100644 index 0000000000..a885b65907 --- /dev/null +++ b/pkg/apis/compute/storage.go @@ -0,0 +1,113 @@ +// 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 compute + +import ( + "yunion.io/x/jsonutils" + + "yunion.io/x/onecloud/pkg/apis" +) + +type StorageCreateInput struct { + apis.StandaloneResourceCreateInput + + // 存储类型 + // + // + // + // | storage_type | 参数 |是否必传 | 默认值 | 说明 | + // | -------- | ------- | -------- | -------- | --------- | + // | rbd | rbd_mon_host | 是 | | ceph mon_host | + // | rbd | rbd_pool | 是 | | ceph pool | + // | rbd | rbd_key | 否 | |若cephx认证开启,此参数必传 | + // | rbd | rbd_rados_mon_op_timeout | 否 | 3 |单位: 秒 | + // | rbd | rbd_rados_osd_op_timeout | 否 | 1200 |单位: 秒 | + // | rbd | rbd_client_mount_timeout | 否 | 120 |单位: 秒 | + // | nfs | nfs_host | 是 | |网络文件系统主机 | + // | nfs | nfs_shared_dir | 是 | |网络文件系统共享目录 | + // local: 本地存储 + // rbd: ceph块存储, ceph存储创建时仅会检测是否重复创建,不会具体检测认证参数是否合法,只有挂载存储时 + // 计算节点会验证参数,若挂载失败,宿主机和存储不会关联,可以通过查看存储日志查找挂载失败原因 + // enum: local, rbd, nfs, gpfs + // required: true + StorageType string `json:"storage_type"` + + // 存储介质类型 + // enum: rotate, ssd, hybird + // required: true + MediumType string `json:"medium_type"` + + // 可用区名称或ID, 建议使用ID + // required: true + Zone string `json:"zone"` + + // swagger:ignore + ZoneId string + + // ceph认证主机, storage_type为 rbd 时,此参数为必传项 + // 单个ip或以逗号分隔的多个ip具体可查询 /etc/ceph/ceph.conf 文件 + // example: 192.168.222.3,192.168.222.4,192.168.222.99 + RbdMonHost string `json:"rbd_mon_host"` + + // swagger:ignore + MonHost string + + // ceph使用的pool, storage_type为 rbd 时,此参数为必传项 + // example: rbd + RbdPool string `json:"rbd_pool"` + + // swagger:ignore + Pool string + + // ceph集群密码,若ceph集群开启cephx认证,此参数必传 + // 可在ceph集群主机的/etc/ceph/ceph.client.admin.keyring文件中找到 + // example: AQDigB9dtnDAKhAAxS6X4zi4BPR/lIle4nf4Dw== + RbdKey string `json:"rbd_key"` + + // swagger:ignore + Key string + + // ceph集群连接超时时间, 单位秒 + // default: 3 + RbdRadosMonOpTimeout int `json:"rbd_rados_mon_op_timeout"` + + // swagger:ignore + RadosMonOpTimeout int + + // ceph osd 操作超时时间, 单位秒 + // default: 1200 + RbdRadosOsdOpTimeout int `json:"rbd_rados_osd_op_timeout"` + + // swagger:ignore + RadosOsdOpTimeout int + + // ceph CephFS挂载超时时间, 单位秒 + // default: 120 + RbdClientMountTimeout int `json:"rbd_client_mount_timeout"` + + // swagger:ignore + ClientMountTimeout int + + // swagger:ignore + StorageConf *jsonutils.JSONDict + + // 网络文件系统主机, storage_type 为 nfs 时,此参数必传 + // example: 192.168.222.2 + NfsHost string `json:"nfs_host"` + + // 网络文件系统共享目录, storage_type 为 nfs 时, 此参数必传 + // example: /nfs_root/ + NfsSharedDir string `json:"nfs_shared_dir"` +} diff --git a/pkg/apis/compute/wire.go b/pkg/apis/compute/wire.go new file mode 100644 index 0000000000..8d04ac7ac7 --- /dev/null +++ b/pkg/apis/compute/wire.go @@ -0,0 +1,43 @@ +// 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 compute + +import "yunion.io/x/onecloud/pkg/apis" + +type WireCreateInput struct { + apis.StandaloneResourceCreateInput + + // 带宽大小,单位: Mbps + // default: 0 + Bandwidth int `json:"bandwidth"` + + // mtu + // minimum: 0 + // maximum: 1000000 + // default: 0 + Mtu int `json:"mtu"` + + // vpc名称或Id + // required: true + Vpc string `json:"vpc"` + // swagger:ignore + VpcId string + + // 可用区名称或Id + // required: true + Zone string `json:"zone"` + // swagger:ignore + ZoneId string +} diff --git a/pkg/apis/compute/zone.go b/pkg/apis/compute/zone.go new file mode 100644 index 0000000000..488d580d27 --- /dev/null +++ b/pkg/apis/compute/zone.go @@ -0,0 +1,31 @@ +// 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 compute + +import "yunion.io/x/onecloud/pkg/apis" + +type ZoneCreateInput struct { + apis.StatusStandaloneResourceCreateInput + + // 区域名称或Id,建议使用Id + Cloudregion string + + // swagger:ignore + Region string + // swagger:ignore + RegionId string + // swagger:ignore + CloudregionId string +} diff --git a/pkg/apis/input.go b/pkg/apis/input.go index 84aa8d7672..5c536f5395 100644 --- a/pkg/apis/input.go +++ b/pkg/apis/input.go @@ -78,7 +78,7 @@ type StandaloneResourceCreateInput struct { // description: resource name, required if generated_name is not given // unique: true - // required: false + // required: true // example: test-network Name string `json:"name"` @@ -96,6 +96,10 @@ type StandaloneResourceCreateInput struct { // description: the resource is an emulated resource // required: false IsEmulated *bool `json:"is_emulated"` + + // 标签列表,最多支持20个 + // example: { "user:rd": "op" } + Metadata map[string]string `json:"__meta__"` } type JoinResourceBaseCreateInput struct { diff --git a/pkg/cloudcommon/db/scoperesource.go b/pkg/cloudcommon/db/scoperesource.go index e06cd6b230..eb80a9b75a 100644 --- a/pkg/cloudcommon/db/scoperesource.go +++ b/pkg/cloudcommon/db/scoperesource.go @@ -21,6 +21,7 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" + api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/rbacutils" @@ -50,19 +51,18 @@ func (m *SScopedResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, userCred return q } -func (m *SScopedResourceBaseManager) ValidateCreateData(man IScopedResourceManager, ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - scope, _ := data.GetString("scope") - if scope == "" { - scope = string(rbacutils.ScopeSystem) +func (m *SScopedResourceBaseManager) ValidateCreateData(man IScopedResourceManager, ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.ScopedResourceCreateInput) (api.ScopedResourceCreateInput, error) { + if input.Scope == "" { + input.Scope = string(rbacutils.ScopeSystem) } - if !utils.IsInStringArray(scope, []string{ + if !utils.IsInStringArray(input.Scope, []string{ string(rbacutils.ScopeSystem), string(rbacutils.ScopeDomain), string(rbacutils.ScopeProject)}) { - return nil, httperrors.NewInputParameterError("invalid scope %s", scope) + return input, httperrors.NewInputParameterError("invalid scope %s", input.Scope) } var allowCreate bool - switch rbacutils.TRbacScope(scope) { + switch rbacutils.TRbacScope(input.Scope) { case rbacutils.ScopeSystem: allowCreate = IsAdminAllowCreate(userCred, man) case rbacutils.ScopeDomain: @@ -71,10 +71,9 @@ func (m *SScopedResourceBaseManager) ValidateCreateData(man IScopedResourceManag allowCreate = IsProjectAllowCreate(userCred, man) } if !allowCreate { - return nil, httperrors.NewForbiddenError("not allow create %s in scope %s", man.ResourceScope(), scope) + return input, httperrors.NewForbiddenError("not allow create %s in scope %s", man.ResourceScope(), input.Scope) } - data.Set("scope", jsonutils.NewString(scope)) - return data, nil + return input, nil } func getScopedResourceScope(domainId, projectId string) rbacutils.TRbacScope { diff --git a/pkg/cloudprovider/cloudprovider.go b/pkg/cloudprovider/cloudprovider.go index 8486cde3d7..c86d6c66b0 100644 --- a/pkg/cloudprovider/cloudprovider.go +++ b/pkg/cloudprovider/cloudprovider.go @@ -32,39 +32,112 @@ const ( ) type SCloudaccountCredential struct { - ProjectName string //OpenStack - DomainName string //OpenStack - Username string //OpenStack Esxi ZStack - Password string //OpenStack Esxi ZStack - AuthUrl string //OpenStack ZStack + // 账号所在的项目 + ProjectName string `json:"project_name"` - AccessKeyId string //Huawei Aliyun Ucloud Aws - AccessKeySecret string //Huawei Aliyun Ucloud Aws - Environment string //Huawei Azure Aws + // 账号所在的域 + // default: Default + DomainName string `json:"domain_name"` - DirectoryId string //Azure - ClientId string //Azure - ClientSecret string //Azure + // 用户名 + Username string `json:"username"` - Host string //Esxi - Port int //Esxi + // 密码 + Password string `json:"password"` - Endpoint string + // 认证地址 + AuthUrl string `json:"auto_url"` - AppId string //Qcloud - SecretId string //Qcloud - SecretKey string //Qcloud + // 秘钥id + AccessKeyId string `json:"access_key_id"` - ClientEmail string //Google - ProjectId string //Google - PrivateKeyId string //Google - PrivateKey string //Google + // 秘钥key + AccessKeySecret string `json:"access_key_secret"` + + // 环境 + Environment string `json:"environment"` + + // 目录ID + DirectoryId string `json:"directory_id"` + + // 客户端ID + ClientId string `json:"client_id"` + + // 客户端秘钥 + ClientSecret string `json:"client_secret"` + + // 主机IP + Host string `json:"host"` + + // 主机端口 + Port int `json:"port"` + + // 端点 + Endpoint string `json:"endpoint"` + + // app id + AppId string `json:"app_id"` + + //秘钥ID + SecretId string `json:"secret_id"` + + //秘钥key + SecretKey string `json:"secret_key"` + + // Google服务账号email + ClientEmail string `json:"client_email"` + // Google服务账号project id + ProjectId string `json:"project_id"` + // Google服务账号秘钥id + PrivateKeyId string `json:"private_key_id"` + // Google服务账号秘钥 + PrivateKey string `json:"private_key"` } type SCloudaccount struct { - Account string - Secret string - AccessUrl string + // 账号信息,各个平台字段不尽相同,以下是各个平台账号创建所需要的字段 + // + // + // + // | 云平台 |字段 | 翻译 | 是否必传 | 默认值 | 可否更新 | 获取方式 | + // | ------ |------ | ------ | --------- | -------- |-------- |-------- | + // |Aliyun |access_key_id |秘钥ID | 是 | | 是 | | + // |Aliyun |access_key_secret |秘钥Key | 是 | | 是 | | + // |Qcloud |app_id |APP ID | 是 | | 否 | | + // |Qcloud |secret_id |秘钥ID | 是 | | 是 | | + // |Qcloud |secret_key |秘钥Key | 是 | | 是 | | + // |OpenStack |project_name |用户所在项目 | 是 | | 是 | | + // |OpenStack |username |用户名 | 是 | | 是 | | + // |OpenStack |password |用户密码 | 是 | | 是 | | + // |OpenStack |auth_url |认证地址 | 是 | | 否 | | + // |OpenStack |domain_name |用户所在的域 | 否 |Default | 是 | | + // |VMware |username |用户名 | 是 | | 是 | | + // |VMware |password |密码 | 是 | | 是 | | + // |VMware |host |主机IP或域名 | 是 | | 否 | | + // |VMware |port |主机端口 | 否 |443 | 否 | | + // |Azure |directory_id |目录ID | 是 | | 否 | | + // |Azure |environment |区域 | 是 | | 否 | | + // |Azure |client_id |客户端ID | 是 | | 是 | | + // |Azure |client_secret |客户端密码 | 是 | | 是 | | + // |Huawei |access_key_id |秘钥ID | 是 | | 是 | | + // |Huawei |access_key_secret |秘钥 | 是 | | 是 | | + // |Huawei |environment |区域 | 是 | | 否 | | + // |Aws |access_key_id |秘钥ID | 是 | | 是 | | + // |Aws |access_key_secret |秘钥 | 是 | | 是 | | + // |Aws |environment |区域 | 是 | | 否 | | + // |Ucloud |access_key_id |秘钥ID | 是 | | 是 | | + // |Ucloud |access_key_secret |秘钥 | 是 | | 是 | | + // |Google |project_id |项目ID | 是 | | 否 | | + // |Google |client_email |客户端email | 是 | | 否 | | + // |Google |private_key_id |秘钥ID | 是 | | 是 | | + // |Google |private_key |秘钥Key | 是 | | 是 | | + Account string `json:"account"` + + // swagger:ignore + Secret string + + // 认证地址 + AccessUrl string `json:"access_url"` } type ICloudProviderFactory interface { diff --git a/pkg/compute/models/dbinstance_accounts.go b/pkg/compute/models/dbinstance_accounts.go index f6dde18f7e..6a8c5824ce 100644 --- a/pkg/compute/models/dbinstance_accounts.go +++ b/pkg/compute/models/dbinstance_accounts.go @@ -194,17 +194,7 @@ func (manager *SDBInstanceAccountManager) FilterByParentId(q *sqlchemy.SQuery, p return q } -func (manager *SDBInstanceAccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - input := &api.SDBInstanceAccountCreateInput{} - instanceV := validators.NewModelIdOrNameValidator("dbinstance", "dbinstance", userCred) - err := instanceV.Validate(data) - if err != nil { - return nil, err - } - err = data.Unmarshal(input) - if err != nil { - return nil, httperrors.NewInputParameterError("Unmarshal input params error: %v", err) - } +func (manager *SDBInstanceAccountManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceAccountCreateInput) (*jsonutils.JSONDict, error) { if len(input.Password) > 0 { if !seclib2.MeetComplxity(input.Password) { return nil, httperrors.NewWeakPasswordError() @@ -212,7 +202,25 @@ func (manager *SDBInstanceAccountManager) ValidateCreateData(ctx context.Context } else { input.Password = seclib2.RandomPassword2(12) } - instance := instanceV.Model.(*SDBInstance) + + for _, instance := range []string{input.DBInstance, input.DBInstanceId} { + if len(instance) > 0 { + input.DBInstance = instance + break + } + } + if len(input.DBInstance) == 0 { + return nil, httperrors.NewMissingParameterError("dbinstance") + } + _instance, err := DBInstanceManager.FetchByIdOrName(userCred, input.DBInstance) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found dbinstance %s", input.DBInstance) + } + return nil, httperrors.NewGeneralError(errors.Wrap(err, "DBInstanceManager.FetchByIdOrName")) + } + instance := _instance.(*SDBInstance) + input.DBInstanceId = instance.Id if instance.Status != api.DBINSTANCE_RUNNING { return nil, httperrors.NewInputParameterError("DBInstance %s(%s) status is %s require status is %s", instance.Name, instance.Id, instance.Status, api.DBINSTANCE_RUNNING) } @@ -231,6 +239,12 @@ func (manager *SDBInstanceAccountManager) ValidateCreateData(ctx context.Context if err != nil { return nil, err } + + input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput) + if err != nil { + return nil, err + } + return input.JSON(input), nil } @@ -257,7 +271,7 @@ func (self *SDBInstanceAccount) GetPassword() (string, error) { func (self *SDBInstanceAccount) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { self.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data) - input := &api.SDBInstanceAccountCreateInput{} + input := &api.DBInstanceAccountCreateInput{} data.Unmarshal(input) self.savePassword(input.Password) self.StartDBInstanceAccountCreateTask(ctx, userCred, data.(*jsonutils.JSONDict), "") diff --git a/pkg/compute/models/dbinstance_backups.go b/pkg/compute/models/dbinstance_backups.go index 788e1a8c3a..13bde172b4 100644 --- a/pkg/compute/models/dbinstance_backups.go +++ b/pkg/compute/models/dbinstance_backups.go @@ -122,26 +122,34 @@ func (manager *SDBInstanceBackupManager) ListItemFilter(ctx context.Context, q * }) } -func (manager *SDBInstanceBackupManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - instanceV := validators.NewModelIdOrNameValidator("dbinstance", "dbinstance", userCred) - err := instanceV.Validate(data) - if err != nil { - return nil, err +func (manager *SDBInstanceBackupManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceBackupCreateInput) (*jsonutils.JSONDict, error) { + for _, instance := range []string{input.DBInstance, input.DBInstanceId} { + if len(instance) > 0 { + input.DBInstance = instance + break + } } - input := &api.SDBInstanceBackupCreateInput{} - err = data.Unmarshal(input) - if err != nil { - return nil, httperrors.NewInputParameterError("Failed to unmarshal input params: %v", err) + if len(input.DBInstance) == 0 { + return nil, httperrors.NewMissingParameterError("dbinstance") } + _instance, err := DBInstanceManager.FetchByIdOrName(userCred, input.DBInstance) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found dbinstance %s", input.DBInstance) + } + return nil, httperrors.NewGeneralError(errors.Wrap(err, "DBInstanceManager.FetchByIdOrName")) + } + instance := _instance.(*SDBInstance) + input.DBInstanceId = instance.Id input.BackupMode = api.BACKUP_MODE_MANUAL input.DBNames = strings.Join(input.Databases, ",") - instance := instanceV.Model.(*SDBInstance) - if instance.Status != api.DBINSTANCE_RUNNING { - return nil, httperrors.NewInputParameterError("DBInstance %s(%s) status is %s require status is %s", instance.Name, instance.Id, instance.Status, api.DBINSTANCE_RUNNING) - } input.Engine = instance.Engine input.EngineVersion = instance.EngineVersion input.ManagerId = instance.ManagerId + + if instance.Status != api.DBINSTANCE_RUNNING { + return nil, httperrors.NewInputParameterError("DBInstance %s(%s) status is %s require status is %s", instance.Name, instance.Id, instance.Status, api.DBINSTANCE_RUNNING) + } region := instance.GetRegion() if region == nil { return nil, httperrors.NewInputParameterError("failed to found region for dbinstance %s(%s)", instance.Name, instance.Id) @@ -152,6 +160,11 @@ func (manager *SDBInstanceBackupManager) ValidateCreateData(ctx context.Context, return nil, err } + input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput) + if err != nil { + return nil, err + } + return input.JSON(input), nil } diff --git a/pkg/compute/models/dbinstance_databases.go b/pkg/compute/models/dbinstance_databases.go index e00e1d5c73..8593887b99 100644 --- a/pkg/compute/models/dbinstance_databases.go +++ b/pkg/compute/models/dbinstance_databases.go @@ -16,6 +16,7 @@ package models import ( "context" + "database/sql" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -157,19 +158,26 @@ func (manager *SDBInstanceDatabaseManager) FilterByParentId(q *sqlchemy.SQuery, return q } -func (manager *SDBInstanceDatabaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - instanceV := validators.NewModelIdOrNameValidator("dbinstance", "dbinstance", userCred) - err := instanceV.Validate(data) - if err != nil { - return nil, err +func (manager *SDBInstanceDatabaseManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceDatabaseCreateInput) (*jsonutils.JSONDict, error) { + for _, instance := range []string{input.DBInstance, input.DBInstanceId} { + if len(instance) > 0 { + input.DBInstance = instance + break + } } + if len(input.DBInstance) == 0 { + return nil, httperrors.NewMissingParameterError("dbinstance") + } + _instance, err := DBInstanceManager.FetchByIdOrName(userCred, input.DBInstance) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found dbinstance %s", input.DBInstance) + } + return nil, httperrors.NewGeneralError(errors.Wrap(err, "DBInstanceManager.FetchByIdOrName")) + } + instance := _instance.(*SDBInstance) + input.DBInstanceId = instance.Id - input := &api.SDBInstanceDatabaseCreateInput{} - err = data.Unmarshal(input) - if err != nil { - return nil, httperrors.NewInputParameterError("Failed to unmarshal input params: %v", err) - } - instance := instanceV.Model.(*SDBInstance) if instance.Status != api.DBINSTANCE_RUNNING { return nil, httperrors.NewInputParameterError("DBInstance %s(%s) status is %s require status is %s", instance.Name, instance.Id, instance.Status, api.DBINSTANCE_RUNNING) } @@ -190,6 +198,11 @@ func (manager *SDBInstanceDatabaseManager) ValidateCreateData(ctx context.Contex return nil, err } + input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput) + if err != nil { + return nil, err + } + return input.JSON(input), nil } diff --git a/pkg/compute/models/dbinstances.go b/pkg/compute/models/dbinstances.go index aa5752d8d1..e6463600e8 100644 --- a/pkg/compute/models/dbinstances.go +++ b/pkg/compute/models/dbinstances.go @@ -153,7 +153,8 @@ func (man *SDBInstanceManager) ListItemFilter(ctx context.Context, q *sqlchemy.S return q, nil } -func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { +func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.DBInstanceCreateInput) (*jsonutils.JSONDict, error) { + data := input.JSON(input) networkV := validators.NewModelIdOrNameValidator("network", "network", ownerId) addressV := validators.NewIPv4AddrValidator("address") secgroupV := validators.NewModelIdOrNameValidator("secgroup", "secgroup", ownerId) @@ -177,7 +178,6 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred } } - input := &api.SDBInstanceCreateInput{} err := data.Unmarshal(input) if err != nil { return nil, errors.Wrapf(err, "Unmarshal input failed: %v", err) @@ -221,13 +221,13 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred } } - if duration, _ := data.GetString("duration"); len(duration) > 0 { - billingCycle, err := billing.ParseBillingCycle(duration) + if len(input.Duration) > 0 { + billingCycle, err := billing.ParseBillingCycle(input.Duration) if err != nil { - return nil, httperrors.NewInputParameterError("invalid duration %s", duration) + return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration) } if !region.GetDriver().IsSupportedBillingCycle(billingCycle, man.KeywordPlural()) { - return nil, httperrors.NewInputParameterError("unsupported duration %s", duration) + return nil, httperrors.NewInputParameterError("unsupported duration %s", input.Duration) } input.BillingType = billing_api.BILLING_TYPE_PREPAID input.BillingCycle = billingCycle.String() @@ -305,6 +305,11 @@ func (man *SDBInstanceManager) ValidateCreateData(ctx context.Context, userCred input.VmemSizeMb = skus[0].VmemSizeMb } + input.VirtualResourceCreateInput, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput) + if err != nil { + return nil, err + } + input, err = region.GetDriver().ValidateCreateDBInstanceData(ctx, userCred, ownerId, input, skus, network) if err != nil { return nil, err diff --git a/pkg/compute/models/disks.go b/pkg/compute/models/disks.go index 61ca229ef7..24d0d42b6b 100644 --- a/pkg/compute/models/disks.go +++ b/pkg/compute/models/disks.go @@ -35,7 +35,6 @@ import ( billing_api "yunion.io/x/onecloud/pkg/apis/billing" api "yunion.io/x/onecloud/pkg/apis/compute" imageapi "yunion.io/x/onecloud/pkg/apis/image" - "yunion.io/x/onecloud/pkg/cloudcommon/cmdline" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" @@ -434,13 +433,10 @@ func diskCreateInput2ComputeQuotaKeys(input api.DiskCreateInput, ownerId mcclien return keys } -func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - input, err := cmdline.FetchDiskCreateInputByJSON(data) - if err != nil { - return nil, httperrors.NewInputParameterError("parse disk input: %v", err) - } +func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, oinput api.DiskCreateInput) (*jsonutils.JSONDict, error) { + input := &oinput diskConfig := input.DiskConfig - diskConfig, err = parseDiskInfo(ctx, userCred, diskConfig) + diskConfig, err := parseDiskInfo(ctx, userCred, diskConfig) if err != nil { return nil, err } diff --git a/pkg/compute/models/elasticips.go b/pkg/compute/models/elasticips.go index cf8d25af13..d7820f39d6 100644 --- a/pkg/compute/models/elasticips.go +++ b/pkg/compute/models/elasticips.go @@ -27,7 +27,6 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -679,59 +678,62 @@ func (manager *SElasticipManager) getEipByExtEip(ctx context.Context, userCred m return manager.newFromCloudEip(ctx, userCred, extEip, provider, region, syncOwnerId) } -func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - regionStr := jsonutils.GetAnyString(data, []string{"region", "region_id"}) - if len(regionStr) == 0 { - return nil, httperrors.NewMissingParameterError("region_id") +func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SElasticipCreateInput) (*jsonutils.JSONDict, error) { + for _, cloudregion := range []string{input.Cloudregion, input.Region, input.RegionId} { + if len(cloudregion) > 0 { + input.Cloudregion = cloudregion + break + } } - _region, err := CloudregionManager.FetchByIdOrName(nil, regionStr) + if len(input.Cloudregion) == 0 { + return nil, httperrors.NewMissingParameterError("cloudregion") + } + _region, err := CloudregionManager.FetchByIdOrName(nil, input.Cloudregion) if err != nil { if err != sql.ErrNoRows { return nil, httperrors.NewGeneralError(err) } else { - return nil, httperrors.NewResourceNotFoundError("Region %s not found", regionStr) + return nil, httperrors.NewResourceNotFoundError("Region %s not found", input.Cloudregion) } } region := _region.(*SCloudregion) - data.Add(jsonutils.NewString(region.GetId()), "cloudregion_id") + input.CloudregionId = region.GetId() - managerStr := jsonutils.GetAnyString(data, []string{"manager", "manager_id"}) - if len(managerStr) == 0 { - return nil, httperrors.NewMissingParameterError("manager_id") + for _, cloudprovider := range []string{input.Cloudprovider, input.Manager, input.ManagerId} { + if len(cloudprovider) > 0 { + input.Cloudprovider = cloudprovider + break + } + } + if len(input.Cloudprovider) == 0 { + return nil, httperrors.NewMissingParameterError("cloudprovider") } - providerObj, err := CloudproviderManager.FetchByIdOrName(nil, managerStr) + providerObj, err := CloudproviderManager.FetchByIdOrName(nil, input.Cloudprovider) if err != nil { if err != sql.ErrNoRows { return nil, httperrors.NewGeneralError(err) } else { - return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", managerStr) + return nil, httperrors.NewResourceNotFoundError("Cloud provider %s not found", input.Cloudprovider) } } provider := providerObj.(*SCloudprovider) - data.Add(jsonutils.NewString(provider.Id), "manager_id") + input.ManagerId = provider.Id - chargeType := jsonutils.GetAnyString(data, []string{"charge_type"}) - if len(chargeType) == 0 { - chargeType = api.EIP_CHARGE_TYPE_DEFAULT + if len(input.ChargeType) == 0 { + input.ChargeType = api.EIP_CHARGE_TYPE_DEFAULT } - if !utils.IsInStringArray(chargeType, []string{api.EIP_CHARGE_TYPE_BY_BANDWIDTH, api.EIP_CHARGE_TYPE_BY_TRAFFIC}) { - return nil, httperrors.NewInputParameterError("charge type %s not supported", chargeType) + if !utils.IsInStringArray(input.ChargeType, []string{api.EIP_CHARGE_TYPE_BY_BANDWIDTH, api.EIP_CHARGE_TYPE_BY_TRAFFIC}) { + return nil, httperrors.NewInputParameterError("charge type %s not supported", input.ChargeType) } - data.Add(jsonutils.NewString(chargeType), "charge_type") - - input := apis.VirtualResourceCreateInput{} - err = data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal VirtualResourceCreateInput fail %s", err) - } - input, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) + + err = region.GetDriver().ValidateCreateEipData(ctx, userCred, &input) //避免参数重名后还有pending.eip残留 eipPendingUsage := &SRegionQuota{Eip: 1} @@ -742,7 +744,7 @@ func (manager *SElasticipManager) ValidateCreateData(ctx context.Context, userCr return nil, err } - return region.GetDriver().ValidateCreateEipData(ctx, userCred, data) + return input.JSON(input), nil } func (eip *SElasticip) GetQuotaKeys() (quotas.IQuotaKeys, error) { diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index 3a9d49071c..fdbc25e4f0 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1308,8 +1308,8 @@ func (manager *SGuestManager) BatchCreateValidateCreateData(ctx context.Context, } // 创建虚拟机实例 -func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - input, err := manager.validateCreateData(ctx, userCred, ownerId, query, data) +func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, oinput api.ServerCreateInput) (*jsonutils.JSONDict, error) { + input, err := manager.validateCreateData(ctx, userCred, ownerId, query, oinput.JSON(oinput)) if err != nil { return nil, err } diff --git a/pkg/compute/models/keypairs.go b/pkg/compute/models/keypairs.go index da33bf8331..639644f828 100644 --- a/pkg/compute/models/keypairs.go +++ b/pkg/compute/models/keypairs.go @@ -20,11 +20,11 @@ import ( "golang.org/x/crypto/ssh" "yunion.io/x/jsonutils" - "yunion.io/x/log" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" + api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -144,59 +144,44 @@ func (self *SKeypair) GetLinkedGuestsCount() (int, error) { return GuestManager.Query().Equals("keypair_id", self.Id).CountWithError() } -func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - publicKey, _ := data.GetString("public_key") - if len(publicKey) == 0 { - scheme, _ := data.GetString("scheme") - if len(scheme) > 0 { - if !utils.IsInStringArray(scheme, []string{"RSA", "DSA"}) { - return nil, httperrors.NewInputParameterError("Unsupported scheme %s", scheme) - } - } else { - scheme = "RSA" +func (manager *SKeypairManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.KeypairCreateInput) (*jsonutils.JSONDict, error) { + if len(input.PublicKey) == 0 { + if len(input.Scheme) == 0 { + input.Scheme = api.KEYPAIRE_SCHEME_RSA } - var privKey, pubKey string + if !utils.IsInStringArray(input.Scheme, api.KEYPAIR_SCHEMAS) { + return nil, httperrors.NewInputParameterError("Unsupported scheme %s", input.Scheme) + } + var err error - if scheme == "RSA" { - privKey, pubKey, err = seclib2.GenerateRSASSHKeypair() + if input.Scheme == api.KEYPAIRE_SCHEME_RSA { + input.PrivateKey, input.PublicKey, err = seclib2.GenerateRSASSHKeypair() } else { - privKey, pubKey, err = seclib2.GenerateDSASSHKeypair() + input.PrivateKey, input.PublicKey, err = seclib2.GenerateDSASSHKeypair() } if err != nil { - log.Errorf("fail to generate ssh keypair %s", err) - return nil, httperrors.NewGeneralError(err) + return nil, httperrors.NewGeneralError(errors.Wrapf(err, "Generate%sSSHKeypair", input.Scheme)) } - publicKey = pubKey - data.Set("public_key", jsonutils.NewString(pubKey)) - data.Set("private_key", jsonutils.NewString(privKey)) } - pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey)) + pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(input.PublicKey)) if err != nil { - log.Errorf("invalid public key %s", err) - return nil, httperrors.NewInputParameterError("invalid public") + return nil, httperrors.NewInputParameterError("invalid public error: %v", err) } // 只允许上传RSA格式密钥。PS: AWS只支持RSA格式。 scheme := seclib2.GetPublicKeyScheme(pubKey) - if scheme != "RSA" { + if scheme != api.KEYPAIRE_SCHEME_RSA { return nil, httperrors.NewInputParameterError("Unsupported scheme %s", scheme) } - data.Set("fingerprint", jsonutils.NewString(ssh.FingerprintLegacyMD5(pubKey))) - data.Set("scheme", jsonutils.NewString(scheme)) - data.Set("owner_id", jsonutils.NewString(userCred.GetUserId())) + input.Fingerprint = ssh.FingerprintLegacyMD5(pubKey) + input.OwnerId = userCred.GetUserId() - input := apis.StandaloneResourceCreateInput{} - err = data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StandaloneRes ourceCreateInput fail %s", err) - } - input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + return input.JSON(input), nil } func (self *SKeypair) ValidateDeleteCondition(ctx context.Context) error { diff --git a/pkg/compute/models/regiondrivers.go b/pkg/compute/models/regiondrivers.go index 00afa2b6f9..d4fc1e3198 100644 --- a/pkg/compute/models/regiondrivers.go +++ b/pkg/compute/models/regiondrivers.go @@ -86,7 +86,7 @@ type IRegionDriver interface { RequestDeleteLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *SLoadbalancerListenerRule, task taskman.ITask) error ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) - ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) + ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error // Region Driver Snapshot Policy Apis //ValidateCreateSnapshotPolicyData(context.Context, mcclient.TokenCredential, *compute.SSnapshotPolicyCreateInput, mcclient.IIdentityProvider, *jsonutils.JSONDict) error @@ -100,7 +100,7 @@ type IRegionDriver interface { // Region Driver Snapshot Apis ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error - ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, storage *SStorage, input *api.SSnapshotCreateInput) error + ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, storage *SStorage, input *api.SnapshotCreateInput) error RequestCreateSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error RequestDeleteSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error SnapshotIsOutOfChain(disk *SDisk) bool @@ -128,10 +128,10 @@ type IRegionDriver interface { } type IDBInstanceDriver interface { - ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.SDBInstanceCreateInput, skus []SDBInstanceSku, network *SNetwork) (*api.SDBInstanceCreateInput, error) - ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input *api.SDBInstanceAccountCreateInput) (*api.SDBInstanceAccountCreateInput, error) - ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input *api.SDBInstanceDatabaseCreateInput) (*api.SDBInstanceDatabaseCreateInput, error) - ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input *api.SDBInstanceBackupCreateInput) (*api.SDBInstanceBackupCreateInput, error) + ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []SDBInstanceSku, network *SNetwork) (api.DBInstanceCreateInput, error) + ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) + ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) + ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, input *api.SDBInstanceChangeConfigInput) error ValidateDBInstanceAccountPrivilege(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, account string, privilege string) error ValidateResetDBInstancePassword(ctx context.Context, userCred mcclient.TokenCredential, instance *SDBInstance, account string) error diff --git a/pkg/compute/models/schedtags.go b/pkg/compute/models/schedtags.go index 3eb184157b..29ae3f3b5d 100644 --- a/pkg/compute/models/schedtags.go +++ b/pkg/compute/models/schedtags.go @@ -25,7 +25,6 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/httperrors" @@ -187,39 +186,33 @@ func validateDefaultStrategy(defStrategy string) error { return nil } -func (manager *SSchedtagManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - defStrategy, _ := data.GetString("default_strategy") - if len(defStrategy) > 0 { - err := validateDefaultStrategy(defStrategy) +func (manager *SSchedtagManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.SchedtagCreateInput) (*jsonutils.JSONDict, error) { + if len(input.DefaultStrategy) > 0 { + err := validateDefaultStrategy(input.DefaultStrategy) if err != nil { return nil, err } } // set resourceType to hosts if not provided by client - resourceType, _ := data.GetString("resource_type") - if resourceType == "" { - resourceType = HostManager.KeywordPlural() - data.Set("resource_type", jsonutils.NewString(resourceType)) + if input.ResourceType == "" { + input.ResourceType = HostManager.KeywordPlural() } - if !utils.IsInStringArray(resourceType, manager.GetResourceTypes()) { - return nil, httperrors.NewInputParameterError("Not support resource_type %s", resourceType) + if !utils.IsInStringArray(input.ResourceType, manager.GetResourceTypes()) { + return nil, httperrors.NewInputParameterError("Not support resource_type %s", input.ResourceType) } - data, err := manager.SScopedResourceBaseManager.ValidateCreateData(manager, ctx, userCred, ownerId, query, data) + + var err error + input.ScopedResourceCreateInput, err = manager.SScopedResourceBaseManager.ValidateCreateData(manager, ctx, userCred, ownerId, query, input.ScopedResourceCreateInput) if err != nil { return nil, err } - input := apis.StandaloneResourceCreateInput{} - err = data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err) - } - input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + + return input.JSON(input), nil } func (manager *SSchedtagManager) GetResourceSchedtags(resType string) ([]SSchedtag, error) { diff --git a/pkg/compute/models/skus.go b/pkg/compute/models/skus.go index 8eb7a4304e..1baed782b6 100644 --- a/pkg/compute/models/skus.go +++ b/pkg/compute/models/skus.go @@ -33,7 +33,6 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -302,96 +301,78 @@ func (manager *SServerSkuManager) AllowCreateItem(ctx context.Context, userCred return db.IsAdminAllowCreate(userCred, manager) } -func (self *SServerSkuManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - enabledV := validators.NewBoolValidator("enabled") - regionV := validators.NewModelIdOrNameValidator("cloudregion", "cloudregion", ownerId) - zoneV := validators.NewModelIdOrNameValidator("zone", "zone", ownerId) - cpuV := validators.NewRangeValidator("cpu_core_count", 1, 256) - memV := validators.NewRangeValidator("memory_size_mb", 512, 1024*512) - categoryV := validators.NewStringChoicesValidator("instance_type_category", api.SKU_FAMILIES) - keyV := map[string]validators.IValidator{ - "enabled": enabledV.Default(true), - "region": regionV.Optional(true), - "zone": zoneV.Optional(true), - "cpu_core_count": cpuV, - "memory_size_mb": memV, - "instance_type_category": categoryV.Default(api.SkuCategoryGeneralPurpose), +func (self *SServerSkuManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.ServerSkuCreateInput) (*jsonutils.JSONDict, error) { + if len(input.Cloudregion) == 0 { + input.Cloudregion = api.DEFAULT_REGION_ID } - - for _, v := range keyV { - err := v.Validate(data) - if err != nil { - return nil, err + region, err := CloudregionManager.FetchByIdOrName(nil, input.Cloudregion) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found cloudregion %s", input.Cloudregion) } + return nil, httperrors.NewGeneralError(err) } + input.CloudregionId = region.GetId() - provider, _ := data.GetString("provider") - brand, _ := data.GetString("brand") - if (len(provider) == 0 && len(brand) == 0) || provider == api.CLOUD_PROVIDER_ONECLOUD || brand == api.ONECLOUD_BRAND_ONECLOUD { - provider = api.CLOUD_PROVIDER_ONECLOUD - brand = api.ONECLOUD_BRAND_ONECLOUD - } else if len(brand) > 0 { - q := CloudaccountManager.Query().Equals("brand", brand).IsFalse("is_public_cloud").IsFalse("is_on_premise") - cloudaccounts := []SCloudaccount{} - err := db.FetchModelObjects(CloudaccountManager, q, &cloudaccounts) + if len(input.Zone) > 0 { + zone, err := ZoneManager.FetchByIdOrName(nil, input.Zone) if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found zone %s", input.Zone) + } return nil, httperrors.NewGeneralError(err) } - if len(cloudaccounts) == 0 { - return nil, httperrors.NewInputParameterError("Not support brand %s or not import %s cloudaccount", brand, brand) - } - if len(provider) > 0 && provider != cloudaccounts[0].Provider { - return nil, httperrors.NewInputParameterError("") - } - provider = cloudaccounts[0].Provider - } else if len(provider) > 0 { - q := CloudaccountManager.Query().Equals("provider", provider).IsFalse("is_public_cloud").IsFalse("is_on_premise") - cloudaccounts := []SCloudaccount{} - err := db.FetchModelObjects(CloudaccountManager, q, &cloudaccounts) - if err != nil { - return nil, httperrors.NewGeneralError(err) - } - if len(cloudaccounts) == 0 { - return nil, httperrors.NewInputParameterError("Not support provider %s or not import %s cloudaccount", provider, provider) - } - brand = provider + input.ZoneId = zone.GetId() } - data.Set("provider", jsonutils.NewString(provider)) - data.Set("brand", jsonutils.NewString(brand)) - data.Set("status", jsonutils.NewString(api.SkuStatusReady)) - family := api.InstanceFamilies[categoryV.Value] - data.Add(jsonutils.NewString(categoryV.Value), "local_category") - data.Set("instance_type_family", jsonutils.NewString(family)) + if input.CpuCoreCount < 1 || input.CpuCoreCount > 256 { + return nil, httperrors.NewOutOfRangeError("cpu_core_count should be range of 1~256") + } - if !data.Contains("name") { + if input.MemorySizeMB < 512 || input.MemorySizeMB > 1024*512 { + return nil, httperrors.NewOutOfRangeError("memory_size_mb, shoud be range of 512~%d", 1024*512) + } + + if len(input.InstanceTypeCategory) == 0 { + input.InstanceTypeCategory = api.SkuCategoryGeneralPurpose + } + + if !utils.IsInStringArray(input.InstanceTypeCategory, api.SKU_FAMILIES) { + return nil, httperrors.NewInputParameterError("instance_type_category shoud be one of %s", api.SKU_FAMILIES) + } + + if input.Enabled == nil { + enabled := true + input.Enabled = &enabled + } + + input.Provider = api.CLOUD_PROVIDER_ONECLOUD + input.Status = api.SkuStatusReady + + input.LocalCategory = input.InstanceTypeCategory + input.InstanceTypeFamily = api.InstanceFamilies[input.InstanceTypeCategory] + + if len(input.Name) == 0 { // 格式 ecs.g1.c1m1 - name, err := genInstanceType(family, cpuV.Value, memV.Value) + input.Name, err = genInstanceType(input.InstanceTypeFamily, input.CpuCoreCount, input.MemorySizeMB) if err != nil { return nil, httperrors.NewInputParameterError(err.Error()) } - q := self.Query().Equals("name", name) + q := self.Query().Equals("name", input.Name) count, err := q.CountWithError() if err != nil { return nil, httperrors.NewGeneralError(fmt.Errorf("checkout server sku name duplicate error: %v", err)) } if count > 0 { - return nil, httperrors.NewDuplicateResourceError("Duplicate sku %s", name) + return nil, httperrors.NewDuplicateResourceError("Duplicate sku %s", input.Name) } - data.Set("name", jsonutils.NewString(name)) } - input := apis.StatusStandaloneResourceCreateInput{} - err := data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StatusStandaloneResourceCreateInput fail %s", err) - } - input, err = self.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + input.StatusStandaloneResourceCreateInput, err = self.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + return input.JSON(input), nil } func (self *SServerSku) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) { diff --git a/pkg/compute/models/snapshots.go b/pkg/compute/models/snapshots.go index 6b1f534274..65b11294ef 100644 --- a/pkg/compute/models/snapshots.go +++ b/pkg/compute/models/snapshots.go @@ -33,7 +33,6 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" - "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/httperrors" @@ -222,22 +221,27 @@ func (manager *SSnapshotManager) ValidateCreateData( userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, - input api.SSnapshotCreateInput, -) (api.SSnapshotCreateInput, error) { - data := jsonutils.Marshal(input).(*jsonutils.JSONDict) - - diskV := validators.NewModelIdOrNameValidator("disk", "disk", ownerId) - err := diskV.Validate(data) - if err != nil { - return input, err + input api.SnapshotCreateInput, +) (*jsonutils.JSONDict, error) { + for _, disk := range []string{input.Disk, input.DiskId} { + if len(disk) > 0 { + input.Disk = disk + break + } + } + if len(input.Disk) == 0 { + return nil, httperrors.NewMissingParameterError("disk") } - err = data.Unmarshal(&input) + _disk, err := DiskManager.FetchByIdOrName(userCred, input.Disk) if err != nil { - return input, httperrors.NewInputParameterError("failed to unmarshal input params: %v", err) + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found disk %s", input.Disk) + } + return nil, httperrors.NewGeneralError(errors.Wrap(err, "DiskManager.FetchByIdOrName")) } - - disk := diskV.Model.(*SDisk) + disk := _disk.(*SDisk) + input.DiskId = disk.Id input.DiskType = disk.DiskType input.Size = disk.DiskSize @@ -248,33 +252,38 @@ func (manager *SSnapshotManager) ValidateCreateData( input.ManagerId = storage.ManagerId region := storage.GetRegion() if region == nil { - return input, httperrors.NewInputParameterError("failed to found region for disk's storage %s(%s)", storage.Name, storage.Id) + return nil, httperrors.NewInputParameterError("failed to found region for disk's storage %s(%s)", storage.Name, storage.Id) } input.CloudregionId = region.Id driver, err := storage.GetRegionDriver() if err != nil { - return input, err + return nil, errors.Wrap(err, "storage.GetRegionDriver") } input.OutOfChain = driver.SnapshotIsOutOfChain(disk) err = driver.ValidateCreateSnapshotData(ctx, userCred, disk, storage, &input) if err != nil { - return input, err + return nil, errors.Wrap(err, "driver.ValidateCreateSnapshotData") + } + + input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput) + if err != nil { + return nil, err } pendingUsage := &SRegionQuota{Snapshot: 1} keys, err := disk.GetQuotaKeys() if err != nil { - return input, err + return nil, err } pendingUsage.SetKeys(keys.(SComputeResourceKeys).SRegionalCloudResourceKeys) err = quotas.CheckSetPendingQuota(ctx, userCred, pendingUsage) if err != nil { - return input, err + return nil, err } - return input, nil + return input.JSON(input), nil } func (self *SSnapshot) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error { diff --git a/pkg/compute/models/storagedrivers.go b/pkg/compute/models/storagedrivers.go index c2bf0a2bfd..f342d9c038 100644 --- a/pkg/compute/models/storagedrivers.go +++ b/pkg/compute/models/storagedrivers.go @@ -27,7 +27,7 @@ import ( type IStorageDriver interface { GetStorageType() string - ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) + ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, storage *SStorage) (*jsonutils.JSONDict, error) DoStorageUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, task taskman.ITask) error @@ -35,7 +35,7 @@ type IStorageDriver interface { PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, data jsonutils.JSONObject) ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error - ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, input *api.SSnapshotCreateInput) error + ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, input *api.SnapshotCreateInput) error RequestCreateSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error RequestDeleteSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error SnapshotIsOutOfChain(disk *SDisk) bool diff --git a/pkg/compute/models/storages.go b/pkg/compute/models/storages.go index 8bd209fa49..2e9e891223 100644 --- a/pkg/compute/models/storages.go +++ b/pkg/compute/models/storages.go @@ -28,7 +28,6 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -173,47 +172,40 @@ func (manager *SStorageManager) GetStorageTypesByHostType(hostType string) ([]st return storages, nil } -func (manager *SStorageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - storageType, _ := data.GetString("storage_type") - mediumType, _ := data.GetString("medium_type") - - if !utils.IsInStringArray(storageType, api.STORAGE_TYPES) { - return nil, httperrors.NewInputParameterError("Invalid storage type %s", storageType) +func (manager *SStorageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.StorageCreateInput) (*jsonutils.JSONDict, error) { + if !utils.IsInStringArray(input.StorageType, api.STORAGE_TYPES) { + return nil, httperrors.NewInputParameterError("Invalid storage type %s", input.StorageType) } - if !utils.IsInStringArray(mediumType, api.DISK_TYPES) { - return nil, httperrors.NewInputParameterError("Invalid medium type %s", mediumType) + if !utils.IsInStringArray(input.MediumType, api.DISK_TYPES) { + return nil, httperrors.NewInputParameterError("Invalid medium type %s", input.MediumType) } - zoneId, err := data.GetString("zone") - if err != nil { + if len(input.Zone) == 0 { return nil, httperrors.NewMissingParameterError("zone") } - zone, _ := ZoneManager.FetchByIdOrName(userCred, zoneId) - if zone == nil { - return nil, httperrors.NewResourceNotFoundError("zone %s", zoneId) + zone, err := ZoneManager.FetchByIdOrName(userCred, input.Zone) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found zone %s", input.Zone) + } + return nil, httperrors.NewGeneralError(errors.Wrap(err, "ZoneManager.FetchByIdOrName")) } - data.Set("zone_id", jsonutils.NewString(zone.GetId())) + input.ZoneId = zone.GetId() - storageDirver := GetStorageDriver(storageType) + storageDirver := GetStorageDriver(input.StorageType) if storageDirver == nil { - return nil, httperrors.NewUnsupportOperationError("Not support create %s storage", storageType) + return nil, httperrors.NewUnsupportOperationError("Not support create %s storage", input.StorageType) } - data, err = storageDirver.ValidateCreateData(ctx, userCred, data) + err = storageDirver.ValidateCreateData(ctx, userCred, &input) if err != nil { return nil, err } - input := apis.StandaloneResourceCreateInput{} - err = data.Unmarshal(&input) - if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err) - } - input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + return input.JSON(input), nil } func (self *SStorage) ValidateDeleteCondition(ctx context.Context) error { diff --git a/pkg/compute/models/wires.go b/pkg/compute/models/wires.go index 5272ac3237..54da8660d9 100644 --- a/pkg/compute/models/wires.go +++ b/pkg/compute/models/wires.go @@ -28,7 +28,6 @@ import ( "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -98,45 +97,65 @@ func (self *SWire) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenC return db.IsAdminAllowDelete(userCred, self) } -func (manager *SWireManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - keysV := []validators.IValidator{ - validators.NewNonNegativeValidator("bandwidth"), - validators.NewRangeValidator("mtu", 1, 1000000).Optional(true), +func (manager *SWireManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.WireCreateInput) (*jsonutils.JSONDict, error) { + if input.Bandwidth < 0 { + return nil, httperrors.NewOutOfRangeError("bandwidth must be greater than 0") } - for _, v := range keysV { - if err := v.Validate(data); err != nil { - return nil, err + + if input.Mtu < 0 || input.Mtu > 1000000 { + return nil, httperrors.NewOutOfRangeError("mtu must be range of 0~1000000") + } + + for _, vpc := range []string{input.Vpc, input.VpcId} { + if len(vpc) > 0 { + input.Vpc = vpc + break } } - - vpcStr := jsonutils.GetAnyString(data, []string{"vpc", "vpc_id"}) - if len(vpcStr) == 0 { - return nil, httperrors.NewMissingParameterError("vpc_id") + if len(input.Vpc) == 0 { + return nil, httperrors.NewMissingParameterError("vpc") } - if len(vpcStr) > 0 { - vpcObj, err := VpcManager.FetchByIdOrName(userCred, vpcStr) - if err != nil { - if err == sql.ErrNoRows { - return nil, httperrors.NewNotFoundError("Vpc %s not found", vpcStr) - } else { - return nil, httperrors.NewInternalServerError("Fetch Vpc %s error %s", vpcStr, err) - } - } - data.Add(jsonutils.NewString(vpcObj.GetId()), "vpc_id") - } - - input := apis.StandaloneResourceCreateInput{} - err := data.Unmarshal(&input) + _vpc, err := VpcManager.FetchByIdOrName(userCred, input.Vpc) if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StandaloneResourceCreateInput fail %s", err) + if err == sql.ErrNoRows { + return nil, httperrors.NewNotFoundError("Vpc %s not found", input.Vpc) + } else { + return nil, httperrors.NewInternalServerError("Fetch Vpc %s error %s", input.Vpc, err) + } } - input, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + vpc := _vpc.(*SVpc) + input.VpcId = vpc.Id + if len(vpc.ManagerId) > 0 { + return nil, httperrors.NewNotSupportedError("Currently only kvm platform supports creating wire") + } + + for _, zone := range []string{input.Zone, input.ZoneId} { + if len(zone) > 0 { + input.Zone = zone + break + } + } + + if len(input.Zone) == 0 { + return nil, httperrors.NewMissingParameterError("zone") + } + + zone, err := ZoneManager.FetchByIdOrName(nil, input.Zone) + if err != nil { + if err == sql.ErrNoRows { + return nil, httperrors.NewNotFoundError("Zone %s not found", input.Vpc) + } else { + return nil, httperrors.NewInternalServerError("Fetch Zone %s error %s", input.Vpc, err) + } + } + input.ZoneId = zone.GetId() + + input.StandaloneResourceCreateInput, err = manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + return input.JSON(input), nil } func (wire *SWire) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { diff --git a/pkg/compute/models/zones.go b/pkg/compute/models/zones.go index 6b6629be94..23e84fbbbc 100644 --- a/pkg/compute/models/zones.go +++ b/pkg/compute/models/zones.go @@ -24,7 +24,6 @@ import ( "yunion.io/x/pkg/util/compare" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" @@ -669,34 +668,31 @@ func (self *SZone) getMaxDataDiskCount() int { return options.Options.MaxDataDiskCount } -func (manager *SZoneManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - regionStr := jsonutils.GetAnyString(data, []string{"region", "region_id", "cloudregion", "cloudregion_id"}) - var regionId string - if len(regionStr) > 0 { - regionObj, err := CloudregionManager.FetchByIdOrName(nil, regionStr) - if err != nil { - if err == sql.ErrNoRows { - return nil, httperrors.NewResourceNotFoundError("Region %s not found", regionStr) - } else { - return nil, httperrors.NewInternalServerError("Query region %s fail %s", regionStr, err) - } +func (manager *SZoneManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.ZoneCreateInput) (*jsonutils.JSONDict, error) { + for _, cloudregion := range []string{input.Cloudregion, input.Region, input.RegionId, input.CloudregionId, "default"} { + if len(cloudregion) > 0 { + input.Cloudregion = cloudregion + break } - regionId = regionObj.GetId() - } else { - regionId = "default" } - data.Add(jsonutils.NewString(regionId), "cloudregion_id") - data.Set("status", jsonutils.NewString(api.ZONE_ENABLE)) - - input := apis.StatusStandaloneResourceCreateInput{} - err := data.Unmarshal(&input) + _region, err := CloudregionManager.FetchByIdOrName(nil, input.Cloudregion) if err != nil { - return nil, httperrors.NewInternalServerError("unmarshal StatusStandaloneResourceCreateInput fail %s", err) + if err != sql.ErrNoRows { + return nil, httperrors.NewResourceNotFoundError("failed to found cloudregion %s", input.Cloudregion) + } + return nil, httperrors.NewGeneralError(err) } - input, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input) + region := _region.(*SCloudregion) + input.CloudregionId = region.Id + input.Status = api.ZONE_ENABLE + if region.Provider != api.CLOUD_PROVIDER_ONECLOUD { + return nil, httperrors.NewNotSupportedError("not support create %s zone", region.Provider) + } + + input.StatusStandaloneResourceCreateInput, err = manager.SStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.StatusStandaloneResourceCreateInput) if err != nil { return nil, err } - data.Update(jsonutils.Marshal(input)) - return data, nil + + return input.JSON(input), nil } diff --git a/pkg/compute/regiondrivers/aliyun.go b/pkg/compute/regiondrivers/aliyun.go index 28de41ecc7..8f1a191a26 100644 --- a/pkg/compute/regiondrivers/aliyun.go +++ b/pkg/compute/regiondrivers/aliyun.go @@ -845,7 +845,7 @@ func (self *SAliyunRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context return nil } -func (self *SAliyunRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error { +func (self *SAliyunRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { if strings.HasPrefix(input.Name, "auto") || strings.HasPrefix(input.Name, "http://") || strings.HasPrefix(input.Name, "https://") { return httperrors.NewBadRequestError( "Snapshot for %s name can't start with auto, http:// or https://", self.GetProvider()) @@ -968,18 +968,18 @@ func (self *SAliyunRegionDriver) IsSecurityGroupBelongVpc() bool { return true } -func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.SDBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (*api.SDBInstanceCreateInput, error) { +func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) { if input.BillingType == billing_api.BILLING_TYPE_PREPAID && len(input.MasterInstanceId) > 0 { - return nil, httperrors.NewInputParameterError("slave dbinstance not support prepaid billing type") + return input, httperrors.NewInputParameterError("slave dbinstance not support prepaid billing type") } wire := network.GetWire() if wire == nil { - return nil, httperrors.NewGeneralError(fmt.Errorf("failed to found wire for network %s(%s)", network.Name, network.Id)) + return input, httperrors.NewGeneralError(fmt.Errorf("failed to found wire for network %s(%s)", network.Name, network.Id)) } zone := wire.GetZone() if zone == nil { - return nil, httperrors.NewGeneralError(fmt.Errorf("failed to found zone for wire %s(%s)", wire.Name, wire.Id)) + return input, httperrors.NewGeneralError(fmt.Errorf("failed to found zone for wire %s(%s)", wire.Name, wire.Id)) } match := false @@ -991,7 +991,7 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Contex } if !match { - return nil, httperrors.NewInputParameterError("failed to match any skus in the network %s(%s) zone %s(%s)", network.Name, network.Id, zone.Name, zone.Id) + return input, httperrors.NewInputParameterError("failed to match any skus in the network %s(%s) zone %s(%s)", network.Name, network.Id, zone.Name, zone.Id) } var master *models.SDBInstance @@ -1002,7 +1002,7 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Contex master = _master.(*models.SDBInstance) slaves, err = master.GetSlaveDBInstances() if err != nil { - return nil, httperrors.NewGeneralError(err) + return input, httperrors.NewGeneralError(err) } switch master.Engine { @@ -1012,49 +1012,49 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceData(ctx context.Contex break case "5.7", "8.0": if master.Category != api.ALIYUN_DBINSTANCE_CATEGORY_HA { - return nil, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s %s", master.EngineVersion, master.Category) + return input, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s %s", master.EngineVersion, master.Category) } if master.StorageType != api.ALIYUN_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD { - return nil, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s %s with storage type %s, only support %s", master.EngineVersion, master.Category, master.StorageType, api.ALIYUN_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD) + return input, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s %s with storage type %s, only support %s", master.EngineVersion, master.Category, master.StorageType, api.ALIYUN_DBINSTANCE_STORAGE_TYPE_LOCAL_SSD) } default: - return nil, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s", master.EngineVersion) + return input, httperrors.NewInputParameterError("Not support create readonly dbinstance for MySQL %s", master.EngineVersion) } case api.DBINSTANCE_TYPE_SQLSERVER: if master.Category != api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON || master.EngineVersion != "2017_ent" { - return nil, httperrors.NewInputParameterError("SQL Server only support create readonly dbinstance for 2017_ent") + return input, httperrors.NewInputParameterError("SQL Server only support create readonly dbinstance for 2017_ent") } if len(slaves) >= 7 { - return nil, httperrors.NewInputParameterError("SQL Server cannot have more than seven read-only dbinstances") + return input, httperrors.NewInputParameterError("SQL Server cannot have more than seven read-only dbinstances") } default: - return nil, httperrors.NewInputParameterError("Not support create readonly dbinstance which master dbinstance engine is", master.Engine) + return input, httperrors.NewInputParameterError("Not support create readonly dbinstance which master dbinstance engine is", master.Engine) } } switch input.Engine { case api.DBINSTANCE_TYPE_MYSQL: if input.VmemSizeMb/1024 >= 64 && len(slaves) >= 10 { - return nil, httperrors.NewInputParameterError("Master dbinstance memory ≥64GB, up to 10 read-only instances are allowed to be created") + return input, httperrors.NewInputParameterError("Master dbinstance memory ≥64GB, up to 10 read-only instances are allowed to be created") } else if input.VmemSizeMb/1024 < 64 && len(slaves) >= 5 { - return nil, httperrors.NewInputParameterError("Master dbinstance memory <64GB, up to 5 read-only instances are allowed to be created") + return input, httperrors.NewInputParameterError("Master dbinstance memory <64GB, up to 5 read-only instances are allowed to be created") } case api.DBINSTANCE_TYPE_SQLSERVER: if input.Category == api.ALIYUN_DBINSTANCE_CATEGORY_ALWAYSON { vpc := network.GetVpc() count, err := vpc.GetNetworkCount() if err != nil { - return nil, httperrors.NewGeneralError(err) + return input, httperrors.NewGeneralError(err) } if count < 2 { - return nil, httperrors.NewInputParameterError("At least two networks are required under vpc %s(%s) whith aliyun %s(%s)", vpc.Name, vpc.Id, input.Engine, input.Category) + return input, httperrors.NewInputParameterError("At least two networks are required under vpc %s(%s) whith aliyun %s(%s)", vpc.Name, vpc.Id, input.Engine, input.Category) } } } if len(input.Name) > 0 { if strings.HasPrefix(input.Description, "http://") || strings.HasPrefix(input.Description, "https://") { - return nil, httperrors.NewInputParameterError("Description can not start with http:// or https://") + return input, httperrors.NewInputParameterError("Description can not start with http:// or https://") } } @@ -1103,9 +1103,9 @@ func (self *SAliyunRegionDriver) RequestCreateDBInstanceBackup(ctx context.Conte return nil } -func (self *SAliyunRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceAccountCreateInput) (*api.SDBInstanceAccountCreateInput, error) { +func (self *SAliyunRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) { if len(input.Name) < 2 || len(input.Name) > 16 { - return nil, httperrors.NewInputParameterError("Aliyun DBInstance account name length shoud be 2~16 characters") + return input, httperrors.NewInputParameterError("Aliyun DBInstance account name length shoud be 2~16 characters") } DENY_KEY := map[string][]string{ @@ -1114,44 +1114,44 @@ func (self *SAliyunRegionDriver) ValidateCreateDBInstanceAccountData(ctx context } if keys, ok := DENY_KEY[instance.Engine]; ok && utils.IsInStringArray(input.Name, keys) { - return nil, httperrors.NewInputParameterError("%s is reserved for aliyun %s, please use another", input.Name, instance.Engine) + return input, httperrors.NewInputParameterError("%s is reserved for aliyun %s, please use another", input.Name, instance.Engine) } for i, s := range input.Name { if !unicode.IsLetter(s) && !unicode.IsDigit(s) && s != '_' { - return nil, httperrors.NewInputParameterError("invalid character %s for account name", s) + return input, httperrors.NewInputParameterError("invalid character %s for account name", s) } if s == '_' && (i == 0 || i == len(input.Name)) { - return nil, httperrors.NewInputParameterError("account name can not start or end with _") + return input, httperrors.NewInputParameterError("account name can not start or end with _") } } for _, privilege := range input.Privileges { err := self.ValidateDBInstanceAccountPrivilege(ctx, userCred, instance, input.Name, privilege.Privilege) if err != nil { - return nil, err + return input, err } } return input, nil } -func (self *SAliyunRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceDatabaseCreateInput) (*api.SDBInstanceDatabaseCreateInput, error) { +func (self *SAliyunRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) { if len(input.CharacterSet) == 0 { - return nil, httperrors.NewMissingParameterError("character_set") + return input, httperrors.NewMissingParameterError("character_set") } for _, account := range input.Accounts { err := self.ValidateDBInstanceAccountPrivilege(ctx, userCred, instance, account.Account, account.Privilege) if err != nil { - return nil, err + return input, err } } return input, nil } -func (self *SAliyunRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceBackupCreateInput) (*api.SDBInstanceBackupCreateInput, error) { +func (self *SAliyunRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) { return input, nil } diff --git a/pkg/compute/regiondrivers/base.go b/pkg/compute/regiondrivers/base.go index 5435151d9a..3e135be1e7 100644 --- a/pkg/compute/regiondrivers/base.go +++ b/pkg/compute/regiondrivers/base.go @@ -157,7 +157,7 @@ func (self *SBaseRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapsh return fmt.Errorf("Not Implement RequestDeleteSnapshot") } -func (self *SBaseRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error { +func (self *SBaseRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return fmt.Errorf("Not Implement ValidateCreateSnapshotData") } @@ -235,7 +235,7 @@ func (self *SBaseRegionDriver) RequestSyncSecurityGroup(ctx context.Context, use return "", fmt.Errorf("Not Implemented RequestSyncSecurityGroup") } -func (self *SBaseRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.SDBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (*api.SDBInstanceCreateInput, error) { +func (self *SBaseRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) { return input, nil } @@ -267,16 +267,16 @@ func (self *SBaseRegionDriver) RequestChangeDBInstanceConfig(ctx context.Context return fmt.Errorf("Not Implement RequestChangeDBInstanceConfig") } -func (self *SBaseRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceAccountCreateInput) (*api.SDBInstanceAccountCreateInput, error) { - return nil, fmt.Errorf("Not Implement ValidateCreateDBInstanceAccountData") +func (self *SBaseRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) { + return input, fmt.Errorf("Not Implement ValidateCreateDBInstanceAccountData") } -func (self *SBaseRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceDatabaseCreateInput) (*api.SDBInstanceDatabaseCreateInput, error) { - return nil, fmt.Errorf("Not Implement ValidateCreateDBInstanceDatabaseData") +func (self *SBaseRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) { + return input, fmt.Errorf("Not Implement ValidateCreateDBInstanceDatabaseData") } -func (self *SBaseRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceBackupCreateInput) (*api.SDBInstanceBackupCreateInput, error) { - return nil, fmt.Errorf("Not Implement ValidateCreateDBInstanceBackupData") +func (self *SBaseRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) { + return input, fmt.Errorf("Not Implement ValidateCreateDBInstanceBackupData") } func (self *SBaseRegionDriver) ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, input *api.SDBInstanceChangeConfigInput) error { diff --git a/pkg/compute/regiondrivers/esxi.go b/pkg/compute/regiondrivers/esxi.go index e0092c9989..0f985dfca5 100644 --- a/pkg/compute/regiondrivers/esxi.go +++ b/pkg/compute/regiondrivers/esxi.go @@ -51,6 +51,6 @@ func (self *SEsxiRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx con return nil, httperrors.NewNotImplementedError("%s does not support creating loadbalancer certificate", self.GetProvider()) } -func (self *SEsxiRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error { +func (self *SEsxiRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return fmt.Errorf("%s does not support creating snapshot", self.GetProvider()) } diff --git a/pkg/compute/regiondrivers/huawei.go b/pkg/compute/regiondrivers/huawei.go index 6a5e072ba4..870f773ce3 100644 --- a/pkg/compute/regiondrivers/huawei.go +++ b/pkg/compute/regiondrivers/huawei.go @@ -2117,21 +2117,21 @@ func (self *SHuaWeiRegionDriver) IsSecurityGroupBelongVpc() bool { return true } -func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input *api.SDBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (*api.SDBInstanceCreateInput, error) { +func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) { if len(input.MasterInstanceId) > 0 && input.Engine == api.DBINSTANCE_TYPE_SQLSERVER { - return nil, httperrors.NewInputParameterError("Not support create read-only dbinstance for %s", input.Engine) + return input, httperrors.NewInputParameterError("Not support create read-only dbinstance for %s", input.Engine) } if len(input.Name) < 4 || len(input.Name) > 64 { - return nil, httperrors.NewInputParameterError("Huawei dbinstance name length shoud be 4~64 characters") + return input, httperrors.NewInputParameterError("Huawei dbinstance name length shoud be 4~64 characters") } if input.DiskSizeGB < 40 || input.DiskSizeGB > 4000 { - return nil, httperrors.NewInputParameterError("%s require disk size must in 40 ~ 4000 GB", self.GetProvider()) + return input, httperrors.NewInputParameterError("%s require disk size must in 40 ~ 4000 GB", self.GetProvider()) } if input.DiskSizeGB%10 > 0 { - return nil, httperrors.NewInputParameterError("The disk_size_gb must be an integer multiple of 10") + return input, httperrors.NewInputParameterError("The disk_size_gb must be an integer multiple of 10") } return input, nil @@ -2174,9 +2174,9 @@ func (self *SHuaWeiRegionDriver) IsSupportedBillingCycle(bc billing.SBillingCycl return false } -func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceAccountCreateInput) (*api.SDBInstanceAccountCreateInput, error) { +func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) { if utils.IsInStringArray(instance.Engine, []string{api.DBINSTANCE_TYPE_POSTGRESQL, api.DBINSTANCE_TYPE_SQLSERVER}) { - return nil, httperrors.NewInputParameterError("Not support create account for huawei cloud %s instance", instance.Engine) + return input, httperrors.NewInputParameterError("Not support create account for huawei cloud %s instance", instance.Engine) } if len(input.Name) == len(input.Password) { for i := range input.Name { @@ -2184,25 +2184,25 @@ func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceAccountData(ctx context return input, nil } } - return nil, httperrors.NewInputParameterError("Huawei rds password cannot be in the same reverse order as the account") + return input, httperrors.NewInputParameterError("Huawei rds password cannot be in the same reverse order as the account") } return input, nil } -func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceDatabaseCreateInput) (*api.SDBInstanceDatabaseCreateInput, error) { +func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) { if utils.IsInStringArray(instance.Engine, []string{api.DBINSTANCE_TYPE_POSTGRESQL, api.DBINSTANCE_TYPE_SQLSERVER}) { - return nil, httperrors.NewInputParameterError("Not support create database for huawei cloud %s instance", instance.Engine) + return input, httperrors.NewInputParameterError("Not support create database for huawei cloud %s instance", instance.Engine) } return input, nil } -func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input *api.SDBInstanceBackupCreateInput) (*api.SDBInstanceBackupCreateInput, error) { +func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) { if len(input.Name) < 4 || len(input.Name) > 64 { - return nil, httperrors.NewInputParameterError("Huawei DBInstance backup name length shoud be 4~64 characters") + return input, httperrors.NewInputParameterError("Huawei DBInstance backup name length shoud be 4~64 characters") } if len(input.Databases) > 0 && instance.Engine != api.DBINSTANCE_TYPE_SQLSERVER { - return nil, httperrors.NewInputParameterError("Huawei only supports specified databases with %s", api.DBINSTANCE_TYPE_SQLSERVER) + return input, httperrors.NewInputParameterError("Huawei only supports specified databases with %s", api.DBINSTANCE_TYPE_SQLSERVER) } return input, nil diff --git a/pkg/compute/regiondrivers/kvm.go b/pkg/compute/regiondrivers/kvm.go index 1148c76b01..647cec1472 100644 --- a/pkg/compute/regiondrivers/kvm.go +++ b/pkg/compute/regiondrivers/kvm.go @@ -725,8 +725,8 @@ func (self *SKVMRegionDriver) ValidateCreateVpcData(ctx context.Context, userCre return data, nil } -func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("Not Implement EIP") +func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { + return httperrors.NewNotImplementedError("Not Implement EIP") } func (self *SKVMRegionDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error { @@ -745,7 +745,7 @@ func (self *SKVMRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapsho return models.GetStorageDriver(storage.StorageType).RequestDeleteSnapshot(ctx, snapshot, task) } -func (self *SKVMRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error { +func (self *SKVMRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { host := storage.GetMasterHost() if host == nil { return fmt.Errorf("failed to get master host, maybe the host is offline") diff --git a/pkg/compute/regiondrivers/managedvirtual.go b/pkg/compute/regiondrivers/managedvirtual.go index 07783cb8b5..4cdc4fb485 100644 --- a/pkg/compute/regiondrivers/managedvirtual.go +++ b/pkg/compute/regiondrivers/managedvirtual.go @@ -1097,8 +1097,8 @@ func (self *SManagedVirtualizationRegionDriver) ValidateCreateVpcData(ctx contex return data, nil } -func (self *SManagedVirtualizationRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return data, nil +func (self *SManagedVirtualizationRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { + return nil } func (self *SManagedVirtualizationRegionDriver) RequestUpdateSnapshotPolicy(ctx context.Context, userCred mcclient. @@ -1209,7 +1209,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshot(ctx contex return nil } -func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error { +func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return nil } diff --git a/pkg/compute/regiondrivers/openstack.go b/pkg/compute/regiondrivers/openstack.go index f4f1328fe5..f770581b4f 100644 --- a/pkg/compute/regiondrivers/openstack.go +++ b/pkg/compute/regiondrivers/openstack.go @@ -16,11 +16,11 @@ package regiondrivers import ( "context" + "database/sql" "yunion.io/x/jsonutils" api "yunion.io/x/onecloud/pkg/apis/compute" - "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -51,24 +51,30 @@ func (self *SOpenStackRegionDriver) ValidateCreateLoadbalancerCertificateData(ct return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) } -func (self *SOpenStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - networkV := validators.NewModelIdOrNameValidator("network", "network", nil) - err := networkV.Validate(data) - if err != nil { - return nil, err +func (self *SOpenStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { + if len(input.Network) == 0 { + return httperrors.NewMissingParameterError("network") } - network := networkV.Model.(*models.SNetwork) + _network, err := models.NetworkManager.FetchByIdOrName(userCred, input.Network) + if err != nil { + if err == sql.ErrNoRows { + return httperrors.NewResourceNotFoundError("failed to found network %s", input.Network) + } + return httperrors.NewGeneralError(err) + } + network := _network.(*models.SNetwork) + input.NetworkId = network.Id vpc := network.GetVpc() if vpc == nil { - return nil, httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id) + return httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id) } region, err := vpc.GetRegion() if err != nil { - return nil, err + return err } if region.GetDriver().GetProvider() != self.GetProvider() { - return nil, httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider()) + return httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider()) } - return data, nil + return nil } diff --git a/pkg/compute/regiondrivers/zstack.go b/pkg/compute/regiondrivers/zstack.go index dbb2478be8..ed14eec1fe 100644 --- a/pkg/compute/regiondrivers/zstack.go +++ b/pkg/compute/regiondrivers/zstack.go @@ -16,11 +16,11 @@ package regiondrivers import ( "context" + "database/sql" "yunion.io/x/jsonutils" api "yunion.io/x/onecloud/pkg/apis/compute" - "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" @@ -51,24 +51,30 @@ func (self *SZStackRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx c return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) } -func (self *SZStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - networkV := validators.NewModelIdOrNameValidator("network", "network", nil) - err := networkV.Validate(data) - if err != nil { - return nil, err +func (self *SZStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { + if len(input.Network) == 0 { + return httperrors.NewMissingParameterError("network") } - network := networkV.Model.(*models.SNetwork) + _network, err := models.NetworkManager.FetchByIdOrName(userCred, input.Network) + if err != nil { + if err == sql.ErrNoRows { + return httperrors.NewResourceNotFoundError("failed to found network %s", input.Network) + } + return httperrors.NewGeneralError(err) + } + network := _network.(*models.SNetwork) + input.NetworkId = network.Id vpc := network.GetVpc() if vpc == nil { - return nil, httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id) + return httperrors.NewInputParameterError("failed to found vpc for network %s(%s)", network.Name, network.Id) } region, err := vpc.GetRegion() if err != nil { - return nil, err + return err } if region.GetDriver().GetProvider() != self.GetProvider() { - return nil, httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider()) + return httperrors.NewUnsupportOperationError("network %s(%s) does not belong to %s", network.Name, network.Id, self.GetProvider()) } - return data, nil + return nil } diff --git a/pkg/compute/storagedrivers/base.go b/pkg/compute/storagedrivers/base.go index f0c3966d31..cd89f7919c 100644 --- a/pkg/compute/storagedrivers/base.go +++ b/pkg/compute/storagedrivers/base.go @@ -35,8 +35,8 @@ import ( type SBaseStorageDriver struct { } -func (self *SBaseStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, fmt.Errorf("Not Implement ValidateCreateData") +func (self *SBaseStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error { + return fmt.Errorf("Not Implement ValidateCreateData") } func (self *SBaseStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) { @@ -66,7 +66,7 @@ func (self *SBaseStorageDriver) ValidateSnapshotDelete(ctx context.Context, snap return nil } -func (self *SBaseStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SSnapshotCreateInput) error { +func (self *SBaseStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SnapshotCreateInput) error { guests := disk.GetGuests() if len(guests) != 1 { return httperrors.NewBadRequestError("Disk %s dosen't attach guest ?", disk.Id) diff --git a/pkg/compute/storagedrivers/gpfs.go b/pkg/compute/storagedrivers/gpfs.go index 1609a94f26..965c258296 100644 --- a/pkg/compute/storagedrivers/gpfs.go +++ b/pkg/compute/storagedrivers/gpfs.go @@ -42,8 +42,8 @@ func (self *SGpfsStorageDriver) GetStorageType() string { return api.STORAGE_GPFS } -func (self *SGpfsStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return data, nil +func (self *SGpfsStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error { + return nil } func (self *SGpfsStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) { diff --git a/pkg/compute/storagedrivers/local.go b/pkg/compute/storagedrivers/local.go index b2f3ac7d07..69f20859f1 100644 --- a/pkg/compute/storagedrivers/local.go +++ b/pkg/compute/storagedrivers/local.go @@ -37,8 +37,8 @@ func (self *SLocalStorageDriver) GetStorageType() string { return api.STORAGE_LOCAL } -func (self *SLocalStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return data, nil +func (self *SLocalStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error { + return nil } func (self *SLocalStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) { diff --git a/pkg/compute/storagedrivers/nfs.go b/pkg/compute/storagedrivers/nfs.go index 79fc76a5e1..661d21bc80 100644 --- a/pkg/compute/storagedrivers/nfs.go +++ b/pkg/compute/storagedrivers/nfs.go @@ -42,19 +42,19 @@ func (self *SNfsStorageDriver) GetStorageType() string { return api.STORAGE_NFS } -func (self *SNfsStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - conf := jsonutils.NewDict() - for _, v := range []string{"nfs_host", "nfs_shared_dir"} { - value, _ := data.GetString(v) - if len(value) == 0 { - return nil, httperrors.NewMissingParameterError(v) - } - conf.Set(v, jsonutils.NewString(value)) +func (self *SNfsStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error { + input.StorageConf = jsonutils.NewDict() + if len(input.NfsHost) == 0 { + return httperrors.NewMissingParameterError("nfs_host") } - - data.Set("storage_conf", conf) - - return data, nil + if len(input.NfsSharedDir) == 0 { + return httperrors.NewMissingParameterError("nfs_shared_dir") + } + input.StorageConf.Update(jsonutils.Marshal(map[string]string{ + "nfs_host": input.NfsHost, + "nfs_shared_dir": input.NfsSharedDir, + })) + return nil } func (self *SNfsStorageDriver) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *models.SStorage, data jsonutils.JSONObject) { diff --git a/pkg/compute/storagedrivers/rbd.go b/pkg/compute/storagedrivers/rbd.go index 3a2b5ec2a3..fb3f9c0f4b 100644 --- a/pkg/compute/storagedrivers/rbd.go +++ b/pkg/compute/storagedrivers/rbd.go @@ -46,50 +46,57 @@ func (self *SRbdStorageDriver) GetStorageType() string { return api.STORAGE_RBD } -func (self *SRbdStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - conf := jsonutils.NewDict() - for _, v := range []string{"rbd_mon_host", "rbd_pool"} { - if !data.Contains(v) { - return nil, httperrors.NewMissingParameterError(v) - } - value, _ := data.GetString(v) - conf.Add(jsonutils.NewString(value), strings.TrimPrefix(v, "rbd_")) - } - if key, _ := data.GetString("rbd_key"); len(key) > 0 { - conf.Add(jsonutils.NewString(key), "key") +func (self *SRbdStorageDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.StorageCreateInput) error { + input.StorageConf = jsonutils.NewDict() + if len(input.RbdMonHost) == 0 { + return httperrors.NewMissingParameterError("rbd_mon_host") } + input.MonHost = input.RbdMonHost - for k, v := range map[string]int64{ - "rbd_rados_mon_op_timeout": api.RBD_DEFAULT_MON_TIMEOUT, - "rbd_rados_osd_op_timeout": api.RBD_DEFAULT_OSD_TIMEOUT, - "rbd_client_mount_timeout": api.RBD_DEFAULT_MOUNT_TIMEOUT, - } { - if timeout, _ := data.Int(k); timeout > 0 { - conf.Add(jsonutils.NewInt(timeout), strings.TrimPrefix(k, "rbd_")) - } else { - conf.Add(jsonutils.NewInt(v), strings.TrimPrefix(k, "rbd_")) - } + if len(input.RbdPool) == 0 { + return httperrors.NewMissingParameterError("rbd_pool") + } + input.Pool = input.RbdPool + input.Key = input.RbdKey + + input.RadosMonOpTimeout = input.RbdRadosMonOpTimeout + if input.RadosMonOpTimeout <= 0 { + input.RadosMonOpTimeout = api.RBD_DEFAULT_MON_TIMEOUT + } + input.RadosOsdOpTimeout = input.RbdRadosOsdOpTimeout + if input.RadosOsdOpTimeout <= 0 { + input.RadosOsdOpTimeout = api.RBD_DEFAULT_OSD_TIMEOUT + } + input.ClientMountTimeout = input.RbdClientMountTimeout + if input.ClientMountTimeout <= 0 { + input.ClientMountTimeout = api.RBD_DEFAULT_MOUNT_TIMEOUT } storages := []models.SStorage{} q := models.StorageManager.Query().Equals("storage_type", api.STORAGE_RBD) - if err := db.FetchModelObjects(models.StorageManager, q, &storages); err != nil { - return nil, httperrors.NewGeneralError(err) + err := db.FetchModelObjects(models.StorageManager, q, &storages) + if err != nil { + return httperrors.NewGeneralError(err) } - inputHost, _ := conf.GetString("mon_host") - inputPool, _ := conf.GetString("pool") for i := 0; i < len(storages); i++ { host, _ := storages[i].StorageConf.GetString("mon_host") pool, _ := storages[i].StorageConf.GetString("pool") - if inputHost == host && inputPool == pool { - return nil, httperrors.NewDuplicateResourceError("This RBD Storage[%s/%s] has already exist", storages[i].Name, inputPool) + if input.MonHost == host && input.Pool == pool { + return httperrors.NewDuplicateResourceError("This RBD Storage[%s/%s] has already exist", storages[i].Name, input.Pool) } } - data.Set("storage_conf", conf) - - return data, nil + input.StorageConf.Update( + jsonutils.Marshal(map[string]interface{}{ + "mon_host": input.MonHost, + "pool": input.Pool, + "key": input.Key, + "rados_mon_op_timeout": input.RadosMonOpTimeout, + "rados_osd_op_timeout": input.RadosOsdOpTimeout, + "client_mount_timeout": input.ClientMountTimeout, + })) + return nil } func (self *SRbdStorageDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, storage *models.SStorage) (*jsonutils.JSONDict, error) { @@ -179,7 +186,7 @@ func (self *SRbdStorageDriver) ValidateSnapshotDelete(ctx context.Context, snaps return nil } -func (self *SRbdStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SSnapshotCreateInput) error { +func (self *SRbdStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SnapshotCreateInput) error { return nil } diff --git a/pkg/compute/tasks/dbinstance_account_create_task.go b/pkg/compute/tasks/dbinstance_account_create_task.go index 43d0ae862c..ecaf8c847d 100644 --- a/pkg/compute/tasks/dbinstance_account_create_task.go +++ b/pkg/compute/tasks/dbinstance_account_create_task.go @@ -102,7 +102,7 @@ func (self *DBInstanceAccountCreateTask) CreateDBInstanceAccount(ctx context.Con db.SetExternalId(account, self.UserCred, iAccount.GetGlobalId()) - input := api.SDBInstanceAccountCreateInput{} + input := api.DBInstanceAccountCreateInput{} self.GetParams().Unmarshal(&input) if len(input.Privileges) == 0 { account.SetStatus(self.UserCred, api.DBINSTANCE_USER_AVAILABLE, "") diff --git a/pkg/compute/tasks/dbinstance_database_create_task.go b/pkg/compute/tasks/dbinstance_database_create_task.go index aa297c0012..e23ec64cd4 100644 --- a/pkg/compute/tasks/dbinstance_database_create_task.go +++ b/pkg/compute/tasks/dbinstance_database_create_task.go @@ -103,7 +103,7 @@ func (self *DBInstanceDatabaseCreateTask) CreateDBInstanceDatabase(ctx context.C db.SetExternalId(database, self.UserCred, iDatabase.GetGlobalId()) - input := api.SDBInstanceDatabaseCreateInput{} + input := api.DBInstanceDatabaseCreateInput{} self.GetParams().Unmarshal(&input) if len(input.Accounts) == 0 { database.SetStatus(self.UserCred, api.DBINSTANCE_DATABASE_RUNNING, "")