diff --git a/src/client/glance/index.js b/src/client/glance/index.js index 8ac50522..7fd1cfea 100644 --- a/src/client/glance/index.js +++ b/src/client/glance/index.js @@ -56,6 +56,11 @@ class GlanceClient extends Base { }, }), }, + { + key: 'import', + method: 'post', + isDetail: true, + }, ], subResources: [ { diff --git a/src/locales/en.json b/src/locales/en.json index 8b7d57d6..a184c899 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -763,6 +763,7 @@ "Fiji": "Fiji", "File": "File", "File System Free Space": "File System Free Space", + "File URL": "File URL", "Filename": "Filename", "Files: {names}": "Files: {names}", "Fill In The Parameters": "Fill In The Parameters", @@ -1431,6 +1432,8 @@ "Platform Info": "Platform Info", "Please confirm your password!": "Please confirm your password!", "Please enter JSON in the correct format!": "Please enter JSON in the correct format!", + "Please enter URL!": "Please enter URL!", + "Please enter a file link starting with \"http://\" or \"https://\"!": "Please enter a file link starting with \"http://\" or \"https://\"!", "Please enter a memory page size, such as: 1024, 1024MB": "Please enter a memory page size, such as: 1024, 1024MB", "Please enter a valid ASCII code": "Please enter a valid ASCII code", "Please enter a valid Email Address!": "Please enter a valid Email Address!", @@ -2065,6 +2068,7 @@ "Updating": "Updating", "Updating Password": "Updating Password", "Upload File": "Upload File", + "Upload Type": "Upload Type", "Upload progress": "Upload progress", "Uploading": "Uploading", "Uruguay": "Uruguay", diff --git a/src/locales/zh.json b/src/locales/zh.json index 687d6115..c6cc80cf 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -763,6 +763,7 @@ "Fiji": "斐济", "File": "文件", "File System Free Space": "文件系统可用空间", + "File URL": "文件URL", "Filename": "文件名", "Files: {names}": "文件:{names}", "Fill In The Parameters": "参数填写", @@ -1431,6 +1432,8 @@ "Platform Info": "平台概况", "Please confirm your password!": "请确认您的密码", "Please enter JSON in the correct format!": "请输入正确格式的JSON!", + "Please enter URL!": "请输入URL!", + "Please enter a file link starting with \"http://\" or \"https://\"!": "请输入以“http://”或“https://”开头的文件链接!", "Please enter a memory page size, such as: 1024, 1024MB": "请输入内存页大小,如:1024, 1024MB", "Please enter a valid ASCII code": "请输入有效的ASCII码", "Please enter a valid Email Address!": "请输入一个有效的邮箱地址", @@ -2065,6 +2068,7 @@ "Updating": "更新中", "Updating Password": "更新密码中", "Upload File": "上传文件", + "Upload Type": "上传方式", "Upload progress": "上传进度", "Uploading": "上传中", "Uruguay": "乌拉圭", diff --git a/src/pages/compute/containers/Image/actions/Create.jsx b/src/pages/compute/containers/Image/actions/Create.jsx index 4b2aa206..8addebc6 100644 --- a/src/pages/compute/containers/Image/actions/Create.jsx +++ b/src/pages/compute/containers/Image/actions/Create.jsx @@ -82,6 +82,7 @@ export class CreateForm extends FormAction { get defaultValue() { return { + uploadType: 'file', hw_qemu_guest_agent: 'yes', usage_type: 'common', visibility: this.isAdminPage ? 'public' : false, @@ -133,6 +134,13 @@ export class CreateForm extends FormAction { }); } + get typeList() { + return [ + { value: 'file', label: t('Upload File') }, + { value: 'url', label: t('File URL') }, + ]; + } + checkFileType = (file) => { const types = Object.keys(this.imageFormats); const { name } = file; @@ -155,9 +163,21 @@ export class CreateForm extends FormAction { return Promise.resolve(); }; + validateURL = (rule, value) => { + if (!value) return Promise.reject(t('Please enter URL!')); + const urlReg = /^https?:\/\/(.*)/; + if (!urlReg.test(value)) { + return Promise.reject( + t('Please enter a file link starting with "http://" or "https://"!') + ); + } + return Promise.resolve(); + }; + get formItems() { - const { more, visibility } = this.state; + const { more, visibility, uploadType } = this.state; const isShare = this.isAdminPage && visibility === 'shared'; + const isUrl = uploadType === 'url'; return [ { name: 'name', @@ -176,12 +196,27 @@ export class CreateForm extends FormAction { isLoading: this.projectStore.list.isLoading, ...projectTableOptions, }, + { + name: 'uploadType', + label: t('Upload Type'), + type: 'radio', + options: this.typeList, + }, { name: 'file', label: t('File'), type: 'upload', - required: true, validator: this.validateFile, + required: !isUrl, + hidden: isUrl, + }, + { + name: 'url', + label: t('File URL'), + type: 'input', + required: isUrl, + hidden: !isUrl, + validator: this.validateURL, }, { name: 'disk_format', @@ -297,7 +332,9 @@ export class CreateForm extends FormAction { onSubmit = (values) => { const { + uploadType, file, + url, visibility, more, hw_cpu_policy, @@ -328,7 +365,8 @@ export class CreateForm extends FormAction { } const mems = visibility === 'shared' ? members.selectedRowKeys : []; const config = this.getUploadRequestConf(); - return this.store.create(body, file, mems, config); + const actualFile = uploadType === 'file' ? file : url; + return this.store.create(body, actualFile, mems, config); }; } diff --git a/src/stores/glance/image.js b/src/stores/glance/image.js index 9cb43f18..ffc1a2a6 100644 --- a/src/stores/glance/image.js +++ b/src/stores/glance/image.js @@ -16,6 +16,7 @@ import { action, observable } from 'mobx'; import client from 'client'; import Base from 'stores/base'; import { imageOS } from 'resources/image'; +import { isString } from 'lodash'; export class ImageStore extends Base { @observable @@ -84,6 +85,17 @@ export class ImageStore extends Base { return this.client.uploadFile(imageId, file, conf); } + @action + async importFileUrl(imageId, uri) { + const data = { + method: { + name: 'web-download', + uri, + }, + }; + return this.client.import(imageId, data); + } + @action async create(data, file, members, conf) { this.isSubmitting = true; @@ -93,7 +105,11 @@ export class ImageStore extends Base { if (members.length > 0) { await Promise.all(members.map((it) => this.createMember(id, it))); } - await this.uploadImage(id, file, conf); + if (isString(file)) { + await this.importFileUrl(id, file); + } else { + await this.uploadImage(id, file, conf); + } this.isSubmitting = false; return Promise.resolve(); }