mirror of https://github.com/openspug/spug
fix issues
parent
f3a6858c6f
commit
92f4e744b1
|
@ -31,7 +31,10 @@ def cloud_import(request):
|
||||||
Argument('ak', help='请输入AccessKey ID'),
|
Argument('ak', help='请输入AccessKey ID'),
|
||||||
Argument('ac', help='请输入AccessKey Secret'),
|
Argument('ac', help='请输入AccessKey Secret'),
|
||||||
Argument('region_id', help='请选择区域'),
|
Argument('region_id', help='请选择区域'),
|
||||||
Argument('group_id', type=int, help='请选择分组')
|
Argument('group_id', type=int, help='请选择分组'),
|
||||||
|
Argument('username', help='请输入默认SSH用户名'),
|
||||||
|
Argument('port', type=int, help='请输入默认SSH端口号'),
|
||||||
|
Argument('host_type', filter=lambda x: x in ('public', 'private'), help='请选择连接地址'),
|
||||||
).parse(request.body)
|
).parse(request.body)
|
||||||
if error is None:
|
if error is None:
|
||||||
group = Group.objects.filter(pk=form.group_id).first()
|
group = Group.objects.filter(pk=form.group_id).first()
|
||||||
|
@ -46,12 +49,23 @@ def cloud_import(request):
|
||||||
for item in instances:
|
for item in instances:
|
||||||
instance_id = item['instance_id']
|
instance_id = item['instance_id']
|
||||||
host_name = item.pop('instance_name')
|
host_name = item.pop('instance_name')
|
||||||
item['public_ip_address'] = json.dumps(item['public_ip_address'] or [])
|
public_ips = item['public_ip_address'] or []
|
||||||
item['private_ip_address'] = json.dumps(item['private_ip_address'] or [])
|
private_ips = item['private_ip_address'] or []
|
||||||
|
item['public_ip_address'] = json.dumps(public_ips)
|
||||||
|
item['private_ip_address'] = json.dumps(private_ips)
|
||||||
if HostExtend.objects.filter(instance_id=instance_id).exists():
|
if HostExtend.objects.filter(instance_id=instance_id).exists():
|
||||||
HostExtend.objects.filter(instance_id=instance_id).update(**item)
|
HostExtend.objects.filter(instance_id=instance_id).update(**item)
|
||||||
else:
|
else:
|
||||||
host = Host.objects.create(name=host_name, created_by=request.user)
|
if form.host_type == 'public':
|
||||||
|
hostname = public_ips[0] if public_ips else None
|
||||||
|
else:
|
||||||
|
hostname = private_ips[0] if private_ips else None
|
||||||
|
host = Host.objects.create(
|
||||||
|
name=host_name,
|
||||||
|
hostname=hostname,
|
||||||
|
port=form.port,
|
||||||
|
username=form.username,
|
||||||
|
created_by=request.user)
|
||||||
HostExtend.objects.create(host=host, **item)
|
HostExtend.objects.create(host=host, **item)
|
||||||
host_add_ids.append(host.id)
|
host_add_ids.append(host.id)
|
||||||
if host_add_ids:
|
if host_add_ids:
|
||||||
|
|
|
@ -218,14 +218,16 @@ def batch_sync_host(token, hosts, password, ):
|
||||||
with futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
with futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
t = executor.submit(_sync_host_extend, host, private_key, public_key, password)
|
t = executor.submit(_sync_host_extend, host, private_key, public_key, password)
|
||||||
t.h_id = host.id
|
t.host = host
|
||||||
threads.append(t)
|
threads.append(t)
|
||||||
for t in futures.as_completed(threads):
|
for t in futures.as_completed(threads):
|
||||||
exception = t.exception()
|
exception = t.exception()
|
||||||
if exception:
|
if exception:
|
||||||
rds.rpush(token, json.dumps({'key': t.h_id, 'status': 'fail', 'message': f'{exception}'}))
|
rds.rpush(token, json.dumps({'key': t.host.id, 'status': 'fail', 'message': f'{exception}'}))
|
||||||
else:
|
else:
|
||||||
rds.rpush(token, json.dumps({'key': t.h_id, 'status': 'ok'}))
|
rds.rpush(token, json.dumps({'key': t.host.id, 'status': 'ok'}))
|
||||||
|
t.host.is_verified = True
|
||||||
|
t.host.save()
|
||||||
rds.expire(token, 60)
|
rds.expire(token, 60)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { Modal, Form, Input, Select, Button, Steps, Cascader, message } from 'antd';
|
import { Modal, Form, Input, Select, Button, Steps, Cascader, Radio, message } from 'antd';
|
||||||
import http from 'libs/http';
|
import http from 'libs/http';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
|
@ -18,10 +18,22 @@ export default observer(function () {
|
||||||
const [regionId, setRegionId] = useState();
|
const [regionId, setRegionId] = useState();
|
||||||
const [groupId, setGroupId] = useState([]);
|
const [groupId, setGroupId] = useState([]);
|
||||||
const [regions, setRegions] = useState([]);
|
const [regions, setRegions] = useState([]);
|
||||||
|
const [username, setUsername] = useState('root');
|
||||||
|
const [port, setPort] = useState('22');
|
||||||
|
const [host_type, setHostType] = useState('private');
|
||||||
|
|
||||||
function handleSubmit() {
|
function handleSubmit() {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const formData = {ak, ac, type: store.cloudImport, region_id: regionId, group_id: groupId[groupId.length - 1]};
|
const formData = {
|
||||||
|
ak,
|
||||||
|
ac,
|
||||||
|
type: store.cloudImport,
|
||||||
|
region_id: regionId,
|
||||||
|
group_id: groupId[groupId.length - 1],
|
||||||
|
username,
|
||||||
|
port,
|
||||||
|
host_type
|
||||||
|
};
|
||||||
http.post('/api/host/import/cloud/', formData, {timeout: 120000})
|
http.post('/api/host/import/cloud/', formData, {timeout: 120000})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
message.success(`已同步/导入 ${res} 台主机`);
|
message.success(`已同步/导入 ${res} 台主机`);
|
||||||
|
@ -58,14 +70,14 @@ export default observer(function () {
|
||||||
<Form.Item hidden={step === 1} required label="AccessKey Secret">
|
<Form.Item hidden={step === 1} required label="AccessKey Secret">
|
||||||
<Input value={ac} onChange={e => setAC(e.target.value)} placeholder="请输入"/>
|
<Input value={ac} onChange={e => setAC(e.target.value)} placeholder="请输入"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item hidden={step === 0} required label="选择区域">
|
<Form.Item hidden={step === 0} required label="选择区域" tooltip="选择导入指定区域的主机。">
|
||||||
<Select placeholder="请选择" value={regionId} onChange={setRegionId}>
|
<Select placeholder="请选择" value={regionId} onChange={setRegionId}>
|
||||||
{regions.map(item => (
|
{regions.map(item => (
|
||||||
<Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
|
<Select.Option key={item.id} value={item.id}>{item.name}</Select.Option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item hidden={step === 0} required label="选择分组">
|
<Form.Item hidden={step === 0} required label="选择分组" tooltip="将主机导入指定分组。">
|
||||||
<Cascader
|
<Cascader
|
||||||
value={groupId}
|
value={groupId}
|
||||||
onChange={setGroupId}
|
onChange={setGroupId}
|
||||||
|
@ -73,6 +85,20 @@ export default observer(function () {
|
||||||
fieldNames={{label: 'title'}}
|
fieldNames={{label: 'title'}}
|
||||||
placeholder="请选择"/>
|
placeholder="请选择"/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item hidden={step === 0} label="基础信息" tooltip="以下信息用于进行SSH验证,导入完成后通过点击批量验证按钮进行批量验证并同步主机扩展信息。"/>
|
||||||
|
<Form.Item hidden={step === 0} labelCol={{span: 10}} wrapperCol={{span: 12}} label="用户名">
|
||||||
|
<Input value={username} onChange={e => setUsername(e.target.value)} placeholder="默认SSH登录的账户名"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item hidden={step === 0} labelCol={{span: 10}} wrapperCol={{span: 12}} label="端口号">
|
||||||
|
<Input value={port} onChange={e => setPort(e.target.value)} placeholder="默认SSH端口号"/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item hidden={step === 0} labelCol={{span: 10}} wrapperCol={{span: 12}} label="连接地址"
|
||||||
|
extra="将根据选择进行自动匹配获取。">
|
||||||
|
<Radio.Group value={host_type} onChange={e => setHostType(e.target.value)}>
|
||||||
|
<Radio value="public">公网地址</Radio>
|
||||||
|
<Radio value="private">私网地址</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item wrapperCol={{span: 14, offset: 8}}>
|
<Form.Item wrapperCol={{span: 14, offset: 8}}>
|
||||||
{step === 0 ? (
|
{step === 0 ? (
|
||||||
<Button type="primary" loading={loading} disabled={!ak || !ac} onClick={fetchRegions}>下一步</Button>
|
<Button type="primary" loading={loading} disabled={!ak || !ac} onClick={fetchRegions}>下一步</Button>
|
||||||
|
|
Loading…
Reference in New Issue