Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加虚拟机备份、编辑磁盘描述 #170

Merged
merged 10 commits into from
Sep 22, 2016
17 changes: 11 additions & 6 deletions Aries/openstack/middleware/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@
import os
import errno
import time
import ConfigParser

pro_path = os.path.split(os.path.realpath(__file__))[0]
LOG_PATH = os.path.join(pro_path, "log") # 日志路径
DB_PATH = os.path.join(pro_path, "db.sqlite3")
CONFIG_PATH = os.path.join(pro_path,"setting.conf")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上面两行:

LOG_PATH = os.path.join(pro_path, "log")  # 日志路径
DB_PATH =  os.path.join(pro_path, "db.sqlite3")

这两个不是全部已经配置了吗?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已改成从settings里面获取项目路径

LOG_FLAG = True # 日志开关
POLL_TIME_INCR = 0.5
IP_keystone = "192.168.190.11"
PORT_keystone = "5000"
IP_nova = "192.168.190.11"
PORT_nova = "8774"
IP_cinder = "192.168.190.11"
PORT_cinder = "8774"
#读取配置文件
cf = ConfigParser.ConfigParser()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为什么要读取配置文件啊?不是都在settings里面直接引用吗?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些都属于可配置项,在settings里面如果给出的是pyc的文件就不能修改了

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

现在配置都提取到yaml文件中了。你可以看看这个issue. #143
该issue已经修复了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个版本里面配置文件还没改,版本合过去后我把这几个配置写到yaml里面去

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好的。

cf.read(CONFIG_PATH)
IP_keystone = cf.get("global","IP_keystone")
PORT_keystone = cf.get("global","PORT_keystone")
IP_nova = cf.get("global","IP_nova")
PORT_nova = cf.get("global","PORT_nova")
IP_cinder = cf.get("global","IP_cinder")
PORT_cinder = cf.get("global","PORT_cinder")
TIMEOUT = 60


Expand Down
7 changes: 7 additions & 0 deletions Aries/openstack/middleware/common/setting.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[global]
IP_keystone=192.168.190.11
PORT_keystone=5000
IP_nova=192.168.190.11
PORT_nova=8774
IP_cinder=192.168.190.11
PORT_cinder=8776
4 changes: 2 additions & 2 deletions Aries/openstack/middleware/vm/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ def unpause(self, vm_id):
return ret

@plog("vm_control.reboot")
def reboot(self, vm_id):
def reboot(self, vm_id,type="HARD"):
'''
重启虚拟机
:param vm_id:
Expand All @@ -357,7 +357,7 @@ def reboot(self, vm_id):
path = "/v2.1/%s/servers/%s/action" % (self.project_id, vm_id)
method = "POST"
head = {"Content-Type": "application/json", "X-Auth-Token": self.token}
params = {"reboot": {"type": "HARD"}}
params = {"reboot": {"type": type}}
ret = send_request(method, IP_nova, PORT_nova, path, params, head)
assert ret != 1, "send_request error"
return ret
Expand Down
19 changes: 19 additions & 0 deletions Aries/openstack/middleware/volume/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,25 @@ def extend(self,volume_id,size):
assert ret != 1, "send_request error"
return ret

@plog("Volume.change")
def change(self,volume_id,name="",description=""):
'''
修改磁盘信息
:return:
'''
assert self.token != "","not login"
path = "/v2/%s/volumes/%s"%(self.project_id, volume_id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的path。不要写在代码里面了。提取出来放在一个单独的文件中统一管理。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path会随着用户和操作对象的变化而变化,如果只是把相同的部分放在公用变量里面再拼接起来好像没什么意义

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不用拼接吧。url统一定义成模版的形式使用的时候渲染然后集中放在一个地方比较好管理一点。
例如模版:

opensatckUrl = "/v1/{project_id}/volumes/{volume_id}"

使用的时候渲染就可以了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个不是我们程序的url地址,是openstack cinder API的地址,我不确定我们理解的是不是一样的

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你说的openstack cinder API的地址不是可以理解为第3方服务的api地址么?

method = "PUT"
head = {"Content-Type": "application/json", "X-Auth-Token": self.token}
params = {"volume":{}}
if name:
params["volume"].update({"name":name})
if description:
params["volume"].update({"description":description})
ret = send_request(method,IP_cinder,PORT_cinder,path,params,head)
assert ret != 1,"send_request error"
return ret

class Volume_snaps():
def __init__(self):
self.token = get_token()
Expand Down
45 changes: 42 additions & 3 deletions Aries/openstack/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from openstack.middleware.image.image import Image
from openstack.middleware.flavor.flavor import Flavor
from common import json_data
from openstack.middleware.vm.vm import Vm_manage, Vm_control
from openstack.middleware.vm.vm import Vm_manage, Vm_control,Vm_snap
from openstack.middleware.volume.volume import Volume, Volume_attach, Volume_snaps
from django.http import HttpResponse
import json

import logging
openstack_log = logging.getLogger("openstack_log")

def json_data(json_status):
if len(json_status) == 0:
Expand Down Expand Up @@ -213,6 +214,42 @@ def openstack_project(request):
ret = json_data(ret)
return ret

def volumes_Redact(request):
ret = {}
login()
openstack_log.info(request.POST)
volumes_id = request.POST.get('id')
volumes_name = request.POST.get('name')
volumes_desc = request.POST.get('desc')
volume=Volume()
return_data=volume.change(volumes_id,name=volumes_name,description=volumes_desc)
openstack_log.info(return_data)
if return_data != 1:
ret['name']=volumes_name
ret['status']=True
ret['desc']=volumes_desc
else:
ret['status']=False
ret=json_data(ret)
return ret

def instances_backup(request):
ret={}
login()
instances_id=request.POST.get('id')
instances_name = request.POST.get('name')
instances_name_b = request.POST.get('name_bakup')
openstack_log.info(request.POST)
vm_snap=Vm_snap(instances_id)
return_data=vm_snap.create(instances_name_b)
if return_data !=1:
ret['name']=instances_name
ret['status']=True
else:
ret['name']=instances_name
ret['status']=False
ret=json_data(ret)
return ret

def instances_search(request):
login()
Expand Down Expand Up @@ -279,7 +316,7 @@ def instances_search(request):
"GET": {
"instances": instances,
"backup": volumes_backup,
"instances_search": instances_search
"instances_search": instances_search,
},
"POST": {
"CREATE": volumes_create,
Expand All @@ -288,5 +325,7 @@ def instances_search(request):
'Loading_disk': volumes_host,
'uninstall': volumes_uninstall,
'backup': volumes_backup,
'Redact':volumes_Redact,
'instances_backup':instances_backup,
}
}
83 changes: 83 additions & 0 deletions package/Aries/src/functions/Openstack/instances/model_list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,77 @@ const Vm_Type=React.createClass({
}
})


const Vm_Backup=React.createClass({
getInitialState() {
this.rules = {
name(v) {
if (!v) return '请填写用户群'
},
date(v) {
if (!v) return '日期不能为空'
}
}
return {
formData: {
name: this.volumes_id()['name'],
id:this.volumes_id()['id'],
method: 'instances_backup'
},
volumes_id: this.volumes_id()
}
},
volumes_id(){
let volumes_id={}
let volumes_size={}
console.log(this.props.vm_list)
for (let i in this.props.vm_list){
console.log(this.props.vm_list[i])
volumes_id['name']=this.props.vm_list[i]['name']
volumes_id['id']=this.props.vm_list[i]['id']
}
console.log('volumes_id',volumes_id)
return volumes_id
},
handleDateSelect(date) {
const formData = this.state.formData
formData.date = date
this.setState({ formData })
},

handleSave() {
console.log(this.state.formData)
this.refs.form.save()
},

handleSuccess(res) {
console.log(res)
this.props._this.refs.modal.close()
message.success('保存成功!')
},
render() {
const { formData } = this.state
let url=OPEN.UrlList()['volumes_post']
return (
<div >
<Form
ref="form"
action={url}
data={formData}
rules={this.rules}
onSuccess={this.handleSuccess}
>
<FormItem label="备份名称" required name="name_bakup" >
<FormInput style={{width: '200px'}} ></FormInput>
</FormItem>
<button type="button" style={{marginLeft: '100px'}} className="btn btn-primary" onClick={this.handleSave}>创建</button>
</Form>
</div>
)
}
})


const Vm_image=React.createClass({
getInitialState() {
return {
Expand Down Expand Up @@ -393,6 +464,15 @@ const Disk_model=React.createClass({
model:[4]
})
}
if (event['key'] == 1){
this.setState({loading:true})
OPEN.Get_image(this,this.handlerequest)
this.setState({
title:'虚拟机备份',
model:[1]
})
}

if (event['key'] == 5){
this.setState({
title:'强制重启',
Expand Down Expand Up @@ -437,6 +517,9 @@ const Disk_model=React.createClass({
<ModalBody>
<div>
{ this.state.model.map((item,i)=>{
if(item==1){
return(<Vm_Backup key={i} vm_list={this.props.vm_list} _this={this}/>)
}
if (item == 2){
return (<Disk_list key={i} vm_list={this.props.vm_list} disk_list={this.state.disk_list} disk_object={this.state.disk_object} _this={this}/>)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,82 @@ import DataTable from 'bfd/DataTable'
import { Menu, Dropdown } from 'antd';


const Redact = React.createClass({
getInitialState() {
this.rules = {
name(v) {
if (!v) return '请填写用户群'
},
date(v) {
if (!v) return '日期不能为空'
}
}
return {
formData: {
id: this.volumes_id()['id'],
method: 'Redact',
name: this.volumes_id()['name'],
desc: this.volumes_id()['desc']
},
volumes_id: this.volumes_id()
}
},
volumes_id(){
let volumes_id={}
let volumes_size={}
console.log(this.props.volumes_all)
for (let i in this.props.volumes_all){
volumes_id['desc']=this.props.volumes_all[i]['displayDescription']
volumes_id['name']=this.props.volumes_all[i]['name']
volumes_id['id']=this.props.volumes_all[i]['id']
}
return volumes_id
},
handleDateSelect(date) {
const formData = this.state.formData
formData.date = date
this.setState({ formData })
},

handleSave() {
console.log(this.state.formData)
console.log(this.refs.form)
this.refs.form.save()
},

handleSuccess(res) {
console.log(res)
this.props._this.refs.modal.close()
message.success('保存成功!')
},
render() {
const { formData } = this.state
let url=OPEN.UrlList()['volumes_post']
console.log('aaa',this.props.volumes_all,this.state.volumes_id)
return (
<div >
<Form
ref="form"
action={url}
data={formData}
rules={this.rules}
onSuccess={this.handleSuccess}
>
<FormItem label="备份名称" required name="name" >
<FormInput style={{width: '200px'}} ></FormInput>
</FormItem>
<FormItem label="描述" name="desc" help="500个字符以内">
<FormTextarea />
</FormItem>
<button type="button" style={{marginLeft: '100px'}} className="btn btn-primary" onClick={this.handleSave}>修改</button>
</Form>
</div>
)
}
})



const Backup_disk = React.createClass({
getInitialState() {
this.rules = {
Expand Down Expand Up @@ -370,7 +446,7 @@ const Model_list=React.createClass({
},
values(){
return {
'redact':"编辑云盘",
'Redact':"编辑云盘",
'Extend':"扩展云硬盘",
'Loading_disk':"加载云磁盘",
'Uninstall_disk':"卸载云磁盘",
Expand All @@ -382,14 +458,16 @@ const Model_list=React.createClass({
'Extend': <Extend volumes_all={this.props.select_all} _this={this}/>,
'Loading_disk':<Loading_disk volumes_all={this.props.select_all} _this={this}/>,
'Uninstall_disk':<Uninstall_disk volumes_all={this.props.select_all} _this={this}/>,
'Backup_disk':<Backup_disk volumes_all={this.props.select_all} _this={this}/>
'Backup_disk':<Backup_disk volumes_all={this.props.select_all} _this={this}/>,
'Redact':<Redact volumes_all={this.props.select_all} _this={this}/>,
}
},
handleButtonClick(e) {
console.log('click left button', e);
console.log('click left button', e)
},
handleMenuClick(e) {
//console.log('click', e['key']);
console.log(e)
let module=this.modulevalue()[e["key"]]
// console.log(module)
let volumes_id={}
Expand All @@ -410,7 +488,7 @@ const Model_list=React.createClass({
const DropdownButton = Dropdown.Button;
const menu = (
<Menu onClick={this.handleMenuClick}>
<Menu.Item key="1" disabled={this.props.button_status}>编辑云硬盘</Menu.Item>
<Menu.Item key="Redact" disabled={this.props.button_status}>编辑云硬盘</Menu.Item>
<Menu.Item key="Extend" disabled={this.props.button_status} >扩展云硬盘</Menu.Item>
<Menu.Item key="Loading_disk" disabled={this.props.button_status}>加载硬盘</Menu.Item>
<Menu.Item key="Uninstall_disk" disabled={this.props.button_status} >卸载硬盘</Menu.Item>
Expand Down