Delete all rpms and major upgrade from inside...
Change-Id: I12d6307464cc03664b6113807a35c396b652add9 Signed-off-by: Zhijiang Hu <hu.zhijiang@zte.com.cn>
This commit is contained in:
parent
8698f3a15e
commit
2d2da98b35
3
backend/proton/.gitignore
vendored
3
backend/proton/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file !.gitignore
|
@ -1,166 +0,0 @@
|
||||
## HA配置(双机)
|
||||
# 每套HA系统配置一个配置文件,该文件名命令规律如下,一套HA为HA_1.conf,两套HA命令格式为HA_2_1.conf和HA_2_2.conf,依次类推
|
||||
# 建议拷贝该模版改名后再编辑,如使用vi命令,应先执行 export LC_ALL="zh_CN.GB2312" ,否则会有乱码,编辑后unset LC_ALL
|
||||
|
||||
[DEFAULT]
|
||||
# HA安装的OpenCOS组件, 可以填写为loadbalance,database,amqp,keystone,neutron,glance,cinder,nova,horizon,heat,ceilometer,ironic(与下面组件服务列表的关键字一致)
|
||||
# 之中的任意组合,用逗号分开, 全部可简写为all, 无顺序要求,haproxy代表配置LB.
|
||||
# 注意HA是通过conf方式安装的,但这种方式不支持安装ironic,如果这里配置了ironic,应在整个安装流程前手动通过custom方式单独安装ironic
|
||||
# 该配置项必填
|
||||
components=database,amqp,keystone,neutron,glance,cinder,nova,horizon,heat,ceilometer
|
||||
|
||||
# 由HA管理的组件服务(可裁剪),多个服务以逗号分开.
|
||||
# 一般对服务无增加或减少可不必修改如下选项,多余组件也无需注释掉,组件选择与否由“components”决定
|
||||
loadbalance = haproxy
|
||||
|
||||
database=mariadb
|
||||
|
||||
amqp=rabbitmq-server
|
||||
|
||||
keystone=openstack-keystone
|
||||
|
||||
#neutron-metadata-agent,neutron-lbaas-agent don't use default
|
||||
neutron=neutron-server,neutron-l3-agent,neutron-dhcp-agent
|
||||
|
||||
#openstack-glance-scrubber don't use default
|
||||
glance=openstack-glance-api,openstack-glance-registry
|
||||
|
||||
#openstack-cinder-backup don't use default
|
||||
cinder=openstack-cinder-api,openstack-cinder-scheduler,openstack-cinder-volume
|
||||
|
||||
nova=openstack-nova-api,openstack-nova-conductor,openstack-nova-scheduler,openstack-nova-cert,openstack-nova-consoleauth,openstack-nova-novncproxy
|
||||
|
||||
horizon=httpd,opencos-alarmmanager,opencos-alarmagent
|
||||
|
||||
heat=openstack-heat-api,openstack-heat-engine,openstack-heat-api-cfn,openstack-heat-api-cloudwatch
|
||||
|
||||
ceilometer=openstack-ceilometer-api,openstack-ceilometer-central,openstack-ceilometer-alarm-evaluator,openstack-ceilometer-alarm-notifier,openstack-ceilometer-notification,openstack-ceilometer-collector
|
||||
|
||||
ironic=openstack-ironic-api,openstack-ironic-conductor
|
||||
|
||||
# 根据业务需要,增加clone服务资源(每个节点都运行),填写去掉.service后的服务名,多个服务以逗号分隔,可选
|
||||
#clone_service=
|
||||
|
||||
# guard服务名字
|
||||
guard=tfg-guard
|
||||
|
||||
# HA集群心跳线,至少一条,建议三条,每条是一对IP,用逗号分开
|
||||
# 如果LB和HA是使用相同服务器,则此处心跳线不用再填写
|
||||
# 第一条心跳线,例中是外网IP,必填
|
||||
heartbeat_link1=10.43.179.221,10.43.179.222
|
||||
# 第二条心跳线,不能与其他心跳线有相同IP,可选
|
||||
heartbeat_link2=
|
||||
# 第三条心跳线,不能与其他心跳线有相同IP,可选
|
||||
heartbeat_link3=
|
||||
|
||||
#执行HA脚本的节点为local node,其他节点为remote node,这里为ssh登录remote node的root用户密码,必填
|
||||
remote_node_password=ossdbg1
|
||||
|
||||
|
||||
# haproxy浮动IP地址,配置LB时,必填
|
||||
#loadbalance_fip=192.160.0.226
|
||||
#loadbalance_nic=ens33
|
||||
#loadbalance_netmask=23
|
||||
#############DB################
|
||||
# 数据库浮动IP,可以与LB浮动IP相同,必填
|
||||
# 浮动IP地址
|
||||
#database_fip=192.160.0.225
|
||||
# 浮动IP所在网卡
|
||||
#database_nic=baseleft
|
||||
# 掩码,CIDR格式
|
||||
#database_netmask=23
|
||||
|
||||
# 数据库共享磁盘全路径名,组件存在则必填
|
||||
# 磁盘名,建议用lv方式,使用lv时应注意配置为逻辑盘名
|
||||
#database_device=/dev/mapper/vg_mysql-lv_mysql
|
||||
# 文件系统类型
|
||||
#database_fs_type=ext4
|
||||
|
||||
#数据库备份共享磁盘全路径名,不能和其他共享磁盘相同(功能暂不支持),可选
|
||||
#backup_database_device=/dev/mapper/vg_mysqlbackup-lv_mysqlbackup
|
||||
#backup_database_fs_type=ext4
|
||||
|
||||
##############AMQP################
|
||||
# AMQP浮动IP,可以与LB浮动IP相同,必填
|
||||
#amqp_fip=192.160.0.225
|
||||
#amqp_nic=baseleft
|
||||
#amqp_netmask=23
|
||||
|
||||
##############keystone################
|
||||
# keystone浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#keystone_fip=192.160.0.225
|
||||
#keystone_nic=baseleft
|
||||
#keystone_netmask=23
|
||||
|
||||
##############neutron################
|
||||
# neutron 浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#neutron_fip=192.160.0.225
|
||||
#neutron_nic=baseleft
|
||||
#neutron_netmask=23
|
||||
|
||||
##############glance################
|
||||
# glance 浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#glance_fip=192.160.0.225
|
||||
#glance_nic=baseleft
|
||||
#glance_netmask=23
|
||||
|
||||
# 镜像共享磁盘设置,不能和其他共享磁盘相同,组件存在则必填
|
||||
# glance_device_type可选drbd或iscsi
|
||||
|
||||
#glance_device_type=drbd
|
||||
#glance_device=/dev/mapper/vg_glance-lv_glance
|
||||
#glance_fs_type=ext4
|
||||
|
||||
##############cinder################
|
||||
# cinder浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#cinder_fip=192.160.0.225
|
||||
#cinder_nic=baseleft
|
||||
#cinder_netmask=23
|
||||
|
||||
#虚拟机块设备使用的磁阵管理口IP,如果有多个IP,用空格分开,可选
|
||||
#cinder_ping_ip=192.160.0.7
|
||||
|
||||
##############nova################
|
||||
# nova浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#nova_fip=192.160.0.225
|
||||
#nova_nic=baseleft
|
||||
#nova_netmask=23
|
||||
|
||||
##############horizon################
|
||||
# TECS dashboard登录时使用的浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
# 不同浮动IP的组件可以运行在不同节点上,如果还想与
|
||||
# 某个组件运行在相同节点,需配置location_constraint
|
||||
#horizon_fip=10.43.179.230
|
||||
#horizon_nic=kmportv1
|
||||
#horizon_netmask=23
|
||||
|
||||
##############ironic################
|
||||
# ironic 浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#ironic_fip=192.160.0.225
|
||||
#ironic_nic=baseleft
|
||||
#ironic_netmask=23
|
||||
|
||||
##############heat################
|
||||
# heat 浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#heat_fip=192.160.0.225
|
||||
#heat_nic=baseleft
|
||||
#heat_netmask=23
|
||||
|
||||
##############ceilometer################
|
||||
# ceilometer浮动IP,配置为LB时,浮动IP不用填写,否则组件存在则必填
|
||||
#ceilometer_fip=192.160.0.225
|
||||
#ceilometer_nic=baseleft
|
||||
#ceilometer_netmask=23
|
||||
|
||||
# mongod数据库共享磁盘全路径名,建议配置
|
||||
#mongod_device=/dev/mapper/vg_mongodb-lv_mongodb
|
||||
# 文件系统类型
|
||||
#mongod_fs_type=ext4
|
||||
|
||||
# 若mongod数据库使用本地盘则配置成local,否则为空
|
||||
mongod_local=local
|
||||
|
||||
# 如下两个配置项表示共享盘所在的磁阵信息,暂时仅支持本配置中用到的所有共享盘都在一个磁阵上,可选
|
||||
# 参数说明:(主控制器业务口IP地址,主控制器iqn),(备控制器业务口IP地址,备控制器iqn)
|
||||
# 如果两个控制iqn相同,可以配置为(主控制器业务口IP地址,主控制器iqn)
|
||||
#iscsi_storage=(172.32.1.1,iqn.2099-01.cn.com.zte:usp.spr11-4c:09:b4:b0:56:8b),(172.32.1.2,iqn.2099-01.cn.com.zte:usp.spr11-4c:09:b4:b0:56:8c)
|
@ -1,159 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
dhcp_ip="127.0.0.1"
|
||||
DISCOVERD_URL="http://$dhcp_ip:5050/v1/continue"
|
||||
|
||||
function update() {
|
||||
jq "$1" data.json > temp.json || echo "Error: update $1 to json failed"
|
||||
mv temp.json data.json
|
||||
}
|
||||
|
||||
function get_system_info(){
|
||||
PRODUCT=$(dmidecode -s system-product-name)
|
||||
FAMILY=$(dmidecode -t system|grep "Family"|cut -d ":" -f2)
|
||||
VERSION=$(dmidecode -s system-version)
|
||||
SERIAL=$(dmidecode -s system-serial-number)
|
||||
MANUFACTURER=$(dmidecode -s system-manufacturer)
|
||||
UUID=$(dmidecode -s system-uuid)
|
||||
FQDN=$(hostname -f)
|
||||
echo '{"system":{}}' > data.json
|
||||
update ".system[\"product\"] = \"$PRODUCT\""
|
||||
update ".system[\"family\"] = \"$FAMILY\""
|
||||
update ".system[\"fqdn\"] = \"$FQDN\""
|
||||
update ".system[\"version\"] = \"$VERSION\""
|
||||
update ".system[\"serial\"] = \"$SERIAL\""
|
||||
update ".system[\"manufacturer\"] = \"$MANUFACTURER\""
|
||||
update ".system[\"uuid\"] = \"$UUID\""
|
||||
}
|
||||
|
||||
function get_cpu_info(){
|
||||
REAL=$(cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l)
|
||||
TOTAL=$(cat /proc/cpuinfo |grep "processor"|wc -l)
|
||||
update ".cpu[\"real\"] = $REAL"
|
||||
update ".cpu[\"total\"] = $TOTAL"
|
||||
|
||||
for i in $(seq $TOTAL)
|
||||
do
|
||||
if [ ! -z "$i" ]; then
|
||||
SPEC_MODEL=$(cat /proc/cpuinfo | grep name | cut -f2 -d:|sed -n $i"p")
|
||||
SPEC_FRE=$(cat /proc/cpuinfo | grep MHz | cut -f2 -d:|sed -n $i"p")
|
||||
update ".cpu[\"spec_$i\"] = {model:\"$SPEC_MODEL\", frequency:$SPEC_FRE}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function get_memory_info(){
|
||||
PHY_NUM=$(dmidecode -t memory|grep "Physical Memory Array"|wc -l)
|
||||
TOTAL_MEM=$(cat /proc/meminfo |grep MemTotal |cut -d ":" -f2)
|
||||
update ".memory[\"total\"] = \"$TOTAL_MEM\""
|
||||
for num in $(seq $PHY_NUM)
|
||||
do
|
||||
SLOTS=$(dmidecode -t memory |grep "Number Of Devices" |cut -d ":" -f2|sed -n $num"p")
|
||||
MAX_CAP=$(dmidecode -t memory |grep "Maximum Capacity" |cut -d ":" -f2|sed -n $num"p")
|
||||
update ".memory[\"phy_memory_$num\"] = {slots:\"$SLOTS\", maximum_capacity:\"$MAX_CAP\"}"
|
||||
|
||||
for i in $(seq $SLOTS)
|
||||
do
|
||||
if [ ! -z "$i" ]; then
|
||||
DEVICE_FRE=$(dmidecode -t memory |grep "Speed" |cut -d ":" -f2|sed -n $i"p")
|
||||
DEVICE_TYPE=$(dmidecode -t memory |grep 'Type:' |grep -v "Error Correction Type"|cut -d ":" -f2|sed -n $i"p")
|
||||
DEVICE_SIZE=$(dmidecode -t memory |grep Size |cut -d ":" -f2|sed -n $i"p")
|
||||
update ".memory[\"phy_memory_$num\"][\"devices_$i\"] = {frequency:\"$DEVICE_FRE\", type:\"$DEVICE_TYPE\", size:\"$DEVICE_SIZE\"}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
function get_net_info(){
|
||||
physical_networks=`ls -l /sys/class/net/ | grep -v lo |grep "pci"|awk -F 'net/' '{print $2}'`
|
||||
if [ -f "/sys/class/net/bonding_masters" ]; then
|
||||
bond_network=$(cat /sys/class/net/bonding_masters)
|
||||
if [ ! -z "$bond_network" ];then
|
||||
physical_networks+=" $bond_network"
|
||||
fi
|
||||
fi
|
||||
for iface in $physical_networks
|
||||
do
|
||||
NAME=$iface
|
||||
MAC=$(ip link show $iface | awk '/ether/ {print $2}')
|
||||
IP=$(ip addr show $iface | awk '/inet / { sub(/\/.*/, "", $2); print $2 }')
|
||||
NETMASK=$(ifconfig $iface | grep netmask | awk '{print $4}')
|
||||
STATE=$(ip link show $iface | awk '/mtu/ {print $3}')
|
||||
PCI=$(ethtool -i $iface|grep "bus-info"|cut -d " " -f2)
|
||||
CURRENT_SPEED=$(ethtool $iface |grep Speed |awk -F " " '{print $2}')
|
||||
LINE=$(ethtool $iface|grep -n "Supported pause frame use"|awk -F ":" '{print $1}')
|
||||
LINE=$[ LINE - 1 ]
|
||||
LINE_SPEED=$(ethtool $iface|grep -n "Supported link modes"|awk -F ":" '{print $1}')
|
||||
BOND=$(ifconfig $iface | grep MASTER)
|
||||
if [ $LINE -eq $LINE_SPEED ]; then
|
||||
MAX_SPEED=$(ethtool $iface|grep "Supported link modes"|cut -d ":" -f2)
|
||||
else
|
||||
MAX_SPEED=$(ethtool $iface |sed -n $LINE"p"|awk -F " " '{print $1}')
|
||||
fi
|
||||
|
||||
UP="UP"
|
||||
if [[ "$STATE" =~ "$UP" ]]; then
|
||||
STATE="up"
|
||||
else
|
||||
STATE="down"
|
||||
fi
|
||||
if [ -z "$BOND" ]; then
|
||||
TYPE="ether"
|
||||
else
|
||||
TYPE="bond"
|
||||
SLAVES=$(find /etc/sysconfig/network-scripts/ -name "ifcfg-*" |xargs grep "MASTER=$iface"|awk -F 'ifcfg-' '{print $2}'|awk -F ':' '{print $1}')
|
||||
fi
|
||||
if [ ! -z "$MAC" ]; then
|
||||
update ".interfaces[\"$iface\"] = {mac: \"$MAC\", ip: \"$IP\", netmask: \"$NETMASK\", name: \"$iface\", max_speed: \"$MAX_SPEED\", state: \"$STATE\", pci: \"$PCI\", current_speed: \"$CURRENT_SPEED\", type: \"$TYPE\", slaves:\"$SLAVES\"}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function get_disk_info(){
|
||||
for disk in $(fdisk -l|grep Disk|grep "/dev" |cut -d ":" -f1|awk -F "/" '{print $NF}')
|
||||
do
|
||||
DISK_NAME=$disk
|
||||
DISK_SIZE=$(fdisk -l|grep Disk|grep "/dev" |grep -w $disk|cut -d "," -f2)
|
||||
DISK_DISK=$(ls -l /dev/disk/by-path/|grep $disk"$"|awk '{print $9}')
|
||||
DISK_EXTRA_1=$(ls -l /dev/disk/by-id/|grep $disk"$"|awk '{print $9}'|sed -n 1p)
|
||||
DISK_EXTRA_2=$(ls -l /dev/disk/by-id/|grep $disk"$"|awk '{print $9}'|sed -n 2p)
|
||||
MODEL=$(hdparm -I /dev/sda |grep Model | cut -d ":" -f2)
|
||||
REMOVABLE=$(hdparm -I /dev/sda |grep removable|awk '{print $4}')
|
||||
update ".disk[\"$disk\"] = {name: \"$DISK_NAME\", size: \"$DISK_SIZE\", disk: \"$DISK_DISK\", model: \"$MODEL\", removable: \"$REMOVABLE\",extra: [\"$DISK_EXTRA_1\", \"$DISK_EXTRA_2\"]}"
|
||||
done
|
||||
}
|
||||
|
||||
function main(){
|
||||
get_system_info
|
||||
get_cpu_info
|
||||
get_memory_info
|
||||
get_net_info
|
||||
get_disk_info
|
||||
}
|
||||
main
|
||||
|
||||
BMC_ADDRESS=$(ipmitool lan print | grep -e "IP Address [^S]" | awk '{ print $4 }')
|
||||
if [ -z "$BMC_ADDRESS" ]; then
|
||||
BMC_ADDRESS=$(ipmitool lan print 3| grep -e "IP Address [^S]" | awk '{ print $4 }')
|
||||
fi
|
||||
update ".ipmi_address = \"$BMC_ADDRESS\""
|
||||
|
||||
update ".data_name = \"baremetal_source\""
|
||||
|
||||
update ".os_status = \"active\""
|
||||
|
||||
echo Collected:
|
||||
cat data.json
|
||||
|
||||
RESULT=$(eval curl -i -X POST \
|
||||
"-H 'Accept: application/json'" \
|
||||
"-H 'Content-Type: application/json'" \
|
||||
"-d @data.json" \
|
||||
"$DISCOVERD_URL")
|
||||
|
||||
if echo $RESULT | grep "HTTP/1.0 4"; then
|
||||
echo "Ironic API returned error: $RESULT"
|
||||
fi
|
||||
|
||||
echo "Node is now discovered! Halting..."
|
||||
sleep 5
|
Binary file not shown.
Binary file not shown.
@ -1,39 +0,0 @@
|
||||
[
|
||||
{
|
||||
"protocol_type": "ISCSI",
|
||||
"service": "glance",
|
||||
"lun": "0",
|
||||
"data_ips": [
|
||||
"10.43.177.159"
|
||||
],
|
||||
"lvm_config": {
|
||||
"size": 100,
|
||||
"vg_name": "VolGroupHAImage",
|
||||
"lv_name": "lvHAImage",
|
||||
"fs_type": "ext4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"protocol_type": "ISCSI",
|
||||
"service": "db",
|
||||
"lun": "1",
|
||||
"data_ips": [
|
||||
"162.1.1.101"
|
||||
],
|
||||
"lvm_config": {
|
||||
"size": 100,
|
||||
"vg_name": "VolGroupHAMysql",
|
||||
"lv_name": "lvHAMysql",
|
||||
"fs_type": "ext4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"protocol_type": "CEPH",
|
||||
"rbd_config": {
|
||||
"size": 100,
|
||||
"rbd_pool": "mysql",
|
||||
"rbd_volume": "mysql",
|
||||
"fs_type": "ext4" # can be none
|
||||
}
|
||||
}
|
||||
]
|
@ -1,39 +0,0 @@
|
||||
[
|
||||
{
|
||||
"protocol_type": "ISCSI",
|
||||
"service": "glance",
|
||||
"lun": "0",
|
||||
"data_ips": [
|
||||
"10.43.177.159"
|
||||
],
|
||||
"lvm_config": {
|
||||
"size": 100,
|
||||
"vg_name": "VolGroupHAImage",
|
||||
"lv_name": "lvHAImage",
|
||||
"fs_type": "ext4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"protocol_type": "ISCSI",
|
||||
"service": "db",
|
||||
"lun": "1",
|
||||
"data_ips": [
|
||||
"162.1.1.101"
|
||||
],
|
||||
"lvm_config": {
|
||||
"size": 100,
|
||||
"vg_name": "VolGroupHAMysql",
|
||||
"lv_name": "lvHAMysql",
|
||||
"fs_type": "ext4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"protocol_type": "CEPH",
|
||||
"rbd_config": {
|
||||
"size": 100,
|
||||
"rbd_pool": "mysql",
|
||||
"rbd_volume": "mysql",
|
||||
"fs_type": "ext4" # can be none
|
||||
}
|
||||
}
|
||||
]
|
@ -1,144 +0,0 @@
|
||||
# This is a basic configuration file with some examples, for device mapper
|
||||
# mulead of using WWIDs as names.
|
||||
defaults {
|
||||
user_friendly_names yes
|
||||
queue_without_daemon no
|
||||
# find_multipaths yes
|
||||
}
|
||||
##
|
||||
## Here is an example of how to configure some standard options.
|
||||
##
|
||||
#
|
||||
#defaults {
|
||||
# udev_dir /dev
|
||||
# polling_interval 10
|
||||
# selector "round-robin 0"
|
||||
# path_grouping_policy multibus
|
||||
# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
|
||||
# prio alua
|
||||
# path_checker readsector0
|
||||
# rr_min_io 100
|
||||
# max_fds 8192
|
||||
# rr_weight priorities
|
||||
# failback immediate
|
||||
# no_path_retry fail
|
||||
# user_friendly_names yes
|
||||
#}
|
||||
##
|
||||
## The wwid line in the following blacklist section is shown as an example
|
||||
## of how to blacklist devices by wwid. The 2 devnode lines are the
|
||||
## compiled in default blacklist. If you want to blacklist entire types
|
||||
## of devices, such as all scsi devices, you should use a devnode line.
|
||||
## However, if you want to blacklist specific devices, you should use
|
||||
## a wwid line. Since there is no guarantee that a specific device will
|
||||
## not change names on reboot (from /dev/sda to /dev/sdb for example)
|
||||
## devnode lines are not recommended for blacklisting specific devices.
|
||||
##
|
||||
#blacklist {
|
||||
# wwid 26353900f02796769
|
||||
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
|
||||
# devnode "^hd[a-z]"
|
||||
#}
|
||||
#multipaths {
|
||||
# multipath {
|
||||
# wwid 3600508b4000156d700012000000b0000
|
||||
# alias yellow
|
||||
# path_grouping_policy multibus
|
||||
# path_checker readsector0
|
||||
# path_selector "round-robin 0"
|
||||
# failback manual
|
||||
# rr_weight priorities
|
||||
# no_path_retry 5
|
||||
# }
|
||||
# multipath {
|
||||
# wwid 1DEC_____321816758474
|
||||
# alias red
|
||||
# }
|
||||
#}
|
||||
#devices {
|
||||
# device {
|
||||
# vendor "COMPAQ "
|
||||
# product "HSV110 (C)COMPAQ"
|
||||
# path_grouping_policy multibus
|
||||
# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
|
||||
# path_checker readsector0
|
||||
# path_selector "round-robin 0"
|
||||
# hardware_handler "0"
|
||||
# failback 15
|
||||
# rr_weight priorities
|
||||
# no_path_retry queue
|
||||
# }
|
||||
# device {
|
||||
# vendor "COMPAQ "
|
||||
# product "MSA1000 "
|
||||
# path_grouping_policy multibus
|
||||
# }
|
||||
#}
|
||||
devices {
|
||||
device {
|
||||
vendor "FUJITSU"
|
||||
product "ETERNUS_DXL"
|
||||
prio alua
|
||||
path_grouping_policy group_by_prio
|
||||
path_selector "round-robin 0"
|
||||
failback immediate
|
||||
no_path_retry 0 (*1)
|
||||
path_checker tur
|
||||
dev_loss_tmo 2097151 (*2)
|
||||
fast_io_fail_tmo 1
|
||||
}
|
||||
device {
|
||||
vendor "FUJITSU"
|
||||
product "ETERNUS_DXM"
|
||||
prio alua
|
||||
path_grouping_policy group_by_prio
|
||||
path_selector "round-robin 0"
|
||||
failback immediate
|
||||
no_path_retry 0 (*1)
|
||||
path_checker tur
|
||||
dev_loss_tmo 2097151 (*2)
|
||||
fast_io_fail_tmo 1
|
||||
}
|
||||
device {
|
||||
vendor "FUJITSU"
|
||||
product "ETERNUS_DX400"
|
||||
prio alua
|
||||
path_grouping_policy group_by_prio
|
||||
path_selector "round-robin 0"
|
||||
failback immediate
|
||||
no_path_retry 0 (*1)
|
||||
path_checker tur
|
||||
dev_loss_tmo 2097151 (*2)
|
||||
fast_io_fail_tmo 1
|
||||
}
|
||||
device {
|
||||
vendor "FUJITSU"
|
||||
product "ETERNUS_DX8000"
|
||||
prio alua
|
||||
path_grouping_policy group_by_prio
|
||||
path_selector "round-robin 0"
|
||||
failback immediate
|
||||
no_path_retry 0 (*1)
|
||||
path_checker tur
|
||||
dev_loss_tmo 2097151 (*2)
|
||||
fast_io_fail_tmo 1
|
||||
}
|
||||
device {
|
||||
vendor "ZTE"
|
||||
product "ZXUSP"
|
||||
path_grouping_policy group_by_prio
|
||||
path_checker tur
|
||||
prio alua
|
||||
path_selector "round-robin 0"
|
||||
hardware_handler "1 alua"
|
||||
failback immediate
|
||||
rr_weight priorities
|
||||
no_path_retry 0 (*1)
|
||||
rr_min_io_rq 1
|
||||
flush_on_last_del yes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
blacklist {
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
|
||||
import uuid
|
||||
from utils import *
|
||||
from xml.etree.ElementTree import ElementTree, Element
|
||||
|
||||
|
||||
class BaseConfig():
|
||||
_CINDER_CONF_PATH = "/etc/cinder/cinder.conf"
|
||||
SET_CONFIG = \
|
||||
"openstack-config --set {config_file} {section} {key} {value}"
|
||||
GET_CONFIG = \
|
||||
"openstack-config --get {config_file} {section} {key}"
|
||||
instance = None
|
||||
|
||||
def __init__(self):
|
||||
self._BACKEND_MAPPING = {
|
||||
'KS3200_IPSAN': ZTEBackendConfig,
|
||||
'KS3200_FCSAN': ZTEBackendConfig,
|
||||
'FUJISTU_ETERNUS': FUJISTUBackendConfig,
|
||||
'LVM': None,
|
||||
'CEPH': CEPHBackendConfig,
|
||||
}
|
||||
self.instance_mapping = {}
|
||||
|
||||
def __get_backend_instance(self, backend_type):
|
||||
if not backend_type or \
|
||||
backend_type not in self._BACKEND_MAPPING.keys():
|
||||
print_or_raise("Volume driver type '%s' is not valid." %
|
||||
backend_type,
|
||||
ScriptInnerError)
|
||||
|
||||
backend_instance = self.instance_mapping.get(backend_type, BaseConfig)
|
||||
if isinstance(backend_instance, self._BACKEND_MAPPING[backend_type]):
|
||||
return backend_instance
|
||||
else:
|
||||
self.instance_mapping.update(
|
||||
{backend_type: self._BACKEND_MAPPING[backend_type]()})
|
||||
return self.instance_mapping[backend_type]
|
||||
|
||||
@classmethod
|
||||
def single_instance(cls):
|
||||
if not BaseConfig.instance:
|
||||
BaseConfig.instance = BaseConfig()
|
||||
return BaseConfig.instance
|
||||
|
||||
def _construct_particular_cinder_data(self, backend, backend_data):
|
||||
print_or_raise("Backend _construct_particular_cinder_data method no "
|
||||
"implement!", ScriptInnerError)
|
||||
|
||||
def _write_xml(self, fp_xml, **backend_device_args):
|
||||
self.backend_instance._write_xml(fp_xml, **backend_device_args)
|
||||
|
||||
def _construct_commonality_cinder_data(self, backend, backend_data):
|
||||
backend_pools, xml_path = \
|
||||
self.backend_instance._construct_particular_cinder_data(
|
||||
backend, backend_data)
|
||||
|
||||
backend_data['volume_backend_name'] = \
|
||||
backend_data.pop('volume_type')
|
||||
|
||||
set_backend = lambda x, y: self.SET_CONFIG.format(
|
||||
config_file=self._CINDER_CONF_PATH,
|
||||
section=backend,
|
||||
key=x, value=y)
|
||||
|
||||
backend_config_list = list()
|
||||
backend_config_list += map(
|
||||
set_backend, backend_data.keys(), backend_data.values())
|
||||
|
||||
get_bakcends = \
|
||||
self.GET_CONFIG.format(config_file=self._CINDER_CONF_PATH,
|
||||
section="DEFAULT",
|
||||
key="enabled_backends")
|
||||
out, err = execute(get_bakcends, check_exit_code=[0, 1])
|
||||
exist_backends = out.split("\n")[0] if out else ""
|
||||
enabled_backends = \
|
||||
exist_backends if backend in exist_backends else \
|
||||
"%s" % backend if not out else "%s,%s" % \
|
||||
(exist_backends, backend)
|
||||
set_bakcends = \
|
||||
self.SET_CONFIG.format(config_file=self._CINDER_CONF_PATH,
|
||||
section="DEFAULT",
|
||||
key="enabled_backends",
|
||||
value=enabled_backends)
|
||||
|
||||
# write to cinder.conf
|
||||
config_set_all = set_bakcends + ";" + ";".join(backend_config_list)
|
||||
execute(config_set_all)
|
||||
|
||||
return backend_pools, xml_path
|
||||
|
||||
def is_needed_generate_backend_xml(self, backend_driver):
|
||||
if backend_driver in ['KS3200_IPSAN', 'KS3200_FCSAN',
|
||||
'FUJISTU_ETERNUS']:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def config_backend(self, backend_cinder_args, **backend_device_args):
|
||||
"""
|
||||
Config outer interface,for public flow.
|
||||
:param backend_device_args: device config
|
||||
:param backend_cinder_args: backend config
|
||||
:return:
|
||||
"""
|
||||
backend_data = backend_cinder_args[1]
|
||||
backend_driver = backend_data.get('volume_driver', None)
|
||||
self.backend_instance = self.__get_backend_instance(backend_driver)
|
||||
|
||||
# config cinder.conf
|
||||
backend_pools, xml_path = \
|
||||
self._construct_commonality_cinder_data(backend_cinder_args[0],
|
||||
backend_data)
|
||||
|
||||
# config xml
|
||||
if self.is_needed_generate_backend_xml(backend_driver):
|
||||
backend_device_args.update({'pools': backend_pools})
|
||||
with open(xml_path, "w+") as fp_xml:
|
||||
self._write_xml(fp_xml, **backend_device_args)
|
||||
execute("chown cinder:cinder %s" % xml_path)
|
||||
|
||||
def update_xml_node(self, element_obj, node_path, content):
|
||||
node_list = element_obj.findall(node_path)
|
||||
if node_list:
|
||||
node_list[0].text = content
|
||||
else:
|
||||
new_element = Element(node_path.split('/')[-1])
|
||||
new_element.text = content
|
||||
parent_node = element_obj.findall(node_path.split('/')[0])
|
||||
parent_node[0].append(new_element)
|
||||
|
||||
|
||||
class ZTEBackendConfig(BaseConfig):
|
||||
_DEFAULT_USERNAME = "admin"
|
||||
_DEFAULT_USERPWD = "admin"
|
||||
_DEFAULT_XML_FILE_PREFIX = "cinder_zte_conf_file"
|
||||
_DEFAULT_XML_TEMPLATE_PATH = "/etc/cinder/cinder_zte_conf.xml"
|
||||
_ISCSI_DRIVER = 'cinder.volume.drivers.zte.zte_ks.ZteISCSIDriver'
|
||||
_FC_DRIVER = 'cinder.volume.drivers.zte.zte_ks.ZteFCDriver'
|
||||
|
||||
def _construct_particular_cinder_data(self, backend, backend_data):
|
||||
# construct commonality data in cinder.conf
|
||||
backend_data['volume_driver'] = \
|
||||
self._ISCSI_DRIVER \
|
||||
if "KS3200_IPSAN" == backend_data['volume_driver'] \
|
||||
else self._FC_DRIVER
|
||||
backend_data[self._DEFAULT_XML_FILE_PREFIX] = \
|
||||
backend_data.pop('backend_config_file') \
|
||||
if backend_data.get('backend_config_file', None) \
|
||||
else "/etc/cinder/%s_%s.xml" % (self._DEFAULT_XML_FILE_PREFIX,
|
||||
backend)
|
||||
backend_data['use_multipath_for_image_xfer'] = \
|
||||
backend_data.get('multipath_tool', True)
|
||||
backend_pools = backend_data.pop('pools')
|
||||
|
||||
return backend_pools, backend_data[self._DEFAULT_XML_FILE_PREFIX]
|
||||
|
||||
def _write_xml(self, fp, **backend_device_args):
|
||||
if not os.path.exists(self._DEFAULT_XML_TEMPLATE_PATH):
|
||||
print_or_raise("XML file template %s not exists,can't load defult "
|
||||
"params." % self._DEFAULT_XML_TEMPLATE_PATH,
|
||||
ScriptInnerError)
|
||||
|
||||
mgnt_ips = backend_device_args['management_ips']
|
||||
user_name = backend_device_args['user_name']
|
||||
user_pwd = backend_device_args['user_pwd']
|
||||
cinder_host_ip = backend_device_args['cinder_host_ip']
|
||||
pools = backend_device_args['pools']
|
||||
xml_fp = fp
|
||||
|
||||
tree = ElementTree()
|
||||
elements = tree.parse(self._DEFAULT_XML_TEMPLATE_PATH)
|
||||
for index in range(len(mgnt_ips)):
|
||||
self.update_xml_node(
|
||||
elements,
|
||||
"Storage/ControllerIP" + str(index), mgnt_ips[index])
|
||||
|
||||
if cinder_host_ip:
|
||||
self.update_xml_node(elements, "Storage/LocalIP", cinder_host_ip)
|
||||
self.update_xml_node(elements, "Storage/UserName", user_name)
|
||||
self.update_xml_node(elements, "Storage/UserPassword", user_pwd)
|
||||
|
||||
# del all StoragePool and StorageVd node
|
||||
pool_parent_node = elements.findall("LUN")
|
||||
pool_child_nodes = elements.findall("LUN/StoragePool")
|
||||
vd_child_nodes = elements.findall("LUN/StorageVd")
|
||||
map(pool_parent_node[0].remove, pool_child_nodes + vd_child_nodes)
|
||||
|
||||
# add StoragePool node base on pools
|
||||
for pool in pools:
|
||||
element = Element("StoragePool")
|
||||
element.text = pool
|
||||
element.tail = "\n\t"
|
||||
pool_parent_node[0].insert(0, element)
|
||||
|
||||
tree.write(xml_fp, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
class FUJISTUBackendConfig(BaseConfig):
|
||||
_DEFAULT_USERNAME = "root"
|
||||
_DEFAULT_USERPWD = "root"
|
||||
_DEFAULT_XML_FILE_PREFIX = "cinder_eternus_config_file"
|
||||
_DEFAULT_XML_TEMPLATE_PATH = \
|
||||
"/etc/cinder/cinder_fujitsu_eternus_dx.xml"
|
||||
FUJISTU_DRIVER = \
|
||||
"cinder.volume.drivers.fujitsu.eternus_dx_iscsi.FJDXISCSIDriver"
|
||||
|
||||
def _construct_particular_cinder_data(self, backend, backend_data):
|
||||
# construct commonality data in cinder.conf
|
||||
backend_data['volume_driver'] = self.FUJISTU_DRIVER
|
||||
backend_data[self._DEFAULT_XML_FILE_PREFIX] = \
|
||||
backend_data.pop('backend_config_file') \
|
||||
if backend_data.get('backend_config_file', None) \
|
||||
else "/etc/cinder/%s_%s.xml" % (self._DEFAULT_XML_FILE_PREFIX,
|
||||
backend)
|
||||
backend_data['use_multipath_for_image_xfer'] = \
|
||||
backend_data.get('multipath_tool', True)
|
||||
backend_data['use_fujitsu_image_volume'] = \
|
||||
backend_data.get('use_fujitsu_image_volume', True)
|
||||
backend_data['fujitsu_min_image_volume_per_storage'] = \
|
||||
backend_data.get('fujitsu_min_image_volume_per_storage', 1)
|
||||
backend_data['fujitsu_image_management_dir'] = \
|
||||
backend_data.get('fujitsu_image_management_dir',
|
||||
'/var/lib/glance/conversion')
|
||||
backend_pools = backend_data.pop('pools')
|
||||
|
||||
return backend_pools, backend_data[self._DEFAULT_XML_FILE_PREFIX]
|
||||
|
||||
def _write_xml(self, fp, **backend_device_args):
|
||||
if not os.path.exists(self._DEFAULT_XML_TEMPLATE_PATH):
|
||||
print_or_raise("XML file template %s not exists,can't load defult "
|
||||
"params." % self._DEFAULT_XML_TEMPLATE_PATH,
|
||||
ScriptInnerError)
|
||||
|
||||
mgnt_ip = backend_device_args['management_ips'][0]
|
||||
data_ips = backend_device_args['data_ips']
|
||||
user_name = backend_device_args['user_name']
|
||||
user_pwd = backend_device_args['user_pwd']
|
||||
pool = backend_device_args['pools'][0]
|
||||
xml_fp = fp
|
||||
|
||||
tree = ElementTree()
|
||||
elements = tree.parse(self._DEFAULT_XML_TEMPLATE_PATH)
|
||||
self.update_xml_node(elements, "EternusIP", mgnt_ip)
|
||||
self.update_xml_node(elements, "EternusUser", user_name)
|
||||
self.update_xml_node(elements, "EternusPassword", user_pwd)
|
||||
self.update_xml_node(elements, "EternusPool", pool)
|
||||
self.update_xml_node(elements, "EternusSnapPool", pool)
|
||||
|
||||
root = tree.getroot()
|
||||
map(root.remove, root.findall("EternusISCSIIP"))
|
||||
for ip in data_ips:
|
||||
element = Element("EternusISCSIIP")
|
||||
element.text = ip
|
||||
element.tail = "\n"
|
||||
root.insert(4, element)
|
||||
# root.append(element)
|
||||
|
||||
tree.write(xml_fp, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
class CEPHBackendConfig(BaseConfig):
|
||||
NOVA_CONF_FILE = "/etc/nova/nova.conf"
|
||||
GLANCE_API_CONF_FILE = "/etc/glance/glance-api.conf"
|
||||
_RBD_STORE_USER = "cinder"
|
||||
_RBD_POOL = "volumes"
|
||||
_RBD_MAX_CLONE_DEPTH = 5
|
||||
_RBD_FLATTEN_VOLUME_FROM_SNAPSHOT = "False"
|
||||
_RBD_CEPH_CONF = "/etc/ceph/ceph.conf"
|
||||
_RBD_DRIVER = 'cinder.volume.drivers.rbd.RBDDriver'
|
||||
|
||||
def _construct_particular_cinder_data(self, backend, backend_data):
|
||||
backend_data['volume_driver'] = self._RBD_DRIVER
|
||||
backend_data['rbd_pool'] = self._RBD_POOL
|
||||
backend_data['rbd_max_clone_depth'] = self._RBD_MAX_CLONE_DEPTH
|
||||
backend_data['rbd_flatten_volume_from_snapshot'] = \
|
||||
self._RBD_FLATTEN_VOLUME_FROM_SNAPSHOT
|
||||
backend_data['rbd_ceph_conf'] = self._RBD_CEPH_CONF
|
||||
uuid_instance = uuid.uuid3(uuid.NAMESPACE_DNS, "zte.com.cn")
|
||||
backend_data['rbd_secret_uuid'] = uuid_instance.urn.split(":")[2]
|
||||
return [], []
|
@ -1,312 +0,0 @@
|
||||
|
||||
from utils import *
|
||||
|
||||
|
||||
class BaseShareDisk():
|
||||
instance = None
|
||||
|
||||
def __init__(self):
|
||||
self._PROTOCOL_MAPPING = {
|
||||
'ISCSI': ISCSIShareDisk,
|
||||
'CEPH': CEPHShareDisk
|
||||
}
|
||||
self.instance_mapping = {}
|
||||
|
||||
def __get_protocol_instance(self, protocol_type):
|
||||
if not protocol_type or \
|
||||
protocol_type not in self._PROTOCOL_MAPPING.keys():
|
||||
print_or_raise("Protocol type '%s' is not valid." % protocol_type,
|
||||
ScriptInnerError)
|
||||
|
||||
protocol_instance = self.instance_mapping.get(protocol_type,
|
||||
BaseShareDisk)
|
||||
if isinstance(protocol_instance,
|
||||
self._PROTOCOL_MAPPING[protocol_type]):
|
||||
return protocol_instance
|
||||
else:
|
||||
self.instance_mapping.update(
|
||||
{protocol_type: self._PROTOCOL_MAPPING[protocol_type]()})
|
||||
return self.instance_mapping[protocol_type]
|
||||
|
||||
@classmethod
|
||||
def single_instance(cls):
|
||||
if not BaseShareDisk.instance:
|
||||
BaseShareDisk.instance = BaseShareDisk()
|
||||
return BaseShareDisk.instance
|
||||
|
||||
def deploy_share_disk(self, item, host_name):
|
||||
protocol_instance = self.__get_protocol_instance(
|
||||
item.get('protocol_type', 'ISCSI'))
|
||||
protocol_instance.deploy_share_disk(item, host_name)
|
||||
|
||||
|
||||
class ISCSIShareDisk(BaseShareDisk):
|
||||
_LV_DEFAULT_NAME = {
|
||||
'glance': ("VolGroupHAImage", "lvHAImage", 254),
|
||||
'db': ("VolGroupHAMysql", "lvHAMysql", 253),
|
||||
'db_backup': ("VolGroupHABakMysql", "lvHABakMysql", 252),
|
||||
'mongodb': ("VolGroupHAMongodb", "lvHAMongodb", 251),
|
||||
}
|
||||
|
||||
def _get_iscsi_configs(self, record_list):
|
||||
raid_config = {}
|
||||
for record in record_list:
|
||||
discovery_media_ip = record.split(" ")[0].split(":")[0]
|
||||
discovery_media_iqn = record.split(" ")[1]
|
||||
try:
|
||||
execute("ping -c 1 -W 2 %s" % discovery_media_ip)
|
||||
except ProcessExecutionError:
|
||||
execute("iscsiadm -m node -T %s -p %s -o delete" %
|
||||
(discovery_media_iqn, discovery_media_ip),
|
||||
check_exit_code=[0, 1])
|
||||
continue
|
||||
|
||||
if discovery_media_ip in raid_config.get(discovery_media_iqn, []):
|
||||
execute("iscsiadm -m node -T %s -p %s -R" %
|
||||
(discovery_media_iqn, discovery_media_ip),
|
||||
check_exit_code=[0, 1])
|
||||
|
||||
elif discovery_media_iqn in raid_config.keys():
|
||||
raid_config[discovery_media_iqn] += [discovery_media_ip]
|
||||
else:
|
||||
raid_config[discovery_media_iqn] = [discovery_media_ip]
|
||||
|
||||
print_or_raise("Raid config is:\n%s" % str(raid_config))
|
||||
return raid_config
|
||||
|
||||
def _lv_reentrant_check(
|
||||
self, vg_name, lv_name, iscsi_session_setup, lun=None,
|
||||
data_ips=[]):
|
||||
"""
|
||||
Check if share disk operation is reentrant.
|
||||
:return:True,continue follow action; False, do nothing.
|
||||
"""
|
||||
lv_device_path = "/dev/%s/%s" % (vg_name, lv_name)
|
||||
if not os.path.exists(lv_device_path):
|
||||
return True
|
||||
|
||||
if not iscsi_session_setup:
|
||||
exist_volumes = \
|
||||
[sd for sd in self._ls_sd_path() if "-lun-" + lun in sd
|
||||
for ip in data_ips if "ip-" + ip in sd]
|
||||
if not exist_volumes:
|
||||
print_or_raise("Lvm %s is exist, but no sd device match!" %
|
||||
lv_device_path, ScriptInnerError)
|
||||
|
||||
return False
|
||||
|
||||
def _lv_rollback(self, lv, vg, block_device):
|
||||
try:
|
||||
execute("lvremove -y -ff /dev/%s/%s" % (lv, vg),
|
||||
check_exit_code=[0, 1, 5])
|
||||
execute("vgremove -y -ff %s" % vg, check_exit_code=[0, 1, 5])
|
||||
execute("pvremove -y -ff %s" % block_device,
|
||||
check_exit_code=[0, 1, 5])
|
||||
except Exception as e:
|
||||
print_or_raise("Rollback lvm resource failed!", e)
|
||||
|
||||
def _establish_iscsi_session(self, available_data_ips):
|
||||
# discovery
|
||||
discovery_ret = ""
|
||||
for ip in available_data_ips:
|
||||
out, err = execute(
|
||||
"iscsiadm -m discovery -t st -p %s:3260" % ip)
|
||||
discovery_ret += out
|
||||
# if('0' != err) or ('0\n' != err ) or err:
|
||||
# print_or_raise("Discovery ip:%s failed,continue.." % ip)
|
||||
|
||||
if not discovery_ret:
|
||||
print_or_raise("No discovery record!", ScriptInnerError)
|
||||
|
||||
record_list = list(set(discovery_ret.split('\n')[:-1]))
|
||||
print_or_raise(
|
||||
"Discovery successful! Record:\n%s" % "\n".join(record_list))
|
||||
|
||||
# get iqn and ip like {iqn1: ip1, iqn2:ip2}
|
||||
raid_config = self._get_iscsi_configs(record_list)
|
||||
|
||||
# auto config & login
|
||||
login_cmd = \
|
||||
lambda x, y: "iscsiadm -m node -T %s -p %s:3260 -l" % (x, y)
|
||||
auto_cmd = \
|
||||
lambda x, y: "iscsiadm -m node -T %s -p %s -o update -n " \
|
||||
"node.startup -v automatic" % (x, y)
|
||||
login = []
|
||||
auto_config = []
|
||||
for index in range(len(raid_config.keys())):
|
||||
k = raid_config.keys()[index]
|
||||
v = raid_config[k]
|
||||
login += map(login_cmd, [k] * len(v), v)
|
||||
auto_config += map(auto_cmd, [k] * len(v), v)
|
||||
execute(";".join(login))
|
||||
execute(";".join(auto_config))
|
||||
print_or_raise("Login successful!")
|
||||
return raid_config
|
||||
|
||||
def _modify_host_iqn(self, host_name):
|
||||
# modify host IQN
|
||||
host_iqn, err = execute("cat /etc/iscsi/initiatorname.iscsi")
|
||||
md5_str, err = execute("echo -n %s | openssl md5" % host_name)
|
||||
host_iqn = host_iqn.split("=")[1].strip()
|
||||
wish_iqn = "iqn.opencos.rh:" + md5_str.split("=")[1].strip()
|
||||
if wish_iqn != host_iqn:
|
||||
print_or_raise(
|
||||
"The host iqn is:%s, but wish iqn is %s, it will be modified."
|
||||
% (host_iqn, wish_iqn))
|
||||
with open("/etc/iscsi/initiatorname.iscsi", "w") as fp:
|
||||
fp.write("InitiatorName=" + wish_iqn + "\n")
|
||||
execute("systemctl restart iscsid.service")
|
||||
|
||||
def _ls_sd_path(self):
|
||||
out, err = execute("ls /dev/disk/by-path")
|
||||
return out.split("\n")[:-1]
|
||||
|
||||
def _find_multipath_by_sd(self, iqns, lun_id):
|
||||
sd_path = []
|
||||
attemps = 0
|
||||
while not sd_path:
|
||||
sd_path = \
|
||||
[sd for sd in self._ls_sd_path()
|
||||
if filter(lambda complex_sd_path: complex_sd_path in sd,
|
||||
[iqn + "-lun-" + str(lun_id) for iqn in iqns])]
|
||||
attemps += 1
|
||||
|
||||
if attemps == 5:
|
||||
execute("iscsiadm -m node -R")
|
||||
elif attemps > 10:
|
||||
print_or_raise(
|
||||
"After login successful,"
|
||||
"there is no local sd device match with block device.",
|
||||
ScriptInnerError)
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
sd_path = "/dev/disk/by-path/" + sd_path[0]
|
||||
sd_real_path = os.path.realpath(sd_path)
|
||||
|
||||
attemps = 0
|
||||
multipath_path = ""
|
||||
while not os.path.exists(multipath_path):
|
||||
multipath_device, err = execute("multipath -l %s" % sd_real_path)
|
||||
# if not multipath_device or ('0' != err) or ('0\n' != err) or err:
|
||||
# continue
|
||||
|
||||
multipath_path = "/dev/mapper/" + \
|
||||
multipath_device.split("\n")[0].split(" ")[0]
|
||||
attemps += 1
|
||||
|
||||
if attemps > 5:
|
||||
print_or_raise(
|
||||
"No multipath match with local sd device:%s." %
|
||||
sd_real_path,
|
||||
ScriptInnerError)
|
||||
time.sleep(2)
|
||||
|
||||
return multipath_path
|
||||
|
||||
def _create_lv_by_multipath_device(
|
||||
self, multipath, vg_name, lv_name, size, fs_type):
|
||||
try:
|
||||
# create lvm base on block device
|
||||
execute("pvcreate -y -ff %s" % multipath,
|
||||
check_exit_code=[0, 1, 5])
|
||||
execute("vgcreate -y -ff %s %s" % (vg_name, multipath),
|
||||
check_exit_code=[0, 1, 5])
|
||||
|
||||
if size == -1:
|
||||
lvcreate = "lvcreate -W y -l 100%%FREE -n %s %s" % \
|
||||
(lv_name, vg_name)
|
||||
else:
|
||||
lvcreate = "lvcreate -W y -L %sG -n %s %s" % \
|
||||
(round(size * 0.95, 2), lv_name, vg_name)
|
||||
execute(lvcreate, check_exit_code=[0, 1, 5])
|
||||
execute("pvscan --cache --activate ay")
|
||||
|
||||
# make filesystem
|
||||
execute("mkfs.%s /dev/%s/%s" % (fs_type, vg_name, lv_name))
|
||||
except Exception as e:
|
||||
self._lv_rollback(lv_name, vg_name, multipath)
|
||||
print_or_raise("LVM create failed, resource has been rollbacked.",
|
||||
e)
|
||||
|
||||
def deploy_share_disk(self, item, host_name):
|
||||
config_computer()
|
||||
self._modify_host_iqn(host_name)
|
||||
service = item['service']
|
||||
if service not in ['glance', 'db', 'db_backup', 'mongodb']:
|
||||
print_or_raise("Service name '%s' is not valid." % service)
|
||||
|
||||
# check ip
|
||||
available_data_ips, invalid_ips = \
|
||||
get_available_data_ip(item['data_ips'])
|
||||
if not available_data_ips:
|
||||
print_or_raise("No valid data ips,please check.", ScriptInnerError)
|
||||
|
||||
raid_config = self._establish_iscsi_session(available_data_ips)
|
||||
|
||||
lv_config = item.get('lvm_config', None)
|
||||
vg_name = lv_config.get('vg_name', self._LV_DEFAULT_NAME[service][0])
|
||||
lv_name = lv_config.get('lv_name', self._LV_DEFAULT_NAME[service][1])
|
||||
if not self._lv_reentrant_check(vg_name, lv_name, True):
|
||||
return
|
||||
|
||||
multipath = self._find_multipath_by_sd(
|
||||
raid_config.keys(),
|
||||
item.get('lun', self._LV_DEFAULT_NAME[service][2]))
|
||||
|
||||
self._create_lv_by_multipath_device(multipath,
|
||||
vg_name,
|
||||
lv_name,
|
||||
lv_config.get('size', -1),
|
||||
lv_config.get('fs_type', 'ext4'))
|
||||
|
||||
|
||||
class CEPHShareDisk(BaseShareDisk):
|
||||
def __init__(self):
|
||||
self.monitor_ip = ''
|
||||
self.monitor_passwd = ''
|
||||
|
||||
def deploy_share_disk(self, item, host_name):
|
||||
self.monitor_ip = item.get('monitor_ip', '')
|
||||
self.monitor_passwd = item.get('monitor_passwd', '')
|
||||
rbd_pool = item['rbd_config']['rbd_pool']
|
||||
rbd_img = item['rbd_config']['rbd_volume']
|
||||
img_size = int(item['rbd_config']['size'])*1024
|
||||
fs_type = item['rbd_config'].get('fs_type', 'ext4')
|
||||
cmd_create = 'sshpass -p %s ssh %s rbd create -p %s --size %s %s ' % \
|
||||
(self.monitor_passwd,
|
||||
self.monitor_ip,
|
||||
rbd_pool,
|
||||
img_size,
|
||||
rbd_img)
|
||||
cmd_query = 'sshpass -p %s ssh %s rbd ls -l %s' % (
|
||||
self.monitor_passwd, self.monitor_ip, rbd_pool)
|
||||
image_in_monitor = []
|
||||
print_or_raise("Create image %s in pool %s at monitor %s." %
|
||||
(rbd_img, rbd_pool, self.monitor_ip))
|
||||
try:
|
||||
out, err = execute(cmd_query)
|
||||
if out:
|
||||
for line in out.splitlines():
|
||||
image_in_monitor.append(line.split()[0])
|
||||
if rbd_img not in image_in_monitor:
|
||||
execute(cmd_create)
|
||||
except Exception as e:
|
||||
print_or_raise("Query pool %s in monitor error or create image %s "
|
||||
"in pool %s." % (rbd_pool, rbd_img, rbd_pool), e)
|
||||
execute("systemctl stop rbdmap")
|
||||
rbd_map = '%s/%s id=admin,' \
|
||||
'keyring=/etc/ceph/ceph.client.admin.keyring' % (rbd_pool,
|
||||
rbd_img)
|
||||
rbd_map_need_to_write = True
|
||||
print_or_raise("Write rbdmap.")
|
||||
with open("/etc/ceph/rbdmap", "a+") as fp:
|
||||
for line in fp:
|
||||
if line == rbd_map + "\n":
|
||||
rbd_map_need_to_write = False
|
||||
if rbd_map_need_to_write is True:
|
||||
fp.write(rbd_map + "\n")
|
||||
execute("chmod 777 /etc/ceph/rbdmap")
|
||||
execute("systemctl enable rbdmap")
|
||||
execute("systemctl start rbdmap")
|
||||
execute("mkfs.%s /dev/rbd/%s/%s" % (fs_type, rbd_pool, rbd_img))
|
@ -1,231 +0,0 @@
|
||||
import subprocess
|
||||
import random
|
||||
import shlex
|
||||
import signal
|
||||
import time
|
||||
import os
|
||||
import logging
|
||||
|
||||
|
||||
LOG = logging.getLogger()
|
||||
formatter = "%(asctime)s %(name)s %(levelname)s %(message)s"
|
||||
logging.basicConfig(format=formatter,
|
||||
filename="storage_auto_config.log",
|
||||
filemode="a",
|
||||
level=logging.DEBUG)
|
||||
stream_log = logging.StreamHandler()
|
||||
stream_log.setLevel(logging.DEBUG)
|
||||
stream_log.setFormatter(logging.Formatter(formatter))
|
||||
LOG.addHandler(stream_log)
|
||||
|
||||
|
||||
def print_or_raise(msg, exc=None):
|
||||
if not exc:
|
||||
LOG.debug(msg)
|
||||
else:
|
||||
if isinstance(exc, Exception):
|
||||
LOG.error(msg)
|
||||
raise exc
|
||||
elif issubclass(exc, Exception):
|
||||
raise exc(msg)
|
||||
|
||||
|
||||
class ScriptInnerError(Exception):
|
||||
def __init__(self, message=None):
|
||||
super(ScriptInnerError, self).__init__(message)
|
||||
|
||||
|
||||
class UnknownArgumentError(Exception):
|
||||
def __init__(self, message=None):
|
||||
super(UnknownArgumentError, self).__init__(message)
|
||||
|
||||
|
||||
class NoRootWrapSpecified(Exception):
|
||||
def __init__(self, message=None):
|
||||
super(NoRootWrapSpecified, self).__init__(message)
|
||||
|
||||
|
||||
class ProcessExecutionError(Exception):
|
||||
def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
|
||||
description=None):
|
||||
self.exit_code = exit_code
|
||||
self.stderr = stderr
|
||||
self.stdout = stdout
|
||||
self.cmd = cmd
|
||||
self.description = description
|
||||
|
||||
if description is None:
|
||||
description = "Unexpected error while running command."
|
||||
if exit_code is None:
|
||||
exit_code = '-'
|
||||
message = ("%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r"
|
||||
% (description, cmd, exit_code, stdout, stderr))
|
||||
super(ProcessExecutionError, self).__init__(message)
|
||||
|
||||
|
||||
def execute(cmd, **kwargs):
|
||||
"""Helper method to shell out and execute a command through subprocess.
|
||||
|
||||
Allows optional retry.s
|
||||
|
||||
:param cmd: Passed to subprocess.Popen.
|
||||
:type cmd: string
|
||||
TODO:param process_input: Send to opened process.
|
||||
:type proces_input: string
|
||||
TODO:param check_exit_code: Single bool, int, or list of allowed exit
|
||||
codes. Defaults to [0]. Raise
|
||||
:class:`ProcessExecutionError` unless
|
||||
program exits with one of these code.
|
||||
:type check_exit_code: boolean, int, or [int]
|
||||
:param delay_on_retry: True | False. Defaults to True. If set to True,
|
||||
wait a short amount of time before retrying.
|
||||
:type delay_on_retry: boolean
|
||||
:param attempts: How many times to retry cmd.
|
||||
:type attempts: int
|
||||
TODO:param run_as_root: True | False. Defaults to False. If set to True,
|
||||
the command is prefixed by the command specified
|
||||
in the root_helper kwarg.
|
||||
:type run_as_root: boolean
|
||||
:param root_helper: command to prefix to commands called with
|
||||
run_as_root=True
|
||||
:type root_helper: string
|
||||
TODO:param shell: whether or not there should be a shell used to
|
||||
execute this command. Defaults to false.
|
||||
:type shell: boolean
|
||||
:param loglevel: log level for execute commands.
|
||||
:type loglevel: int. (Should be logging.DEBUG or logging.INFO)
|
||||
:returns: (stdout, stderr) from process execution
|
||||
:raises: :class:`UnknownArgumentError` on
|
||||
receiving unknown arguments
|
||||
:raises: :class:`ProcessExecutionError`
|
||||
"""
|
||||
def _subprocess_setup():
|
||||
# Python installs a SIGPIPE handler by default.
|
||||
# This is usually not what non-Python subprocesses expect.
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
|
||||
# stdin
|
||||
process_input = kwargs.pop('process_input', None)
|
||||
check_exit_code = kwargs.pop('check_exit_code', [0])
|
||||
ignore_exit_code = False
|
||||
delay_on_retry = kwargs.pop('delay_on_retry', True)
|
||||
attempts = kwargs.pop('attempts', 1)
|
||||
run_as_root = kwargs.pop('run_as_root', False)
|
||||
root_helper = kwargs.pop('root_helper', '')
|
||||
shell = kwargs.pop('shell', True)
|
||||
silent = kwargs.pop('silent', False)
|
||||
# loglevel = kwargs.pop('loglevel', logging.DEBUG)
|
||||
|
||||
if isinstance(check_exit_code, bool):
|
||||
ignore_exit_code = not check_exit_code
|
||||
check_exit_code = [0]
|
||||
elif isinstance(check_exit_code, int):
|
||||
check_exit_code = [check_exit_code]
|
||||
|
||||
if kwargs:
|
||||
raise UnknownArgumentError(
|
||||
'Got unknown keyword args to utils.execute: %r' % kwargs)
|
||||
|
||||
if run_as_root and hasattr(os, 'geteuid') and os.geteuid() != 0:
|
||||
if not root_helper:
|
||||
raise NoRootWrapSpecified(
|
||||
message=('Command requested root, but did not specify a root '
|
||||
'helper.'))
|
||||
cmd = shlex.split(root_helper) + list(cmd)
|
||||
|
||||
while attempts > 0:
|
||||
attempts -= 1
|
||||
try:
|
||||
if not silent:
|
||||
print_or_raise('Running cmd (subprocess): %s' % cmd)
|
||||
|
||||
# windows
|
||||
if os.name == 'nt':
|
||||
preexec_fn = None
|
||||
close_fds = False
|
||||
else:
|
||||
preexec_fn = _subprocess_setup
|
||||
close_fds = True
|
||||
|
||||
obj = subprocess.Popen(cmd,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
close_fds=close_fds,
|
||||
preexec_fn=preexec_fn,
|
||||
shell=shell)
|
||||
|
||||
if process_input is not None:
|
||||
result = obj.communicate(process_input)
|
||||
else:
|
||||
result = obj.communicate()
|
||||
obj.stdin.close()
|
||||
_returncode = obj.returncode
|
||||
if not silent:
|
||||
print_or_raise('Result was %s' % _returncode)
|
||||
if not ignore_exit_code and _returncode not in check_exit_code:
|
||||
(stdout, stderr) = result
|
||||
raise ProcessExecutionError(exit_code=_returncode,
|
||||
stdout=stdout,
|
||||
stderr=stderr,
|
||||
cmd=cmd)
|
||||
# cmd=sanitized_cmd)
|
||||
return result
|
||||
except ProcessExecutionError:
|
||||
if not attempts:
|
||||
raise
|
||||
else:
|
||||
if not silent:
|
||||
print_or_raise('%r failed. Retrying.' % cmd)
|
||||
if delay_on_retry:
|
||||
time.sleep(random.randint(20, 200) / 100.0)
|
||||
finally:
|
||||
time.sleep(0)
|
||||
|
||||
|
||||
def get_available_data_ip(media_ips):
|
||||
unavailable_ip = []
|
||||
for media_ip in media_ips:
|
||||
try:
|
||||
execute("ping -c 1 -W 2 %s" % media_ip)
|
||||
except ProcessExecutionError:
|
||||
unavailable_ip.append(media_ip)
|
||||
continue
|
||||
return list(set(media_ips) - set(unavailable_ip)), unavailable_ip
|
||||
|
||||
|
||||
def clear_host_iscsi_resource():
|
||||
out, err = execute("iscsiadm -m node", check_exit_code=[0, 21])
|
||||
if not out:
|
||||
return
|
||||
|
||||
sd_ips_list = map(lambda x: x.split(":3260")[0], out.split("\n")[:-1])
|
||||
if not sd_ips_list:
|
||||
return
|
||||
|
||||
valid_ips, invalid_ips = get_available_data_ip(sd_ips_list)
|
||||
clear_resource = ""
|
||||
for ip in invalid_ips:
|
||||
logout_session = "iscsiadm -m node -p %s -u;" % ip
|
||||
del_node = "iscsiadm -m node -p %s -o delete;" % ip
|
||||
# manual_startup = "iscsiadm -m node -p %s -o update -n node.startup "
|
||||
# "-v manual;" % ip
|
||||
clear_resource += (logout_session + del_node)
|
||||
execute(clear_resource, check_exit_code=[0, 21], silent=True)
|
||||
# _execute("multipath -F")
|
||||
|
||||
|
||||
def config_computer():
|
||||
# remove exist iscsi resource
|
||||
clear_host_iscsi_resource()
|
||||
config_multipath()
|
||||
|
||||
|
||||
def config_multipath():
|
||||
if os.path.exists("/etc/multipath.conf"):
|
||||
execute("echo y|mv /etc/multipath.conf /etc/multipath.conf.bak",
|
||||
check_exit_code=[0, 1])
|
||||
|
||||
execute("cp -p base/multipath.conf /etc/")
|
||||
execute("systemctl enable multipathd.service;"
|
||||
"systemctl restart multipathd.service")
|
@ -1,168 +0,0 @@
|
||||
###############################################################################
|
||||
# Author: CG
|
||||
# Description:
|
||||
# 1.The script should be copied to the host, before running.
|
||||
# 2.The script is not thread safe.
|
||||
# 3.Example for script call:
|
||||
# [config share disk]:
|
||||
# python storage_auto_config share_disk <host_pxe_mac>,
|
||||
# we use host_pxe_mac to generate host IQN by md5 and write it to
|
||||
# '/etc/iscsi/initiatorname.iscsi'
|
||||
# [config cinder]: python storage_auto_config cinder_conf 10.43.177.129,
|
||||
# the second parameter for cinder_config is cinder <host_ip>.
|
||||
# If the backend is CEPH,you should call the following command:
|
||||
# python storage_auto_config glance_rbd_conf at glance node &
|
||||
# python storage_auto_config nova_rbd_conf at nova node.
|
||||
# [config multipath]:python storage_auto_config check_multipath.
|
||||
# 4.Before run script,the cinder.json and control.json file
|
||||
# must be must be config.
|
||||
###############################################################################
|
||||
import sys
|
||||
import uuid
|
||||
import traceback
|
||||
from common.utils import *
|
||||
from common.cinder_conf import BaseConfig, CEPHBackendConfig
|
||||
from common.share_disk import BaseShareDisk
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
|
||||
def _set_config_file(file, section, key, value):
|
||||
set_config = BaseConfig.SET_CONFIG.format(
|
||||
config_file=file,
|
||||
section=section,
|
||||
key=key,
|
||||
value=value)
|
||||
execute(set_config)
|
||||
|
||||
|
||||
def config_share_disk(config, host_name):
|
||||
# deploy share_disk
|
||||
for item in config:
|
||||
BaseShareDisk.single_instance().deploy_share_disk(item, host_name)
|
||||
|
||||
|
||||
def config_cinder(config, cinder_host_ip=""):
|
||||
# config xml and cinder.conf
|
||||
for config in config['disk_array']:
|
||||
# load disk array global config
|
||||
backends = config['backend']
|
||||
for item in backends.items():
|
||||
BaseConfig.single_instance().config_backend(
|
||||
item,
|
||||
management_ips=config.get('management_ips', []),
|
||||
data_ips=config.get('data_ips', []),
|
||||
user_name=config.get('user_name', []),
|
||||
user_pwd=config.get('user_pwd', []),
|
||||
cinder_host_ip=cinder_host_ip)
|
||||
|
||||
# config multipath
|
||||
config_computer()
|
||||
|
||||
# enable config
|
||||
execute("systemctl restart openstack-cinder-volume.service")
|
||||
|
||||
|
||||
def config_nova_with_rbd(config):
|
||||
# config xml and cinder.conf
|
||||
for config in config['disk_array']:
|
||||
# load disk array global config
|
||||
backends = config['backend']
|
||||
for key, value in backends.items():
|
||||
if value.get('volume_driver') == 'CEPH':
|
||||
uuid_instance = uuid.uuid3(uuid.NAMESPACE_DNS, "zte.com.cn")
|
||||
uuid_str = uuid_instance.urn.split(":")[2]
|
||||
_set_config_file(CEPHBackendConfig.NOVA_CONF_FILE,
|
||||
'libvirt',
|
||||
'images_type',
|
||||
'rbd')
|
||||
_set_config_file(CEPHBackendConfig.NOVA_CONF_FILE,
|
||||
'libvirt',
|
||||
'rbd_secret_uuid',
|
||||
uuid_str)
|
||||
return
|
||||
|
||||
# enable config
|
||||
execute("systemctl restart openstack-nova-compute.service")
|
||||
|
||||
|
||||
def config_glance_with_rbd(config):
|
||||
# config xml and cinder.conf
|
||||
for config in config['disk_array']:
|
||||
# load disk array global config
|
||||
backends = config['backend']
|
||||
for key, value in backends.items():
|
||||
if value.get('volume_driver') == 'CEPH':
|
||||
_set_config_file(CEPHBackendConfig.GLANCE_API_CONF_FILE,
|
||||
'DEFAULT',
|
||||
'show_image_direct_url',
|
||||
'True')
|
||||
_set_config_file(CEPHBackendConfig.GLANCE_API_CONF_FILE,
|
||||
'glance_store',
|
||||
'default_store',
|
||||
'rbd')
|
||||
return
|
||||
|
||||
# enable config
|
||||
execute("systemctl restart openstack-glance-api.service")
|
||||
|
||||
|
||||
def _launch_script():
|
||||
def subcommand_launcher(args, valid_args_len, json_path, oper_type):
|
||||
if len(args) < valid_args_len:
|
||||
print_or_raise("Too few parameter is given,please check.",
|
||||
ScriptInnerError)
|
||||
|
||||
with open(json_path, "r") as fp_json:
|
||||
params = json.load(fp_json)
|
||||
|
||||
print_or_raise("-----Begin config %s, params is %s.-----" %
|
||||
(oper_type, params))
|
||||
return params
|
||||
|
||||
oper_type = sys.argv[1] if len(sys.argv) > 1 else ""
|
||||
try:
|
||||
if oper_type == "share_disk":
|
||||
share_disk_config = \
|
||||
subcommand_launcher(sys.argv, 3, "base/control.json",
|
||||
oper_type)
|
||||
config_share_disk(share_disk_config, sys.argv[2])
|
||||
elif oper_type == "cinder_conf":
|
||||
cinder_backend_config = subcommand_launcher(sys.argv, 3,
|
||||
"base/cinder.json",
|
||||
oper_type)
|
||||
config_cinder(cinder_backend_config, sys.argv[2])
|
||||
elif oper_type == "nova_rbd_conf":
|
||||
nova_rbd_config = subcommand_launcher(sys.argv, 1,
|
||||
"base/cinder.json",
|
||||
oper_type)
|
||||
config_nova_with_rbd(nova_rbd_config)
|
||||
elif oper_type == "glance_rbd_conf":
|
||||
glance_rbd_config = subcommand_launcher(sys.argv, 1,
|
||||
"base/cinder.json",
|
||||
oper_type)
|
||||
config_glance_with_rbd(glance_rbd_config)
|
||||
elif oper_type == "check_multipath":
|
||||
print_or_raise("-----Begin config %s.-----")
|
||||
config_computer()
|
||||
elif oper_type == "debug":
|
||||
pass
|
||||
else:
|
||||
print_or_raise("Script operation is not given,such as:share_disk,"
|
||||
"cinder_conf,nova_rbd_conf,glance_rbd_conf,"
|
||||
"check_multipath.", ScriptInnerError)
|
||||
except Exception as e:
|
||||
print_or_raise("----------Operation %s is Failed.----------\n"
|
||||
"Exception call chain as follow,%s" %
|
||||
(oper_type, traceback.format_exc()))
|
||||
raise e
|
||||
else:
|
||||
print_or_raise("----------Operation %s is done!----------" %
|
||||
oper_type)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
_launch_script()
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
scriptsdir=$(cd $(dirname $0) && pwd)
|
||||
ISODIR=`mktemp -d /mnt/TFG_ISOXXXXXX`
|
||||
mount -o loop $scriptsdir/*CGSL_VPLAT*.iso ${ISODIR}
|
||||
cp ${ISODIR}/*CGSL_VPLAT*.bin $scriptsdir
|
||||
umount ${ISODIR}
|
||||
[ -e ${ISODIR} ] && rm -rf ${ISODIR}
|
||||
$scriptsdir/*CGSL_VPLAT*.bin upgrade reboot
|
@ -1,93 +0,0 @@
|
||||
#!/bin/sh
|
||||
# 让某个主机彻底信任我,以后ssh登录过去不需要密码
|
||||
|
||||
#检查参数是否合法
|
||||
logfile=/var/log/trustme.log
|
||||
function print_log
|
||||
{
|
||||
local promt="$1"
|
||||
echo -e "$promt"
|
||||
echo -e "`date -d today +"%Y-%m-%d %H:%M:%S"` $promt" >> $logfile
|
||||
}
|
||||
|
||||
ip=$1
|
||||
if [ -z $ip ]; then
|
||||
print_log "Usage: `basename $0` ipaddr passwd"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
passwd=$2
|
||||
if [ -z $passwd ]; then
|
||||
print_log "Usage: `basename $0` ipaddr passwd"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rpm -qi sshpass >/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
print_log "Please install sshpass first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#试试对端能不能ping得通
|
||||
unreachable=`ping $ip -c 1 -W 3 | grep -c "100% packet loss"`
|
||||
if [ $unreachable -eq 1 ]; then
|
||||
print_log "host $ip is unreachable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#如果本机还没有ssh公钥,就生成一个
|
||||
if [ ! -e ~/.ssh/id_dsa.pub ]; then
|
||||
print_log "generating ssh public key ..."
|
||||
ssh-keygen -t dsa -f /root/.ssh/id_dsa -N ""
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh-keygen failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
#首先在对端删除原来保存的信任公钥
|
||||
user=`whoami`
|
||||
host=`hostname`
|
||||
keyend="$user@$host"
|
||||
print_log "my keyend = $keyend"
|
||||
cmd="sed '/$keyend$/d' -i ~/.ssh/authorized_keys"
|
||||
#echo cmd:$cmd
|
||||
print_log "clear my old pub key on $ip ..."
|
||||
sshpass -p $passwd ssh -o StrictHostKeyChecking=no $ip "rm -rf /root/.ssh/known_hosts"
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh $ip to delete known_hosts failed"
|
||||
exit 1
|
||||
fi
|
||||
sshpass -p $passwd ssh -o StrictHostKeyChecking=no $ip "touch ~/.ssh/authorized_keys"
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh $ip to create file authorized_keys failed"
|
||||
exit 1
|
||||
fi
|
||||
sshpass -p $passwd ssh -o StrictHostKeyChecking=no $ip "$cmd"
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh $ip to edit authorized_keys failed"
|
||||
exit 1
|
||||
fi
|
||||
#把新生成的拷贝过去
|
||||
print_log "copy my public key to $ip ..."
|
||||
tmpfile=/tmp/`hostname`.key.pub
|
||||
sshpass -p $passwd scp -o StrictHostKeyChecking=no ~/.ssh/id_dsa.pub $ip:$tmpfile
|
||||
if [ $? != 0 ]; then
|
||||
print_log "scp file to $ip failed"
|
||||
exit 1
|
||||
fi
|
||||
#在对端将其追加到authorized_keys
|
||||
print_log "on $ip, append my public key to ~/.ssh/authorized_keys ..."
|
||||
sshpass -p $passwd ssh -o StrictHostKeyChecking=no $ip "cat $tmpfile >> ~/.ssh/authorized_keys"
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh $ip to add public key for authorized_keys failed"
|
||||
exit 1
|
||||
fi
|
||||
print_log "rm tmp file $ip:$tmpfile"
|
||||
sshpass -p $passwd ssh -o StrictHostKeyChecking=no $ip "rm $tmpfile"
|
||||
if [ $? != 0 ]; then
|
||||
print_log "ssh $ip to delete tmp file failed"
|
||||
exit 1
|
||||
fi
|
||||
print_log "trustme ok!"
|
||||
|
@ -1,62 +0,0 @@
|
||||
#!/bin/sh
|
||||
# 让某个主机彻底信任我,以后ssh登录过去不需要密码
|
||||
|
||||
#检查参数是否合法
|
||||
ip=$1
|
||||
if [ -z $ip ]; then
|
||||
echo "Usage: `basename $0` ipaddr passwd" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
passwd=$2
|
||||
if [ -z $passwd ]; then
|
||||
echo "Usage: `basename $0` ipaddr passwd" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rpm -qi sshpass >/dev/null
|
||||
if [ $? != 0 ]; then
|
||||
echo "Please install sshpass first!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#试试对端能不能ping得通
|
||||
unreachable=`ping $ip -c 1 -W 3 | grep -c "100% packet loss"`
|
||||
if [ $unreachable -eq 1 ]; then
|
||||
echo "host $ip is unreachable!!!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#如果本机还没有ssh公钥,就生成一个
|
||||
if [ ! -e ~/.ssh/id_dsa.pub ]; then
|
||||
echo "generating ssh public key ..."
|
||||
ssh-keygen -t dsa -f /root/.ssh/id_dsa -N ""
|
||||
fi
|
||||
|
||||
#首先在对端删除原来保存的信任公钥
|
||||
user=`whoami`
|
||||
host=`hostname`
|
||||
keyend="$user@$host"
|
||||
echo "my keyend = $keyend"
|
||||
cmd="sed '/$keyend$/d' -i ~/.ssh/authorized_keys"
|
||||
#echo cmd:$cmd
|
||||
echo "clear my old pub key on $ip ..."
|
||||
sshpass -p $passwd ssh $ip "rm -rf /root/.ssh/known_hosts"
|
||||
sshpass -p $passwd ssh $ip "touch ~/.ssh/authorized_keys"
|
||||
sshpass -p $passwd ssh $ip "$cmd"
|
||||
|
||||
#把新生成的拷贝过去
|
||||
echo "copy my public key to $ip ..."
|
||||
tmpfile=/tmp/`hostname`.key.pub
|
||||
sshpass -p $passwd scp ~/.ssh/id_dsa.pub $ip:$tmpfile
|
||||
|
||||
#在对端将其追加到authorized_keys
|
||||
echo "on $ip, append my public key to ~/.ssh/authorized_keys ..."
|
||||
sshpass -p $passwd ssh $ip "cat $tmpfile >> ~/.ssh/authorized_keys"
|
||||
echo "rm tmp file $ip:$tmpfile"
|
||||
sshpass -p $passwd ssh $ip "rm $tmpfile"
|
||||
echo "trustme ok!"
|
||||
|
||||
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
[general]
|
||||
nodeip=192.168.3.1
|
||||
nodeid=1
|
||||
hostname=sdn59
|
||||
needzamp=y
|
||||
zbpips=192.168.3.1
|
||||
zbp_node_num=1
|
||||
zbpnodelist=1,256
|
||||
zampips=192.168.3.1
|
||||
zamp_node_num=1
|
||||
mongodbips=192.168.3.1
|
||||
mongodb_node_num=1
|
||||
zamp_vip=
|
||||
mongodb_vip=
|
||||
MacName=eth1
|
||||
netid=1234
|
||||
memmode=tiny
|
@ -1,899 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# Copyright 2013 IBM Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import copy
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.domain.proxy
|
||||
from daisy import i18n
|
||||
|
||||
_ = i18n._
|
||||
|
||||
|
||||
def is_image_mutable(context, image):
|
||||
"""Return True if the image is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if image.owner is None or context.owner is None:
|
||||
return False
|
||||
|
||||
return image.owner == context.owner
|
||||
|
||||
|
||||
def proxy_image(context, image):
|
||||
if is_image_mutable(context, image):
|
||||
return ImageProxy(image, context)
|
||||
else:
|
||||
return ImmutableImageProxy(image, context)
|
||||
|
||||
|
||||
def is_member_mutable(context, member):
|
||||
"""Return True if the image is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return member.member_id == context.owner
|
||||
|
||||
|
||||
def proxy_member(context, member):
|
||||
if is_member_mutable(context, member):
|
||||
return member
|
||||
else:
|
||||
return ImmutableMemberProxy(member)
|
||||
|
||||
|
||||
def is_task_mutable(context, task):
|
||||
"""Return True if the task is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return task.owner == context.owner
|
||||
|
||||
|
||||
def is_task_stub_mutable(context, task_stub):
|
||||
"""Return True if the task stub is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return task_stub.owner == context.owner
|
||||
|
||||
|
||||
def proxy_task(context, task):
|
||||
if is_task_mutable(context, task):
|
||||
return task
|
||||
else:
|
||||
return ImmutableTaskProxy(task)
|
||||
|
||||
|
||||
def proxy_task_stub(context, task_stub):
|
||||
if is_task_stub_mutable(context, task_stub):
|
||||
return task_stub
|
||||
else:
|
||||
return ImmutableTaskStubProxy(task_stub)
|
||||
|
||||
|
||||
class ImageRepoProxy(daisy.domain.proxy.Repo):
|
||||
|
||||
def __init__(self, image_repo, context):
|
||||
self.context = context
|
||||
self.image_repo = image_repo
|
||||
proxy_kwargs = {'context': self.context}
|
||||
super(ImageRepoProxy, self).__init__(image_repo,
|
||||
item_proxy_class=ImageProxy,
|
||||
item_proxy_kwargs=proxy_kwargs)
|
||||
|
||||
def get(self, image_id):
|
||||
image = self.image_repo.get(image_id)
|
||||
return proxy_image(self.context, image)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
images = self.image_repo.list(*args, **kwargs)
|
||||
return [proxy_image(self.context, i) for i in images]
|
||||
|
||||
|
||||
class ImageMemberRepoProxy(daisy.domain.proxy.Repo):
|
||||
|
||||
def __init__(self, member_repo, image, context):
|
||||
self.member_repo = member_repo
|
||||
self.image = image
|
||||
self.context = context
|
||||
super(ImageMemberRepoProxy, self).__init__(member_repo)
|
||||
|
||||
def get(self, member_id):
|
||||
if (self.context.is_admin or
|
||||
self.context.owner in (self.image.owner, member_id)):
|
||||
member = self.member_repo.get(member_id)
|
||||
return proxy_member(self.context, member)
|
||||
else:
|
||||
message = _("You cannot get image member for %s")
|
||||
raise exception.Forbidden(message % member_id)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
members = self.member_repo.list(*args, **kwargs)
|
||||
if (self.context.is_admin or
|
||||
self.context.owner == self.image.owner):
|
||||
return [proxy_member(self.context, m) for m in members]
|
||||
for member in members:
|
||||
if member.member_id == self.context.owner:
|
||||
return [proxy_member(self.context, member)]
|
||||
message = _("You cannot get image member for %s")
|
||||
raise exception.Forbidden(message % self.image.image_id)
|
||||
|
||||
def remove(self, image_member):
|
||||
if (self.image.owner == self.context.owner or
|
||||
self.context.is_admin):
|
||||
self.member_repo.remove(image_member)
|
||||
else:
|
||||
message = _("You cannot delete image member for %s")
|
||||
raise exception.Forbidden(message
|
||||
% self.image.image_id)
|
||||
|
||||
def add(self, image_member):
|
||||
if (self.image.owner == self.context.owner or
|
||||
self.context.is_admin):
|
||||
self.member_repo.add(image_member)
|
||||
else:
|
||||
message = _("You cannot add image member for %s")
|
||||
raise exception.Forbidden(message
|
||||
% self.image.image_id)
|
||||
|
||||
def save(self, image_member, from_state=None):
|
||||
if (self.context.is_admin or
|
||||
self.context.owner == image_member.member_id):
|
||||
self.member_repo.save(image_member, from_state=from_state)
|
||||
else:
|
||||
message = _("You cannot update image member %s")
|
||||
raise exception.Forbidden(message % image_member.member_id)
|
||||
|
||||
|
||||
class ImageFactoryProxy(daisy.domain.proxy.ImageFactory):
|
||||
|
||||
def __init__(self, image_factory, context):
|
||||
self.image_factory = image_factory
|
||||
self.context = context
|
||||
kwargs = {'context': self.context}
|
||||
super(ImageFactoryProxy, self).__init__(image_factory,
|
||||
proxy_class=ImageProxy,
|
||||
proxy_kwargs=kwargs)
|
||||
|
||||
def new_image(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create images "
|
||||
"owned by '%s'.")
|
||||
raise exception.Forbidden(message % owner)
|
||||
|
||||
return super(ImageFactoryProxy, self).new_image(owner=owner, **kwargs)
|
||||
|
||||
|
||||
class ImageMemberFactoryProxy(object):
|
||||
|
||||
def __init__(self, image_member_factory, context):
|
||||
self.image_member_factory = image_member_factory
|
||||
self.context = context
|
||||
|
||||
def new_image_member(self, image, member_id):
|
||||
owner = image.owner
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create image members "
|
||||
"for the image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
if image.visibility == 'public':
|
||||
message = _("Public images do not have members.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
return self.image_member_factory.new_image_member(image, member_id)
|
||||
|
||||
|
||||
def _immutable_attr(target, attr, proxy=None):
|
||||
|
||||
def get_attr(self):
|
||||
value = getattr(getattr(self, target), attr)
|
||||
if proxy is not None:
|
||||
value = proxy(value)
|
||||
return value
|
||||
|
||||
def forbidden(self, *args, **kwargs):
|
||||
resource = getattr(self, 'resource_name', 'resource')
|
||||
message = _("You are not permitted to modify '%(attr)s' on this "
|
||||
"%(resource)s.")
|
||||
raise exception.Forbidden(message % {'attr': attr,
|
||||
'resource': resource})
|
||||
|
||||
return property(get_attr, forbidden, forbidden)
|
||||
|
||||
|
||||
class ImmutableLocations(list):
|
||||
def forbidden(self, *args, **kwargs):
|
||||
message = _("You are not permitted to modify locations "
|
||||
"for this image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
return ImmutableLocations(copy.deepcopy(list(self), memo))
|
||||
|
||||
append = forbidden
|
||||
extend = forbidden
|
||||
insert = forbidden
|
||||
pop = forbidden
|
||||
remove = forbidden
|
||||
reverse = forbidden
|
||||
sort = forbidden
|
||||
__delitem__ = forbidden
|
||||
__delslice__ = forbidden
|
||||
__iadd__ = forbidden
|
||||
__imul__ = forbidden
|
||||
__setitem__ = forbidden
|
||||
__setslice__ = forbidden
|
||||
|
||||
|
||||
class ImmutableProperties(dict):
|
||||
def forbidden_key(self, key, *args, **kwargs):
|
||||
message = _("You are not permitted to modify '%s' on this image.")
|
||||
raise exception.Forbidden(message % key)
|
||||
|
||||
def forbidden(self, *args, **kwargs):
|
||||
message = _("You are not permitted to modify this image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
__delitem__ = forbidden_key
|
||||
__setitem__ = forbidden_key
|
||||
pop = forbidden
|
||||
popitem = forbidden
|
||||
setdefault = forbidden
|
||||
update = forbidden
|
||||
|
||||
|
||||
class ImmutableTags(set):
|
||||
def forbidden(self, *args, **kwargs):
|
||||
message = _("You are not permitted to modify tags on this image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
add = forbidden
|
||||
clear = forbidden
|
||||
difference_update = forbidden
|
||||
intersection_update = forbidden
|
||||
pop = forbidden
|
||||
remove = forbidden
|
||||
symmetric_difference_update = forbidden
|
||||
update = forbidden
|
||||
|
||||
|
||||
class ImmutableImageProxy(object):
|
||||
def __init__(self, base, context):
|
||||
self.base = base
|
||||
self.context = context
|
||||
self.resource_name = 'image'
|
||||
|
||||
name = _immutable_attr('base', 'name')
|
||||
image_id = _immutable_attr('base', 'image_id')
|
||||
name = _immutable_attr('base', 'name')
|
||||
status = _immutable_attr('base', 'status')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
visibility = _immutable_attr('base', 'visibility')
|
||||
min_disk = _immutable_attr('base', 'min_disk')
|
||||
min_ram = _immutable_attr('base', 'min_ram')
|
||||
protected = _immutable_attr('base', 'protected')
|
||||
locations = _immutable_attr('base', 'locations', proxy=ImmutableLocations)
|
||||
checksum = _immutable_attr('base', 'checksum')
|
||||
owner = _immutable_attr('base', 'owner')
|
||||
disk_format = _immutable_attr('base', 'disk_format')
|
||||
container_format = _immutable_attr('base', 'container_format')
|
||||
size = _immutable_attr('base', 'size')
|
||||
virtual_size = _immutable_attr('base', 'virtual_size')
|
||||
extra_properties = _immutable_attr('base', 'extra_properties',
|
||||
proxy=ImmutableProperties)
|
||||
tags = _immutable_attr('base', 'tags', proxy=ImmutableTags)
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def get_member_repo(self):
|
||||
member_repo = self.base.get_member_repo()
|
||||
return ImageMemberRepoProxy(member_repo, self, self.context)
|
||||
|
||||
def get_data(self, *args, **kwargs):
|
||||
return self.base.get_data(*args, **kwargs)
|
||||
|
||||
def set_data(self, *args, **kwargs):
|
||||
message = _("You are not permitted to upload data for this image.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class ImmutableMemberProxy(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'image member'
|
||||
|
||||
id = _immutable_attr('base', 'id')
|
||||
image_id = _immutable_attr('base', 'image_id')
|
||||
member_id = _immutable_attr('base', 'member_id')
|
||||
status = _immutable_attr('base', 'status')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
|
||||
class ImmutableTaskProxy(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'task'
|
||||
|
||||
task_id = _immutable_attr('base', 'task_id')
|
||||
type = _immutable_attr('base', 'type')
|
||||
status = _immutable_attr('base', 'status')
|
||||
owner = _immutable_attr('base', 'owner')
|
||||
expires_at = _immutable_attr('base', 'expires_at')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
input = _immutable_attr('base', 'input')
|
||||
message = _immutable_attr('base', 'message')
|
||||
result = _immutable_attr('base', 'result')
|
||||
|
||||
def run(self, executor):
|
||||
self.base.run(executor)
|
||||
|
||||
def begin_processing(self):
|
||||
message = _("You are not permitted to set status on this task.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def succeed(self, result):
|
||||
message = _("You are not permitted to set status on this task.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def fail(self, message):
|
||||
message = _("You are not permitted to set status on this task.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class ImmutableTaskStubProxy(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'task stub'
|
||||
|
||||
task_id = _immutable_attr('base', 'task_id')
|
||||
type = _immutable_attr('base', 'type')
|
||||
status = _immutable_attr('base', 'status')
|
||||
owner = _immutable_attr('base', 'owner')
|
||||
expires_at = _immutable_attr('base', 'expires_at')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
|
||||
class ImageProxy(daisy.domain.proxy.Image):
|
||||
|
||||
def __init__(self, image, context):
|
||||
self.image = image
|
||||
self.context = context
|
||||
super(ImageProxy, self).__init__(image)
|
||||
|
||||
def get_member_repo(self, **kwargs):
|
||||
if self.image.visibility == 'public':
|
||||
message = _("Public images do not have members.")
|
||||
raise exception.Forbidden(message)
|
||||
else:
|
||||
member_repo = self.image.get_member_repo(**kwargs)
|
||||
return ImageMemberRepoProxy(member_repo, self, self.context)
|
||||
|
||||
|
||||
class TaskProxy(daisy.domain.proxy.Task):
|
||||
|
||||
def __init__(self, task):
|
||||
self.task = task
|
||||
super(TaskProxy, self).__init__(task)
|
||||
|
||||
|
||||
class TaskFactoryProxy(daisy.domain.proxy.TaskFactory):
|
||||
|
||||
def __init__(self, task_factory, context):
|
||||
self.task_factory = task_factory
|
||||
self.context = context
|
||||
super(TaskFactoryProxy, self).__init__(
|
||||
task_factory,
|
||||
task_proxy_class=TaskProxy)
|
||||
|
||||
def new_task(self, **kwargs):
|
||||
owner = kwargs.get('owner', self.context.owner)
|
||||
|
||||
# NOTE(nikhil): Unlike Images, Tasks are expected to have owner.
|
||||
# We currently do not allow even admins to set the owner to None.
|
||||
if owner is not None and (owner == self.context.owner
|
||||
or self.context.is_admin):
|
||||
return super(TaskFactoryProxy, self).new_task(**kwargs)
|
||||
else:
|
||||
message = _("You are not permitted to create this task with "
|
||||
"owner as: %s")
|
||||
raise exception.Forbidden(message % owner)
|
||||
|
||||
|
||||
class TaskRepoProxy(daisy.domain.proxy.TaskRepo):
|
||||
|
||||
def __init__(self, task_repo, context):
|
||||
self.task_repo = task_repo
|
||||
self.context = context
|
||||
super(TaskRepoProxy, self).__init__(task_repo)
|
||||
|
||||
def get(self, task_id):
|
||||
task = self.task_repo.get(task_id)
|
||||
return proxy_task(self.context, task)
|
||||
|
||||
|
||||
class TaskStubRepoProxy(daisy.domain.proxy.TaskStubRepo):
|
||||
|
||||
def __init__(self, task_stub_repo, context):
|
||||
self.task_stub_repo = task_stub_repo
|
||||
self.context = context
|
||||
super(TaskStubRepoProxy, self).__init__(task_stub_repo)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
task_stubs = self.task_stub_repo.list(*args, **kwargs)
|
||||
return [proxy_task_stub(self.context, t) for t in task_stubs]
|
||||
|
||||
|
||||
# Metadef Namespace classes
|
||||
def is_namespace_mutable(context, namespace):
|
||||
"""Return True if the namespace is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return namespace.owner == context.owner
|
||||
|
||||
|
||||
def proxy_namespace(context, namespace):
|
||||
if is_namespace_mutable(context, namespace):
|
||||
return namespace
|
||||
else:
|
||||
return ImmutableMetadefNamespaceProxy(namespace)
|
||||
|
||||
|
||||
class ImmutableMetadefNamespaceProxy(object):
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'namespace'
|
||||
|
||||
namespace_id = _immutable_attr('base', 'namespace_id')
|
||||
namespace = _immutable_attr('base', 'namespace')
|
||||
display_name = _immutable_attr('base', 'display_name')
|
||||
description = _immutable_attr('base', 'description')
|
||||
owner = _immutable_attr('base', 'owner')
|
||||
visibility = _immutable_attr('base', 'visibility')
|
||||
protected = _immutable_attr('base', 'protected')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this namespace.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def save(self):
|
||||
message = _("You are not permitted to update this namespace.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class MetadefNamespaceProxy(daisy.domain.proxy.MetadefNamespace):
|
||||
|
||||
def __init__(self, namespace):
|
||||
self.namespace_input = namespace
|
||||
super(MetadefNamespaceProxy, self).__init__(namespace)
|
||||
|
||||
|
||||
class MetadefNamespaceFactoryProxy(
|
||||
daisy.domain.proxy.MetadefNamespaceFactory):
|
||||
|
||||
def __init__(self, meta_namespace_factory, context):
|
||||
self.meta_namespace_factory = meta_namespace_factory
|
||||
self.context = context
|
||||
super(MetadefNamespaceFactoryProxy, self).__init__(
|
||||
meta_namespace_factory,
|
||||
meta_namespace_proxy_class=MetadefNamespaceProxy)
|
||||
|
||||
def new_namespace(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create namespace "
|
||||
"owned by '%s'")
|
||||
raise exception.Forbidden(message % (owner))
|
||||
|
||||
return super(MetadefNamespaceFactoryProxy, self).new_namespace(
|
||||
owner=owner, **kwargs)
|
||||
|
||||
|
||||
class MetadefNamespaceRepoProxy(daisy.domain.proxy.MetadefNamespaceRepo):
|
||||
|
||||
def __init__(self, namespace_repo, context):
|
||||
self.namespace_repo = namespace_repo
|
||||
self.context = context
|
||||
super(MetadefNamespaceRepoProxy, self).__init__(namespace_repo)
|
||||
|
||||
def get(self, namespace):
|
||||
namespace_obj = self.namespace_repo.get(namespace)
|
||||
return proxy_namespace(self.context, namespace_obj)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
namespaces = self.namespace_repo.list(*args, **kwargs)
|
||||
return [proxy_namespace(self.context, namespace) for
|
||||
namespace in namespaces]
|
||||
|
||||
|
||||
# Metadef Object classes
|
||||
def is_object_mutable(context, object):
|
||||
"""Return True if the object is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return object.namespace.owner == context.owner
|
||||
|
||||
|
||||
def proxy_object(context, object):
|
||||
if is_object_mutable(context, object):
|
||||
return object
|
||||
else:
|
||||
return ImmutableMetadefObjectProxy(object)
|
||||
|
||||
|
||||
class ImmutableMetadefObjectProxy(object):
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'object'
|
||||
|
||||
object_id = _immutable_attr('base', 'object_id')
|
||||
name = _immutable_attr('base', 'name')
|
||||
required = _immutable_attr('base', 'required')
|
||||
description = _immutable_attr('base', 'description')
|
||||
properties = _immutable_attr('base', 'properties')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this object.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def save(self):
|
||||
message = _("You are not permitted to update this object.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class MetadefObjectProxy(daisy.domain.proxy.MetadefObject):
|
||||
|
||||
def __init__(self, meta_object):
|
||||
self.meta_object = meta_object
|
||||
super(MetadefObjectProxy, self).__init__(meta_object)
|
||||
|
||||
|
||||
class MetadefObjectFactoryProxy(daisy.domain.proxy.MetadefObjectFactory):
|
||||
|
||||
def __init__(self, meta_object_factory, context):
|
||||
self.meta_object_factory = meta_object_factory
|
||||
self.context = context
|
||||
super(MetadefObjectFactoryProxy, self).__init__(
|
||||
meta_object_factory,
|
||||
meta_object_proxy_class=MetadefObjectProxy)
|
||||
|
||||
def new_object(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create object "
|
||||
"owned by '%s'")
|
||||
raise exception.Forbidden(message % (owner))
|
||||
|
||||
return super(MetadefObjectFactoryProxy, self).new_object(**kwargs)
|
||||
|
||||
|
||||
class MetadefObjectRepoProxy(daisy.domain.proxy.MetadefObjectRepo):
|
||||
|
||||
def __init__(self, object_repo, context):
|
||||
self.object_repo = object_repo
|
||||
self.context = context
|
||||
super(MetadefObjectRepoProxy, self).__init__(object_repo)
|
||||
|
||||
def get(self, namespace, object_name):
|
||||
meta_object = self.object_repo.get(namespace, object_name)
|
||||
return proxy_object(self.context, meta_object)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
objects = self.object_repo.list(*args, **kwargs)
|
||||
return [proxy_object(self.context, meta_object) for
|
||||
meta_object in objects]
|
||||
|
||||
|
||||
# Metadef ResourceType classes
|
||||
def is_meta_resource_type_mutable(context, meta_resource_type):
|
||||
"""Return True if the meta_resource_type is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
# (lakshmiS): resource type can exist without an association with
|
||||
# namespace and resource type cannot be created/update/deleted directly(
|
||||
# they have to be associated/de-associated from namespace)
|
||||
if meta_resource_type.namespace:
|
||||
return meta_resource_type.namespace.owner == context.owner
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def proxy_meta_resource_type(context, meta_resource_type):
|
||||
if is_meta_resource_type_mutable(context, meta_resource_type):
|
||||
return meta_resource_type
|
||||
else:
|
||||
return ImmutableMetadefResourceTypeProxy(meta_resource_type)
|
||||
|
||||
|
||||
class ImmutableMetadefResourceTypeProxy(object):
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'meta_resource_type'
|
||||
|
||||
namespace = _immutable_attr('base', 'namespace')
|
||||
name = _immutable_attr('base', 'name')
|
||||
prefix = _immutable_attr('base', 'prefix')
|
||||
properties_target = _immutable_attr('base', 'properties_target')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this meta_resource_type.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class MetadefResourceTypeProxy(daisy.domain.proxy.MetadefResourceType):
|
||||
|
||||
def __init__(self, meta_resource_type):
|
||||
self.meta_resource_type = meta_resource_type
|
||||
super(MetadefResourceTypeProxy, self).__init__(meta_resource_type)
|
||||
|
||||
|
||||
class MetadefResourceTypeFactoryProxy(
|
||||
daisy.domain.proxy.MetadefResourceTypeFactory):
|
||||
|
||||
def __init__(self, resource_type_factory, context):
|
||||
self.meta_resource_type_factory = resource_type_factory
|
||||
self.context = context
|
||||
super(MetadefResourceTypeFactoryProxy, self).__init__(
|
||||
resource_type_factory,
|
||||
resource_type_proxy_class=MetadefResourceTypeProxy)
|
||||
|
||||
def new_resource_type(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create resource_type "
|
||||
"owned by '%s'")
|
||||
raise exception.Forbidden(message % (owner))
|
||||
|
||||
return super(MetadefResourceTypeFactoryProxy, self).new_resource_type(
|
||||
**kwargs)
|
||||
|
||||
|
||||
class MetadefResourceTypeRepoProxy(
|
||||
daisy.domain.proxy.MetadefResourceTypeRepo):
|
||||
|
||||
def __init__(self, meta_resource_type_repo, context):
|
||||
self.meta_resource_type_repo = meta_resource_type_repo
|
||||
self.context = context
|
||||
super(MetadefResourceTypeRepoProxy, self).__init__(
|
||||
meta_resource_type_repo)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
meta_resource_types = self.meta_resource_type_repo.list(
|
||||
*args, **kwargs)
|
||||
return [proxy_meta_resource_type(self.context, meta_resource_type) for
|
||||
meta_resource_type in meta_resource_types]
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
meta_resource_type = self.meta_resource_type_repo.get(*args, **kwargs)
|
||||
return proxy_meta_resource_type(self.context, meta_resource_type)
|
||||
|
||||
|
||||
# Metadef namespace properties classes
|
||||
def is_namespace_property_mutable(context, namespace_property):
|
||||
"""Return True if the object is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return namespace_property.namespace.owner == context.owner
|
||||
|
||||
|
||||
def proxy_namespace_property(context, namespace_property):
|
||||
if is_namespace_property_mutable(context, namespace_property):
|
||||
return namespace_property
|
||||
else:
|
||||
return ImmutableMetadefPropertyProxy(namespace_property)
|
||||
|
||||
|
||||
class ImmutableMetadefPropertyProxy(object):
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'namespace_property'
|
||||
|
||||
property_id = _immutable_attr('base', 'property_id')
|
||||
name = _immutable_attr('base', 'name')
|
||||
schema = _immutable_attr('base', 'schema')
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this property.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def save(self):
|
||||
message = _("You are not permitted to update this property.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class MetadefPropertyProxy(daisy.domain.proxy.MetadefProperty):
|
||||
|
||||
def __init__(self, namespace_property):
|
||||
self.meta_object = namespace_property
|
||||
super(MetadefPropertyProxy, self).__init__(namespace_property)
|
||||
|
||||
|
||||
class MetadefPropertyFactoryProxy(daisy.domain.proxy.MetadefPropertyFactory):
|
||||
|
||||
def __init__(self, namespace_property_factory, context):
|
||||
self.meta_object_factory = namespace_property_factory
|
||||
self.context = context
|
||||
super(MetadefPropertyFactoryProxy, self).__init__(
|
||||
namespace_property_factory,
|
||||
property_proxy_class=MetadefPropertyProxy)
|
||||
|
||||
def new_namespace_property(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
|
||||
if not self.context.is_admin:
|
||||
if owner is None or owner != self.context.owner:
|
||||
message = _("You are not permitted to create property "
|
||||
"owned by '%s'")
|
||||
raise exception.Forbidden(message % (owner))
|
||||
|
||||
return super(MetadefPropertyFactoryProxy, self).new_namespace_property(
|
||||
**kwargs)
|
||||
|
||||
|
||||
class MetadefPropertyRepoProxy(daisy.domain.proxy.MetadefPropertyRepo):
|
||||
|
||||
def __init__(self, namespace_property_repo, context):
|
||||
self.namespace_property_repo = namespace_property_repo
|
||||
self.context = context
|
||||
super(MetadefPropertyRepoProxy, self).__init__(namespace_property_repo)
|
||||
|
||||
def get(self, namespace, object_name):
|
||||
namespace_property = self.namespace_property_repo.get(namespace,
|
||||
object_name)
|
||||
return proxy_namespace_property(self.context, namespace_property)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
namespace_properties = self.namespace_property_repo.list(
|
||||
*args, **kwargs)
|
||||
return [proxy_namespace_property(self.context, namespace_property) for
|
||||
namespace_property in namespace_properties]
|
||||
|
||||
|
||||
# Metadef Tag classes
|
||||
def is_tag_mutable(context, tag):
|
||||
"""Return True if the tag is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return tag.namespace.owner == context.owner
|
||||
|
||||
|
||||
def proxy_tag(context, tag):
|
||||
if is_tag_mutable(context, tag):
|
||||
return tag
|
||||
else:
|
||||
return ImmutableMetadefTagProxy(tag)
|
||||
|
||||
|
||||
class ImmutableMetadefTagProxy(object):
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'tag'
|
||||
|
||||
tag_id = _immutable_attr('base', 'tag_id')
|
||||
name = _immutable_attr('base', 'name')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
def delete(self):
|
||||
message = _("You are not permitted to delete this tag.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
def save(self):
|
||||
message = _("You are not permitted to update this tag.")
|
||||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class MetadefTagProxy(daisy.domain.proxy.MetadefTag):
|
||||
pass
|
||||
|
||||
|
||||
class MetadefTagFactoryProxy(daisy.domain.proxy.MetadefTagFactory):
|
||||
|
||||
def __init__(self, meta_tag_factory, context):
|
||||
self.meta_tag_factory = meta_tag_factory
|
||||
self.context = context
|
||||
super(MetadefTagFactoryProxy, self).__init__(
|
||||
meta_tag_factory,
|
||||
meta_tag_proxy_class=MetadefTagProxy)
|
||||
|
||||
def new_tag(self, **kwargs):
|
||||
owner = kwargs.pop('owner', self.context.owner)
|
||||
if not self.context.is_admin:
|
||||
if owner is None:
|
||||
message = _("Owner must be specified to create a tag.")
|
||||
raise exception.Forbidden(message)
|
||||
elif owner != self.context.owner:
|
||||
message = _("You are not permitted to create a tag"
|
||||
" in the namespace owned by '%s'")
|
||||
raise exception.Forbidden(message % (owner))
|
||||
|
||||
return super(MetadefTagFactoryProxy, self).new_tag(**kwargs)
|
||||
|
||||
|
||||
class MetadefTagRepoProxy(daisy.domain.proxy.MetadefTagRepo):
|
||||
|
||||
def __init__(self, tag_repo, context):
|
||||
self.tag_repo = tag_repo
|
||||
self.context = context
|
||||
super(MetadefTagRepoProxy, self).__init__(tag_repo)
|
||||
|
||||
def get(self, namespace, tag_name):
|
||||
meta_tag = self.tag_repo.get(namespace, tag_name)
|
||||
return proxy_tag(self.context, meta_tag)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
tags = self.tag_repo.list(*args, **kwargs)
|
||||
return [proxy_tag(self.context, meta_tag) for
|
||||
meta_tag in tags]
|
@ -1,235 +1,367 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
|
||||
daisy_path = '/var/lib/daisy/'
|
||||
tecs_backend_name = "tecs"
|
||||
zenic_backend_name = "zenic"
|
||||
proton_backend_name = "proton"
|
||||
os_install_start_time = 0.0
|
||||
|
||||
def subprocess_call(command,file=None):
|
||||
if file:
|
||||
return_code = subprocess.call(command,
|
||||
shell=True,
|
||||
stdout=file,
|
||||
stderr=file)
|
||||
else:
|
||||
return_code = subprocess.call(command,
|
||||
shell=True,
|
||||
stdout=open('/dev/null', 'w'),
|
||||
stderr=subprocess.STDOUT)
|
||||
if return_code != 0:
|
||||
msg = "execute '%s' failed by subprocess call." % command
|
||||
raise exception.SubprocessCmdFailed(msg)
|
||||
|
||||
def get_host_detail(req, host_id):
|
||||
try:
|
||||
host_detail = registry.get_host_metadata(req.context, host_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return host_detail
|
||||
|
||||
def get_roles_detail(req):
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return roles
|
||||
|
||||
def get_cluster_roles_detail(req, cluster_id):
|
||||
try:
|
||||
params = {'cluster_id':cluster_id}
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return roles
|
||||
|
||||
def get_hosts_of_role(req, role_id):
|
||||
try:
|
||||
hosts = registry.get_role_host_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return hosts
|
||||
|
||||
def get_role_detail(req, role_id):
|
||||
try:
|
||||
role = registry.get_role_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role
|
||||
|
||||
def update_role(req, role_id,role_meta):
|
||||
try:
|
||||
registry.update_role_metadata(req.context, role_id, role_meta)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
def update_role_host(req, role_id, role_host):
|
||||
try:
|
||||
registry.update_role_host_metadata(req.context, role_id, role_host)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
def delete_role_hosts(req, role_id):
|
||||
try:
|
||||
registry.delete_role_host_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
def get_cluster_networks_detail(req, cluster_id):
|
||||
try:
|
||||
networks = registry.get_networks_detail(req.context, cluster_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return networks
|
||||
|
||||
def get_assigned_network(req, host_interface_id, network_id):
|
||||
try:
|
||||
assigned_network = registry.get_assigned_network(req.context, host_interface_id, network_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return assigned_network
|
||||
|
||||
def _ping_hosts_test(ips):
|
||||
ping_cmd = 'fping'
|
||||
for ip in set(ips):
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
obj = subprocess.Popen(ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0 or _returncode == 1:
|
||||
ping_result = stdoutput.split('\n')
|
||||
unreachable_hosts = [result.split()[0] for result in ping_result if result and result.split()[2] != 'alive']
|
||||
else:
|
||||
msg = "ping failed beaceuse there is invlid ip in %s" % ips
|
||||
raise exception.InvalidIP(msg)
|
||||
return unreachable_hosts
|
||||
|
||||
|
||||
def check_ping_hosts(ping_ips, max_ping_times):
|
||||
if not ping_ips:
|
||||
LOG.info(_("no ip got for ping test"))
|
||||
return ping_ips
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
LOG.info(_("begin ping test for %s" % ','.join(ping_ips)))
|
||||
while True:
|
||||
if ping_count == 0:
|
||||
ips = _ping_hosts_test(ping_ips)
|
||||
else:
|
||||
ips = _ping_hosts_test(ips)
|
||||
|
||||
ping_count += 1
|
||||
if ips:
|
||||
LOG.debug(_("ping host %s for %s times" % (','.join(ips), ping_count)))
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(_("ping host %s timeout for %ss" % (','.join(ips), ping_count*time_step)))
|
||||
return ips
|
||||
time.sleep(time_step)
|
||||
else:
|
||||
LOG.info(_("ping %s successfully" % ','.join(ping_ips)))
|
||||
return ips
|
||||
|
||||
def _ping_reachable_to_unreachable_host_test(ip,max_ping_times):
|
||||
ping_cmd = 'fping'
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
while True:
|
||||
obj = subprocess.Popen(ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode != 0:
|
||||
return True
|
||||
ping_count += 1
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(_("ping host %s timeout for %ss" % (ip, ping_count*time_step)))
|
||||
return False
|
||||
time.sleep(time_step)
|
||||
return False
|
||||
|
||||
def _ping_unreachable_to_reachable_host_test(ip, max_ping_times):
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
ping_cmd = 'fping'
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
while True:
|
||||
obj = subprocess.Popen(ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0:
|
||||
return True
|
||||
ping_count += 1
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(_("ping host %s timeout for %ss" % (ip, ping_count*time_step)))
|
||||
return False
|
||||
time.sleep(time_step)
|
||||
return False
|
||||
|
||||
def check_reboot_ping(ip):
|
||||
stop_max_ping_times = 360 #ha host reboot may spend 20 min,so timeout time is 30min
|
||||
start_max_ping_times = 60
|
||||
_ping_reachable_to_unreachable_host_test(ip, stop_max_ping_times)
|
||||
_ping_unreachable_to_reachable_host_test(ip, start_max_ping_times)
|
||||
time.sleep(5)
|
||||
|
||||
def cidr_to_netmask(cidr):
|
||||
ip_netmask = cidr.split('/')
|
||||
if len(ip_netmask) != 2 or not ip_netmask[1]:
|
||||
raise exception.InvalidNetworkConfig("cidr is not valid")
|
||||
|
||||
cidr_end = ip_netmask[1]
|
||||
mask = ~(2**(32 - int(cidr_end)) - 1)
|
||||
inter_ip = lambda x: '.'.join([str(x/(256**i)%256) for i in range(3,-1,-1)])
|
||||
netmask = inter_ip(mask)
|
||||
|
||||
return netmask
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import subprocess
|
||||
import time
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from daisy import i18n
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
|
||||
daisy_path = '/var/lib/daisy/'
|
||||
tecs_backend_name = "tecs"
|
||||
zenic_backend_name = "zenic"
|
||||
proton_backend_name = "proton"
|
||||
os_install_start_time = 0.0
|
||||
|
||||
|
||||
def subprocess_call(command, file=None):
|
||||
if file:
|
||||
return_code = subprocess.call(command,
|
||||
shell=True,
|
||||
stdout=file,
|
||||
stderr=file)
|
||||
else:
|
||||
return_code = subprocess.call(command,
|
||||
shell=True,
|
||||
stdout=open('/dev/null', 'w'),
|
||||
stderr=subprocess.STDOUT)
|
||||
if return_code != 0:
|
||||
msg = "execute '%s' failed by subprocess call." % command
|
||||
raise exception.SubprocessCmdFailed(msg)
|
||||
|
||||
|
||||
def get_host_detail(req, host_id):
|
||||
try:
|
||||
host_detail = registry.get_host_metadata(req.context, host_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return host_detail
|
||||
|
||||
|
||||
def get_roles_detail(req):
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return roles
|
||||
|
||||
|
||||
def get_cluster_roles_detail(req, cluster_id):
|
||||
try:
|
||||
params = {'cluster_id': cluster_id}
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return roles
|
||||
|
||||
|
||||
def get_hosts_of_role(req, role_id):
|
||||
try:
|
||||
hosts = registry.get_role_host_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return hosts
|
||||
|
||||
|
||||
def get_role_detail(req, role_id):
|
||||
try:
|
||||
role = registry.get_role_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role
|
||||
|
||||
|
||||
def get_cluster_configs_list(req, cluster_id):
|
||||
roles = get_cluster_roles_detail(req, cluster_id)
|
||||
config_set_list = [role['config_set_id'] for role in roles]
|
||||
cluster_configs_list = []
|
||||
for config_set_id in config_set_list:
|
||||
config_set_metadata = registry.get_config_set_metadata(req.context,
|
||||
config_set_id)
|
||||
if config_set_metadata.get('config', None):
|
||||
cluster_configs_list.extend(config_set_metadata['config'])
|
||||
return cluster_configs_list
|
||||
|
||||
|
||||
def update_role(req, role_id, role_meta):
|
||||
try:
|
||||
registry.update_role_metadata(req.context, role_id, role_meta)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def update_role_host(req, role_id, role_host):
|
||||
try:
|
||||
registry.update_role_host_metadata(req.context, role_id, role_host)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def set_role_status_and_progress(req, cluster_id, opera, status,
|
||||
backend_name='tecs'):
|
||||
"""
|
||||
set information in role of some backend.
|
||||
:status:key in host_role tables, such as:
|
||||
{'messages':'Waiting','progress': '0'}
|
||||
"""
|
||||
roles = get_cluster_roles_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role.get('deployment_backend') == backend_name:
|
||||
role_hosts = get_hosts_of_role(req, role['id'])
|
||||
for role_host in role_hosts:
|
||||
if (opera == 'upgrade' and role_host['status'] in ['active']) \
|
||||
or (opera == 'install' and role_host['status'] not in
|
||||
['active', 'updating', 'update-failed']):
|
||||
update_role_host(req, role_host['id'], status)
|
||||
|
||||
|
||||
def delete_role_hosts(req, role_id):
|
||||
try:
|
||||
registry.delete_role_host_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def get_cluster_networks_detail(req, cluster_id):
|
||||
try:
|
||||
networks = registry.get_networks_detail(req.context, cluster_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return networks
|
||||
|
||||
|
||||
def get_assigned_network(req, host_interface_id, network_id):
|
||||
try:
|
||||
assigned_network = registry.get_assigned_network(
|
||||
req.context, host_interface_id, network_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return assigned_network
|
||||
|
||||
|
||||
def _ping_hosts_test(ips):
|
||||
ping_cmd = 'fping'
|
||||
for ip in set(ips):
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
obj = subprocess.Popen(
|
||||
ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0 or _returncode == 1:
|
||||
ping_result = stdoutput.split('\n')
|
||||
unreachable_hosts = [result.split(
|
||||
)[0] for result in ping_result if result and
|
||||
result.split()[2] != 'alive']
|
||||
else:
|
||||
msg = "ping failed beaceuse there is invlid ip in %s" % ips
|
||||
raise exception.InvalidIP(msg)
|
||||
return unreachable_hosts
|
||||
|
||||
|
||||
def check_ping_hosts(ping_ips, max_ping_times):
|
||||
if not ping_ips:
|
||||
LOG.info(_("no ip got for ping test"))
|
||||
return ping_ips
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
LOG.info(_("begin ping test for %s" % ','.join(ping_ips)))
|
||||
while True:
|
||||
if ping_count == 0:
|
||||
ips = _ping_hosts_test(ping_ips)
|
||||
else:
|
||||
ips = _ping_hosts_test(ips)
|
||||
|
||||
ping_count += 1
|
||||
if ips:
|
||||
LOG.debug(
|
||||
_("ping host %s for %s times" % (','.join(ips), ping_count)))
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(_("ping host %s timeout for %ss" %
|
||||
(','.join(ips), ping_count * time_step)))
|
||||
return ips
|
||||
time.sleep(time_step)
|
||||
else:
|
||||
LOG.info(_("ping %s successfully" % ','.join(ping_ips)))
|
||||
return ips
|
||||
|
||||
|
||||
def _ping_reachable_to_unreachable_host_test(ip, max_ping_times):
|
||||
ping_cmd = 'fping'
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
while True:
|
||||
obj = subprocess.Popen(
|
||||
ping_cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode != 0:
|
||||
return True
|
||||
ping_count += 1
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(
|
||||
_("ping host %s timeout for %ss"
|
||||
% (ip, ping_count * time_step)))
|
||||
return False
|
||||
time.sleep(time_step)
|
||||
return False
|
||||
|
||||
|
||||
def _ping_unreachable_to_reachable_host_test(ip, max_ping_times):
|
||||
ping_count = 0
|
||||
time_step = 5
|
||||
ping_cmd = 'fping'
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
while True:
|
||||
obj = subprocess.Popen(
|
||||
ping_cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0:
|
||||
return True
|
||||
ping_count += 1
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(
|
||||
_("ping host %s timeout for %ss"
|
||||
% (ip, ping_count * time_step)))
|
||||
return False
|
||||
time.sleep(time_step)
|
||||
return False
|
||||
|
||||
|
||||
def check_reboot_ping(ip):
|
||||
# ha host reboot may spend 20 min,so timeout time is 30min
|
||||
stop_max_ping_times = 360
|
||||
start_max_ping_times = 60
|
||||
_ping_reachable_to_unreachable_host_test(ip, stop_max_ping_times)
|
||||
_ping_unreachable_to_reachable_host_test(ip, start_max_ping_times)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def cidr_to_netmask(cidr):
|
||||
ip_netmask = cidr.split('/')
|
||||
if len(ip_netmask) != 2 or not ip_netmask[1]:
|
||||
raise exception.InvalidNetworkConfig("cidr is not valid")
|
||||
|
||||
cidr_end = ip_netmask[1]
|
||||
mask = ~(2 ** (32 - int(cidr_end)) - 1)
|
||||
inter_ip = lambda x: '.'.join(
|
||||
[str(x / (256 ** i) % 256) for i in range(3, -1, -1)])
|
||||
netmask = inter_ip(mask)
|
||||
return netmask
|
||||
|
||||
|
||||
def get_rpm_package_by_name(path, rpm_name):
|
||||
cmd = "ls %s | grep ^%s.*\.rpm" % (path, rpm_name)
|
||||
try:
|
||||
rpm_name = subprocess.check_output(
|
||||
cmd, shell=True, stderr=subprocess.STDOUT).split('\n')[0]
|
||||
except subprocess.CalledProcessError:
|
||||
msg = _("Get rpm %s failed in %s!" % (rpm_name, path))
|
||||
raise exception.SubprocessCmdFailed(message=msg)
|
||||
return rpm_name
|
||||
|
||||
|
||||
def remote_remove_rpm(rpm_name, dest_ip):
|
||||
remove_cmd = 'clush -S -w %s "rpm -q %s && rpm -e %s"' % (dest_ip,
|
||||
rpm_name,
|
||||
rpm_name)
|
||||
subprocess.call(remove_cmd,
|
||||
shell=True,
|
||||
stdout=open('/dev/null', 'w'),
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
|
||||
def remote_install_rpm(rpm_name, rpm_src_path, rpm_dest_path, dest_ips):
|
||||
rpm_package = get_rpm_package_by_name(rpm_src_path, rpm_name)
|
||||
for dest_ip in dest_ips:
|
||||
scp_rpm = "scp -o ConnectTimeout=10 %s/%s root@%s:%s" \
|
||||
% (rpm_src_path, rpm_package, dest_ip, rpm_dest_path)
|
||||
subprocess_call(scp_rpm)
|
||||
|
||||
remote_remove_rpm(rpm_name, dest_ip)
|
||||
|
||||
install_cmd = 'clush -S -w %s "rpm -i %s/%s"' % (dest_ip,
|
||||
rpm_dest_path,
|
||||
rpm_package)
|
||||
subprocess_call(install_cmd)
|
||||
|
||||
|
||||
def remote_upgrade_rpm(rpm_name, rpm_src_path, rpm_dest_path, dest_ip):
|
||||
rpm_package = get_rpm_package_by_name(rpm_src_path, rpm_name)
|
||||
scp_rpm = "scp -o ConnectTimeout=10 %s/%s root@%s:%s" \
|
||||
% (rpm_src_path, rpm_package, dest_ip, rpm_dest_path)
|
||||
subprocess_call(scp_rpm)
|
||||
|
||||
upgrade_cmd = 'clush -S -w %s "rpm -U %s/%s"' % (dest_ip,
|
||||
rpm_dest_path,
|
||||
rpm_package)
|
||||
subprocess.call(upgrade_cmd,
|
||||
shell=True,
|
||||
stdout=open('/dev/null', 'w'),
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
|
||||
def trust_me(host_ips, root_passwd):
|
||||
for host_ip in host_ips:
|
||||
count = 0
|
||||
try_times = 10
|
||||
while count < try_times:
|
||||
try:
|
||||
trust_me_cmd = "/var/lib/daisy/tecs/trustme.sh\
|
||||
%s %s" % (host_ip, root_passwd)
|
||||
subprocess_call(trust_me_cmd)
|
||||
except:
|
||||
count += 1
|
||||
LOG.info("Trying to trust '%s' for %s times" %
|
||||
(host_ip, count))
|
||||
time.sleep(2)
|
||||
if count >= try_times:
|
||||
message = "Setup trust for '%s' failed,"\
|
||||
"see '/var/log/trustme.log' please" % (host_ip)
|
||||
raise exception.TrustMeFailed(message=message)
|
||||
else:
|
||||
message = "Setup trust to '%s' successfully" % (host_ip)
|
||||
LOG.info(message)
|
||||
break
|
||||
|
||||
|
||||
def calc_host_iqn(min_mac):
|
||||
cmd = "echo -n %s |openssl md5" % min_mac
|
||||
obj = subprocess.Popen(cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
iqn = ""
|
||||
if stdoutput:
|
||||
get_uuid = stdoutput.split('=')[1]
|
||||
iqn = "iqn.opencos.rh:" + get_uuid.strip()
|
||||
return iqn
|
||||
|
@ -17,18 +17,15 @@
|
||||
"""
|
||||
Driver base-classes:
|
||||
|
||||
(Beginning of) the contract that deployment backends drivers must follow, and shared
|
||||
types that support that contract
|
||||
(Beginning of) the contract that deployment backends drivers must follow,
|
||||
and shared types that support that contract
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
|
||||
from daisy import i18n
|
||||
from daisy.common import exception
|
||||
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
@ -36,10 +33,13 @@ _LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DeploymentDriver(object):
|
||||
|
||||
"""base class for deployment interface.
|
||||
|
||||
"""
|
||||
|
||||
def install(self, req, cluster_id):
|
||||
raise NotImplementedError()
|
||||
|
||||
@ -48,11 +48,11 @@ class DeploymentDriver(object):
|
||||
|
||||
def uninstall(self, req, cluster_id):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def uninstall_progress(self, req, cluster_id):
|
||||
LOG.info(_("driver no interface for 'uninstall_progress'"))
|
||||
return {}
|
||||
|
||||
|
||||
def upgrade_progress(self, req, cluster_id):
|
||||
LOG.info(_("driver no interface for 'upgrade_progress'"))
|
||||
return {}
|
||||
@ -60,17 +60,19 @@ class DeploymentDriver(object):
|
||||
def exprot_db(self, req, cluster_id):
|
||||
LOG.info(_("driver no interface for 'exprot_db'"))
|
||||
return {}
|
||||
|
||||
|
||||
def update_disk_array(self, req, cluster_id):
|
||||
LOG.info(_("driver no interface for 'update_disk_array'"))
|
||||
return {}
|
||||
|
||||
|
||||
def check_isinstance(obj, cls):
|
||||
"""Checks that obj is of type cls, and lets PyLint infer types."""
|
||||
if isinstance(obj, cls):
|
||||
return obj
|
||||
raise Exception(_('Expected object of type: %s') % (str(cls)))
|
||||
|
||||
|
||||
|
||||
def load_deployment_dirver(backend_name):
|
||||
"""Load a cluster backend installation driver.
|
||||
"""
|
||||
@ -78,8 +80,11 @@ def load_deployment_dirver(backend_name):
|
||||
|
||||
LOG.info(_("Loading deployment backend '%s'") % backend_driver)
|
||||
try:
|
||||
driver = importutils.import_object_ns('daisy.api.backends',backend_driver)
|
||||
driver = importutils.import_object_ns(
|
||||
'daisy.api.backends', backend_driver)
|
||||
return check_isinstance(driver, DeploymentDriver)
|
||||
except ImportError:
|
||||
LOG.exception(_("Error, unable to load the deployment backends '%s'" % backend_driver))
|
||||
LOG.exception(
|
||||
_("Error, unable to load the deployment backends '%s'"
|
||||
% backend_driver))
|
||||
return None
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -54,7 +54,6 @@ def get_proton_ip(req, role_hosts):
|
||||
return proton_ip_list
|
||||
|
||||
|
||||
|
||||
def get_proton_hosts(req, cluster_id):
|
||||
all_roles = proton_cmn.get_roles_detail(req)
|
||||
for role in all_roles:
|
||||
|
@ -1,382 +1,427 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
import commands
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPServerError
|
||||
|
||||
import threading
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.backends.tecs import config
|
||||
from daisy.api.backends import driver
|
||||
from daisy.api.network_api import network as neutron
|
||||
from ironicclient import client as ironic_client
|
||||
import daisy.api.backends.os as os_handle
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
import daisy.api.backends.tecs.install as instl
|
||||
import daisy.api.backends.tecs.uninstall as unstl
|
||||
import daisy.api.backends.tecs.upgrade as upgrd
|
||||
import daisy.api.backends.tecs.disk_array as disk_array
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
CONF = cfg.CONF
|
||||
upgrade_opts = [
|
||||
cfg.StrOpt('max_parallel_os_upgrade_number', default=10,
|
||||
help='Maximum number of hosts upgrade os at the same time.'),
|
||||
]
|
||||
CONF.register_opts(upgrade_opts)
|
||||
|
||||
tecs_state = tecs_cmn.TECS_STATE
|
||||
|
||||
class API(driver.DeploymentDriver):
|
||||
"""
|
||||
The hosts API is a RESTful web service for host data. The API
|
||||
is as follows::
|
||||
|
||||
GET /hosts -- Returns a set of brief metadata about hosts
|
||||
GET /hosts/detail -- Returns a set of detailed metadata about
|
||||
hosts
|
||||
HEAD /hosts/<ID> -- Return metadata about an host with id <ID>
|
||||
GET /hosts/<ID> -- Return host data for host with id <ID>
|
||||
POST /hosts -- Store host data and return metadata about the
|
||||
newly-stored host
|
||||
PUT /hosts/<ID> -- Update host metadata and/or upload host
|
||||
data for a previously-reserved host
|
||||
DELETE /hosts/<ID> -- Delete the host with id <ID>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(API, self).__init__()
|
||||
return
|
||||
|
||||
def install(self, req, cluster_id):
|
||||
"""
|
||||
Install TECS to a cluster.
|
||||
|
||||
param req: The WSGI/Webob Request object
|
||||
cluster_id:cluster id
|
||||
"""
|
||||
|
||||
tecs_install_task = instl.TECSInstallTask(req, cluster_id)
|
||||
tecs_install_task.start()
|
||||
|
||||
def _get_roles_and_hosts_ip_list(self, req, cluster_id):
|
||||
host_ha_list = set()
|
||||
host_ip_list = set()
|
||||
role_id_list = set()
|
||||
hosts_id_list = []
|
||||
hosts_list = []
|
||||
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req,cluster_id)
|
||||
cluster_networks = daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
if role_hosts:
|
||||
for role_host in role_hosts:
|
||||
host = daisy_cmn.get_host_detail(req, role_host['host_id'])
|
||||
host_ip = tecs_cmn.get_host_network_ip(req, host, cluster_networks, 'MANAGEMENT')
|
||||
if role['name'] == "CONTROLLER_HA":
|
||||
host_ha_list.add(host_ip)
|
||||
host_ip_list.add(host_ip)
|
||||
hosts_id_list.append({host['id']:host_ip})
|
||||
role_id_list.add(role['id'])
|
||||
for host in hosts_id_list:
|
||||
if host not in hosts_list:
|
||||
hosts_list.append(host)
|
||||
return (role_id_list, host_ip_list, host_ha_list, hosts_list)
|
||||
|
||||
def _query_progress(self, req, cluster_id, action=""):
|
||||
nodes_list = []
|
||||
roles = daisy_cmn.get_roles_detail(req)
|
||||
(role_id_list,host_ip_list,host_ha_list,hosts_list) = self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
for host in hosts_list:
|
||||
node = {}
|
||||
host_id = host.keys()[0]
|
||||
host = daisy_cmn.get_host_detail(req, host_id)
|
||||
node['id'] = host['id']
|
||||
node['name'] = host['name']
|
||||
|
||||
if 0 == cmp("upgrade", action):
|
||||
node['os-progress'] = host['os_progress']
|
||||
node['os-status'] = host['os_status']
|
||||
node['os-messages'] = host['messages']
|
||||
|
||||
if host['status'] == "with-role":
|
||||
host_roles = [ role for role in roles if role['name'] in host['role'] and role['cluster_id'] == cluster_id]
|
||||
if host_roles:
|
||||
node['role-status'] = host_roles[0]['status']
|
||||
node['role-progress'] = str(host_roles[0]['progress'])
|
||||
# node['role-message'] = host_roles[0]['messages']
|
||||
nodes_list.append(node)
|
||||
if nodes_list:
|
||||
return {'tecs_nodes': nodes_list}
|
||||
else:
|
||||
return {'tecs_nodes': "TECS uninstall successfully, the host has been removed from the host_roles table"}
|
||||
|
||||
def uninstall(self, req, cluster_id):
|
||||
"""
|
||||
Uninstall TECS to a cluster.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
(role_id_list, host_ip_list,host_ha_list, hosts_list) = self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
if role_id_list:
|
||||
if not host_ip_list:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
unstl.update_progress_to_db(req, role_id_list, tecs_state['UNINSTALLING'], hosts_list)
|
||||
|
||||
threads = []
|
||||
for host_ip in host_ip_list:
|
||||
t = threading.Thread(target=unstl.thread_bin,args=(req,host_ip,role_id_list,hosts_list))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
LOG.info(_("Uninstall threads have started, please waiting...."))
|
||||
|
||||
try:
|
||||
for t in threads:
|
||||
t.join()
|
||||
except:
|
||||
LOG.warn(_("Join uninstall thread %s failed!" % t))
|
||||
else:
|
||||
uninstall_failed_flag = False
|
||||
for role_id in role_id_list:
|
||||
role_hosts=daisy_cmn.get_hosts_of_role(req,role_id)
|
||||
for role_host in role_hosts:
|
||||
if role_host['status'] == tecs_state['UNINSTALL_FAILED']:
|
||||
unstl.update_progress_to_db(req, role_id_list, tecs_state['UNINSTALL_FAILED'],hosts_list)
|
||||
uninstall_failed_flag = True
|
||||
break
|
||||
if not uninstall_failed_flag:
|
||||
LOG.info(_("All uninstall threads have done, set all roles status to 'init'!"))
|
||||
unstl.update_progress_to_db(req, role_id_list, tecs_state['INIT'], hosts_list)
|
||||
try:
|
||||
(status, output) = commands.getstatusoutput('rpm -e --nodeps openstack-packstack\
|
||||
openstack-packstack-puppet openstack-puppet-modules puppet')
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
def uninstall_progress(self, req, cluster_id):
|
||||
return self._query_progress(req, cluster_id, "uninstall")
|
||||
|
||||
def upgrade(self, req, cluster_id):
|
||||
"""
|
||||
update TECS to a cluster.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
(role_id_list,host_ip_list,host_ha_list,hosts_list) = self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
if role_id_list:
|
||||
if not host_ip_list:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
unreached_hosts = daisy_cmn.check_ping_hosts(host_ip_list, 1)
|
||||
if unreached_hosts:
|
||||
self.message = "hosts %s ping failed" % unreached_hosts
|
||||
raise exception.NotFound(message=self.message)
|
||||
|
||||
daisy_cmn.subprocess_call('rm -rf /root/.ssh/known_hosts')
|
||||
|
||||
if os_handle.check_tfg_exist():
|
||||
os_handle.upgrade_os(req, hosts_list)
|
||||
unreached_hosts = daisy_cmn.check_ping_hosts(host_ip_list, 30)
|
||||
if unreached_hosts:
|
||||
self.message = "hosts %s ping failed after tfg upgrade" % unreached_hosts
|
||||
raise exception.NotFound(message=self.message)
|
||||
# check and get TECS version
|
||||
tecs_version_pkg_file = tecs_cmn.check_and_get_tecs_version(tecs_cmn.daisy_tecs_path)
|
||||
if not tecs_version_pkg_file:
|
||||
self.state = tecs_state['INSTALL_FAILED']
|
||||
self.message = "TECS version file not found in %s" % tecs_cmn.daisy_tecs_path
|
||||
raise exception.NotFound(message=self.message)
|
||||
threads = []
|
||||
LOG.info(_("Begin to update TECS controller nodes, please waiting...."))
|
||||
upgrd.update_progress_to_db(req, role_id_list, tecs_state['UPDATING'], hosts_list)
|
||||
for host_ip in host_ha_list:
|
||||
LOG.info(_("Update TECS controller node %s..." % host_ip))
|
||||
rc = upgrd.thread_bin(req,role_id_list,host_ip,hosts_list)
|
||||
if rc == 0:
|
||||
LOG.info(_("Update TECS for %s successfully" % host_ip))
|
||||
else:
|
||||
LOG.info(_("Update TECS failed for %s, return %s" % (host_ip,rc)))
|
||||
return
|
||||
LOG.info(_("Begin to update TECS other nodes, please waiting...."))
|
||||
max_parallel_upgrade_number = int(CONF.max_parallel_os_upgrade_number)
|
||||
compute_ip_list = host_ip_list - host_ha_list
|
||||
while compute_ip_list:
|
||||
threads = []
|
||||
if len(compute_ip_list) > max_parallel_upgrade_number:
|
||||
upgrade_hosts = compute_ip_list[:max_parallel_upgrade_number]
|
||||
compute_ip_list = compute_ip_list[max_parallel_upgrade_number:]
|
||||
else:
|
||||
upgrade_hosts = compute_ip_list
|
||||
compute_ip_list = []
|
||||
for host_ip in upgrade_hosts:
|
||||
t = threading.Thread(target=upgrd.thread_bin,args=(req,role_id_list,host_ip,hosts_list))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
try:
|
||||
for t in threads:
|
||||
t.join()
|
||||
except:
|
||||
LOG.warn(_("Join update thread %s failed!" % t))
|
||||
|
||||
for role_id in role_id_list:
|
||||
role_hosts=daisy_cmn.get_hosts_of_role(req,role_id)
|
||||
for role_host in role_hosts:
|
||||
if (role_host['status'] == tecs_state['UPDATE_FAILED'] or
|
||||
role_host['status'] == tecs_state['UPDATING']):
|
||||
role_id = [role_host['role_id']]
|
||||
upgrd.update_progress_to_db(req,
|
||||
role_id,
|
||||
tecs_state['UPDATE_FAILED'],
|
||||
hosts_list)
|
||||
break
|
||||
elif role_host['status'] == tecs_state['ACTIVE']:
|
||||
role_id = [role_host['role_id']]
|
||||
upgrd.update_progress_to_db(req,
|
||||
role_id,
|
||||
tecs_state['ACTIVE'],
|
||||
hosts_list)
|
||||
|
||||
def upgrade_progress(self, req, cluster_id):
|
||||
return self._query_progress(req, cluster_id, "upgrade")
|
||||
|
||||
|
||||
def export_db(self, req, cluster_id):
|
||||
"""
|
||||
Export daisy db data to tecs.conf and HA.conf.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
|
||||
(tecs_config, mgnt_ip_list) =\
|
||||
instl.get_cluster_tecs_config(req, cluster_id)
|
||||
|
||||
config_files = {'tecs_conf':'','ha_conf':''}
|
||||
tecs_install_path = "/home/tecs_install"
|
||||
tecs_config_file = ''
|
||||
if tecs_config:
|
||||
cluster_conf_path = tecs_install_path + "/" + cluster_id
|
||||
create_cluster_conf_path =\
|
||||
"rm -rf %s;mkdir %s" %(cluster_conf_path, cluster_conf_path)
|
||||
daisy_cmn.subprocess_call(create_cluster_conf_path)
|
||||
config.update_tecs_config(tecs_config, cluster_conf_path)
|
||||
|
||||
get_tecs_conf = "ls %s|grep tecs.conf" % cluster_conf_path
|
||||
obj = subprocess.Popen(get_tecs_conf,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
tecs_conf_file = ""
|
||||
if stdoutput:
|
||||
tecs_conf_file = stdoutput.split('\n')[0]
|
||||
config_files['tecs_conf'] =\
|
||||
cluster_conf_path + "/" + tecs_conf_file
|
||||
|
||||
get_ha_conf_cmd = "ls %s|grep HA_1.conf" % cluster_conf_path
|
||||
obj = subprocess.Popen(get_ha_conf_cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
ha_conf_file = ""
|
||||
if stdoutput:
|
||||
ha_conf_file = stdoutput.split('\n')[0]
|
||||
config_files['ha_conf'] =\
|
||||
cluster_conf_path + "/" + ha_conf_file
|
||||
else:
|
||||
LOG.info(_("No TECS config files generated."))
|
||||
|
||||
return config_files
|
||||
|
||||
def update_disk_array(self, req, cluster_id):
|
||||
(share_disk_info, volume_disk_info) =\
|
||||
disk_array.get_disk_array_info(req, cluster_id)
|
||||
(controller_ha_nodes, computer_ips) =\
|
||||
disk_array.get_ha_and_compute_ips(req, cluster_id)
|
||||
all_nodes_ip = computer_ips + controller_ha_nodes.keys()
|
||||
|
||||
if all_nodes_ip:
|
||||
compute_error_msg =\
|
||||
disk_array.config_compute_multipath(all_nodes_ip)
|
||||
if compute_error_msg:
|
||||
return compute_error_msg
|
||||
else:
|
||||
LOG.info(_("Config Disk Array multipath successfully"))
|
||||
|
||||
if share_disk_info:
|
||||
ha_error_msg =\
|
||||
disk_array.config_ha_share_disk(share_disk_info,
|
||||
controller_ha_nodes)
|
||||
if ha_error_msg:
|
||||
return ha_error_msg
|
||||
else:
|
||||
LOG.info(_("Config Disk Array for HA nodes successfully"))
|
||||
|
||||
if volume_disk_info:
|
||||
cinder_error_msg =\
|
||||
disk_array.config_ha_cinder_volume(volume_disk_info,
|
||||
controller_ha_nodes.keys())
|
||||
if cinder_error_msg:
|
||||
return cinder_error_msg
|
||||
else:
|
||||
LOG.info(_("Config cinder volume for HA nodes successfully"))
|
||||
|
||||
return 'update successfully'
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import subprocess
|
||||
import commands
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
|
||||
import threading
|
||||
|
||||
from daisy import i18n
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy.api.backends.tecs import config
|
||||
from daisy.api.backends import driver
|
||||
import daisy.api.backends.os as os_handle
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
import daisy.api.backends.tecs.install as instl
|
||||
import daisy.api.backends.tecs.uninstall as unstl
|
||||
import daisy.api.backends.tecs.upgrade as upgrd
|
||||
import daisy.api.backends.tecs.disk_array as disk_array
|
||||
from daisy.api.backends.tecs import write_configs
|
||||
import daisy.registry.client.v1.api as registry
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
CONF = cfg.CONF
|
||||
upgrade_opts = [
|
||||
cfg.StrOpt('max_parallel_os_upgrade_number', default=10,
|
||||
help='Maximum number of hosts upgrade os at the same time.'),
|
||||
]
|
||||
CONF.register_opts(upgrade_opts)
|
||||
|
||||
tecs_state = tecs_cmn.TECS_STATE
|
||||
daisy_tecs_path = tecs_cmn.daisy_tecs_path
|
||||
|
||||
|
||||
class API(driver.DeploymentDriver):
|
||||
|
||||
"""
|
||||
The hosts API is a RESTful web service for host data. The API
|
||||
is as follows::
|
||||
|
||||
GET /hosts -- Returns a set of brief metadata about hosts
|
||||
GET /hosts/detail -- Returns a set of detailed metadata about
|
||||
hosts
|
||||
HEAD /hosts/<ID> -- Return metadata about an host with id <ID>
|
||||
GET /hosts/<ID> -- Return host data for host with id <ID>
|
||||
POST /hosts -- Store host data and return metadata about the
|
||||
newly-stored host
|
||||
PUT /hosts/<ID> -- Update host metadata and/or upload host
|
||||
data for a previously-reserved host
|
||||
DELETE /hosts/<ID> -- Delete the host with id <ID>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(API, self).__init__()
|
||||
return
|
||||
|
||||
def install(self, req, cluster_id):
|
||||
"""
|
||||
Install TECS to a cluster.
|
||||
|
||||
param req: The WSGI/Webob Request object
|
||||
cluster_id:cluster id
|
||||
"""
|
||||
write_configs.update_configset(req, cluster_id)
|
||||
|
||||
tecs_install_task = instl.TECSInstallTask(req, cluster_id)
|
||||
tecs_install_task.start()
|
||||
|
||||
def _get_roles_and_hosts_ip_list(self, req, cluster_id):
|
||||
role_host_ips = {'ha': set(), 'lb': set(), 'all': set()}
|
||||
role_id_list = set()
|
||||
hosts_id_list = []
|
||||
hosts_list = []
|
||||
tecs_install_failed_list = set()
|
||||
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
cluster_networks = daisy_cmn.get_cluster_networks_detail(
|
||||
req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
if role_hosts:
|
||||
for role_host in role_hosts:
|
||||
host = daisy_cmn.get_host_detail(req, role_host['host_id'])
|
||||
host_ip = tecs_cmn.get_host_network_ip(
|
||||
req, host, cluster_networks, 'MANAGEMENT')
|
||||
if role['name'] == "CONTROLLER_HA":
|
||||
role_host_ips['ha'].add(host_ip)
|
||||
if role['name'] == "CONTROLLER_LB":
|
||||
role_host_ips['lb'].add(host_ip)
|
||||
role_host_ips['all'].add(host_ip)
|
||||
hosts_id_list.append({host['id']: host_ip})
|
||||
if role_host['status'] == tecs_state['INSTALL_FAILED']:
|
||||
tecs_install_failed_list.add(host_ip)
|
||||
role_id_list.add(role['id'])
|
||||
for host in hosts_id_list:
|
||||
if host not in hosts_list:
|
||||
hosts_list.append(host)
|
||||
return (role_id_list, role_host_ips,
|
||||
hosts_list, tecs_install_failed_list)
|
||||
|
||||
def _query_progress(self, req, cluster_id, action=""):
|
||||
nodes_list = []
|
||||
roles = daisy_cmn.get_roles_detail(req)
|
||||
(role_id_list, role_host_ips, hosts_list, tecs_install_failed_list) =\
|
||||
self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
for host in hosts_list:
|
||||
node = {}
|
||||
host_id = host.keys()[0]
|
||||
host = daisy_cmn.get_host_detail(req, host_id)
|
||||
node['id'] = host['id']
|
||||
node['name'] = host['name']
|
||||
|
||||
if 0 == cmp("upgrade", action):
|
||||
node['os-progress'] = host['os_progress']
|
||||
node['os-status'] = host['os_status']
|
||||
node['os-messages'] = host['messages']
|
||||
|
||||
if host['status'] == "with-role":
|
||||
host_roles = [role for role in roles if role['name'] in host[
|
||||
'role'] and role['cluster_id'] == cluster_id]
|
||||
if host_roles:
|
||||
node['role-status'] = host_roles[0]['status']
|
||||
node['role-progress'] = str(host_roles[0]['progress'])
|
||||
# node['role-message'] = host_roles[0]['messages']
|
||||
nodes_list.append(node)
|
||||
if nodes_list:
|
||||
return {'tecs_nodes': nodes_list}
|
||||
else:
|
||||
return {'tecs_nodes': "TECS uninstall successfully,\
|
||||
the host has been removed from the host_roles table"}
|
||||
|
||||
def _modify_running_version_of_configs(self, req,
|
||||
running_version, cluster_id):
|
||||
cluster_configs_list = daisy_cmn.get_cluster_configs_list(req,
|
||||
cluster_id)
|
||||
if cluster_configs_list:
|
||||
for cluster_config in cluster_configs_list:
|
||||
registry.update_config_metadata(req.context,
|
||||
cluster_config['id'],
|
||||
{'running_version':
|
||||
running_version})
|
||||
|
||||
def uninstall(self, req, cluster_id):
|
||||
"""
|
||||
Uninstall TECS to a cluster.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
(role_id_list, role_host_ips, hosts_list, tecs_install_failed_list) =\
|
||||
self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
if role_id_list:
|
||||
if not role_host_ips['all']:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, tecs_state['UNINSTALLING'], hosts_list)
|
||||
|
||||
threads = []
|
||||
for host_ip in role_host_ips['all']:
|
||||
t = threading.Thread(
|
||||
target=unstl.thread_bin, args=(req, host_ip, role_id_list,
|
||||
hosts_list))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
LOG.info(_("Uninstall threads have started, please waiting...."))
|
||||
|
||||
try:
|
||||
for t in threads:
|
||||
t.join()
|
||||
except:
|
||||
LOG.warn(_("Join uninstall thread %s failed!" % t))
|
||||
else:
|
||||
uninstall_failed_flag = False
|
||||
for role_id in role_id_list:
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role_id)
|
||||
for role_host in role_hosts:
|
||||
if role_host['status'] ==\
|
||||
tecs_state['UNINSTALL_FAILED']:
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, tecs_state[
|
||||
'UNINSTALL_FAILED'], hosts_list)
|
||||
uninstall_failed_flag = True
|
||||
break
|
||||
if not uninstall_failed_flag:
|
||||
LOG.info(
|
||||
_("All uninstall threads have done,\
|
||||
set all roles status to 'init'!"))
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, tecs_state['INIT'], hosts_list)
|
||||
LOG.info(_("modify the running_version of configs to 0"))
|
||||
running_version = 0
|
||||
self._modify_running_version_of_configs(
|
||||
req, running_version, cluster_id)
|
||||
tecs_cmn.inform_provider_cloud_state(req.context, cluster_id,
|
||||
operation='delete')
|
||||
try:
|
||||
(status, output) = commands.getstatusoutput('rpm -e --nodeps openstack-packstack\
|
||||
openstack-packstack-puppet \
|
||||
openstack-puppet-modules puppet')
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
def uninstall_progress(self, req, cluster_id):
|
||||
return self._query_progress(req, cluster_id, "uninstall")
|
||||
|
||||
def upgrade(self, req, cluster_id):
|
||||
"""
|
||||
update TECS to a cluster.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
# daisy_update_path = '/home/daisy_update/'
|
||||
|
||||
(role_id_list, role_host_ips, hosts_list, tecs_install_failed_list) =\
|
||||
self._get_roles_and_hosts_ip_list(req, cluster_id)
|
||||
if role_id_list:
|
||||
if not role_host_ips['all']:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
unreached_hosts = daisy_cmn.check_ping_hosts(
|
||||
role_host_ips['all'], 1)
|
||||
if unreached_hosts:
|
||||
self.message = "hosts %s ping failed" % unreached_hosts
|
||||
raise exception.NotFound(message=self.message)
|
||||
daisy_cmn.subprocess_call('rm -rf /root/.ssh/known_hosts')
|
||||
if os_handle.check_tfg_exist():
|
||||
os_handle.upgrade_os(req, hosts_list)
|
||||
unreached_hosts = daisy_cmn.check_ping_hosts(
|
||||
role_host_ips['all'], 30)
|
||||
if unreached_hosts:
|
||||
self.message = "hosts %s ping failed after tfg upgrade" \
|
||||
% unreached_hosts
|
||||
raise exception.NotFound(message=self.message)
|
||||
# check and get TECS version
|
||||
tecs_version_pkg_file = tecs_cmn.check_and_get_tecs_version(
|
||||
tecs_cmn.daisy_tecs_path)
|
||||
if not tecs_version_pkg_file:
|
||||
self.state = tecs_state['UPDATE_FAILED']
|
||||
self.message = "TECS version file not found in %s"\
|
||||
% tecs_cmn.daisy_tecs_path
|
||||
raise exception.NotFound(message=self.message)
|
||||
threads = []
|
||||
LOG.info(
|
||||
_("Begin to update TECS controller nodes, please waiting...."))
|
||||
upgrd.update_progress_to_db(
|
||||
req, role_id_list, tecs_state['UPDATING'], hosts_list)
|
||||
for host_ip in role_host_ips['ha']:
|
||||
if host_ip in tecs_install_failed_list:
|
||||
continue
|
||||
LOG.info(_("Update TECS controller node %s..." % host_ip))
|
||||
rc = upgrd.thread_bin(req, role_id_list, host_ip, hosts_list)
|
||||
if rc == 0:
|
||||
LOG.info(_("Update TECS for %s successfully" % host_ip))
|
||||
else:
|
||||
LOG.info(
|
||||
_("Update TECS failed for %s, return %s"
|
||||
% (host_ip, rc)))
|
||||
return
|
||||
|
||||
LOG.info(_("Begin to update TECS other nodes, please waiting...."))
|
||||
max_parallel_upgrade_number = int(
|
||||
CONF.max_parallel_os_upgrade_number)
|
||||
compute_ip_list = role_host_ips[
|
||||
'all'] - role_host_ips['ha'] - tecs_install_failed_list
|
||||
while compute_ip_list:
|
||||
threads = []
|
||||
if len(compute_ip_list) > max_parallel_upgrade_number:
|
||||
upgrade_hosts = compute_ip_list[
|
||||
:max_parallel_upgrade_number]
|
||||
compute_ip_list = compute_ip_list[
|
||||
max_parallel_upgrade_number:]
|
||||
else:
|
||||
upgrade_hosts = compute_ip_list
|
||||
compute_ip_list = []
|
||||
for host_ip in upgrade_hosts:
|
||||
t = threading.Thread(
|
||||
target=upgrd.thread_bin,
|
||||
args=(req, role_id_list, host_ip, hosts_list))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
try:
|
||||
for t in threads:
|
||||
t.join()
|
||||
except:
|
||||
LOG.warn(_("Join update thread %s failed!" % t))
|
||||
|
||||
for role_id in role_id_list:
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role_id)
|
||||
for role_host in role_hosts:
|
||||
if (role_host['status'] == tecs_state['UPDATE_FAILED'] or
|
||||
role_host['status'] == tecs_state['UPDATING']):
|
||||
role_id = [role_host['role_id']]
|
||||
upgrd.update_progress_to_db(req,
|
||||
role_id,
|
||||
tecs_state[
|
||||
'UPDATE_FAILED'],
|
||||
hosts_list)
|
||||
break
|
||||
elif role_host['status'] == tecs_state['ACTIVE']:
|
||||
role_id = [role_host['role_id']]
|
||||
upgrd.update_progress_to_db(req,
|
||||
role_id,
|
||||
tecs_state['ACTIVE'],
|
||||
hosts_list)
|
||||
|
||||
def upgrade_progress(self, req, cluster_id):
|
||||
return self._query_progress(req, cluster_id, "upgrade")
|
||||
|
||||
def export_db(self, req, cluster_id):
|
||||
"""
|
||||
Export daisy db data to tecs.conf and HA.conf.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
|
||||
tecs_config =\
|
||||
instl.get_cluster_tecs_config(req, cluster_id)
|
||||
|
||||
config_files = {'tecs_conf': '', 'ha_conf': ''}
|
||||
tecs_install_path = "/home/tecs_install"
|
||||
if tecs_config:
|
||||
cluster_conf_path = tecs_install_path + "/" + cluster_id
|
||||
create_cluster_conf_path =\
|
||||
"rm -rf %s;mkdir %s" % (cluster_conf_path, cluster_conf_path)
|
||||
daisy_cmn.subprocess_call(create_cluster_conf_path)
|
||||
config.update_tecs_config(tecs_config, cluster_conf_path)
|
||||
|
||||
get_tecs_conf = "ls %s|grep tecs.conf" % cluster_conf_path
|
||||
obj = subprocess.Popen(get_tecs_conf,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
tecs_conf_file = ""
|
||||
if stdoutput:
|
||||
tecs_conf_file = stdoutput.split('\n')[0]
|
||||
config_files['tecs_conf'] =\
|
||||
cluster_conf_path + "/" + tecs_conf_file
|
||||
|
||||
get_ha_conf_cmd = "ls %s|grep HA_1.conf" % cluster_conf_path
|
||||
obj = subprocess.Popen(get_ha_conf_cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
ha_conf_file = ""
|
||||
if stdoutput:
|
||||
ha_conf_file = stdoutput.split('\n')[0]
|
||||
config_files['ha_conf'] =\
|
||||
cluster_conf_path + "/" + ha_conf_file
|
||||
else:
|
||||
LOG.info(_("No TECS config files generated."))
|
||||
|
||||
return config_files
|
||||
|
||||
def update_disk_array(self, req, cluster_id):
|
||||
(share_disk_info, volume_disk_info) =\
|
||||
disk_array.get_disk_array_info(req, cluster_id)
|
||||
array_nodes_addr =\
|
||||
tecs_cmn.get_disk_array_nodes_addr(req, cluster_id)
|
||||
|
||||
ha_nodes_ip = array_nodes_addr['ha'].keys()
|
||||
all_nodes_ip = list(array_nodes_addr['computer']) + ha_nodes_ip
|
||||
|
||||
if all_nodes_ip:
|
||||
compute_error_msg =\
|
||||
disk_array.config_compute_multipath(all_nodes_ip)
|
||||
if compute_error_msg:
|
||||
return compute_error_msg
|
||||
else:
|
||||
LOG.info(_("Config Disk Array multipath successfully"))
|
||||
|
||||
if share_disk_info:
|
||||
ha_error_msg =\
|
||||
disk_array.config_ha_share_disk(share_disk_info,
|
||||
array_nodes_addr['ha'])
|
||||
if ha_error_msg:
|
||||
return ha_error_msg
|
||||
else:
|
||||
LOG.info(_("Config Disk Array for HA nodes successfully"))
|
||||
|
||||
if volume_disk_info:
|
||||
cinder_error_msg =\
|
||||
disk_array.config_ha_cinder_volume(volume_disk_info,
|
||||
ha_nodes_ip)
|
||||
if cinder_error_msg:
|
||||
return cinder_error_msg
|
||||
else:
|
||||
LOG.info(_("Config cinder volume for HA nodes successfully"))
|
||||
|
||||
return 'update successfully'
|
||||
|
@ -19,33 +19,21 @@
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
import re
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
from daisy.common import utils
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
from daisyclient.v1 import client as daisy_client
|
||||
import ConfigParser
|
||||
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
STR_MASK = '*' * 8
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
@ -53,11 +41,12 @@ _LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
|
||||
daisy_tecs_path = '/var/lib/daisy/tecs/'
|
||||
tecs_install_path = '/home/tecs_install'
|
||||
|
||||
TECS_STATE = {
|
||||
'INIT' : 'init',
|
||||
'INSTALLING' : 'installing',
|
||||
'ACTIVE' : 'active',
|
||||
'INIT': 'init',
|
||||
'INSTALLING': 'installing',
|
||||
'ACTIVE': 'active',
|
||||
'INSTALL_FAILED': 'install-failed',
|
||||
'UNINSTALLING': 'uninstalling',
|
||||
'UNINSTALL_FAILED': 'uninstall-failed',
|
||||
@ -66,42 +55,65 @@ TECS_STATE = {
|
||||
}
|
||||
|
||||
|
||||
def get_daisyclient():
|
||||
"""Get Daisy client instance."""
|
||||
config_daisy = ConfigParser.ConfigParser()
|
||||
config_daisy.read("/etc/daisy/daisy-api.conf")
|
||||
daisy_port = config_daisy.get("DEFAULT", "bind_port")
|
||||
args = {'version': 1.0, 'endpoint': 'http://127.0.0.1:' + daisy_port}
|
||||
return daisy_client.Client(**args)
|
||||
|
||||
|
||||
def mkdir_tecs_install(host_ips=None):
|
||||
if not host_ips:
|
||||
cmd = "mkdir -p %s" % tecs_install_path
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
return
|
||||
for host_ip in host_ips:
|
||||
cmd = 'clush -S -w %s "mkdir -p %s"' % (host_ip, tecs_install_path)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
|
||||
|
||||
def _get_cluster_network(cluster_networks, network_name):
|
||||
network = [cn for cn in cluster_networks
|
||||
if cn['name'] in network_name]
|
||||
network = [cn for cn in cluster_networks if cn['name'] == network_name]
|
||||
if not network or not network[0]:
|
||||
msg = "network %s is not exist" % (network_name)
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
else:
|
||||
return network[0]
|
||||
|
||||
|
||||
def get_host_interface_by_network(host_detail, network_name):
|
||||
host_detail_info = copy.deepcopy(host_detail)
|
||||
interface_list = [hi for hi in host_detail_info['interfaces']
|
||||
for assigned_network in hi['assigned_networks']
|
||||
if assigned_network and network_name == assigned_network['name']]
|
||||
interface_list = [hi for hi in host_detail_info['interfaces']
|
||||
for assigned_network in hi['assigned_networks']
|
||||
if assigned_network and
|
||||
network_name == assigned_network['name']]
|
||||
interface = {}
|
||||
if interface_list:
|
||||
interface = interface_list[0]
|
||||
|
||||
|
||||
if not interface and 'MANAGEMENT' == network_name:
|
||||
msg = "network %s of host %s is not exist" % (network_name, host_detail_info['id'])
|
||||
msg = "network %s of host %s is not exist" % (
|
||||
network_name, host_detail_info['id'])
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
|
||||
return interface
|
||||
|
||||
|
||||
def get_host_network_ip(req, host_detail, cluster_networks, network_name):
|
||||
interface_network_ip = ''
|
||||
host_interface = get_host_interface_by_network(host_detail, network_name)
|
||||
if host_interface:
|
||||
network = _get_cluster_network(cluster_networks, network_name)
|
||||
assigned_network = daisy_cmn.get_assigned_network(req,
|
||||
host_interface['id'],
|
||||
network['id'])
|
||||
assigned_network = daisy_cmn.get_assigned_network(req,
|
||||
host_interface['id'],
|
||||
network['id'])
|
||||
interface_network_ip = assigned_network['ip']
|
||||
|
||||
if not interface_network_ip and 'MANAGEMENT' == network_name :
|
||||
msg = "%s network ip of host %s can't be empty" % (network_name, host_detail['id'])
|
||||
if not interface_network_ip and 'MANAGEMENT' == network_name:
|
||||
msg = "%s network ip of host %s can't be empty" % (
|
||||
network_name, host_detail['id'])
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
return interface_network_ip
|
||||
|
||||
@ -147,26 +159,36 @@ def get_network_netmask(cluster_networks, network_name):
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
return netmask
|
||||
|
||||
|
||||
# every host only have one gateway
|
||||
def get_network_gateway(cluster_networks, network_name):
|
||||
network = _get_cluster_network(cluster_networks, network_name)
|
||||
gateway = network['gateway']
|
||||
if not gateway and 'MANAGEMENT' == network_name:
|
||||
msg = "gateway of network %s can't be empty" % (network_name)
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
return gateway
|
||||
|
||||
|
||||
def get_network_cidr(cluster_networks, network_name):
|
||||
network = _get_cluster_network(cluster_networks, network_name)
|
||||
cidr = network['cidr']
|
||||
if not cidr:
|
||||
msg = "cidr of network %s is not exist" % (network_name)
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
return cidr
|
||||
|
||||
|
||||
def get_mngt_network_vlan_id(cluster_networks):
|
||||
mgnt_vlan_id = ""
|
||||
management_network = [network for network in cluster_networks if network['network_type'] == 'MANAGEMENT']
|
||||
management_network = [network for network in cluster_networks if network[
|
||||
'network_type'] == 'MANAGEMENT']
|
||||
if (not management_network or
|
||||
not management_network[0] or
|
||||
not management_network[0].has_key('vlan_id')):
|
||||
not management_network[0] or
|
||||
# not management_network[0].has_key('vlan_id')):
|
||||
'vlan_id' not in management_network[0]):
|
||||
msg = "can't get management network vlan id"
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
else:
|
||||
mgnt_vlan_id = management_network[0]['vlan_id']
|
||||
return mgnt_vlan_id
|
||||
return mgnt_vlan_id
|
||||
|
||||
|
||||
def get_network_vlan_id(cluster_networks, network_type):
|
||||
@ -174,7 +196,8 @@ def get_network_vlan_id(cluster_networks, network_type):
|
||||
general_network = [network for network in cluster_networks
|
||||
if network['network_type'] == network_type]
|
||||
if (not general_network or not general_network[0] or
|
||||
not general_network[0].has_key('vlan_id')):
|
||||
# not general_network[0].has_key('vlan_id')):
|
||||
'vlan_id' not in general_network[0]):
|
||||
msg = "can't get %s network vlan id" % network_type
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
else:
|
||||
@ -182,7 +205,7 @@ def get_network_vlan_id(cluster_networks, network_type):
|
||||
return vlan_id
|
||||
|
||||
|
||||
def sort_interfaces_by_pci(host_detail):
|
||||
def sort_interfaces_by_pci(networks, host_detail):
|
||||
"""
|
||||
Sort interfaces by pci segment, if interface type is bond,
|
||||
user the pci of first memeber nic.This function is fix bug for
|
||||
@ -192,61 +215,45 @@ def sort_interfaces_by_pci(host_detail):
|
||||
:return:
|
||||
"""
|
||||
interfaces = eval(host_detail.get('interfaces', None)) \
|
||||
if isinstance(host_detail, unicode) else host_detail.get('interfaces', None)
|
||||
if isinstance(host_detail, unicode) else \
|
||||
host_detail.get('interfaces', None)
|
||||
if not interfaces:
|
||||
LOG.info("This host don't have /interfaces info.")
|
||||
LOG.info("This host has no interfaces info.")
|
||||
return host_detail
|
||||
|
||||
tmp_interfaces = copy.deepcopy(interfaces)
|
||||
if not [interface for interface in tmp_interfaces
|
||||
if interface.get('name', None) and len(interface['name']) > 8]:
|
||||
LOG.info("The interfaces name of host is all less than 9 character, no need sort.")
|
||||
return host_detail
|
||||
|
||||
# add pci segment for the bond nic, the pci is equal to the first member nic pci
|
||||
slaves_name_list = []
|
||||
for interface in tmp_interfaces:
|
||||
if interface.get('type', None) == "bond" and \
|
||||
interface.get('slave1', None) and interface.get('slave2', None):
|
||||
|
||||
if interface.get('type', None) == "bond" and\
|
||||
interface.get('slave1', None) and\
|
||||
interface.get('slave2', None):
|
||||
slaves_name_list.append(interface['slave1'])
|
||||
slaves_name_list.append(interface['slave2'])
|
||||
first_member_nic_name = interface['slave1']
|
||||
|
||||
tmp_pci = [interface_tmp['pci']
|
||||
for interface_tmp in tmp_interfaces
|
||||
if interface_tmp.get('name', None) and
|
||||
interface_tmp.get('pci', None) and
|
||||
interface_tmp['name'] == first_member_nic_name]
|
||||
for interface in interfaces:
|
||||
if interface.get('name') not in slaves_name_list:
|
||||
vlan_id_len_list = [len(network['vlan_id'])
|
||||
for assigned_network in interface.get(
|
||||
'assigned_networks', [])
|
||||
for network in networks
|
||||
if assigned_network.get('name') ==
|
||||
network.get('name') and network.get('vlan_id')]
|
||||
max_vlan_id_len = max(vlan_id_len_list) if vlan_id_len_list else 0
|
||||
interface_name_len = len(interface['name'])
|
||||
redundant_bit = interface_name_len + max_vlan_id_len - 14
|
||||
interface['name'] = interface['name'][
|
||||
redundant_bit:] if redundant_bit > 0 else interface['name']
|
||||
return host_detail
|
||||
|
||||
if len(tmp_pci) != 1:
|
||||
LOG.error("This host have two nics with same pci.")
|
||||
continue
|
||||
interface['pci'] = tmp_pci[0]
|
||||
|
||||
tmp_interfaces = [interface for interface in tmp_interfaces
|
||||
if interface.get('name', None) and
|
||||
interface['name'] not in slaves_name_list]
|
||||
|
||||
tmp_interfaces = sorted(tmp_interfaces, key = lambda interface: interface['pci'])
|
||||
for index in range(0, len(tmp_interfaces)):
|
||||
for interface in interfaces:
|
||||
if interface['name'] != tmp_interfaces[index]['name']:
|
||||
continue
|
||||
|
||||
interface['name'] = "b" + str(index) if interface['type'] == "bond" else "e" + str(index)
|
||||
|
||||
tmp_host_detail = copy.deepcopy(host_detail)
|
||||
tmp_host_detail.update({'interfaces': interfaces})
|
||||
return tmp_host_detail
|
||||
|
||||
def check_and_get_tecs_version(daisy_tecs_pkg_path):
|
||||
tecs_version_pkg_file = ""
|
||||
get_tecs_version_pkg = "ls %s| grep ^ZXTECS.*\.bin$" % daisy_tecs_pkg_path
|
||||
obj = subprocess.Popen(get_tecs_version_pkg,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
if stdoutput:
|
||||
tecs_version_pkg_name = stdoutput.split('\n')[0]
|
||||
@ -255,33 +262,60 @@ def check_and_get_tecs_version(daisy_tecs_pkg_path):
|
||||
daisy_cmn.subprocess_call(chmod_for_tecs_version)
|
||||
return tecs_version_pkg_file
|
||||
|
||||
|
||||
def get_service_disk_list(req, params):
|
||||
try:
|
||||
service_disks = registry.list_service_disk_metadata(req.context, **params)
|
||||
service_disks = registry.list_service_disk_metadata(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return service_disks
|
||||
|
||||
|
||||
def get_cinder_volume_list(req, params):
|
||||
try:
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(req.context, **params)
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return cinder_volumes
|
||||
|
||||
|
||||
def get_network_configuration_rpm_name():
|
||||
cmd = "ls %s | grep ^network-configuration.*\.rpm" % daisy_tecs_path
|
||||
def mask_string(unmasked, mask_list=None, replace_list=None):
|
||||
"""
|
||||
Replaces words from mask_list with MASK in unmasked string.
|
||||
If words are needed to be transformed before masking, transformation
|
||||
could be describe in replace list. For example [("'","'\\''")]
|
||||
replaces all ' characters with '\\''.
|
||||
"""
|
||||
mask_list = mask_list or []
|
||||
replace_list = replace_list or []
|
||||
|
||||
masked = unmasked
|
||||
for word in sorted(mask_list, lambda x, y: len(y) - len(x)):
|
||||
if not word:
|
||||
continue
|
||||
for before, after in replace_list:
|
||||
word = word.replace(before, after)
|
||||
masked = masked.replace(word, STR_MASK)
|
||||
return masked
|
||||
|
||||
|
||||
def run_scrip(script, ip=None, password=None, msg=None):
|
||||
try:
|
||||
network_rpm_name = subprocess.check_output(
|
||||
cmd, shell=True, stderr=subprocess.STDOUT).split('\n')[0]
|
||||
except subprocess.CalledProcessError:
|
||||
msg = _("Get network-configuration rpm name by subprocess failed!")
|
||||
raise exception.SubprocessCmdFailed(message=msg)
|
||||
return network_rpm_name
|
||||
_run_scrip(script, ip, password)
|
||||
except:
|
||||
msg1 = 'Error occurred during running scripts.'
|
||||
message = msg1 + msg if msg else msg1
|
||||
LOG.error(message)
|
||||
raise HTTPForbidden(explanation=message)
|
||||
else:
|
||||
LOG.info('Running scripts successfully!')
|
||||
|
||||
|
||||
def run_scrip(script, ip=None, password=None):
|
||||
def _run_scrip(script, ip=None, password=None):
|
||||
mask_list = []
|
||||
repl_list = [("'", "'\\''")]
|
||||
script = "\n".join(script)
|
||||
_PIPE = subprocess.PIPE
|
||||
if ip:
|
||||
@ -297,31 +331,117 @@ def run_scrip(script, ip=None, password=None):
|
||||
|
||||
script = "function t(){ exit $? ; } \n trap t ERR \n" + script
|
||||
out, err = obj.communicate(script)
|
||||
return out, err
|
||||
masked_out = mask_string(out, mask_list, repl_list)
|
||||
masked_err = mask_string(err, mask_list, repl_list)
|
||||
if obj.returncode:
|
||||
pattern = (r'^ssh\:')
|
||||
if re.search(pattern, err):
|
||||
LOG.error(_("Network error occured when run script."))
|
||||
raise exception.NetworkError(masked_err, stdout=out, stderr=err)
|
||||
else:
|
||||
msg = ('Failed to run remote script, stdout: %s\nstderr: %s' %
|
||||
(masked_out, masked_err))
|
||||
LOG.error(msg)
|
||||
raise exception.ScriptRuntimeError(msg, stdout=out, stderr=err)
|
||||
return obj.returncode, out
|
||||
|
||||
|
||||
def inform_provider_cloud_state(context, cluster_id, **kwargs):
|
||||
params = dict()
|
||||
daisyclient = get_daisyclient()
|
||||
cluster = registry.get_cluster_metadata(context, cluster_id)
|
||||
params['operation'] = kwargs.get('operation')
|
||||
params['name'] = cluster.get('name')
|
||||
params['url'] = "http://" + cluster.get('public_vip')
|
||||
params['provider_ip'] = cluster.get('hwm_ip')
|
||||
daisyclient.node.cloud_state(**params)
|
||||
|
||||
|
||||
def get_disk_array_nodes_addr(req, cluster_id):
|
||||
controller_ha_nodes = {}
|
||||
computer_ips = set()
|
||||
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
cluster_networks =\
|
||||
daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
for role_host in role_hosts:
|
||||
# host has installed tecs are exclusive
|
||||
if (role_host['status'] == TECS_STATE['ACTIVE'] or
|
||||
role_host['status'] == TECS_STATE['UPDATING'] or
|
||||
role_host['status'] == TECS_STATE['UPDATE_FAILED']):
|
||||
continue
|
||||
host_detail = daisy_cmn.get_host_detail(req,
|
||||
role_host['host_id'])
|
||||
host_ip = get_host_network_ip(req,
|
||||
host_detail,
|
||||
cluster_networks,
|
||||
'MANAGEMENT')
|
||||
if role['name'] == "CONTROLLER_HA":
|
||||
min_mac = utils.get_host_min_mac(host_detail['interfaces'])
|
||||
controller_ha_nodes[host_ip] = min_mac
|
||||
if role['name'] == "COMPUTER":
|
||||
computer_ips.add(host_ip)
|
||||
return {'ha': controller_ha_nodes, 'computer': computer_ips}
|
||||
|
||||
|
||||
def get_ctl_ha_nodes_min_mac(req, cluster_id):
|
||||
'''
|
||||
ctl_ha_nodes_min_mac = {'host_name1':'min_mac1', ...}
|
||||
'''
|
||||
ctl_ha_nodes_min_mac = {}
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
cluster_networks =\
|
||||
daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
for role_host in role_hosts:
|
||||
# host has installed tecs are exclusive
|
||||
if (role_host['status'] == TECS_STATE['ACTIVE'] or
|
||||
role_host['status'] == TECS_STATE['UPDATING'] or
|
||||
role_host['status'] == TECS_STATE['UPDATE_FAILED']):
|
||||
continue
|
||||
host_detail = daisy_cmn.get_host_detail(req,
|
||||
role_host['host_id'])
|
||||
host_name = host_detail['name']
|
||||
if role['name'] == "CONTROLLER_HA":
|
||||
min_mac = utils.get_host_min_mac(host_detail['interfaces'])
|
||||
ctl_ha_nodes_min_mac[host_name] = min_mac
|
||||
return ctl_ha_nodes_min_mac
|
||||
|
||||
|
||||
class TecsShellExector(object):
|
||||
|
||||
"""
|
||||
Class config task before install tecs bin.
|
||||
"""
|
||||
def __init__(self, mgnt_ip, task_type, params={}):
|
||||
|
||||
def __init__(self, mgnt_ip, task_type, params={}):
|
||||
self.task_type = task_type
|
||||
self.mgnt_ip = mgnt_ip
|
||||
self.params = params
|
||||
self.clush_cmd = ""
|
||||
self.rpm_name = get_network_configuration_rpm_name()
|
||||
self.rpm_name =\
|
||||
daisy_cmn.get_rpm_package_by_name(daisy_tecs_path,
|
||||
'network-configuration')
|
||||
self.NETCFG_RPM_PATH = daisy_tecs_path + self.rpm_name
|
||||
self.oper_type = {
|
||||
'install_rpm' : self._install_netcfg_rpm,
|
||||
'uninstall_rpm' : self._uninstall_netcfg_rpm,
|
||||
'update_rpm' : self._update_netcfg_rpm,
|
||||
'install_rpm': self._install_netcfg_rpm,
|
||||
'uninstall_rpm': self._uninstall_netcfg_rpm,
|
||||
'update_rpm': self._update_netcfg_rpm,
|
||||
}
|
||||
self.oper_shell = {
|
||||
'CMD_SSHPASS_PRE': "sshpass -p ossdbg1 %(ssh_ip)s %(cmd)s",
|
||||
'CMD_RPM_UNINSTALL': "rpm -e network-configuration",
|
||||
'CMD_RPM_INSTALL': "rpm -i /home/%(rpm)s" % {'rpm': self.rpm_name},
|
||||
'CMD_RPM_UPDATE': "rpm -U /home/%(rpm)s" % {'rpm': self.rpm_name},
|
||||
'CMD_RPM_SCP': "scp -o StrictHostKeyChecking=no %(path)s root@%(ssh_ip)s:/home" %
|
||||
'CMD_RPM_SCP': "scp -o StrictHostKeyChecking=no \
|
||||
%(path)s root@%(ssh_ip)s:/home" %
|
||||
{'path': self.NETCFG_RPM_PATH, 'ssh_ip': mgnt_ip}
|
||||
}
|
||||
LOG.info(_("<<<Network configuration rpm is %s>>>" % self.rpm_name))
|
||||
@ -329,13 +449,17 @@ class TecsShellExector(object):
|
||||
|
||||
def _uninstall_netcfg_rpm(self):
|
||||
self.clush_cmd = self.oper_shell['CMD_SSHPASS_PRE'] % \
|
||||
{"ssh_ip":"ssh -o StrictHostKeyChecking=no " + self.mgnt_ip, "cmd":self.oper_shell['CMD_RPM_UNINSTALL']}
|
||||
subprocess.check_output(self.clush_cmd, shell = True, stderr=subprocess.STDOUT)
|
||||
{"ssh_ip": "ssh -o StrictHostKeyChecking=no " + self.mgnt_ip,
|
||||
"cmd": self.oper_shell['CMD_RPM_UNINSTALL']}
|
||||
subprocess.check_output(
|
||||
self.clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
def _update_netcfg_rpm(self):
|
||||
self.clush_cmd = self.oper_shell['CMD_SSHPASS_PRE'] % \
|
||||
{"ssh_ip":"ssh -o StrictHostKeyChecking=no " + self.mgnt_ip, "cmd":self.oper_shell['CMD_RPM_UPDATE']}
|
||||
subprocess.check_output(self.clush_cmd, shell = True, stderr=subprocess.STDOUT)
|
||||
{"ssh_ip": "ssh -o StrictHostKeyChecking=no " + self.mgnt_ip,
|
||||
"cmd": self.oper_shell['CMD_RPM_UPDATE']}
|
||||
subprocess.check_output(
|
||||
self.clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
def _install_netcfg_rpm(self):
|
||||
if not os.path.exists(self.NETCFG_RPM_PATH):
|
||||
@ -343,22 +467,30 @@ class TecsShellExector(object):
|
||||
return
|
||||
|
||||
self.clush_cmd = "%s;%s" % \
|
||||
(self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip":"", "cmd":self.oper_shell['CMD_RPM_SCP']}, \
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip":"ssh -o StrictHostKeyChecking=no " + self.mgnt_ip, "cmd":self.oper_shell['CMD_RPM_INSTALL']})
|
||||
subprocess.check_output(self.clush_cmd, shell = True, stderr=subprocess.STDOUT)
|
||||
(self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip": "", "cmd": self.oper_shell['CMD_RPM_SCP']},
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip": "ssh -o StrictHostKeyChecking=no " +
|
||||
self.mgnt_ip, "cmd": self.oper_shell['CMD_RPM_INSTALL']})
|
||||
subprocess.check_output(
|
||||
self.clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
def _execute(self):
|
||||
try:
|
||||
if not self.task_type or not self.mgnt_ip :
|
||||
LOG.error(_("<<<TecsShellExector::execute, input params invalid on %s!>>>" % self.mgnt_ip, ))
|
||||
if not self.task_type or not self.mgnt_ip:
|
||||
LOG.error(
|
||||
_("<<<TecsShellExector::execute, input params invalid on \
|
||||
%s!>>>" % self.mgnt_ip, ))
|
||||
return
|
||||
|
||||
self.oper_type[self.task_type]()
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warn(_("<<<TecsShellExector::execute:Execute command failed on %s! Reason:%s>>>" % (self.mgnt_ip, e.output.strip())))
|
||||
LOG.warn(_("<<<TecsShellExector::execute:Execute command failed on\
|
||||
%s! Reason:%s>>>" % (
|
||||
self.mgnt_ip, e.output.strip())))
|
||||
except Exception as e:
|
||||
LOG.exception(_(e.message))
|
||||
else:
|
||||
LOG.info(_("<<<TecsShellExector::execute:Execute command:%s,successful on %s!>>>" % (self.clush_cmd, self.mgnt_ip)))
|
||||
LOG.info(_("<<<TecsShellExector::execute:Execute command:\
|
||||
%s,successful on %s!>>>" % (
|
||||
self.clush_cmd, self.mgnt_ip)))
|
||||
|
@ -4,6 +4,8 @@ import re
|
||||
import commands
|
||||
import types
|
||||
import subprocess
|
||||
import socket
|
||||
import netaddr
|
||||
from oslo_log import log as logging
|
||||
from ConfigParser import ConfigParser
|
||||
from daisy.common import exception
|
||||
@ -21,16 +23,18 @@ service_map = {
|
||||
'ha': '',
|
||||
'mariadb': 'mariadb',
|
||||
'amqp': 'rabbitmq-server',
|
||||
'ceilometer-api':'openstack-ceilometer-api',
|
||||
'ceilometer-collector':'openstack-ceilometer-collector,openstack-ceilometer-mend',
|
||||
'ceilometer-central':'openstack-ceilometer-central',
|
||||
'ceilometer-notification':'openstack-ceilometer-notification',
|
||||
'ceilometer-alarm':'openstack-ceilometer-alarm-evaluator,openstack-ceilometer-alarm-notifier',
|
||||
'ceilometer-api': 'openstack-ceilometer-api',
|
||||
'ceilometer-collector': 'openstack-ceilometer-collector,\
|
||||
openstack-ceilometer-mend',
|
||||
'ceilometer-central': 'openstack-ceilometer-central',
|
||||
'ceilometer-notification': 'openstack-ceilometer-notification',
|
||||
'ceilometer-alarm': 'openstack-ceilometer-alarm-evaluator,\
|
||||
openstack-ceilometer-alarm-notifier',
|
||||
'heat-api': 'openstack-heat-api',
|
||||
'heat-api-cfn': 'openstack-heat-api-cfn',
|
||||
'heat-engine': 'openstack-heat-engine',
|
||||
'ironic': 'openstack-ironic-api,openstack-ironic-conductor',
|
||||
'horizon': 'httpd',
|
||||
'horizon': 'httpd,opencos-alarmmanager',
|
||||
'keystone': 'openstack-keystone',
|
||||
'glance': 'openstack-glance-api,openstack-glance-registry',
|
||||
'cinder-volume': 'openstack-cinder-volume',
|
||||
@ -47,8 +51,9 @@ service_map = {
|
||||
'nova-vncproxy': 'openstack-nova-novncproxy,openstack-nova-consoleauth',
|
||||
'nova-conductor': 'openstack-nova-conductor',
|
||||
'nova-api': 'openstack-nova-api',
|
||||
'nova-cells': 'openstack-nova-cells'
|
||||
}
|
||||
'nova-cells': 'openstack-nova-cells',
|
||||
'camellia-api': 'camellia-api'
|
||||
}
|
||||
|
||||
|
||||
def add_service_with_host(services, name, host):
|
||||
@ -63,36 +68,33 @@ def add_service_with_hosts(services, name, hosts):
|
||||
for h in hosts:
|
||||
services[name].append(h['management']['ip'])
|
||||
|
||||
|
||||
def test_ping(ping_src_nic, ping_desc_ips):
|
||||
ping_cmd = 'fping'
|
||||
for ip in set(ping_desc_ips):
|
||||
ping_cmd = ping_cmd + ' -I ' + ping_src_nic + ' ' + ip
|
||||
obj = subprocess.Popen(ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
obj = subprocess.Popen(
|
||||
ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0 or _returncode == 1:
|
||||
ping_result = stdoutput.split('\n')
|
||||
unreachable_hosts = [result.split()[0] for result in ping_result if result and result.split()[2] != 'alive']
|
||||
if "No such device" in erroutput:
|
||||
return []
|
||||
reachable_hosts = [result.split(
|
||||
)[0] for result in ping_result if result and
|
||||
result.split()[2] == 'alive']
|
||||
else:
|
||||
msg = "ping failed beaceuse there is invlid ip in %s" % ping_desc_ips
|
||||
raise exception.InvalidIP(msg)
|
||||
return unreachable_hosts
|
||||
return reachable_hosts
|
||||
|
||||
def get_local_deployment_ip(tecs_deployment_ip):
|
||||
def _get_ip_segment(full_ip):
|
||||
if not full_ip:
|
||||
return None
|
||||
match = re.search('([0-9]{1,3}\.){3}', full_ip)
|
||||
if match:
|
||||
return match.group()
|
||||
else:
|
||||
print "can't find ip segment"
|
||||
return None
|
||||
|
||||
|
||||
def get_local_deployment_ip(tecs_deployment_ips):
|
||||
(status, output) = commands.getstatusoutput('ifconfig')
|
||||
netcard_pattern = re.compile('\S*: ')
|
||||
ip_str = '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||
ip_pattern = re.compile('(inet %s)' % ip_str)
|
||||
# ip_pattern = re.compile('(inet %s)' % ip_str)
|
||||
pattern = re.compile(ip_str)
|
||||
nic_ip = {}
|
||||
for netcard in re.finditer(netcard_pattern, str(output)):
|
||||
@ -108,20 +110,20 @@ def get_local_deployment_ip(tecs_deployment_ip):
|
||||
nic_ip[nic_name] = ip.group()
|
||||
|
||||
deployment_ip = ''
|
||||
ip_segment = _get_ip_segment(tecs_deployment_ip)
|
||||
for nic in nic_ip.keys():
|
||||
if ip_segment == _get_ip_segment(nic_ip[nic]):
|
||||
if nic_ip[nic] in tecs_deployment_ips:
|
||||
deployment_ip = nic_ip[nic]
|
||||
break
|
||||
if not deployment_ip:
|
||||
for nic,ip in nic_ip.items():
|
||||
if not test_ping(nic,[tecs_deployment_ip]):
|
||||
for nic, ip in nic_ip.items():
|
||||
if test_ping(nic, tecs_deployment_ips):
|
||||
deployment_ip = nic_ip[nic]
|
||||
break
|
||||
return deployment_ip
|
||||
|
||||
|
||||
class AnalsyConfig(object):
|
||||
|
||||
def __init__(self, all_configs):
|
||||
self.all_configs = all_configs
|
||||
|
||||
@ -139,24 +141,39 @@ class AnalsyConfig(object):
|
||||
self.glance_vip = ''
|
||||
self.public_vip = ''
|
||||
self.share_disk_services = []
|
||||
self.share_cluster_disk_services = []
|
||||
self.ha_conf = {}
|
||||
self.child_cell_dict = {}
|
||||
self.ha_master_host = {}
|
||||
|
||||
def get_heartbeats(self, host_interfaces):
|
||||
for network in host_interfaces:
|
||||
#if network.has_key("deployment") and network["deployment"]["ip"]:
|
||||
# self.heartbeats[0].append(network["deployment"]["ip"])
|
||||
self.heartbeats[0].append(network["management"]["ip"])
|
||||
if network.has_key("storage") and network["storage"]["ip"]:
|
||||
self.heartbeats[1].append(network["storage"]["ip"])
|
||||
# if network.has_key("heartbeat1") and network["heartbeat1"]["ip"]:
|
||||
if "heartbeat1" in network and network["heartbeat1"]["ip"]:
|
||||
self.heartbeats[1].append(network["heartbeat1"]["ip"])
|
||||
|
||||
#delete empty heartbeat line
|
||||
# if network.has_key("heartbeat2") and network["heartbeat2"]["ip"]:
|
||||
if "heartbeat2" in network and network["heartbeat2"]["ip"]:
|
||||
self.heartbeats[2].append(network["heartbeat2"]["ip"])
|
||||
|
||||
# if network.has_key("storage") and network["storage"]["ip"]:
|
||||
if "storage" in network and network["storage"]["ip"]:
|
||||
# if not network.has_key("heartbeat1"):
|
||||
if "heartbeat1" not in network:
|
||||
self.heartbeats[1].append(network["storage"]["ip"])
|
||||
# if network.has_key("heartbeat1") and not \
|
||||
# network.has_key("heartbeat2"):
|
||||
if "heartbeat1" in network and \
|
||||
"heartbeat2" not in network:
|
||||
self.heartbeats[2].append(network["storage"]["ip"])
|
||||
|
||||
# delete empty heartbeat line
|
||||
if not self.heartbeats[0]:
|
||||
self.heartbeats[0] = self.heartbeats[1]
|
||||
self.heartbeats[1] = self.heartbeats[2]
|
||||
self.heartbeats[0] = self.heartbeats[1]
|
||||
self.heartbeats[1] = self.heartbeats[2]
|
||||
if not self.heartbeats[1]:
|
||||
self.heartbeats[1] = self.heartbeats[2]
|
||||
self.heartbeats[1] = self.heartbeats[2]
|
||||
|
||||
# remove repeated ip
|
||||
if set(self.heartbeats[1]) == set(self.heartbeats[0]):
|
||||
@ -164,7 +181,8 @@ class AnalsyConfig(object):
|
||||
if set(self.heartbeats[2]) != set(self.heartbeats[0]):
|
||||
self.heartbeats[1] = self.heartbeats[2]
|
||||
self.heartbeats[2] = []
|
||||
if set(self.heartbeats[2]) == set(self.heartbeats[0]) or set(self.heartbeats[2]) == set(self.heartbeats[1]):
|
||||
if set(self.heartbeats[2]) == set(self.heartbeats[0]) or \
|
||||
set(self.heartbeats[2]) == set(self.heartbeats[1]):
|
||||
self.heartbeats[2] = []
|
||||
|
||||
def prepare_child_cell(self, child_cell_name, configs):
|
||||
@ -181,69 +199,105 @@ class AnalsyConfig(object):
|
||||
child_cell_host = configs['host_interfaces'][0]['management']['ip']
|
||||
self.child_cell_dict[repr(child_cell_host).strip("u'")] \
|
||||
= repr(cell_compute_hosts).strip("u'")
|
||||
add_service_with_host(self.services, 'CONFIG_CHILD_CELL_DICT',
|
||||
str(self.child_cell_dict))
|
||||
|
||||
def prepare_ha_lb(self, role_configs, is_ha, is_lb):
|
||||
if is_lb:
|
||||
self.ha_master_host['ip'] = role_configs['host_interfaces'][0]['management']['ip']
|
||||
self.ha_master_host['hostname'] = role_configs['host_interfaces'][0]['name']
|
||||
self.components.append('CONFIG_LB_INSTALL')
|
||||
add_service_with_hosts(self.services,
|
||||
'CONFIG_LB_BACKEND_HOSTS',
|
||||
role_configs['host_interfaces'])
|
||||
self.lb_vip = role_configs['vip']
|
||||
if is_ha:
|
||||
self.ha_vip = role_configs['vip']
|
||||
self.share_disk_services += role_configs['share_disk_services']
|
||||
local_deployment_ip = get_local_deployment_ip(
|
||||
role_configs['host_interfaces'][0]['management']['ip'])
|
||||
if local_deployment_ip:
|
||||
if is_lb:
|
||||
self.ha_master_host['ip'] = role_configs[
|
||||
'host_interfaces'][0]['management']['ip']
|
||||
self.ha_master_host['hostname'] = role_configs[
|
||||
'host_interfaces'][0]['name']
|
||||
self.components.append('CONFIG_LB_INSTALL')
|
||||
add_service_with_hosts(self.services,
|
||||
'CONFIG_LB_BACKEND_HOSTS',
|
||||
role_configs['host_interfaces'])
|
||||
self.lb_vip = role_configs['vip']
|
||||
if is_ha:
|
||||
# convert dns to ip
|
||||
manage_ips = []
|
||||
for host_interface in role_configs['host_interfaces']:
|
||||
manage_ip = ''
|
||||
management_addr =\
|
||||
host_interface['management']['ip']
|
||||
try:
|
||||
ip_lists = socket.gethostbyname_ex(management_addr)
|
||||
manage_ip = ip_lists[2][0]
|
||||
except Exception:
|
||||
if netaddr.IPAddress(management_addr).version == 6:
|
||||
manage_ip = management_addr
|
||||
else:
|
||||
raise exception.InvalidNetworkConfig(
|
||||
"manage ip is not valid %s" % management_addr)
|
||||
finally:
|
||||
manage_ips.append(manage_ip)
|
||||
|
||||
self.ha_vip = role_configs['vip']
|
||||
self.share_disk_services += role_configs['share_disk_services']
|
||||
self.share_cluster_disk_services += \
|
||||
role_configs['share_cluster_disk_services']
|
||||
local_deployment_ip = get_local_deployment_ip(manage_ips)
|
||||
filename = r'/etc/zte-docker'
|
||||
if local_deployment_ip:
|
||||
if os.path.exists(filename):
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_REPO',
|
||||
'http://'+local_deployment_ip+'/tecs_install/')
|
||||
'http://' + local_deployment_ip +
|
||||
':18080' + '/tecs_install/')
|
||||
else:
|
||||
msg = "can't find ip for yum repo"
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
self.components.append('CONFIG_HA_INSTALL')
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_REPO',
|
||||
'http://' + local_deployment_ip + '/tecs_install/')
|
||||
else:
|
||||
msg = "can't find ip for yum repo"
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
self.components.append('CONFIG_HA_INSTALL')
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_HA_HOST',
|
||||
role_configs['host_interfaces'][0]['management']['ip'])
|
||||
add_service_with_hosts(self.services, 'CONFIG_HA_HOSTS',
|
||||
role_configs['host_interfaces'])
|
||||
ntp_host = role_configs['ntp_server'] \
|
||||
if role_configs['ntp_server'] else role_configs['vip']
|
||||
add_service_with_host(self.services, 'CONFIG_NTP_SERVERS',
|
||||
ntp_host)
|
||||
|
||||
if role_configs['db_vip']:
|
||||
self.db_vip = role_configs['db_vip']
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_HA_HOST',
|
||||
role_configs['host_interfaces'][0]['management']['ip'])
|
||||
add_service_with_hosts(self.services, 'CONFIG_HA_HOSTS',
|
||||
role_configs['host_interfaces'])
|
||||
ntp_host = role_configs['ntp_server'] \
|
||||
if role_configs['ntp_server'] else role_configs['vip']
|
||||
add_service_with_host(self.services, 'CONFIG_NTP_SERVERS',
|
||||
ntp_host)
|
||||
self.services, 'CONFIG_MARIADB_HOST',
|
||||
role_configs['db_vip'])
|
||||
else:
|
||||
self.db_vip = role_configs['vip']
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_MARIADB_HOST', role_configs['vip'])
|
||||
|
||||
if role_configs['db_vip']:
|
||||
self.db_vip = role_configs['db_vip']
|
||||
add_service_with_host(self.services, 'CONFIG_MARIADB_HOST', role_configs['db_vip'])
|
||||
else:
|
||||
self.db_vip = role_configs['vip']
|
||||
add_service_with_host(self.services, 'CONFIG_MARIADB_HOST', role_configs['vip'])
|
||||
if role_configs['glance_vip']:
|
||||
self.glance_vip = role_configs['glance_vip']
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_GLANCE_HOST',
|
||||
role_configs['glance_vip'])
|
||||
else:
|
||||
self.glance_vip = role_configs['vip']
|
||||
add_service_with_host(
|
||||
self.services, 'CONFIG_GLANCE_HOST', role_configs['vip'])
|
||||
|
||||
if role_configs['glance_vip']:
|
||||
self.glance_vip = role_configs['glance_vip']
|
||||
add_service_with_host(self.services, 'CONFIG_GLANCE_HOST', role_configs['glance_vip'])
|
||||
else:
|
||||
self.glance_vip = role_configs['vip']
|
||||
add_service_with_host(self.services, 'CONFIG_GLANCE_HOST', role_configs['vip'])
|
||||
if role_configs['public_vip']:
|
||||
self.public_vip = role_configs['public_vip']
|
||||
else:
|
||||
self.public_vip = role_configs['vip']
|
||||
|
||||
if role_configs['public_vip']:
|
||||
vip = role_configs['public_vip']
|
||||
self.public_vip = role_configs['public_vip']
|
||||
else:
|
||||
vip = role_configs['vip']
|
||||
|
||||
self.public_vip = vip
|
||||
add_service_with_host(self.services,
|
||||
'CONFIG_NOVA_VNCPROXY_HOST', vip)
|
||||
add_service_with_host(self.services, 'CONFIG_PUBLIC_IP', vip)
|
||||
add_service_with_host(self.services, 'CONFIG_HORIZON_HOST', vip)
|
||||
|
||||
add_service_with_host(self.services, 'CONFIG_ADMIN_IP', vip)
|
||||
add_service_with_host(self.services, 'CONFIG_INTERNAL_IP', vip)
|
||||
add_service_with_host(self.services,
|
||||
'CONFIG_NOVA_VNCPROXY_HOST',
|
||||
self.public_vip)
|
||||
add_service_with_host(self.services, 'CONFIG_PUBLIC_IP',
|
||||
self.public_vip)
|
||||
add_service_with_host(self.services, 'CONFIG_HORIZON_HOST',
|
||||
self.public_vip)
|
||||
'''
|
||||
add_service_with_host(self.services, 'CONFIG_ADMIN_IP',
|
||||
role_configs['vip'])
|
||||
add_service_with_host(self.services, 'CONFIG_INTERNAL_IP',
|
||||
role_configs['vip'])
|
||||
'''
|
||||
|
||||
def prepare_role_service(self, is_ha, service, role_configs):
|
||||
host_key_name = "CONFIG_%s_HOST" % service
|
||||
@ -251,7 +305,8 @@ class AnalsyConfig(object):
|
||||
|
||||
add_service_with_hosts(self.services, hosts_key_name,
|
||||
role_configs['host_interfaces'])
|
||||
if service != 'LB' and service not in ['NOVA_VNCPROXY', 'MARIADB', 'GLANCE', 'HORIZON']:
|
||||
if service != 'LB' and service not in ['NOVA_VNCPROXY', 'MARIADB',
|
||||
'GLANCE', 'HORIZON']:
|
||||
add_service_with_host(self.services, host_key_name,
|
||||
role_configs['vip'])
|
||||
|
||||
@ -272,11 +327,12 @@ class AnalsyConfig(object):
|
||||
{'CONFIG_GLANCE_API_INSTALL_MODE': 'LB'})
|
||||
self.modes.update(
|
||||
{'CONFIG_GLANCE_REGISTRY_INSTALL_MODE': 'LB'})
|
||||
#if s == 'HEAT':
|
||||
# if s == 'HEAT':
|
||||
# self.modes.update({'CONFIG_HEAT_API_INSTALL_MODE': 'LB'})
|
||||
# self.modes.update({'CONFIG_HEAT_API_CFN_INSTALL_MODE': 'LB'})
|
||||
#if s == 'CEILOMETER':
|
||||
# self.modes.update({'CONFIG_CEILOMETER_API_INSTALL_MODE': 'LB'})
|
||||
# if s == 'CEILOMETER':
|
||||
# self.modes.update({
|
||||
# 'CONFIG_CEILOMETER_API_INSTALL_MODE': 'LB'})
|
||||
if service == 'IRONIC':
|
||||
self.modes.update(
|
||||
{'CONFIG_IRONIC_API_INSTALL_MODE': 'LB'})
|
||||
@ -287,8 +343,8 @@ class AnalsyConfig(object):
|
||||
if component not in self.services_in_component.keys():
|
||||
self.services_in_component[component] = {}
|
||||
self.services_in_component[component]["service"] = []
|
||||
self.services_in_component[component]["service"].append(service_map[service])
|
||||
|
||||
self.services_in_component[component][
|
||||
"service"].append(service_map[service])
|
||||
|
||||
if component == "horizon":
|
||||
self.services_in_component[component]["fip"] = self.public_vip
|
||||
@ -296,13 +352,13 @@ class AnalsyConfig(object):
|
||||
self.services_in_component[component]["fip"] = self.db_vip
|
||||
elif component == "glance":
|
||||
self.services_in_component[component]["fip"] = self.glance_vip
|
||||
else:
|
||||
else:
|
||||
self.services_in_component[component]["fip"] = role_configs["vip"]
|
||||
|
||||
|
||||
|
||||
network_name = ''
|
||||
if component in ['horizon'] and role_configs["host_interfaces"][0].has_key('public'):
|
||||
network_name = 'public'
|
||||
if component in ['horizon'] and\
|
||||
'publicapi' in role_configs["host_interfaces"][0]:
|
||||
network_name = 'publicapi'
|
||||
else:
|
||||
network_name = 'management'
|
||||
|
||||
@ -311,10 +367,10 @@ class AnalsyConfig(object):
|
||||
self.services_in_component[component]["nic_name"] = \
|
||||
role_configs["host_interfaces"][0][network_name]["name"]
|
||||
if component == 'loadbalance' and \
|
||||
self.all_configs.has_key('CONTROLLER_LB') and \
|
||||
'CONTROLLER_LB' in self.all_configs and \
|
||||
self.all_configs['CONTROLLER_LB']['vip']:
|
||||
self.services_in_component[component]["fip"] = \
|
||||
self.all_configs['CONTROLLER_LB']['vip']
|
||||
self.services_in_component[component]["fip"] = \
|
||||
self.all_configs['CONTROLLER_LB']['vip']
|
||||
|
||||
def prepare_amqp_mariadb(self):
|
||||
if self.lb_vip:
|
||||
@ -331,15 +387,20 @@ class AnalsyConfig(object):
|
||||
else:
|
||||
amqp_vip = self.ha_vip
|
||||
amqp_dict = "{'%s':'%s,%s,%s,%s'}" % (amqp_vip, self.ha_vip,
|
||||
self.lb_vip, self.glance_vip, self.public_vip)
|
||||
self.lb_vip, self.glance_vip,
|
||||
self.public_vip)
|
||||
mariadb_dict = "{'%s':'%s,%s,%s,%s'}" % (self.db_vip, self.ha_vip,
|
||||
self.lb_vip, self.glance_vip, self.public_vip)
|
||||
self.lb_vip,
|
||||
self.glance_vip,
|
||||
self.public_vip)
|
||||
add_service_with_host(self.services, 'CONFIG_LB_HOST', self.lb_vip)
|
||||
elif self.ha_vip:
|
||||
amqp_dict = "{'%s':'%s,%s,%s'}" % (self.ha_vip, self.ha_vip,
|
||||
self.glance_vip, self.public_vip)
|
||||
self.glance_vip,
|
||||
self.public_vip)
|
||||
mariadb_dict = "{'%s':'%s,%s,%s'}" % (self.db_vip, self.ha_vip,
|
||||
self.glance_vip, self.public_vip)
|
||||
self.glance_vip,
|
||||
self.public_vip)
|
||||
else:
|
||||
amqp_dict = "{}"
|
||||
mariadb_dict = "{}"
|
||||
@ -382,50 +443,51 @@ class AnalsyConfig(object):
|
||||
|
||||
self.prepare_amqp_mariadb()
|
||||
|
||||
if self.child_cell_dict:
|
||||
add_service_with_host(self.services, 'CONFIG_CHILD_CELL_DICT',
|
||||
str(self.child_cell_dict))
|
||||
|
||||
def update_conf_with_services(self, tecs):
|
||||
for s in self.services:
|
||||
if tecs.has_option("general", s):
|
||||
print "%s is update" % s
|
||||
if type(self.services[s]) is types.ListType:
|
||||
# if type(self.services[s]) is types.ListType:
|
||||
if isinstance(self.services[s], types.ListType):
|
||||
if self.services[s] and not self.services[s][0]:
|
||||
return
|
||||
tecs.set("general", s, ','.join(self.services[s]))
|
||||
else:
|
||||
print "service %s is not exit in conf file" % s
|
||||
msg = "service %s is not exit in conf file" % s
|
||||
LOG.info(msg)
|
||||
|
||||
def update_conf_with_components(self, tecs):
|
||||
for s in self.components:
|
||||
if tecs.has_option("general", s):
|
||||
print "Component %s is update" % s
|
||||
tecs.set("general", s, 'y')
|
||||
else:
|
||||
print "component %s is not exit in conf file" % s
|
||||
msg = "component %s is not exit in conf file" % s
|
||||
LOG.info(msg)
|
||||
|
||||
def update_conf_with_modes(self, tecs):
|
||||
for k, v in self.modes.items():
|
||||
if tecs.has_option("general", k):
|
||||
print "mode %s is update" % k
|
||||
tecs.set("general", k, v)
|
||||
else:
|
||||
print "mode %s is not exit in conf file" % k
|
||||
msg = "mode %s is not exit in conf file" % k
|
||||
LOG.info(msg)
|
||||
|
||||
def update_tecs_conf(self, tecs):
|
||||
self.update_conf_with_services(tecs)
|
||||
self.update_conf_with_components(tecs)
|
||||
self.update_conf_with_modes(tecs)
|
||||
|
||||
|
||||
def update_ha_conf(self, ha, ha_nic_name, tecs=None):
|
||||
print "heartbeat line is update"
|
||||
heart_beat_list = []
|
||||
if self.all_configs['OTHER'].get('dns_config'):
|
||||
for heartbeat in self.heartbeats:
|
||||
tmp_list = []
|
||||
for name_ip in self.all_configs['OTHER']['dns_config']:
|
||||
for tmp in heartbeat:
|
||||
if tmp == name_ip.keys()[0]:
|
||||
tmp_list.append(name_ip.values()[0])
|
||||
heart_beat_list.append(tmp_list)
|
||||
self.heartbeats = heart_beat_list
|
||||
heartbeat.remove(tmp)
|
||||
heartbeat.append(name_ip.values()[0])
|
||||
|
||||
for k, v in self.services_in_component.items():
|
||||
for name_ip in self.all_configs['OTHER']['dns_config']:
|
||||
@ -435,65 +497,110 @@ class AnalsyConfig(object):
|
||||
ha.set('DEFAULT', 'heartbeat_link2', ','.join(self.heartbeats[1]))
|
||||
ha.set('DEFAULT', 'heartbeat_link3', ','.join(self.heartbeats[2]))
|
||||
|
||||
ha.set('DEFAULT', 'components', ','.join(self.services_in_component.keys()))
|
||||
ha.set('DEFAULT', 'components', ','.join(
|
||||
self.services_in_component.keys()))
|
||||
|
||||
for k, v in self.services_in_component.items():
|
||||
print "component %s is update" % k
|
||||
ha.set('DEFAULT', k, ','.join(v['service']))
|
||||
if k == 'glance':
|
||||
if 'glance' in self.share_disk_services:
|
||||
ha.set('DEFAULT', 'glance_device_type', 'iscsi')
|
||||
ha.set('DEFAULT', 'glance_device', '/dev/mapper/vg_glance-lv_glance')
|
||||
ha.set(
|
||||
'DEFAULT', 'glance_device',
|
||||
'/dev/mapper/vg_glance-lv_glance')
|
||||
ha.set('DEFAULT', 'glance_fs_type', 'ext4')
|
||||
else:
|
||||
ha.set('DEFAULT', 'glance_device_type', 'drbd')
|
||||
ha.set('DEFAULT', 'glance_device', '/dev/vg_data/lv_glance')
|
||||
ha.set(
|
||||
'DEFAULT', 'glance_device', '/dev/vg_data/lv_glance')
|
||||
ha.set('DEFAULT', 'glance_fs_type', 'ext4')
|
||||
# mariadb now not support db cluster, don't support share disk.
|
||||
if k == "database":
|
||||
if 'db' in self.share_disk_services:
|
||||
ha.set('DEFAULT', 'database_device', '/dev/mapper/vg_db-lv_db')
|
||||
ha.set(
|
||||
'DEFAULT', 'database_device',
|
||||
'/dev/mapper/vg_db-lv_db')
|
||||
ha.set('DEFAULT', 'database_fs_type', 'ext4')
|
||||
|
||||
ha.set('DEFAULT', 'database_device_type', 'share')
|
||||
if tecs:
|
||||
tecs.set(
|
||||
"general",
|
||||
'CONFIG_HA_INSTALL_MARIADB_LOCAL',
|
||||
'n')
|
||||
elif 'db' in self.share_cluster_disk_services:
|
||||
ha.set(
|
||||
'DEFAULT', 'database_device',
|
||||
'/dev/mapper/vg_db-lv_db')
|
||||
ha.set('DEFAULT', 'database_fs_type', 'ext4')
|
||||
ha.set('DEFAULT', 'database_device_type', 'share_cluster')
|
||||
if tecs:
|
||||
tecs.set(
|
||||
"general",
|
||||
'CONFIG_HA_INSTALL_MARIADB_LOCAL',
|
||||
'y')
|
||||
else:
|
||||
ha.set('DEFAULT', 'database_device_type', 'local_cluster')
|
||||
if tecs:
|
||||
tecs.set(
|
||||
"general",
|
||||
'CONFIG_HA_INSTALL_MARIADB_LOCAL',
|
||||
'y')
|
||||
|
||||
if 'db_backup' in self.share_disk_services:
|
||||
ha.set(
|
||||
'DEFAULT',
|
||||
'backup_database_device',
|
||||
'/dev/mapper/vg_db_backup-lv_db_backup')
|
||||
ha.set('DEFAULT', 'backup_database_fs_type', 'ext4')
|
||||
|
||||
if "mongod" in v['service']:
|
||||
if 'mongodb' in self.share_disk_services:
|
||||
ha.set('DEFAULT', 'mongod_device', '/dev/mapper/vg_mongodb-lv_mongodb')
|
||||
ha.set(
|
||||
'DEFAULT', 'mongod_device',
|
||||
'/dev/mapper/vg_mongodb-lv_mongodb')
|
||||
ha.set('DEFAULT', 'mongod_fs_type', 'ext4')
|
||||
ha.set('DEFAULT', 'mongod_local', '')
|
||||
if tecs:
|
||||
tecs.set("general", 'CONFIG_HA_INSTALL_MONGODB_LOCAL', 'n')
|
||||
tecs.set(
|
||||
"general",
|
||||
'CONFIG_HA_INSTALL_MONGODB_LOCAL', 'n')
|
||||
else:
|
||||
ha.set('DEFAULT', 'mongod_fs_type', 'ext4')
|
||||
ha.set('DEFAULT', 'mongod_local', 'yes')
|
||||
if tecs:
|
||||
tecs.set("general", 'CONFIG_HA_INSTALL_MONGODB_LOCAL', 'y')
|
||||
tecs.set(
|
||||
"general",
|
||||
'CONFIG_HA_INSTALL_MONGODB_LOCAL', 'y')
|
||||
|
||||
if k not in self.lb_components:
|
||||
# if "bond" in v['nic_name']:
|
||||
# v['nic_name'] = "vport"
|
||||
ha.set('DEFAULT', k+'_fip', v['fip'])
|
||||
ha.set('DEFAULT', k + '_fip', v['fip'])
|
||||
if ha_nic_name and k not in ['horizon']:
|
||||
nic_name = ha_nic_name
|
||||
else:
|
||||
nic_name = v['nic_name']
|
||||
ha.set('DEFAULT', k+'_nic', nic_name)
|
||||
ha.set('DEFAULT', k + '_nic', nic_name)
|
||||
cidr_netmask = reduce(lambda x, y: x + y,
|
||||
[bin(int(i)).count('1') for i in v['netmask'].split('.')])
|
||||
ha.set('DEFAULT', k+'_netmask', cidr_netmask)
|
||||
[bin(int(i)).count('1')
|
||||
for i in v['netmask'].split('.')])
|
||||
ha.set('DEFAULT', k + '_netmask', cidr_netmask)
|
||||
|
||||
|
||||
def update_conf(tecs, key, value):
|
||||
tecs.set("general", key, value)
|
||||
|
||||
|
||||
def get_conf(tecs_conf_file, **kwargs):
|
||||
result = {}
|
||||
if not kwargs:
|
||||
return result
|
||||
return result
|
||||
|
||||
tecs = ConfigParser()
|
||||
tecs.optionxform = str
|
||||
tecs.read(tecs_conf_file)
|
||||
|
||||
result = {key : tecs.get("general", kwargs.get(key, None))
|
||||
result = {key: tecs.get("general", kwargs.get(key, None))
|
||||
for key in kwargs.keys()
|
||||
if tecs.has_option("general", kwargs.get(key, None))}
|
||||
return result
|
||||
@ -563,6 +670,7 @@ class DvsDaisyConfig(object):
|
||||
# common
|
||||
self.dvs_network_type = []
|
||||
self.dvs_vswitch_type = {}
|
||||
self.dvs_cpu_sets = []
|
||||
self.dvs_physnics = []
|
||||
self.enable_sdn = False
|
||||
|
||||
@ -586,6 +694,9 @@ class DvsDaisyConfig(object):
|
||||
return
|
||||
self.dvs_vswitch_type.update(vswitch_type)
|
||||
|
||||
dvs_cpu_sets = network.get('dvs_cpu_sets')
|
||||
self.dvs_cpu_sets.extend(dvs_cpu_sets)
|
||||
|
||||
network_type = network['network_config'].get('network_type')
|
||||
|
||||
if network_type in ['vlan']:
|
||||
@ -601,13 +712,16 @@ class DvsDaisyConfig(object):
|
||||
self.dvs_vswitch_type.get('ovs_agent_patch')) and (
|
||||
len(self.dvs_vswitch_type.get('ovs_agent_patch')) > 0):
|
||||
return
|
||||
|
||||
if not self.dvs_vswitch_type.get('ovs_agent_patch') and not self.dvs_vswitch_type.get('ovdk'):
|
||||
|
||||
if not self.dvs_vswitch_type.get('ovs_agent_patch') and not\
|
||||
self.dvs_vswitch_type.get('ovdk'):
|
||||
return
|
||||
|
||||
|
||||
update_conf(self.tecs, 'CONFIG_DVS_TYPE', self.dvs_vswitch_type)
|
||||
update_conf(self.tecs, 'CONFIG_DVS_PHYSICAL_NICS',
|
||||
",".join(set(self.dvs_physnics)))
|
||||
# cpu sets for dvs, add CONFIG_DVS_CPU_SETS to tecs.conf firstly
|
||||
update_conf(self.tecs, 'CONFIG_DVS_CPU_SETS', self.dvs_cpu_sets)
|
||||
|
||||
if 'vlan' in self.dvs_network_type:
|
||||
update_conf(self.tecs, 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS',
|
||||
@ -693,12 +807,13 @@ class DvsDaisyConfig(object):
|
||||
default_tecs_conf_template_path = "/var/lib/daisy/tecs/"
|
||||
tecs_conf_template_path = default_tecs_conf_template_path
|
||||
|
||||
|
||||
def private_network_conf(tecs, private_networks_config):
|
||||
if private_networks_config:
|
||||
mode_str = {
|
||||
'0':'(active-backup;off;"%s-%s")',
|
||||
'1':'(balance-slb;off;"%s-%s")',
|
||||
'2':'(balance-tcp;active;"%s-%s")'
|
||||
'0': '(active-backup;off;"%s-%s")',
|
||||
'1': '(balance-slb;off;"%s-%s")',
|
||||
'2': '(balance-tcp;active;"%s-%s")'
|
||||
}
|
||||
|
||||
config_neutron_sriov_bridge_mappings = []
|
||||
@ -709,10 +824,11 @@ def private_network_conf(tecs, private_networks_config):
|
||||
type = private_network.get('type', None)
|
||||
name = private_network.get('name', None)
|
||||
assign_networks = private_network.get('assigned_networks', None)
|
||||
slave1 = private_network.get('slave1', None)
|
||||
slave2 = private_network.get('slave2', None)
|
||||
slave1 = private_network.get('slave1', None)
|
||||
slave2 = private_network.get('slave2', None)
|
||||
mode = private_network.get('mode', None)
|
||||
if not type or not name or not assign_networks or not slave1 or not slave2 or not mode:
|
||||
if not type or not name or not assign_networks or not\
|
||||
slave1 or not slave2 or not mode:
|
||||
break
|
||||
|
||||
for assign_network in assign_networks:
|
||||
@ -724,23 +840,33 @@ def private_network_conf(tecs, private_networks_config):
|
||||
break
|
||||
|
||||
# ether
|
||||
if 0 == cmp(type, 'ether') and 0 == cmp(network_type, 'PRIVATE'):
|
||||
if 0 == cmp(type, 'ether') and\
|
||||
0 == cmp(network_type, 'DATAPLANE'):
|
||||
if 0 == cmp(ml2_type, 'sriov'):
|
||||
config_neutron_sriov_bridge_mappings.append("%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_sriov_physnet_ifaces.append("%s:%s" % (physnet_name, name))
|
||||
elif 0 == cmp(ml2_type, 'ovs'):
|
||||
config_neutron_ovs_bridge_mappings.append("%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_ovs_physnet_ifaces.append("%s:%s" % (physnet_name, name))
|
||||
# bond
|
||||
elif 0 == cmp(type, 'bond') and 0 == cmp(network_type, 'PRIVATE'):
|
||||
if 0 == cmp(ml2_type, 'sriov'):
|
||||
config_neutron_sriov_bridge_mappings.append("%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_sriov_bridge_mappings.append(
|
||||
"%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_sriov_physnet_ifaces.append(
|
||||
"%s:%s" % (physnet_name, name + mode_str[mode] % (slave1, slave2)))
|
||||
"%s:%s" % (physnet_name, name))
|
||||
elif 0 == cmp(ml2_type, 'ovs'):
|
||||
config_neutron_ovs_bridge_mappings.append("%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_ovs_bridge_mappings.append(
|
||||
"%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_ovs_physnet_ifaces.append(
|
||||
"%s:%s" % (physnet_name, name + mode_str[mode] % (slave1, slave2)))
|
||||
"%s:%s" % (physnet_name, name))
|
||||
# bond
|
||||
elif 0 == cmp(type, 'bond') and\
|
||||
0 == cmp(network_type, 'DATAPLANE'):
|
||||
if 0 == cmp(ml2_type, 'sriov'):
|
||||
config_neutron_sriov_bridge_mappings.append(
|
||||
"%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_sriov_physnet_ifaces.append(
|
||||
"%s:%s" % (physnet_name, name + mode_str[mode]
|
||||
% (slave1, slave2)))
|
||||
elif 0 == cmp(ml2_type, 'ovs'):
|
||||
config_neutron_ovs_bridge_mappings.append(
|
||||
"%s:%s" % (physnet_name, "br-" + name))
|
||||
config_neutron_ovs_physnet_ifaces.append(
|
||||
"%s:%s" % (physnet_name, name + mode_str[mode]
|
||||
% (slave1, slave2)))
|
||||
|
||||
if config_neutron_sriov_bridge_mappings:
|
||||
update_conf(tecs,
|
||||
@ -750,18 +876,18 @@ def private_network_conf(tecs, private_networks_config):
|
||||
update_conf(tecs,
|
||||
'CONFIG_NEUTRON_SRIOV_PHYSNET_IFACES',
|
||||
",".join(config_neutron_sriov_physnet_ifaces))
|
||||
if config_neutron_ovs_bridge_mappings :
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS', ",".join(config_neutron_ovs_bridge_mappings))
|
||||
if config_neutron_ovs_bridge_mappings:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS',
|
||||
",".join(config_neutron_ovs_bridge_mappings))
|
||||
if config_neutron_ovs_physnet_ifaces:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_OVS_PHYSNET_IFACES', ",".join(config_neutron_ovs_physnet_ifaces))
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_OVS_PHYSNET_IFACES',
|
||||
",".join(config_neutron_ovs_physnet_ifaces))
|
||||
|
||||
|
||||
def update_tecs_config(config_data, cluster_conf_path):
|
||||
print "tecs config data is:"
|
||||
import pprint
|
||||
pprint.pprint(config_data)
|
||||
msg="tecs config data is: %s" % config_data
|
||||
msg = "tecs config data is: %s" % config_data
|
||||
LOG.info(msg)
|
||||
|
||||
|
||||
daisy_tecs_path = tecs_conf_template_path
|
||||
tecs_conf_template_file = os.path.join(daisy_tecs_path, "tecs.conf")
|
||||
ha_conf_template_file = os.path.join(daisy_tecs_path, "HA.conf")
|
||||
@ -773,49 +899,67 @@ def update_tecs_config(config_data, cluster_conf_path):
|
||||
tecs = ConfigParser()
|
||||
tecs.optionxform = str
|
||||
tecs.read(tecs_conf_template_file)
|
||||
|
||||
|
||||
cluster_data = config_data['OTHER']['cluster_data']
|
||||
update_conf(tecs, 'CLUSTER_ID', cluster_data['id'])
|
||||
if cluster_data.has_key('networking_parameters'):
|
||||
# if cluster_data.has_key('networking_parameters'):
|
||||
if 'networking_parameters' in cluster_data:
|
||||
networking_parameters = cluster_data['networking_parameters']
|
||||
if networking_parameters.has_key('base_mac') and networking_parameters['base_mac']:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_BASE_MAC', networking_parameters['base_mac'])
|
||||
if networking_parameters.has_key('gre_id_range') and len(networking_parameters['gre_id_range'])>1 \
|
||||
and networking_parameters['gre_id_range'][0] and networking_parameters['gre_id_range'][1]:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TUNNEL_ID_RANGES', ("%s:%s" % (networking_parameters['gre_id_range'][0],networking_parameters['gre_id_range'][1])))
|
||||
if networking_parameters.get("vni_range",['1000','3000']) and len(networking_parameters['vni_range'])>1 \
|
||||
and networking_parameters['vni_range'][0] and networking_parameters['vni_range'][1]:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_VNI_RANGES', ("%s:%s" % (networking_parameters['vni_range'][0],networking_parameters['vni_range'][1])))
|
||||
if networking_parameters.get("segmentation_type","vlan"):
|
||||
segmentation_type = networking_parameters.get("segmentation_type","vlan")
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES', segmentation_type)
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TYPE_DRIVERS', segmentation_type)
|
||||
# if networking_parameters.has_key('base_mac') and\
|
||||
if 'base_mac'in networking_parameters and\
|
||||
networking_parameters['base_mac']:
|
||||
update_conf(
|
||||
tecs, 'CONFIG_NEUTRON_BASE_MAC',
|
||||
networking_parameters['base_mac'])
|
||||
# if networking_parameters.has_key('gre_id_range') and\
|
||||
if 'gre_id_range' in networking_parameters and\
|
||||
len(networking_parameters['gre_id_range']) > 1 \
|
||||
and networking_parameters['gre_id_range'][0] and\
|
||||
networking_parameters['gre_id_range'][1]:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TUNNEL_ID_RANGES',
|
||||
("%s:%s" % (networking_parameters['gre_id_range'][0],
|
||||
networking_parameters['gre_id_range'][1])))
|
||||
if 'vxlan' in config_data['OTHER'].get('segmentation_type', {}):
|
||||
update_conf(
|
||||
tecs, 'CONFIG_NEUTRON_ML2_VNI_RANGES',
|
||||
config_data['OTHER']['segmentation_type']['vxlan']['vni_range'])
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES', 'vxlan')
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TYPE_DRIVERS', 'vxlan')
|
||||
else:
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES', 'vlan')
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_TYPE_DRIVERS', 'vlan')
|
||||
|
||||
physic_network_cfg = config_data['OTHER']['physic_network_config']
|
||||
if physic_network_cfg.get('json_path', None):
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_JSON_PATH', physic_network_cfg['json_path'])
|
||||
update_conf(
|
||||
tecs, 'CONFIG_NEUTRON_ML2_JSON_PATH',
|
||||
physic_network_cfg['json_path'])
|
||||
if physic_network_cfg.get('vlan_ranges', None):
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_VLAN_RANGES',physic_network_cfg['vlan_ranges'])
|
||||
update_conf(tecs, 'CONFIG_NEUTRON_ML2_VLAN_RANGES',
|
||||
physic_network_cfg['vlan_ranges'])
|
||||
if config_data['OTHER']['tecs_installed_hosts']:
|
||||
update_conf(tecs, 'EXCLUDE_SERVERS', ",".join(config_data['OTHER']['tecs_installed_hosts']))
|
||||
update_conf(tecs, 'EXCLUDE_SERVERS', ",".join(
|
||||
config_data['OTHER']['tecs_installed_hosts']))
|
||||
|
||||
ha = ConfigParser()
|
||||
ha.optionxform = str
|
||||
ha.read(ha_conf_template_file)
|
||||
|
||||
config = AnalsyConfig(config_data)
|
||||
if config_data['OTHER'].has_key('ha_nic_name'):
|
||||
# if config_data['OTHER'].has_key('ha_nic_name'):
|
||||
if 'ha_nic_name'in config_data['OTHER']:
|
||||
ha_nic_name = config_data['OTHER']['ha_nic_name']
|
||||
else:
|
||||
ha_nic_name = ""
|
||||
|
||||
config.prepare()
|
||||
|
||||
|
||||
config.update_tecs_conf(tecs)
|
||||
config.update_ha_conf(ha, ha_nic_name, tecs)
|
||||
|
||||
update_conf_with_zenic(tecs, config_data['OTHER']['zenic_config'])
|
||||
if config_data['OTHER']['dvs_config'].has_key('network_config'):
|
||||
# if config_data['OTHER']['dvs_config'].has_key('network_config'):
|
||||
if 'network_config' in config_data['OTHER']['dvs_config']:
|
||||
config_data['OTHER']['dvs_config']['network_config']['enable_sdn'] = \
|
||||
config_data['OTHER']['zenic_config'].get('vip', False)
|
||||
dvs_config = DvsDaisyConfig(tecs, config_data['OTHER']['dvs_config'])
|
||||
@ -824,7 +968,7 @@ def update_tecs_config(config_data, cluster_conf_path):
|
||||
|
||||
tecs.write(open(tecs_conf_out, "w+"))
|
||||
ha.write(open(ha_config_out, "w+"))
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
@ -16,25 +16,12 @@
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
|
||||
@ -48,183 +35,281 @@ _ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
tecs_state = tecs_cmn.TECS_STATE
|
||||
|
||||
|
||||
def _get_service_disk_for_disk_array(req, role_id):
|
||||
disk_info = []
|
||||
service_disks = tecs_cmn.get_service_disk_list(req, {'filters': {'role_id': role_id}})
|
||||
service_disks = tecs_cmn.get_service_disk_list(req,
|
||||
{'filters': {
|
||||
'role_id': role_id}})
|
||||
for service_disk in service_disks:
|
||||
share_disk = {}
|
||||
if service_disk['disk_location'] == 'share':
|
||||
share_disk['service'] = service_disk['service']
|
||||
share_disk['protocol_type'] = service_disk['protocol_type']
|
||||
share_disk['lun'] = service_disk['lun']
|
||||
share_disk['data_ips'] = service_disk['data_ips'].split(',')
|
||||
if service_disk['protocol_type'] == 'FIBER':
|
||||
share_disk['fc_hba_wwpn'] = \
|
||||
service_disk['data_ips'].split(',')
|
||||
else:
|
||||
share_disk['data_ips'] = service_disk['data_ips'].split(',')
|
||||
share_disk['lvm_config'] = {}
|
||||
share_disk['lvm_config']['size'] = service_disk['size']
|
||||
share_disk['lvm_config']['vg_name'] = 'vg_%s' % service_disk['service']
|
||||
share_disk['lvm_config']['lv_name'] = 'lv_%s' % service_disk['service']
|
||||
share_disk['lvm_config']['vg_name'] =\
|
||||
'vg_%s' % service_disk['service']
|
||||
share_disk['lvm_config']['lv_name'] =\
|
||||
'lv_%s' % service_disk['service']
|
||||
share_disk['lvm_config']['fs_type'] = 'ext4'
|
||||
disk_info.append(share_disk)
|
||||
return disk_info
|
||||
|
||||
|
||||
def _get_share_cluster_disk_for_disk_array(req, role_id):
|
||||
'''
|
||||
disk_info = [{'service': 'db', 'lun': 'lun1', 'data_ips':'data_ip1'},
|
||||
{'service': 'db', 'lun': 'lun2', 'data_ips':'data_ip2'},
|
||||
{'service': 'glance', 'lun': 'lun3', 'data_ips':'data_ip3'},
|
||||
{'service': 'glance', 'lun': 'lun4', 'data_ips':'data_ip4'},]
|
||||
'''
|
||||
disk_info = []
|
||||
service_disks = \
|
||||
tecs_cmn.get_service_disk_list(req, {'filters': {'role_id': role_id}})
|
||||
service_name = 'db'
|
||||
for service_disk in service_disks:
|
||||
share_cluster_disk = {}
|
||||
if service_disk['disk_location'] == 'share_cluster':
|
||||
share_cluster_disk['service'] = service_disk['service']
|
||||
share_cluster_disk['protocol_type'] = service_disk['protocol_type']
|
||||
share_cluster_disk['lun'] = service_disk['lun']
|
||||
if service_disk['protocol_type'] == 'FIBER':
|
||||
share_cluster_disk['fc_hba_wwpn'] = \
|
||||
service_disk['data_ips'].split(',')
|
||||
else:
|
||||
share_cluster_disk['data_ips'] = \
|
||||
service_disk['data_ips'].split(',')
|
||||
share_cluster_disk['lvm_config'] = {}
|
||||
share_cluster_disk['lvm_config']['size'] = service_disk['size']
|
||||
share_cluster_disk['lvm_config']['vg_name'] =\
|
||||
'vg_%s' % service_disk['service']
|
||||
share_cluster_disk['lvm_config']['lv_name'] =\
|
||||
'lv_%s' % service_disk['service']
|
||||
share_cluster_disk['lvm_config']['fs_type'] = 'ext4'
|
||||
disk_info.append(share_cluster_disk)
|
||||
return disk_info
|
||||
|
||||
|
||||
def _get_cinder_volume_for_disk_array(req, role_id):
|
||||
cinder_volume_info = []
|
||||
cinder_volumes = tecs_cmn.get_cinder_volume_list(req, {'filters': {'role_id': role_id}})
|
||||
cinder_volumes = tecs_cmn.get_cinder_volume_list(req,
|
||||
{'filters': {
|
||||
'role_id': role_id}})
|
||||
for cinder_volume in cinder_volumes:
|
||||
cv_info = {}
|
||||
cv_info['management_ips'] = cinder_volume['management_ips'].split(',')
|
||||
cv_info['management_ips'] =\
|
||||
cinder_volume['management_ips'].split(',')
|
||||
cv_info['data_ips'] = cinder_volume['data_ips'].split(',')
|
||||
cv_info['user_name'] = cinder_volume['user_name']
|
||||
cv_info['user_pwd'] = cinder_volume['user_pwd']
|
||||
index = cinder_volume['backend_index']
|
||||
cv_info['backend'] = {index:{}}
|
||||
cv_info['backend'][index]['volume_driver'] = cinder_volume['volume_driver']
|
||||
cv_info['backend'][index]['volume_type'] = cinder_volume['volume_type']
|
||||
cv_info['backend'][index]['pools'] = cinder_volume['pools'].split(',')
|
||||
cv_info['backend'] = {index: {}}
|
||||
cv_info['backend'][index]['volume_driver'] =\
|
||||
cinder_volume['volume_driver']
|
||||
cv_info['backend'][index]['volume_type'] =\
|
||||
cinder_volume['volume_type']
|
||||
cv_info['backend'][index]['pools'] =\
|
||||
cinder_volume['pools'].split(',')
|
||||
cinder_volume_info.append(cv_info)
|
||||
return cinder_volume_info
|
||||
|
||||
|
||||
def get_disk_array_info(req, cluster_id):
|
||||
share_disk_info = []
|
||||
share_cluster_disk_info = []
|
||||
volume_disk_info = {}
|
||||
cinder_volume_disk_list = []
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req,cluster_id)
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
if role['name'] == 'CONTROLLER_HA':
|
||||
share_disks = _get_service_disk_for_disk_array(req, role['id'])
|
||||
share_disk_info += share_disks
|
||||
cinder_volumes = _get_cinder_volume_for_disk_array(req, role['id'])
|
||||
share_disks = _get_service_disk_for_disk_array(req, role['id'])
|
||||
share_cluster_disks = \
|
||||
_get_share_cluster_disk_for_disk_array(req, role['id'])
|
||||
share_disk_info += share_disks
|
||||
share_cluster_disk_info += share_cluster_disks
|
||||
cinder_volumes =\
|
||||
_get_cinder_volume_for_disk_array(req, role['id'])
|
||||
cinder_volume_disk_list += cinder_volumes
|
||||
if cinder_volume_disk_list:
|
||||
volume_disk_info['disk_array'] = cinder_volume_disk_list
|
||||
return (share_disk_info, volume_disk_info)
|
||||
return (share_disk_info, volume_disk_info, share_cluster_disk_info)
|
||||
|
||||
def get_host_min_mac(host_interfaces):
|
||||
macs = [interface['mac'] for interface in host_interfaces
|
||||
if interface['type'] == 'ether' and interface['mac']]
|
||||
macs.sort()
|
||||
return macs[0]
|
||||
|
||||
def get_ha_and_compute_ips(req, cluster_id):
|
||||
controller_ha_nodes = {}
|
||||
computer_ips = []
|
||||
def config_ha_share_disk(share_disk_info,
|
||||
controller_ha_nodes,
|
||||
share_cluster_disk_info=None):
|
||||
'''
|
||||
share_disk_info = \
|
||||
[{'service': 'db', 'lun': 'lun1', 'data_ips':'data_ip1'},
|
||||
{'service': 'glance', 'lun': 'lun3', 'data_ips':'data_ip3'},]
|
||||
share_cluster_disk_info = \
|
||||
[{'service': 'db', 'lun': 'lun1', 'data_ips':'data_ip1', ...},
|
||||
{'service': 'db', 'lun': 'lun2', 'data_ips':'data_ip2', ...},
|
||||
{'service': 'glance', 'lun': 'lun3', 'data_ips':'data_ip3'},
|
||||
{'service': 'glance', 'lun': 'lun4', 'data_ips':'data_ip4'},]
|
||||
controller_ha_nodes[host_ip] = min_mac
|
||||
'''
|
||||
sorted_db_share_cluster = []
|
||||
if share_cluster_disk_info:
|
||||
db_share_cluster_disk = \
|
||||
[disk for disk in share_cluster_disk_info
|
||||
if disk['service'] == 'db']
|
||||
if len(db_share_cluster_disk) != 2:
|
||||
error_msg = 'share cluster disk: %s must be existed in pair.' % \
|
||||
db_share_cluster_disk
|
||||
LOG.error(error_msg)
|
||||
raise exception.InstallException(error_msg)
|
||||
sorted_db_share_cluster = \
|
||||
sorted(db_share_cluster_disk, key=lambda s: s['lun'])
|
||||
sorted_ha_nodes = \
|
||||
sorted(controller_ha_nodes.iteritems(), key=lambda d: d[1])
|
||||
sorted_ha_nodes_ip = [node[0] for node in sorted_ha_nodes]
|
||||
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req,cluster_id)
|
||||
cluster_networks = daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.tecs_backend_name:
|
||||
continue
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
for role_host in role_hosts:
|
||||
#host has installed tecs are exclusive
|
||||
if (role_host['status'] == tecs_state['ACTIVE'] or
|
||||
role_host['status'] == tecs_state['UPDATING'] or
|
||||
role_host['status'] == tecs_state['UPDATE_FAILED']):
|
||||
continue
|
||||
host_detail = daisy_cmn.get_host_detail(req,
|
||||
role_host['host_id'])
|
||||
host_ip = tecs_cmn.get_host_network_ip(req,
|
||||
host_detail,
|
||||
cluster_networks,
|
||||
'MANAGEMENT')
|
||||
if role['name'] == "CONTROLLER_HA":
|
||||
pxe_mac = [interface['mac'] for interface in host_detail['interfaces']
|
||||
if interface['is_deployment'] == True]
|
||||
if pxe_mac and pxe_mac[0]:
|
||||
controller_ha_nodes[host_ip] = pxe_mac[0]
|
||||
else:
|
||||
min_mac = get_host_min_mac(host_detail['interfaces'])
|
||||
controller_ha_nodes[host_ip] = min_mac
|
||||
if role['name'] == "COMPUTER":
|
||||
computer_ips.append(host_ip)
|
||||
return (controller_ha_nodes, computer_ips)
|
||||
|
||||
def config_ha_share_disk(share_disk_info, controller_ha_nodes):
|
||||
|
||||
error_msg = ""
|
||||
all_share_disk_info = []
|
||||
if sorted_db_share_cluster:
|
||||
all_share_disk_info = \
|
||||
[[disk] + share_disk_info for disk in sorted_db_share_cluster]
|
||||
# all_share_disk_info = \
|
||||
# [[{'lun': 'lun1', 'service': 'db', 'data_ips': 'data_ip1'},
|
||||
# {'lun': 'lun3', 'service': 'glance', 'data_ips': 'data_ip3'}],
|
||||
# [{'lun': 'lun2', 'service': 'db', 'data_ips': 'data_ip2'},
|
||||
# {'lun': 'lun3', 'service': 'glance', 'data_ips': 'data_ip3'}]]
|
||||
else:
|
||||
for index in range(len(sorted_ha_nodes)):
|
||||
all_share_disk_info.append(share_disk_info)
|
||||
# all_share_disk_info = \
|
||||
# [{'lun': 'lun3', 'service': 'glance', 'data_ips': 'data_ip3'},
|
||||
# {'lun': 'lun3', 'service': 'glance', 'data_ips': 'data_ip3'}]
|
||||
|
||||
'''
|
||||
cmd = 'rm -rf /var/lib/daisy/tecs/storage_auto_config/base/*.json'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
with open("/var/lib/daisy/tecs/storage_auto_config/base/control.json", "w") as fp:
|
||||
with open("/var/lib/daisy/tecs/storage_auto_config/base/control.json",\
|
||||
"w") as fp:
|
||||
json.dump(share_disk_info, fp, indent=2)
|
||||
|
||||
|
||||
|
||||
for host_ip in controller_ha_nodes.keys():
|
||||
password = "ossdbg1"
|
||||
cmd = '/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/tecs_install"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
try:
|
||||
scp_bin_result = subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r /var/lib/daisy/tecs/storage_auto_config %s:/home/tecs_install' % (host_ip,),
|
||||
'scp -o StrictHostKeyChecking=no -r\
|
||||
/var/lib/daisy/tecs/storage_auto_config\
|
||||
%s:/home/tecs_install' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config to %s failed!" % host_ip
|
||||
return error_msg
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config\
|
||||
to %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
try:
|
||||
LOG.info(_("Config share disk for host %s" % host_ip))
|
||||
cmd = "cd /home/tecs_install/storage_auto_config/; python storage_auto_config.py share_disk %s" % controller_ha_nodes[host_ip]
|
||||
exc_result = subprocess.check_output('clush -S -w %s "%s"' % (host_ip,cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
cmd = "cd /home/tecs_install/storage_auto_config/;\
|
||||
python storage_auto_config.py share_disk %s"\
|
||||
% controller_ha_nodes[host_ip]
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -w %s "%s"' % (host_ip,cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.info(_("Storage script error message: %s" % e.output))
|
||||
error_msg = "config Disk Array share disks on %s failed!" % host_ip
|
||||
return error_msg
|
||||
return error_msg
|
||||
error_msg = "config Disk Array share disks\
|
||||
on %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
'''
|
||||
|
||||
def config_ha_cinder_volume(volume_disk_info, controller_ha_ips):
|
||||
error_msg = ""
|
||||
cmd = 'rm -rf /var/lib/daisy/tecs/storage_auto_config/base/*.json'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
with open("/var/lib/daisy/tecs/storage_auto_config/base/cinder.json", "w") as fp:
|
||||
|
||||
for (host_ip, share_disk) in zip(sorted_ha_nodes_ip, all_share_disk_info):
|
||||
with open("/var/lib/daisy/tecs/storage_auto_config/base/control.json",
|
||||
"w") as fp:
|
||||
json.dump(share_disk, fp, indent=2)
|
||||
|
||||
try:
|
||||
subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r\
|
||||
/var/lib/daisy/tecs/storage_auto_config\
|
||||
%s:/home/tecs_install' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config\
|
||||
to %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
|
||||
try:
|
||||
LOG.info(_("Config share disk for host %s" % host_ip))
|
||||
cmd = "cd /home/tecs_install/storage_auto_config/;\
|
||||
python storage_auto_config.py share_disk %s"\
|
||||
% controller_ha_nodes[host_ip]
|
||||
subprocess.check_output(
|
||||
'clush -S -w %s "%s"' % (host_ip, cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.info(_("Storage script error message: %s" % e.output))
|
||||
error_msg = "config Disk Array share disks\
|
||||
on %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
|
||||
|
||||
def config_ha_cinder_volume(volume_disk_info, controller_ha_ips):
|
||||
cmd = 'rm -rf /var/lib/daisy/tecs/storage_auto_config/base/*.json'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
with open("/var/lib/daisy/tecs/storage_auto_config/base/cinder.json",
|
||||
"w") as fp:
|
||||
json.dump(volume_disk_info, fp, indent=2)
|
||||
for host_ip in controller_ha_ips:
|
||||
password = "ossdbg1"
|
||||
cmd = '/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/tecs_install"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
try:
|
||||
scp_bin_result = subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r /var/lib/daisy/tecs/storage_auto_config %s:/home/tecs_install' % (host_ip,),
|
||||
subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r\
|
||||
/var/lib/daisy/tecs/storage_auto_config\
|
||||
%s:/home/tecs_install' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config to %s failed!" % host_ip
|
||||
return error_msg
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config\
|
||||
to %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
try:
|
||||
LOG.info(_("Config cinder volume for host %s" % host_ip))
|
||||
cmd = 'cd /home/tecs_install/storage_auto_config/; python storage_auto_config.py cinder_conf %s' % host_ip
|
||||
exc_result = subprocess.check_output('clush -S -w %s "%s"' % (host_ip,cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.info(_("Storage script error message: %s" % e.output))
|
||||
error_msg = "config Disk Array cinder volumes on %s failed!" % host_ip
|
||||
return error_msg
|
||||
return error_msg
|
||||
|
||||
def config_compute_multipath(all_nodes_ip):
|
||||
error_msg = ""
|
||||
for host_ip in all_nodes_ip:
|
||||
password = "ossdbg1"
|
||||
cmd = '/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/tecs_install"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
try:
|
||||
scp_bin_result = subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r /var/lib/daisy/tecs/storage_auto_config %s:/home/tecs_install' % (host_ip,),
|
||||
cmd = 'cd /home/tecs_install/storage_auto_config/;\
|
||||
python storage_auto_config.py cinder_conf %s' % host_ip
|
||||
subprocess.check_output(
|
||||
'clush -S -w %s "%s"' % (host_ip, cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config to %s failed!" % host_ip
|
||||
return error_msg
|
||||
LOG.info(_("Storage script error message: %s" % e.output))
|
||||
error_msg = "config Disk Array cinder volumes\
|
||||
on %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
|
||||
|
||||
def config_compute_multipath(hosts_ip):
|
||||
for host_ip in hosts_ip:
|
||||
try:
|
||||
subprocess.check_output(
|
||||
'scp -o StrictHostKeyChecking=no -r\
|
||||
/var/lib/daisy/tecs/storage_auto_config\
|
||||
%s:/home/tecs_install' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "scp /var/lib/daisy/tecs/storage_auto_config\
|
||||
to %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
try:
|
||||
LOG.info(_("Config multipath for host %s" % host_ip))
|
||||
cmd = 'cd /home/tecs_install/storage_auto_config/; python storage_auto_config.py check_multipath'
|
||||
exc_result = subprocess.check_output('clush -S -w %s "%s"' % (host_ip,cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
cmd = 'cd /home/tecs_install/storage_auto_config/;\
|
||||
python storage_auto_config.py check_multipath'
|
||||
subprocess.check_output(
|
||||
'clush -S -w %s "%s"' % (host_ip, cmd),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.info(_("Storage script error message: %s" % e.output))
|
||||
error_msg = "config Disk Array multipath on %s failed!" % host_ip
|
||||
return error_msg
|
||||
return error_msg
|
||||
error_msg = "config Disk Array multipath\
|
||||
on %s failed!" % host_ip
|
||||
raise exception.InstallException(error_msg)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,31 +17,12 @@
|
||||
/hosts endpoint for Daisy v1 API
|
||||
"""
|
||||
|
||||
import webob.exc
|
||||
import subprocess
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread, Lock
|
||||
import threading
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
import daisy.registry.client.v1.api as registry
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -51,9 +32,11 @@ _LW = i18n._LW
|
||||
|
||||
tecs_state = tecs_cmn.TECS_STATE
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, hosts_list,host_ip=None):
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, hosts_list, host_ip=None):
|
||||
"""
|
||||
Write uninstall progress and status to db, we use global lock object 'uninstall_mutex'
|
||||
Write uninstall progress and status to db,
|
||||
we use global lock object 'uninstall_mutex'
|
||||
to make sure this function is thread safety.
|
||||
:param req: http req.
|
||||
:param role_id_list: Column neeb be update in role table.
|
||||
@ -63,26 +46,27 @@ def update_progress_to_db(req, role_id_list, status, hosts_list,host_ip=None):
|
||||
for role_id in role_id_list:
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role_id)
|
||||
for host_id_ip in hosts_list:
|
||||
host_ip_tmp=host_id_ip.values()[0]
|
||||
host_id_tmp=host_id_ip.keys()[0]
|
||||
host_ip_tmp = host_id_ip.values()[0]
|
||||
host_id_tmp = host_id_ip.keys()[0]
|
||||
if host_ip:
|
||||
for role_host in role_hosts:
|
||||
if (host_ip_tmp == host_ip and
|
||||
role_host['host_id']== host_id_tmp):
|
||||
role_host['host_id'] == host_id_tmp):
|
||||
role_host_meta = {}
|
||||
if 0 == cmp(status, tecs_state['UNINSTALLING']):
|
||||
role_host_meta['progress'] = 10
|
||||
role_host_meta['messages'] = 'TECS uninstalling'
|
||||
if 0 == cmp(status, tecs_state['UNINSTALL_FAILED']):
|
||||
role_host_meta['messages'] = 'TECS uninstalled failed'
|
||||
elif 0 == cmp(status, tecs_state['ACTIVE']):
|
||||
if 0 == cmp(status, tecs_state['UNINSTALL_FAILED']):
|
||||
role_host_meta[
|
||||
'messages'] = 'TECS uninstalled failed'
|
||||
elif 0 == cmp(status, tecs_state['INIT']):
|
||||
role_host_meta['progress'] = 100
|
||||
role_host_meta['messages'] = 'TECS uninstalled successfully'
|
||||
role_host_meta[
|
||||
'messages'] = 'TECS uninstalled successfully'
|
||||
if role_host_meta:
|
||||
role_host_meta['status'] = status
|
||||
daisy_cmn.update_role_host(req,
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
daisy_cmn.update_role_host(req, role_host['id'],
|
||||
role_host_meta)
|
||||
else:
|
||||
role = {}
|
||||
if 0 == cmp(status, tecs_state['UNINSTALLING']):
|
||||
@ -91,11 +75,11 @@ def update_progress_to_db(req, role_id_list, status, hosts_list,host_ip=None):
|
||||
role_host_meta['status'] = status
|
||||
role_host_meta['progress'] = 0
|
||||
daisy_cmn.update_role_host(req,
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
role['progress']=0
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
role['progress'] = 0
|
||||
role['messages'] = 'TECS uninstalling'
|
||||
if 0 == cmp(status, tecs_state['UNINSTALL_FAILED']):
|
||||
if 0 == cmp(status, tecs_state['UNINSTALL_FAILED']):
|
||||
role['messages'] = 'TECS uninstalled failed'
|
||||
elif 0 == cmp(status, tecs_state['INIT']):
|
||||
role['progress'] = 100
|
||||
@ -103,53 +87,64 @@ def update_progress_to_db(req, role_id_list, status, hosts_list,host_ip=None):
|
||||
if role:
|
||||
role['status'] = status
|
||||
daisy_cmn.update_role(req, role_id, role)
|
||||
if 0 == cmp(status, tecs_state['INIT']):
|
||||
daisy_cmn.delete_role_hosts(req, role_id)
|
||||
|
||||
def _thread_bin(req, host_ip, role_id_list,hosts_list):
|
||||
|
||||
def _thread_bin(req, host_ip, role_id_list, hosts_list):
|
||||
# uninstall network-configuration-1.1.1-15.x86_64.rpm
|
||||
update_progress_to_db(req,role_id_list,tecs_state['UNINSTALLING'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state['UNINSTALLING'], hosts_list, host_ip)
|
||||
tecs_cmn.TecsShellExector(host_ip, 'uninstall_rpm')
|
||||
|
||||
cmd = 'mkdir -p /var/log/daisy/daisy_uninstall/'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
password = "ossdbg1"
|
||||
var_log_path = "/var/log/daisy/daisy_uninstall/%s_uninstall_tecs.log" % host_ip
|
||||
password = "ossdbg1"
|
||||
var_log_path = "/var/log/daisy/daisy_uninstall/\
|
||||
%s_uninstall_tecs.log" % host_ip
|
||||
with open(var_log_path, "w+") as fp:
|
||||
cmd = '/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
cmd = 'clush -S -b -w %s "rm -rf /home/daisy_uninstall"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/daisy_uninstall"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
try:
|
||||
scp_bin_result = subprocess.check_output(
|
||||
'clush -S -w %s -c /var/lib/daisy/tecs/ZXTECS*.bin --dest=/home/daisy_uninstall' % (host_ip,),
|
||||
subprocess.check_output(
|
||||
'clush -S -w %s -c /var/lib/daisy/tecs/ZXTECS*.bin \
|
||||
--dest=/home/daisy_uninstall' % (
|
||||
host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, tecs_state['UNINSTALL_FAILED'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state[
|
||||
'UNINSTALL_FAILED'], hosts_list, host_ip)
|
||||
LOG.error(_("scp TECS bin for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
|
||||
|
||||
cmd = 'clush -S -w %s "chmod 777 /home/daisy_uninstall/*"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -w %s /home/daisy_uninstall/ZXTECS*.bin clean' % (host_ip,),
|
||||
'clush -S -w %s /home/daisy_uninstall/ZXTECS*.bin clean' % (
|
||||
host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, tecs_state['UNINSTALL_FAILED'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state[
|
||||
'UNINSTALL_FAILED'], hosts_list, host_ip)
|
||||
LOG.error(_("Uninstall TECS for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
else:
|
||||
update_progress_to_db(req, role_id_list, tecs_state['ACTIVE'], hosts_list,host_ip)
|
||||
update_progress_to_db(req, role_id_list, tecs_state['INIT'],
|
||||
hosts_list, host_ip)
|
||||
LOG.info(_("Uninstall TECS for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
# this will be raise raise all the exceptions of the thread to log file
|
||||
|
||||
|
||||
def thread_bin(req, host_ip, role_id_list, hosts_list):
|
||||
try:
|
||||
_thread_bin(req, host_ip, role_id_list, hosts_list)
|
||||
except Exception as e:
|
||||
LOG.exception(e.message)
|
||||
LOG.exception(e.message)
|
||||
|
@ -17,30 +17,10 @@
|
||||
/update endpoint for Daisy v1 API
|
||||
"""
|
||||
|
||||
import webob.exc
|
||||
import subprocess
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread, Lock
|
||||
import threading
|
||||
import time
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
from daisy.api.backends import os as os_handle
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
|
||||
@ -53,7 +33,8 @@ _LW = i18n._LW
|
||||
|
||||
tecs_state = tecs_cmn.TECS_STATE
|
||||
|
||||
def update_progress_to_db(req,role_id_list,status,hosts_list,host_ip=None):
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, hosts_list, host_ip=None):
|
||||
"""
|
||||
Write update progress and status to db,
|
||||
to make sure this function is thread safety.
|
||||
@ -65,40 +46,43 @@ def update_progress_to_db(req,role_id_list,status,hosts_list,host_ip=None):
|
||||
for role_id in role_id_list:
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role_id)
|
||||
for host_id_ip in hosts_list:
|
||||
host_ip_tmp=host_id_ip.values()[0]
|
||||
host_id_tmp=host_id_ip.keys()[0]
|
||||
host_ip_tmp = host_id_ip.values()[0]
|
||||
host_id_tmp = host_id_ip.keys()[0]
|
||||
if host_ip:
|
||||
for role_host in role_hosts:
|
||||
if (host_ip_tmp == host_ip and
|
||||
role_host['host_id']== host_id_tmp):
|
||||
role_host['host_id'] == host_id_tmp):
|
||||
role_host_meta = {}
|
||||
if 0 == cmp(status, tecs_state['UPDATING']):
|
||||
role_host_meta['progress'] = 10
|
||||
role_host_meta['messages'] = 'TECS upgrading'
|
||||
if 0 == cmp(status, tecs_state['UPDATE_FAILED']):
|
||||
if 0 == cmp(status, tecs_state['UPDATE_FAILED']):
|
||||
role_host_meta['messages'] = 'TECS upgraded failed'
|
||||
elif 0 == cmp(status, tecs_state['ACTIVE']):
|
||||
role_host_meta['progress'] = 100
|
||||
role_host_meta['messages'] = 'TECS upgraded successfully'
|
||||
role_host_meta[
|
||||
'messages'] = 'TECS upgraded successfully'
|
||||
if role_host_meta:
|
||||
role_host_meta['status'] = status
|
||||
daisy_cmn.update_role_host(req,
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
else:
|
||||
role = {}
|
||||
if 0 == cmp(status, tecs_state['UPDATING']):
|
||||
for role_host in role_hosts:
|
||||
if role_host['status'] == tecs_state['INSTALL_FAILED']:
|
||||
continue
|
||||
role_host_meta = {}
|
||||
role_host_meta['status'] = status
|
||||
role_host_meta['progress'] = 0
|
||||
role_host_meta['messages'] = 'TECS upgrading'
|
||||
daisy_cmn.update_role_host(req,
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
role['progress']=0
|
||||
role_host['id'],
|
||||
role_host_meta)
|
||||
role['progress'] = 0
|
||||
role['messages'] = 'TECS upgrading'
|
||||
if 0 == cmp(status, tecs_state['UPDATE_FAILED']):
|
||||
if 0 == cmp(status, tecs_state['UPDATE_FAILED']):
|
||||
role['messages'] = 'TECS upgraded failed'
|
||||
elif 0 == cmp(status, tecs_state['ACTIVE']):
|
||||
role['progress'] = 100
|
||||
@ -106,46 +90,56 @@ def update_progress_to_db(req,role_id_list,status,hosts_list,host_ip=None):
|
||||
if role:
|
||||
role['status'] = status
|
||||
daisy_cmn.update_role(req, role_id, role)
|
||||
|
||||
def thread_bin(req,role_id_list, host_ip,hosts_list):
|
||||
|
||||
|
||||
def thread_bin(req, role_id_list, host_ip, hosts_list):
|
||||
# update network-configuration-1.1.1-15.x86_64.rpm
|
||||
update_progress_to_db(req,role_id_list,tecs_state['UPDATING'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state['UPDATING'], hosts_list, host_ip)
|
||||
cmd = 'mkdir -p /var/log/daisy/daisy_update/'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
password = "ossdbg1"
|
||||
var_log_path = "/var/log/daisy/daisy_update/%s_update_tecs.log" % host_ip
|
||||
with open(var_log_path, "w+") as fp:
|
||||
cmd = '/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/daisy_update"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
cmd = 'clush -S -b -w %s "rm -rf /home/daisy_update/ZXTECS*.bin"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
cmd = 'clush -S -w %s "mkdir -p /home/tecs_update/"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
cmd = 'clush -S -b -w %s "rm -rf /home/tecs_update/ZXTECS*.bin"' % (
|
||||
host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
tecs_cmn.TecsShellExector(host_ip, 'update_rpm')
|
||||
try:
|
||||
scp_bin_result = subprocess.check_output(
|
||||
'clush -S -w %s -c /var/lib/daisy/tecs/ZXTECS*.bin --dest=/home/daisy_update' % (host_ip,),
|
||||
subprocess.check_output(
|
||||
'clush -S -w %s -c /var/lib/daisy/tecs/ZXTECS*.bin \
|
||||
--dest=/home/tecs_update' % (
|
||||
host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req,role_id_list,tecs_state['UPDATE_FAILED'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state[
|
||||
'UPDATE_FAILED'], hosts_list, host_ip)
|
||||
LOG.error(_("scp TECS bin for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
return 1
|
||||
|
||||
cmd = 'clush -S -w %s "chmod 777 /home/daisy_update/*"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
|
||||
cmd = 'clush -S -w %s "chmod 777 /home/tecs_update/*"' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -w %s "/home/daisy_update/ZXTECS*.bin upgrade"' % (host_ip,),
|
||||
'clush -S -w %s "/home/tecs_update/ZXTECS*.bin upgrade"' % (
|
||||
host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req,role_id_list,tecs_state['UPDATE_FAILED'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state[
|
||||
'UPDATE_FAILED'], hosts_list, host_ip)
|
||||
LOG.error(_("Update TECS for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
return 2
|
||||
else:
|
||||
update_progress_to_db(req,role_id_list,tecs_state['ACTIVE'],hosts_list,host_ip)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, tecs_state['ACTIVE'], hosts_list, host_ip)
|
||||
fp.write(exc_result)
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
142
code/daisy/daisy/api/backends/tecs/write_configs.py
Executable file
142
code/daisy/daisy/api/backends/tecs/write_configs.py
Executable file
@ -0,0 +1,142 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/install endpoint for tecs API
|
||||
"""
|
||||
import daisy.registry.client.v1.api as registry
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
from daisy.common import utils
|
||||
|
||||
|
||||
def _write_role_configs_to_db(req, cluster_id, role_name, configs):
|
||||
config_meta = {'cluster': cluster_id,
|
||||
'role': role_name,
|
||||
'config': configs}
|
||||
registry.config_interface_metadata(req.context,
|
||||
config_meta)
|
||||
|
||||
|
||||
def _write_host_configs_to_db(req, host_id, configs):
|
||||
config_meta = {'host_id': host_id,
|
||||
'config': configs}
|
||||
registry.config_interface_metadata(req.context,
|
||||
config_meta)
|
||||
|
||||
|
||||
def _get_config_item(file, section, key, value, description):
|
||||
return {'file-name': file,
|
||||
'section': section,
|
||||
'key': key,
|
||||
'value': value,
|
||||
'description': description}
|
||||
|
||||
|
||||
def _add_configs_for_nova(req, host_detail):
|
||||
config_file = '/etc/nova/nova.conf'
|
||||
default_section = 'DEFAULT'
|
||||
|
||||
key_name = 'vcpu_pin_set'
|
||||
key_value = host_detail.get(key_name)
|
||||
config_items = []
|
||||
if not key_value:
|
||||
key_value = host_detail.get('isolcpus')
|
||||
|
||||
nova_key_name = key_name
|
||||
description = 'vcpu pin set for all vm'
|
||||
item = _get_config_item(config_file,
|
||||
default_section,
|
||||
nova_key_name,
|
||||
key_value,
|
||||
description)
|
||||
config_items.append(item)
|
||||
|
||||
key_name = 'dvs_high_cpuset'
|
||||
key_value = host_detail.get(key_name)
|
||||
|
||||
nova_key_name = 'dvs_high_cpu_set'
|
||||
description = 'vcpu pin set for high-performance dvs vm'
|
||||
item = _get_config_item(config_file,
|
||||
default_section,
|
||||
nova_key_name,
|
||||
key_value,
|
||||
description)
|
||||
config_items.append(item)
|
||||
|
||||
numa_cpus = utils.get_numa_node_cpus(host_detail.get('cpu', {}))
|
||||
numa_nodes = utils.get_numa_node_from_cpus(numa_cpus, key_value)
|
||||
if numa_nodes:
|
||||
libvirt_section = 'libvirt'
|
||||
nova_key_name = 'reserved_huge_pages'
|
||||
# only support one NUMA node for DVS now
|
||||
key_value = 'node:%s,size:1048576,count:4' % numa_nodes[0]
|
||||
description = 'reserved huges for DVS service '\
|
||||
'on high NUMA node'
|
||||
config_items.append({'file-name': config_file,
|
||||
'key': nova_key_name,
|
||||
'section': libvirt_section,
|
||||
'value': key_value,
|
||||
'description': description})
|
||||
|
||||
key_name = 'pci_high_cpuset'
|
||||
pci_key_value = host_detail.get(key_name)
|
||||
|
||||
nova_key_name = 'vsg_card_cpu_set'
|
||||
description = 'vcpu pin set for high-performance CLC card vm'
|
||||
item = _get_config_item(config_file,
|
||||
default_section,
|
||||
nova_key_name,
|
||||
pci_key_value,
|
||||
description)
|
||||
config_items.append(item)
|
||||
if pci_key_value:
|
||||
nova_key_name = 'default_ephemeral_format'
|
||||
description = 'config for CLC card'
|
||||
key_value = 'ext3'
|
||||
item = _get_config_item(config_file,
|
||||
default_section,
|
||||
nova_key_name,
|
||||
key_value,
|
||||
description)
|
||||
config_items.append(item)
|
||||
|
||||
nova_key_name = 'pci_passthrough_whitelist'
|
||||
description = 'config for CLC card'
|
||||
key_value = '[{"vendor_id": "8086","product_id": "0435"}]'
|
||||
item = _get_config_item(config_file,
|
||||
default_section,
|
||||
nova_key_name,
|
||||
key_value,
|
||||
description)
|
||||
config_items.append(item)
|
||||
|
||||
_write_host_configs_to_db(req,
|
||||
host_detail['id'],
|
||||
config_items)
|
||||
|
||||
|
||||
def update_configset(req, cluster_id):
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
# now only computer has configs
|
||||
if role['name'] != 'COMPUTER':
|
||||
continue
|
||||
role_meta = {'config_set_update_progress': 0}
|
||||
daisy_cmn.update_role(req, role['id'], role_meta)
|
||||
|
||||
role_hosts = daisy_cmn.get_hosts_of_role(req, role['id'])
|
||||
for host in role_hosts:
|
||||
host_detail = daisy_cmn.get_host_detail(req, host['host_id'])
|
||||
_add_configs_for_nova(req, host_detail)
|
@ -16,46 +16,21 @@
|
||||
"""
|
||||
/install endpoint for zenic API
|
||||
"""
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
import commands
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPServerError
|
||||
|
||||
import threading
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.backends.zenic import config
|
||||
from daisy.api.backends import driver
|
||||
from daisy.api.network_api import network as neutron
|
||||
from ironicclient import client as ironic_client
|
||||
import daisy.api.backends.os as os_handle
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.zenic.common as zenic_cmn
|
||||
import daisy.api.backends.zenic.install as instl
|
||||
import daisy.api.backends.zenic.uninstall as unstl
|
||||
import daisy.api.backends.zenic.upgrade as upgrd
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -65,12 +40,13 @@ _LW = i18n._LW
|
||||
|
||||
zenic_state = zenic_cmn.ZENIC_STATE
|
||||
|
||||
|
||||
class API(driver.DeploymentDriver):
|
||||
|
||||
def __init__(self):
|
||||
super(API, self).__init__()
|
||||
return
|
||||
|
||||
|
||||
def install(self, req, cluster_id):
|
||||
"""
|
||||
Install zenic to a cluster.
|
||||
@ -79,23 +55,26 @@ class API(driver.DeploymentDriver):
|
||||
cluster_id:cluster id
|
||||
"""
|
||||
|
||||
#instl.pxe_server_build(req, install_meta)
|
||||
# instl.pxe_server_build(req, install_meta)
|
||||
# get hosts config which need to install OS
|
||||
#hosts_need_os = instl.get_cluster_hosts_config(req, cluster_id)
|
||||
# if have hosts need to install os, ZENIC installataion executed in OSInstallTask
|
||||
#if hosts_need_os:
|
||||
#os_install_obj = instl.OSInstallTask(req, cluster_id, hosts_need_os)
|
||||
#os_install_thread = Thread(target=os_install_obj.run)
|
||||
#os_install_thread.start()
|
||||
#else:
|
||||
LOG.info(_("No host need to install os, begin install ZENIC for cluster %s." % cluster_id))
|
||||
# hosts_need_os = instl.get_cluster_hosts_config(req, cluster_id)
|
||||
# if have hosts need to install os, ZENIC installataion executed
|
||||
# in OSInstallTask
|
||||
# if hosts_need_os:
|
||||
# os_install_obj = instl.OSInstallTask(req, cluster_id, hosts_need_os)
|
||||
# os_install_thread = Thread(target=os_install_obj.run)
|
||||
# os_install_thread.start()
|
||||
# else:
|
||||
LOG.info(
|
||||
_("No host need to install os, begin install ZENIC for cluster %s."
|
||||
% cluster_id))
|
||||
zenic_install_task = instl.ZENICInstallTask(req, cluster_id)
|
||||
zenic_install_task.start()
|
||||
|
||||
|
||||
LOG.info((_("begin install zenic, please waiting....")))
|
||||
time.sleep(5)
|
||||
LOG.info((_("install zenic successfully")))
|
||||
|
||||
LOG.info((_("install zenic successfully")))
|
||||
|
||||
def uninstall(self, req, cluster_id):
|
||||
"""
|
||||
Uninstall ZENIC to a cluster.
|
||||
@ -105,18 +84,22 @@ class API(driver.DeploymentDriver):
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(req, cluster_id)
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(
|
||||
req, cluster_id)
|
||||
if role_id_list:
|
||||
if not hosts_list:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
unstl.update_progress_to_db(req, role_id_list, zenic_state['UNINSTALLING'], 0.0)
|
||||
uninstall_progress_percentage = round(1*1.0/len(hosts_list), 2)*100
|
||||
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UNINSTALLING'], 0.0)
|
||||
uninstall_progress_percentage =\
|
||||
round(1 * 1.0 / len(hosts_list), 2) * 100
|
||||
|
||||
threads = []
|
||||
for host in hosts_list:
|
||||
t = threading.Thread(target=unstl.thread_bin,args=(req,host,role_id_list,uninstall_progress_percentage))
|
||||
t = threading.Thread(target=unstl.thread_bin, args=(
|
||||
req, host, role_id_list, uninstall_progress_percentage))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
@ -132,16 +115,20 @@ class API(driver.DeploymentDriver):
|
||||
for role_id in role_id_list:
|
||||
role = daisy_cmn.get_role_detail(req, role_id)
|
||||
if role['progress'] == 100:
|
||||
unstl.update_progress_to_db(req, role_id_list, zenic_state['UNINSTALL_FAILED'])
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UNINSTALL_FAILED'])
|
||||
uninstall_failed_flag = True
|
||||
break
|
||||
if role['status'] == zenic_state['UNINSTALL_FAILED']:
|
||||
uninstall_failed_flag = True
|
||||
break
|
||||
if not uninstall_failed_flag:
|
||||
LOG.info(_("all uninstall threads have done, set all roles status to 'init'!"))
|
||||
unstl.update_progress_to_db(req, role_id_list, zenic_state['INIT'])
|
||||
|
||||
LOG.info(
|
||||
_("all uninstall threads have done,\
|
||||
set all roles status to 'init'!"))
|
||||
unstl.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INIT'])
|
||||
|
||||
LOG.info((_("begin uninstall zenic, please waiting....")))
|
||||
time.sleep(5)
|
||||
LOG.info((_("uninstall zenic successfully")))
|
||||
@ -153,19 +140,22 @@ class API(driver.DeploymentDriver):
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
|
||||
|
||||
"""
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(req, cluster_id)
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(
|
||||
req, cluster_id)
|
||||
if not hosts_list:
|
||||
msg = _("there is no host in cluster %s") % cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
upgrd.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATING'], 0.0)
|
||||
update_progress_percentage = round(1 * 1.0 / len(hosts_list), 2) * 100
|
||||
|
||||
upgrd.update_progress_to_db(req, role_id_list, zenic_state['UPDATING'], 0.0)
|
||||
update_progress_percentage = round(1*1.0/len(hosts_list), 2)*100
|
||||
|
||||
threads = []
|
||||
for host in hosts_list:
|
||||
t = threading.Thread(target=upgrd.thread_bin,args=(req,host,role_id_list,update_progress_percentage))
|
||||
t = threading.Thread(target=upgrd.thread_bin, args=(
|
||||
req, host, role_id_list, update_progress_percentage))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
@ -181,14 +171,16 @@ class API(driver.DeploymentDriver):
|
||||
for role_id in role_id_list:
|
||||
role = daisy_cmn.get_role_detail(req, role_id)
|
||||
if role['progress'] == 0:
|
||||
upgrd.update_progress_to_db(req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
upgrd.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
update_failed_flag = True
|
||||
break
|
||||
if role['status'] == zenic_state['UPDATE_FAILED']:
|
||||
update_failed_flag = True
|
||||
break
|
||||
if not update_failed_flag:
|
||||
LOG.info(_("all update threads have done, set all roles status to 'active'!"))
|
||||
upgrd.update_progress_to_db(req, role_id_list, zenic_state['ACTIVE'])
|
||||
|
||||
|
||||
LOG.info(
|
||||
_("all update threads have done, \
|
||||
set all roles status to 'active'!"))
|
||||
upgrd.update_progress_to_db(
|
||||
req, role_id_list, zenic_state['ACTIVE'])
|
||||
|
@ -19,33 +19,16 @@
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
@ -54,9 +37,9 @@ _LW = i18n._LW
|
||||
|
||||
daisy_zenic_path = '/var/lib/daisy/zenic/'
|
||||
ZENIC_STATE = {
|
||||
'INIT' : 'init',
|
||||
'INSTALLING' : 'installing',
|
||||
'ACTIVE' : 'active',
|
||||
'INIT': 'init',
|
||||
'INSTALLING': 'installing',
|
||||
'ACTIVE': 'active',
|
||||
'INSTALL_FAILED': 'install-failed',
|
||||
'UNINSTALLING': 'uninstalling',
|
||||
'UNINSTALL_FAILED': 'uninstall-failed',
|
||||
@ -64,6 +47,7 @@ ZENIC_STATE = {
|
||||
'UPDATE_FAILED': 'update-failed',
|
||||
}
|
||||
|
||||
|
||||
def get_cluster_hosts(req, cluster_id):
|
||||
try:
|
||||
cluster_hosts = registry.get_cluster_hosts(req.context, cluster_id)
|
||||
@ -71,13 +55,15 @@ def get_cluster_hosts(req, cluster_id):
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return cluster_hosts
|
||||
|
||||
|
||||
def get_host_detail(req, host_id):
|
||||
try:
|
||||
host_detail = registry.get_host_metadata(req.context, host_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return host_detail
|
||||
|
||||
|
||||
|
||||
def get_roles_detail(req):
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
@ -85,13 +71,15 @@ def get_roles_detail(req):
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return roles
|
||||
|
||||
|
||||
def get_hosts_of_role(req, role_id):
|
||||
try:
|
||||
hosts = registry.get_role_host_metadata(req.context, role_id)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return hosts
|
||||
|
||||
|
||||
|
||||
def get_role_detail(req, role_id):
|
||||
try:
|
||||
role = registry.get_role_metadata(req.context, role_id)
|
||||
@ -99,17 +87,20 @@ def get_role_detail(req, role_id):
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role
|
||||
|
||||
def update_role(req, role_id,role_meta):
|
||||
|
||||
def update_role(req, role_id, role_meta):
|
||||
try:
|
||||
registry.update_role_metadata(req.context, role_id, role_meta)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def update_role_host(req, role_id, role_host):
|
||||
try:
|
||||
registry.update_role_host_metadata(req.context, role_id, role_host)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def delete_role_hosts(req, role_id):
|
||||
try:
|
||||
@ -117,67 +108,81 @@ def delete_role_hosts(req, role_id):
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
|
||||
def _get_cluster_network(cluster_networks, network_type):
|
||||
network = [cn for cn in cluster_networks
|
||||
if cn['name'] in network_type]
|
||||
network = [cn for cn in cluster_networks
|
||||
if cn['name'] in network_type]
|
||||
if not network or not network[0]:
|
||||
msg = "network %s is not exist" % (network_type)
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
else:
|
||||
return network[0]
|
||||
|
||||
|
||||
def get_host_interface_by_network(host_detail, network_type):
|
||||
host_detail_info = copy.deepcopy(host_detail)
|
||||
interface_list = [hi for hi in host_detail_info['interfaces']
|
||||
for assigned_network in hi['assigned_networks']
|
||||
if assigned_network and network_type == assigned_network['name']]
|
||||
interface_list = [hi for hi in host_detail_info['interfaces']
|
||||
for assigned_network in hi['assigned_networks']
|
||||
if assigned_network and
|
||||
network_type == assigned_network['name']]
|
||||
interface = {}
|
||||
if interface_list:
|
||||
interface = interface_list[0]
|
||||
|
||||
|
||||
if not interface:
|
||||
msg = "network %s of host %s is not exist" % (network_type, host_detail_info['id'])
|
||||
msg = "network %s of host %s is not exist" % (
|
||||
network_type, host_detail_info['id'])
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
|
||||
return interface
|
||||
return interface
|
||||
|
||||
|
||||
def get_host_network_ip(req, host_detail, cluster_networks, network_type):
|
||||
interface_network_ip = ''
|
||||
host_interface = get_host_interface_by_network(host_detail, network_type)
|
||||
if host_interface:
|
||||
network = _get_cluster_network(cluster_networks, network_type)
|
||||
assigned_network = daisy_cmn.get_assigned_network(req,
|
||||
host_interface['id'],
|
||||
network['id'])
|
||||
assigned_network = daisy_cmn.get_assigned_network(req,
|
||||
host_interface['id'],
|
||||
network['id'])
|
||||
interface_network_ip = assigned_network['ip']
|
||||
|
||||
if not interface_network_ip:
|
||||
msg = "%s network ip of host %s can't be empty" % (network_type, host_detail['id'])
|
||||
msg = "%s network ip of host %s can't be empty" % (
|
||||
network_type, host_detail['id'])
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
return interface_network_ip
|
||||
|
||||
def get_deploy_node_cfg(req, host_detail, cluster_networks):
|
||||
host_deploy_network = get_host_interface_by_network(host_detail, 'DEPLOYMENT')
|
||||
host_deploy_ip = get_host_network_ip(req, host_detail, cluster_networks, 'DEPLOYMENT')
|
||||
|
||||
def get_deploy_node_cfg(req, host_detail, cluster_networks):
|
||||
host_deploy_network = get_host_interface_by_network(
|
||||
host_detail, 'DEPLOYMENT')
|
||||
host_deploy_ip = get_host_network_ip(
|
||||
req, host_detail, cluster_networks, 'DEPLOYMENT')
|
||||
if not host_deploy_ip:
|
||||
msg = "deployment ip of host %s can't be empty" % host_detail['id']
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
host_deploy_macname = host_deploy_network['name']
|
||||
if not host_deploy_macname:
|
||||
msg = "deployment macname of host %s can't be empty" % host_detail['id']
|
||||
msg = "deployment macname of host %s can't be empty" % host_detail[
|
||||
'id']
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
|
||||
host_mgt_ip = get_host_network_ip(req, host_detail, cluster_networks, 'MANAGEMENT')
|
||||
host_mgt_ip = get_host_network_ip(
|
||||
req, host_detail, cluster_networks, 'MANAGEMENT')
|
||||
if not host_mgt_ip:
|
||||
msg = "management ip of host %s can't be empty" % host_detail['id']
|
||||
raise exception.InvalidNetworkConfig(msg)
|
||||
|
||||
|
||||
memmode = 'tiny'
|
||||
host_memory = 0
|
||||
|
||||
if host_detail.has_key('memory'):
|
||||
host_memory = (int(host_detail['memory']['total'].strip().split()[0]))/(1024*1024)
|
||||
|
||||
|
||||
# if host_detail.has_key('memory'):
|
||||
if 'memory' in host_detail:
|
||||
host_memory = (
|
||||
int(host_detail['memory'][
|
||||
'total'].strip().split()[0])) / (1024 * 1024)
|
||||
|
||||
if host_memory < 8:
|
||||
memmode = 'tiny'
|
||||
elif host_memory < 16:
|
||||
@ -186,24 +191,24 @@ def get_deploy_node_cfg(req, host_detail, cluster_networks):
|
||||
memmode = 'medium'
|
||||
else:
|
||||
memmode = 'large'
|
||||
|
||||
|
||||
|
||||
deploy_node_cfg = {}
|
||||
deploy_node_cfg.update({'hostid':host_detail['id']})
|
||||
deploy_node_cfg.update({'hostname':host_detail['name']})
|
||||
deploy_node_cfg.update({'nodeip':host_deploy_ip})
|
||||
deploy_node_cfg.update({'MacName':host_deploy_macname})
|
||||
deploy_node_cfg.update({'memmode':memmode})
|
||||
deploy_node_cfg.update({'mgtip':host_mgt_ip})
|
||||
deploy_node_cfg.update({'hostid': host_detail['id']})
|
||||
deploy_node_cfg.update({'hostname': host_detail['name']})
|
||||
deploy_node_cfg.update({'nodeip': host_deploy_ip})
|
||||
deploy_node_cfg.update({'MacName': host_deploy_macname})
|
||||
deploy_node_cfg.update({'memmode': memmode})
|
||||
deploy_node_cfg.update({'mgtip': host_mgt_ip})
|
||||
return deploy_node_cfg
|
||||
|
||||
def get_roles_and_hosts_list(req, cluster_id):
|
||||
|
||||
def get_roles_and_hosts_list(req, cluster_id):
|
||||
roles_id_list = set()
|
||||
hosts_id_list = set()
|
||||
hosts_id_list = set()
|
||||
hosts_list = []
|
||||
|
||||
cluster_networks = daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req,cluster_id)
|
||||
roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
for role in roles:
|
||||
if role['deployment_backend'] != daisy_cmn.zenic_backend_name:
|
||||
continue
|
||||
@ -212,56 +217,62 @@ def get_roles_and_hosts_list(req, cluster_id):
|
||||
for role_host in role_hosts:
|
||||
if role_host['host_id'] not in hosts_id_list:
|
||||
host = daisy_cmn.get_host_detail(req, role_host['host_id'])
|
||||
host_ip = get_host_network_ip(req, host, cluster_networks, 'MANAGEMENT')
|
||||
host_ip = get_host_network_ip(
|
||||
req, host, cluster_networks, 'MANAGEMENT')
|
||||
hosts_id_list.add(host['id'])
|
||||
|
||||
|
||||
host_cfg = {}
|
||||
host_cfg['mgtip'] = host_ip
|
||||
host_cfg['rootpwd'] = host['root_pwd']
|
||||
hosts_list.append(host_cfg)
|
||||
|
||||
|
||||
roles_id_list.add(role['id'])
|
||||
|
||||
|
||||
return (roles_id_list, hosts_list)
|
||||
|
||||
|
||||
|
||||
def check_and_get_zenic_version(daisy_zenic_pkg_path):
|
||||
zenic_version_pkg_file = ""
|
||||
zenic_version_pkg_name = ""
|
||||
get_zenic_version_pkg = "ls %s| grep ^ZENIC.*\.zip$" % daisy_zenic_pkg_path
|
||||
obj = subprocess.Popen(get_zenic_version_pkg,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
if stdoutput:
|
||||
zenic_version_pkg_name = stdoutput.split('\n')[0]
|
||||
zenic_version_pkg_file = daisy_zenic_pkg_path + zenic_version_pkg_name
|
||||
chmod_for_zenic_version = 'chmod +x %s' % zenic_version_pkg_file
|
||||
daisy_cmn.subprocess_call(chmod_for_zenic_version)
|
||||
return (zenic_version_pkg_file,zenic_version_pkg_name)
|
||||
|
||||
return (zenic_version_pkg_file, zenic_version_pkg_name)
|
||||
|
||||
|
||||
class ZenicShellExector():
|
||||
|
||||
"""
|
||||
Class config task before install zenic bin.
|
||||
"""
|
||||
def __init__(self, mgt_ip, task_type, params={}):
|
||||
|
||||
def __init__(self, mgt_ip, task_type, params={}):
|
||||
self.task_type = task_type
|
||||
self.mgt_ip = mgt_ip
|
||||
self.params = params
|
||||
self.clush_cmd = ""
|
||||
self.clush_cmd = ""
|
||||
self.PKG_NAME = self.params['pkg_name']
|
||||
self.PKG_PATH = daisy_zenic_path + self.PKG_NAME
|
||||
self.CFG_PATH =daisy_zenic_path + mgt_ip + "_zenic.conf"
|
||||
self.PKG_PATH = daisy_zenic_path + self.PKG_NAME
|
||||
self.CFG_PATH = daisy_zenic_path + mgt_ip + "_zenic.conf"
|
||||
self.oper_type = {
|
||||
'install' : self._install_pkg
|
||||
'install': self._install_pkg
|
||||
}
|
||||
self.oper_shell = {
|
||||
'CMD_SSHPASS_PRE' : "sshpass -p ossdbg1 %(ssh_ip)s %(cmd)s",
|
||||
'CMD_CFG_SCP' : "scp %(path)s root@%(ssh_ip)s:/etc/zenic/config" %
|
||||
{'path': self.CFG_PATH, 'ssh_ip':mgt_ip},
|
||||
'CMD_PKG_UNZIP' : "unzip /home/workspace/%(pkg_name)s -d /home/workspace/PKG" % {'pkg_name':self.PKG_NAME},
|
||||
'CMD_PKG_SCP' : "scp %(path)s root@%(ssh_ip)s:/home/workspace/" %
|
||||
{'path': self.PKG_PATH, 'ssh_ip':mgt_ip}
|
||||
'CMD_SSHPASS_PRE': "sshpass -p ossdbg1 %(ssh_ip)s %(cmd)s",
|
||||
'CMD_CFG_SCP': "scp %(path)s root@%(ssh_ip)s:/etc/zenic/config" %
|
||||
{'path': self.CFG_PATH, 'ssh_ip': mgt_ip},
|
||||
'CMD_PKG_UNZIP': "unzip /home/workspace/%(pkg_name)s \
|
||||
-d /home/workspace/PKG" % {'pkg_name': self.PKG_NAME},
|
||||
'CMD_PKG_SCP': "scp %(path)s root@%(ssh_ip)s:/home/workspace/" %
|
||||
{'path': self.PKG_PATH, 'ssh_ip': mgt_ip}
|
||||
}
|
||||
|
||||
self._execute()
|
||||
@ -270,31 +281,39 @@ class ZenicShellExector():
|
||||
if not os.path.exists(self.CFG_PATH):
|
||||
LOG.error(_("<<<CFG %s not exist>>>" % self.CFG_PATH))
|
||||
return
|
||||
|
||||
|
||||
if not os.path.exists(self.PKG_PATH):
|
||||
LOG.error(_("<<<PKG %s not exist>>>" % self.PKG_PATH))
|
||||
return
|
||||
|
||||
self.clush_cmd = "%s;%s;%s" % \
|
||||
(self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip":"", "cmd":self.oper_shell['CMD_PKG_SCP']}, \
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip":"", "cmd":self.oper_shell['CMD_CFG_SCP']}, \
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip":"ssh " + self.mgt_ip, "cmd":self.oper_shell['CMD_PKG_UNZIP']})
|
||||
|
||||
subprocess.check_output(self.clush_cmd, shell = True, stderr=subprocess.STDOUT)
|
||||
self.clush_cmd = "%s;%s;%s" % \
|
||||
(self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip": "", "cmd": self.oper_shell['CMD_PKG_SCP']},
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip": "", "cmd": self.oper_shell['CMD_CFG_SCP']},
|
||||
self.oper_shell['CMD_SSHPASS_PRE'] %
|
||||
{"ssh_ip": "ssh " + self.mgt_ip, "cmd": self.oper_shell[
|
||||
'CMD_PKG_UNZIP']})
|
||||
|
||||
subprocess.check_output(
|
||||
self.clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
|
||||
def _execute(self):
|
||||
try:
|
||||
if not self.task_type or not self.mgt_ip :
|
||||
LOG.error(_("<<<ZenicShellExector::execute, input params invalid!>>>"))
|
||||
if not self.task_type or not self.mgt_ip:
|
||||
LOG.error(
|
||||
_("<<<ZenicShellExector::execute, \
|
||||
input params invalid!>>>"))
|
||||
return
|
||||
|
||||
self.oper_type[self.task_type]()
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.warn(_("<<<ZenicShellExector::execute:Execute command failed! Reason:%s>>>" % e.output.strip()))
|
||||
LOG.warn(
|
||||
_("<<<ZenicShellExector::execute:Execute command failed! Reason\
|
||||
:%s>>>" % e.output.strip()))
|
||||
except Exception as e:
|
||||
LOG.exception(_(e.message))
|
||||
else:
|
||||
LOG.info(_("<<<ZenicShellExector::execute:Execute command:%s,successful!>>>" % self.clush_cmd))
|
||||
LOG.info(
|
||||
_("<<<ZenicShellExector::execute:Execute command:\
|
||||
%s,successful!>>>" % self.clush_cmd))
|
||||
|
@ -1,62 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import re
|
||||
import commands
|
||||
import types
|
||||
import subprocess
|
||||
from ConfigParser import ConfigParser
|
||||
from daisy.common import exception
|
||||
|
||||
|
||||
|
||||
default_zenic_conf_template_path = "/var/lib/daisy/zenic/"
|
||||
zenic_conf_template_path = default_zenic_conf_template_path
|
||||
|
||||
|
||||
def update_conf(zenic, key, value):
|
||||
zenic.set("general", key, value)
|
||||
|
||||
|
||||
def get_conf(zenic_conf_file, **kwargs):
|
||||
result = {}
|
||||
if not kwargs:
|
||||
return result
|
||||
return result
|
||||
|
||||
zenic = ConfigParser()
|
||||
zenic.optionxform = str
|
||||
zenic.read(zenic_conf_file)
|
||||
|
||||
result = {key : zenic.get("general", kwargs.get(key, None))
|
||||
result = {key: zenic.get("general", kwargs.get(key, None))
|
||||
for key in kwargs.keys()
|
||||
if zenic.has_option("general", kwargs.get(key, None))}
|
||||
return result
|
||||
|
||||
def get_nodeid(deploy_ip,zbp_ips):
|
||||
|
||||
|
||||
def get_nodeid(deploy_ip, zbp_ips):
|
||||
nodeid = 0
|
||||
i = 0
|
||||
for ip in zbp_ips:
|
||||
if deploy_ip == ip:
|
||||
break
|
||||
else:
|
||||
i=i+1
|
||||
|
||||
i = i + 1
|
||||
|
||||
if i == 0:
|
||||
nodeid = 1
|
||||
elif i == 1:
|
||||
nodeid = 256
|
||||
else:
|
||||
nodeid = i
|
||||
|
||||
|
||||
return nodeid
|
||||
|
||||
|
||||
|
||||
|
||||
def update_zenic_conf(config_data, cluster_conf_path):
|
||||
print "zenic config data is:"
|
||||
import pprint
|
||||
pprint.pprint(config_data)
|
||||
|
||||
|
||||
daisy_zenic_path = zenic_conf_template_path
|
||||
zenic_conf_template_file = os.path.join(daisy_zenic_path, "zenic.conf")
|
||||
if not os.path.exists(cluster_conf_path):
|
||||
os.makedirs(cluster_conf_path)
|
||||
os.makedirs(cluster_conf_path)
|
||||
|
||||
zenic = ConfigParser()
|
||||
zenic.optionxform = str
|
||||
@ -67,15 +64,15 @@ def update_zenic_conf(config_data, cluster_conf_path):
|
||||
if not zbpips:
|
||||
zbpips = ip
|
||||
else:
|
||||
zbpips = zbpips + ',' + ip
|
||||
zbpips = zbpips + ',' + ip
|
||||
update_conf(zenic, 'zbpips', zbpips)
|
||||
update_conf(zenic, 'zbp_node_num', config_data['zbp_node_num'])
|
||||
update_conf(zenic, 'zbp_node_num', config_data['zbp_node_num'])
|
||||
nodelist = '1,256'
|
||||
if len(config_data['zbp_ips']) > 2:
|
||||
for i in range(2,len(config_data['zbp_ips'])):
|
||||
nodelist = nodelist + ',' + 'i'
|
||||
update_conf(zenic, 'zbpnodelist',nodelist)
|
||||
|
||||
for i in range(2, len(config_data['zbp_ips'])):
|
||||
nodelist = nodelist + ',' + 'i'
|
||||
update_conf(zenic, 'zbpnodelist', nodelist)
|
||||
|
||||
zampips = ''
|
||||
for ip in config_data['zamp_ips']:
|
||||
if not zampips:
|
||||
@ -84,52 +81,50 @@ def update_zenic_conf(config_data, cluster_conf_path):
|
||||
zampips = zampips + ',' + ip
|
||||
update_conf(zenic, 'zampips', zampips)
|
||||
update_conf(zenic, 'zamp_node_num', config_data['zamp_node_num'])
|
||||
|
||||
|
||||
mongodbips = ''
|
||||
for ip in config_data['mongodb_ips']:
|
||||
if not mongodbips:
|
||||
mongodbips = ip
|
||||
else:
|
||||
mongodbips = mongodbips + ',' + ip
|
||||
mongodbips = mongodbips + ',' + ip
|
||||
update_conf(zenic, 'mongodbips', mongodbips)
|
||||
update_conf(zenic, 'mongodb_node_num', config_data['mongodb_node_num'])
|
||||
update_conf(zenic, 'mongodb_node_num', config_data['mongodb_node_num'])
|
||||
|
||||
update_conf(zenic, 'zamp_vip', config_data['zamp_vip'])
|
||||
update_conf(zenic, 'mongodb_vip', config_data['mongodb_vip'])
|
||||
|
||||
|
||||
deploy_hosts = config_data['deploy_hosts']
|
||||
for deploy_host in deploy_hosts:
|
||||
for deploy_host in deploy_hosts:
|
||||
nodeip = deploy_host['nodeip']
|
||||
hostname = deploy_host['hostname']
|
||||
MacName = deploy_host['MacName']
|
||||
memmode = deploy_host['memmode']
|
||||
|
||||
update_conf(zenic,'nodeip',nodeip)
|
||||
update_conf(zenic,'hostname',hostname)
|
||||
update_conf(zenic,'MacName',MacName)
|
||||
update_conf(zenic,'memmode',memmode)
|
||||
|
||||
nodeid = get_nodeid(nodeip,config_data['zbp_ips'])
|
||||
update_conf(zenic,'nodeid',nodeid)
|
||||
|
||||
update_conf(zenic, 'nodeip', nodeip)
|
||||
update_conf(zenic, 'hostname', hostname)
|
||||
update_conf(zenic, 'MacName', MacName)
|
||||
update_conf(zenic, 'memmode', memmode)
|
||||
|
||||
nodeid = get_nodeid(nodeip, config_data['zbp_ips'])
|
||||
update_conf(zenic, 'nodeid', nodeid)
|
||||
|
||||
if nodeip in config_data['zamp_ips']:
|
||||
update_conf(zenic,'needzamp','y')
|
||||
update_conf(zenic, 'needzamp', 'y')
|
||||
else:
|
||||
update_conf(zenic,'needzamp','n')
|
||||
|
||||
update_conf(zenic, 'needzamp', 'n')
|
||||
|
||||
zenic_conf = "%s_zenic.conf" % deploy_host['mgtip']
|
||||
zenic_conf_cluster_out = os.path.join(cluster_conf_path, zenic_conf)
|
||||
zenic_conf_out = os.path.join(daisy_zenic_path, zenic_conf)
|
||||
zenic_conf_out = os.path.join(daisy_zenic_path, zenic_conf)
|
||||
zenic.write(open(zenic_conf_cluster_out, "w+"))
|
||||
|
||||
with open(zenic_conf_cluster_out,'r') as fr,open(zenic_conf_out,'w') as fw:
|
||||
with open(zenic_conf_cluster_out, 'r') as fr,\
|
||||
open(zenic_conf_out, 'w') as fw:
|
||||
for line in fr.readlines():
|
||||
fw.write(line.replace(' ', ''))
|
||||
return
|
||||
|
||||
|
||||
|
||||
def test():
|
||||
print("Hello, world!")
|
||||
|
@ -16,43 +16,23 @@
|
||||
"""
|
||||
/install endpoint for zenic API
|
||||
"""
|
||||
import os
|
||||
import copy
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import traceback
|
||||
import webob.exc
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPServerError
|
||||
|
||||
from threading import Thread, Lock
|
||||
import threading
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.backends.zenic import config
|
||||
from daisy.api.backends import driver
|
||||
from daisy.api.network_api import network as neutron
|
||||
from ironicclient import client as ironic_client
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.zenic.common as zenic_cmn
|
||||
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
@ -76,21 +56,24 @@ CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
host_os_status = {
|
||||
'INIT' : 'init',
|
||||
'INSTALLING' : 'installing',
|
||||
'ACTIVE' : 'active',
|
||||
'INIT': 'init',
|
||||
'INSTALLING': 'installing',
|
||||
'ACTIVE': 'active',
|
||||
'FAILED': 'install-failed'
|
||||
}
|
||||
|
||||
zenic_state = zenic_cmn.ZENIC_STATE
|
||||
daisy_zenic_path = zenic_cmn.daisy_zenic_path
|
||||
|
||||
install_zenic_progress=0.0
|
||||
install_zenic_progress = 0.0
|
||||
install_mutex = threading.Lock()
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.0):
|
||||
|
||||
def update_progress_to_db(req, role_id_list,
|
||||
status, progress_percentage_step=0.0):
|
||||
"""
|
||||
Write install progress and status to db, we use global lock object 'install_mutex'
|
||||
Write install progress and status to db,
|
||||
we use global lock object 'install_mutex'
|
||||
to make sure this function is thread safety.
|
||||
:param req: http req.
|
||||
:param role_id_list: Column neeb be update in role table.
|
||||
@ -107,7 +90,7 @@ def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.
|
||||
if 0 == cmp(status, zenic_state['INSTALLING']):
|
||||
role['status'] = status
|
||||
role['progress'] = install_zenic_progress
|
||||
if 0 == cmp(status, zenic_state['INSTALL_FAILED']):
|
||||
if 0 == cmp(status, zenic_state['INSTALL_FAILED']):
|
||||
role['status'] = status
|
||||
elif 0 == cmp(status, zenic_state['ACTIVE']):
|
||||
role['status'] = status
|
||||
@ -115,21 +98,26 @@ def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.
|
||||
daisy_cmn.update_role(req, role_id, role)
|
||||
install_mutex.release()
|
||||
|
||||
|
||||
def _ping_hosts_test(ips):
|
||||
ping_cmd = 'fping'
|
||||
for ip in set(ips):
|
||||
ping_cmd = ping_cmd + ' ' + ip
|
||||
obj = subprocess.Popen(ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
obj = subprocess.Popen(
|
||||
ping_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(stdoutput, erroutput) = obj.communicate()
|
||||
_returncode = obj.returncode
|
||||
if _returncode == 0 or _returncode == 1:
|
||||
ping_result = stdoutput.split('\n')
|
||||
unreachable_hosts = [result.split()[0] for result in ping_result if result and result.split()[2] != 'alive']
|
||||
unreachable_hosts = [result.split(
|
||||
)[0] for result in ping_result if result and
|
||||
result.split()[2] != 'alive']
|
||||
else:
|
||||
msg = "ping failed beaceuse there is invlid ip in %s" % ips
|
||||
raise exception.InvalidIP(msg)
|
||||
return unreachable_hosts
|
||||
|
||||
|
||||
def _check_ping_hosts(ping_ips, max_ping_times):
|
||||
if not ping_ips:
|
||||
LOG.info(_("no ip got for ping test"))
|
||||
@ -145,9 +133,11 @@ def _check_ping_hosts(ping_ips, max_ping_times):
|
||||
|
||||
ping_count += 1
|
||||
if ips:
|
||||
LOG.debug(_("ping host %s for %s times" % (','.join(ips), ping_count)))
|
||||
LOG.debug(
|
||||
_("ping host %s for %s times" % (','.join(ips), ping_count)))
|
||||
if ping_count >= max_ping_times:
|
||||
LOG.info(_("ping host %s timeout for %ss" % (','.join(ips), ping_count*time_step)))
|
||||
LOG.info(_("ping host %s timeout for %ss" %
|
||||
(','.join(ips), ping_count * time_step)))
|
||||
return ips
|
||||
time.sleep(time_step)
|
||||
else:
|
||||
@ -155,13 +145,15 @@ def _check_ping_hosts(ping_ips, max_ping_times):
|
||||
time.sleep(120)
|
||||
LOG.info(_("120s after ping host %s success" % ','.join(ping_ips)))
|
||||
return ips
|
||||
|
||||
|
||||
|
||||
def _get_host_private_networks(host_detail, cluster_private_networks_name):
|
||||
host_private_networks = [hi for pn in cluster_private_networks_name
|
||||
for hi in host_detail['interfaces'] if pn in hi['assigned_networks']]
|
||||
|
||||
# If port type is bond,use pci segment of member port replace pci1 & pci2 segments of bond port
|
||||
for hi in
|
||||
host_detail['interfaces'] if pn in
|
||||
hi['assigned_networks']]
|
||||
# If port type is bond,use pci segment of member port replace pci1 & pci2
|
||||
# segments of bond port
|
||||
for interface_outer in host_private_networks:
|
||||
if 0 != cmp(interface_outer.get('type', None), "bond"):
|
||||
continue
|
||||
@ -180,38 +172,41 @@ def _get_host_private_networks(host_detail, cluster_private_networks_name):
|
||||
|
||||
def get_cluster_zenic_config(req, cluster_id):
|
||||
LOG.info(_("get zenic config from database..."))
|
||||
params = dict(limit=1000000)
|
||||
|
||||
# params = dict(limit=1000000)
|
||||
|
||||
zenic_config = {}
|
||||
|
||||
|
||||
deploy_hosts = []
|
||||
deploy_host_cfg = {}
|
||||
|
||||
mgt_ip = ''
|
||||
zbp_ip_list = set()
|
||||
mgt_ip_list = set()
|
||||
|
||||
|
||||
zamp_ip_list = set()
|
||||
zamp_vip = ''
|
||||
|
||||
|
||||
mongodb_ip_list = set()
|
||||
mongodb_vip= ''
|
||||
mongodb_vip = ''
|
||||
|
||||
cluster_networks = daisy_cmn.get_cluster_networks_detail(req, cluster_id)
|
||||
|
||||
all_roles = zenic_cmn.get_roles_detail(req)
|
||||
|
||||
roles = [role for role in all_roles if (role['cluster_id'] == cluster_id and role['deployment_backend'] == daisy_cmn.zenic_backend_name)]
|
||||
for role in roles:
|
||||
|
||||
all_roles = zenic_cmn.get_roles_detail(req)
|
||||
|
||||
roles = [role for role in all_roles if (role['cluster_id'] ==
|
||||
cluster_id and role[
|
||||
'deployment_backend'] ==
|
||||
daisy_cmn.zenic_backend_name)]
|
||||
for role in roles:
|
||||
if not (role['name'] == 'ZENIC_CTL' or role['name'] == 'ZENIC_NFM'):
|
||||
continue
|
||||
if role['name'] == 'ZENIC_NFM':
|
||||
if role['name'] == 'ZENIC_NFM':
|
||||
if not zamp_vip:
|
||||
zamp_vip = role['vip']
|
||||
zamp_vip = role['vip']
|
||||
if not mongodb_vip:
|
||||
mongodb_vip = role['mongodb_vip']
|
||||
mongodb_vip = role['mongodb_vip']
|
||||
role_hosts = zenic_cmn.get_hosts_of_role(req, role['id'])
|
||||
|
||||
|
||||
for role_host in role_hosts:
|
||||
mgt_ip = ''
|
||||
for deploy_host in deploy_hosts:
|
||||
@ -220,139 +215,157 @@ def get_cluster_zenic_config(req, cluster_id):
|
||||
deploy_ip = deploy_host['nodeip']
|
||||
break
|
||||
if not mgt_ip:
|
||||
host_detail = zenic_cmn.get_host_detail(req, role_host['host_id'])
|
||||
deploy_host_cfg = zenic_cmn.get_deploy_node_cfg(req, host_detail, cluster_networks)
|
||||
host_detail = zenic_cmn.get_host_detail(
|
||||
req, role_host['host_id'])
|
||||
deploy_host_cfg = zenic_cmn.get_deploy_node_cfg(
|
||||
req, host_detail, cluster_networks)
|
||||
deploy_hosts.append(deploy_host_cfg)
|
||||
mgt_ip = deploy_host_cfg['mgtip']
|
||||
deploy_ip = deploy_host_cfg['nodeip']
|
||||
|
||||
|
||||
mgt_ip_list.add(mgt_ip)
|
||||
if role['name'] == 'ZENIC_CTL':
|
||||
if role['name'] == 'ZENIC_CTL':
|
||||
zbp_ip_list.add(deploy_ip)
|
||||
elif role['name'] == 'ZENIC_NFM':
|
||||
zamp_ip_list.add(deploy_ip)
|
||||
mongodb_ip_list.add(deploy_ip)
|
||||
mongodb_ip_list.add(deploy_ip)
|
||||
else:
|
||||
LOG.warn(_("<<<Zenic Install role %s is invalid >>>" % role['name']))
|
||||
LOG.warn(
|
||||
_("<<<Zenic Install role %s is invalid >>>"
|
||||
% role['name']))
|
||||
|
||||
zenic_config.update({'deploy_hosts':deploy_hosts})
|
||||
zenic_config.update({'zbp_ips':zbp_ip_list})
|
||||
zenic_config.update({'zbp_node_num':len(zbp_ip_list)})
|
||||
zenic_config.update({'zamp_ips':zamp_ip_list})
|
||||
zenic_config.update({'zamp_node_num':len(zamp_ip_list)})
|
||||
zenic_config.update({'mongodb_ips':mongodb_ip_list})
|
||||
zenic_config.update({'mongodb_node_num':len(mongodb_ip_list)})
|
||||
zenic_config.update({'zamp_vip':zamp_vip})
|
||||
zenic_config.update({'mongodb_vip':mongodb_vip})
|
||||
zenic_config.update({'deploy_hosts': deploy_hosts})
|
||||
zenic_config.update({'zbp_ips': zbp_ip_list})
|
||||
zenic_config.update({'zbp_node_num': len(zbp_ip_list)})
|
||||
zenic_config.update({'zamp_ips': zamp_ip_list})
|
||||
zenic_config.update({'zamp_node_num': len(zamp_ip_list)})
|
||||
zenic_config.update({'mongodb_ips': mongodb_ip_list})
|
||||
zenic_config.update({'mongodb_node_num': len(mongodb_ip_list)})
|
||||
zenic_config.update({'zamp_vip': zamp_vip})
|
||||
zenic_config.update({'mongodb_vip': mongodb_vip})
|
||||
return (zenic_config, mgt_ip_list)
|
||||
|
||||
|
||||
|
||||
def generate_zenic_config_file(cluster_id, zenic_config):
|
||||
LOG.info(_("generate zenic config..."))
|
||||
if zenic_config:
|
||||
cluster_conf_path = daisy_zenic_path + cluster_id
|
||||
config.update_zenic_conf(zenic_config, cluster_conf_path)
|
||||
|
||||
def thread_bin(req,host, role_id_list, pkg_name, install_progress_percentage):
|
||||
|
||||
|
||||
def thread_bin(req, host, role_id_list, pkg_name, install_progress_percentage):
|
||||
host_ip = host['mgtip']
|
||||
password = host['rootpwd']
|
||||
|
||||
|
||||
cmd = 'mkdir -p /var/log/daisy/daisy_install/'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
|
||||
var_log_path = "/var/log/daisy/daisy_install/%s_install_zenic.log" % host_ip
|
||||
|
||||
var_log_path =\
|
||||
"/var/log/daisy/daisy_install/%s_install_zenic.log" % host_ip
|
||||
with open(var_log_path, "w+") as fp:
|
||||
|
||||
cmd = '/var/lib/daisy/zenic/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s mkdir -p /home/workspace' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s mkdir -p /etc/zenic' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s rm -rf /etc/zenic/config' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/zenic' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/unipack' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
pkg_file = daisy_zenic_path + pkg_name
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/%s' % (host_ip,pkg_name)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/%s' % (
|
||||
host_ip, pkg_name)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
|
||||
cfg_file = daisy_zenic_path + host_ip + "_zenic.conf"
|
||||
cfg_file = daisy_zenic_path + host_ip + "_zenic.conf"
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/etc/zenic/config' % (cfg_file,host_ip,),
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/etc/zenic/config' % (
|
||||
cfg_file, host_ip,),
|
||||
shell=True, stderr=fp)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
LOG.info(_("scp zenic pkg for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
exit()
|
||||
else:
|
||||
else:
|
||||
LOG.info(_("scp zenic config for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
fp.write(exc_result)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/home/workspace/' % (pkg_file,host_ip,),
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/home/workspace/' % (
|
||||
pkg_file, host_ip,),
|
||||
shell=True, stderr=fp)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
LOG.info(_("scp zenic pkg for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
exit()
|
||||
else:
|
||||
else:
|
||||
LOG.info(_("scp zenic pkg for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
cmd = 'clush -S -b -w %s unzip /home/workspace/%s -d /home/workspace/unipack' % (host_ip,pkg_name,)
|
||||
|
||||
cmd = 'clush -S -b -w %s unzip /home/workspace/%s \
|
||||
-d /home/workspace/unipack' % (
|
||||
host_ip, pkg_name,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -b -w %s /home/workspace/unipack/node_install.sh' % (host_ip,),
|
||||
'clush -S -b -w %s /home/workspace/unipack/node_install.sh'
|
||||
% (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
LOG.info(_("install zenic for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
exit()
|
||||
else:
|
||||
else:
|
||||
LOG.info(_("install zenic for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -b -w %s /home/zenic/node_start.sh' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
LOG.info(_("start zenic for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
exit()
|
||||
else:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALLING'], install_progress_percentage)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALLING'],
|
||||
install_progress_percentage)
|
||||
LOG.info(_("start zenic for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
|
||||
|
||||
class ZENICInstallTask(Thread):
|
||||
|
||||
"""
|
||||
Class for install tecs bin.
|
||||
"""
|
||||
""" Definition for install states."""
|
||||
INSTALL_STATES = {
|
||||
'INIT' : 'init',
|
||||
'INSTALLING' : 'installing',
|
||||
'ACTIVE' : 'active',
|
||||
'INIT': 'init',
|
||||
'INSTALLING': 'installing',
|
||||
'ACTIVE': 'active',
|
||||
'FAILED': 'install-failed'
|
||||
}
|
||||
|
||||
@ -371,9 +384,6 @@ class ZENICInstallTask(Thread):
|
||||
self.ping_times = 36
|
||||
self.log_file = "/var/log/daisy/zenic_%s_install.log" % self.cluster_id
|
||||
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self._run()
|
||||
@ -388,40 +398,47 @@ class ZENICInstallTask(Thread):
|
||||
self.state = zenic_state['ACTIVE']
|
||||
self.message = "Zenic install successfully"
|
||||
LOG.info(_("install Zenic for cluster %s successfully."
|
||||
% self.cluster_id))
|
||||
|
||||
% self.cluster_id))
|
||||
|
||||
def _run(self):
|
||||
|
||||
(zenic_config, self.mgt_ip_list) = get_cluster_zenic_config(self.req, self.cluster_id)
|
||||
|
||||
(zenic_config, self.mgt_ip_list) = get_cluster_zenic_config(
|
||||
self.req, self.cluster_id)
|
||||
|
||||
if not self.mgt_ip_list:
|
||||
msg = _("there is no host in cluster %s") % self.cluster_id
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
raise exception.ThreadBinException(msg)
|
||||
|
||||
unreached_hosts = _check_ping_hosts(self.mgt_ip_list, self.ping_times)
|
||||
if unreached_hosts:
|
||||
self.state = zenic_state['INSTALL_FAILED']
|
||||
self.message = "hosts %s ping failed" % unreached_hosts
|
||||
raise exception.NotFound(message=self.message)
|
||||
|
||||
|
||||
generate_zenic_config_file(self.cluster_id, zenic_config)
|
||||
|
||||
|
||||
# check and get ZENIC version
|
||||
(zenic_version_pkg_file,zenic_version_pkg_name) = zenic_cmn.check_and_get_zenic_version(daisy_zenic_path)
|
||||
if not zenic_version_pkg_file:
|
||||
(zenic_version_pkg_file, zenic_version_pkg_name) =\
|
||||
zenic_cmn.check_and_get_zenic_version(
|
||||
daisy_zenic_path)
|
||||
if not zenic_version_pkg_file:
|
||||
self.state = zenic_state['INSTALL_FAILED']
|
||||
self.message = "ZENIC version file not found in %s" % daisy_zenic_path
|
||||
self.message = \
|
||||
"ZENIC version file not found in %s" % daisy_zenic_path
|
||||
raise exception.NotFound(message=self.message)
|
||||
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(self.req, self.cluster_id)
|
||||
|
||||
update_progress_to_db(self.req, role_id_list, zenic_state['INSTALLING'], 0.0)
|
||||
install_progress_percentage = round(1*1.0/len(hosts_list), 2)*100
|
||||
|
||||
|
||||
(role_id_list, hosts_list) = zenic_cmn.get_roles_and_hosts_list(
|
||||
self.req, self.cluster_id)
|
||||
|
||||
update_progress_to_db(
|
||||
self.req, role_id_list, zenic_state['INSTALLING'], 0.0)
|
||||
install_progress_percentage = round(1 * 1.0 / len(hosts_list), 2) * 100
|
||||
|
||||
threads = []
|
||||
for host in hosts_list:
|
||||
t = threading.Thread(target=thread_bin,args=(self.req,host,role_id_list,zenic_version_pkg_name,install_progress_percentage))
|
||||
t = threading.Thread(target=thread_bin, args=(
|
||||
self.req, host, role_id_list,
|
||||
zenic_version_pkg_name, install_progress_percentage))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
threads.append(t)
|
||||
@ -437,14 +454,16 @@ class ZENICInstallTask(Thread):
|
||||
for role_id in role_id_list:
|
||||
role = daisy_cmn.get_role_detail(self.req, role_id)
|
||||
if role['progress'] == 0:
|
||||
update_progress_to_db(self.req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
self.req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
install_failed_flag = True
|
||||
break
|
||||
if role['status'] == zenic_state['INSTALL_FAILED']:
|
||||
install_failed_flag = True
|
||||
break
|
||||
if not install_failed_flag:
|
||||
LOG.info(_("all install threads have done, set all roles status to 'active'!"))
|
||||
update_progress_to_db(self.req, role_id_list, zenic_state['ACTIVE'])
|
||||
|
||||
|
||||
LOG.info(
|
||||
_("all install threads have done, \
|
||||
set all roles status to 'active'!"))
|
||||
update_progress_to_db(
|
||||
self.req, role_id_list, zenic_state['ACTIVE'])
|
||||
|
@ -17,30 +17,12 @@
|
||||
/hosts endpoint for Daisy v1 API
|
||||
"""
|
||||
|
||||
import os
|
||||
import webob.exc
|
||||
|
||||
import subprocess
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread, Lock
|
||||
import threading
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
from daisy.api.backends.zenic.common import ZenicShellExector
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.zenic.common as zenic_cmn
|
||||
|
||||
@ -52,12 +34,15 @@ _LW = i18n._LW
|
||||
|
||||
zenic_state = zenic_cmn.ZENIC_STATE
|
||||
|
||||
uninstall_zenic_progress=100.0
|
||||
uninstall_zenic_progress = 100.0
|
||||
uninstall_mutex = threading.Lock()
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.0):
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status,
|
||||
progress_percentage_step=0.0):
|
||||
"""
|
||||
Write uninstall progress and status to db, we use global lock object 'uninstall_mutex'
|
||||
Write uninstall progress and status to db,
|
||||
we use global lock object 'uninstall_mutex'
|
||||
to make sure this function is thread safety.
|
||||
:param req: http req.
|
||||
:param role_id_list: Column neeb be update in role table.
|
||||
@ -74,33 +59,36 @@ def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.
|
||||
if 0 == cmp(status, zenic_state['UNINSTALLING']):
|
||||
role['status'] = status
|
||||
role['progress'] = uninstall_zenic_progress
|
||||
if 0 == cmp(status, zenic_state['UNINSTALL_FAILED']):
|
||||
if 0 == cmp(status, zenic_state['UNINSTALL_FAILED']):
|
||||
role['status'] = status
|
||||
elif 0 == cmp(status, zenic_state['INIT']):
|
||||
role['status'] = status
|
||||
role['progress'] = 0
|
||||
daisy_cmn.update_role(req, role_id, role)
|
||||
uninstall_mutex.release()
|
||||
|
||||
def thread_bin(req, host, role_id_list,uninstall_progress_percentage):
|
||||
|
||||
|
||||
def thread_bin(req, host, role_id_list, uninstall_progress_percentage):
|
||||
host_ip = host['mgtip']
|
||||
password = host['rootpwd']
|
||||
cmd = 'mkdir -p /var/log/daisy/daisy_uninstall/'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
var_log_path = "/var/log/daisy/daisy_uninstall/%s_uninstall_zenic.log" % host_ip
|
||||
var_log_path =\
|
||||
"/var/log/daisy/daisy_uninstall/%s_uninstall_zenic.log" % host_ip
|
||||
with open(var_log_path, "w+") as fp:
|
||||
cmd = '/var/lib/daisy/zenic/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -b -w %s /home/zenic/node_stop.sh' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UNINSTALL_FAILED'])
|
||||
fp.write(e.output.strip())
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UNINSTALL_FAILED'])
|
||||
fp.write(e.output.strip())
|
||||
else:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UNINSTALLING'], uninstall_progress_percentage)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UNINSTALLING'],
|
||||
uninstall_progress_percentage)
|
||||
fp.write(exc_result)
|
||||
|
||||
|
||||
|
@ -17,30 +17,13 @@
|
||||
/update endpoint for Daisy v1 API
|
||||
"""
|
||||
|
||||
import os
|
||||
import webob.exc
|
||||
import subprocess
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from threading import Thread, Lock
|
||||
import threading
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
from daisy.api.backends.zenic.common import ZenicShellExector
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
import daisy.api.backends.zenic.common as zenic_cmn
|
||||
|
||||
@ -54,12 +37,15 @@ zenic_state = zenic_cmn.ZENIC_STATE
|
||||
daisy_zenic_path = zenic_cmn.daisy_zenic_path
|
||||
|
||||
|
||||
update_zenic_progress=0.0
|
||||
update_zenic_progress = 0.0
|
||||
update_mutex = threading.Lock()
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.0):
|
||||
|
||||
def update_progress_to_db(req, role_id_list, status,
|
||||
progress_percentage_step=0.0):
|
||||
"""
|
||||
Write update progress and status to db, we use global lock object 'update_mutex'
|
||||
Write update progress and status to db,
|
||||
we use global lock object 'update_mutex'
|
||||
to make sure this function is thread safety.
|
||||
:param req: http req.
|
||||
:param role_id_list: Column neeb be update in role table.
|
||||
@ -76,7 +62,7 @@ def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.
|
||||
if 0 == cmp(status, zenic_state['UPDATING']):
|
||||
role['status'] = status
|
||||
role['progress'] = update_zenic_progress
|
||||
if 0 == cmp(status, zenic_state['UPDATE_FAILED']):
|
||||
if 0 == cmp(status, zenic_state['UPDATE_FAILED']):
|
||||
role['status'] = status
|
||||
elif 0 == cmp(status, zenic_state['ACTIVE']):
|
||||
role['status'] = status
|
||||
@ -85,60 +71,70 @@ def update_progress_to_db(req, role_id_list, status, progress_percentage_step=0.
|
||||
update_mutex.release()
|
||||
|
||||
|
||||
def thread_bin(req, host,role_id_list,update_progress_percentage):
|
||||
def thread_bin(req, host, role_id_list, update_progress_percentage):
|
||||
|
||||
(zenic_version_pkg_file,zenic_version_pkg_name) = zenic_cmn.check_and_get_zenic_version(daisy_zenic_path)
|
||||
(zenic_version_pkg_file, zenic_version_pkg_name) = \
|
||||
zenic_cmn.check_and_get_zenic_version(
|
||||
daisy_zenic_path)
|
||||
if not zenic_version_pkg_file:
|
||||
self.state = zenic_state['INSTALL_FAILED']
|
||||
self.message = "ZENIC version file not found in %s" % daisy_zenic_path
|
||||
raise exception.NotFound(message=self.message)
|
||||
# selfstate = zenic_state['INSTALL_FAILED']
|
||||
selfmessage = "ZENIC version file not found in %s" % daisy_zenic_path
|
||||
raise exception.NotFound(message=selfmessage)
|
||||
|
||||
host_ip = host['mgtip']
|
||||
password = host['rootpwd']
|
||||
|
||||
|
||||
cmd = 'mkdir -p /var/log/daisy/daisy_upgrade/'
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
|
||||
var_log_path = "/var/log/daisy/daisy_upgrade/%s_upgrade_zenic.log" % host_ip
|
||||
var_log_path = \
|
||||
"/var/log/daisy/daisy_upgrade/%s_upgrade_zenic.log" % host_ip
|
||||
with open(var_log_path, "w+") as fp:
|
||||
cmd = '/var/lib/daisy/zenic/trustme.sh %s %s' % (host_ip, password)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
cmd = 'clush -S -b -w %s /home/zenic/node_stop.sh' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/%s' % (host_ip,zenic_version_pkg_name)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/%s' % (
|
||||
host_ip, zenic_version_pkg_name)
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
cmd = 'clush -S -b -w %s rm -rf /home/workspace/unipack' % (host_ip,)
|
||||
daisy_cmn.subprocess_call(cmd,fp)
|
||||
|
||||
daisy_cmn.subprocess_call(cmd, fp)
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/home/workspace/' % (zenic_version_pkg_file,host_ip,),
|
||||
'sshpass -p ossdbg1 scp %s root@%s:/home/workspace/' % (
|
||||
zenic_version_pkg_file, host_ip,),
|
||||
shell=True, stderr=fp)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['INSTALL_FAILED'])
|
||||
LOG.info(_("scp zenic pkg for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
exit()
|
||||
else:
|
||||
else:
|
||||
LOG.info(_("scp zenic pkg for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
cmd = 'clush -S -b -w %s unzip /home/workspace/%s -d /home/workspace/unipack' % (host_ip,zenic_version_pkg_name,)
|
||||
|
||||
cmd = 'clush -S -b -w %s unzip /home/workspace/%s \
|
||||
-d /home/workspace/unipack' % (host_ip, zenic_version_pkg_name,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
|
||||
|
||||
try:
|
||||
exc_result = subprocess.check_output(
|
||||
'clush -S -b -w %s /home/workspace/unipack/node_upgrade.sh' % (host_ip,),
|
||||
'clush -S -b -w %s /home/workspace/unipack/node_upgrade.sh'
|
||||
% (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
LOG.info(_("Upgrade zenic for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
else:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UPDATING'], update_progress_percentage)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATING'],
|
||||
update_progress_percentage)
|
||||
LOG.info(_("Upgrade zenic for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
@ -147,12 +143,13 @@ def thread_bin(req, host,role_id_list,update_progress_percentage):
|
||||
'clush -S -b -w %s /home/zenic/node_start.sh' % (host_ip,),
|
||||
shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATE_FAILED'])
|
||||
LOG.info(_("Start zenic for %s failed!" % host_ip))
|
||||
fp.write(e.output.strip())
|
||||
else:
|
||||
update_progress_to_db(req, role_id_list, zenic_state['UPDATING'], update_progress_percentage)
|
||||
update_progress_to_db(
|
||||
req, role_id_list, zenic_state['UPDATING'],
|
||||
update_progress_percentage)
|
||||
LOG.info(_("Start zenic for %s successfully!" % host_ip))
|
||||
fp.write(exc_result)
|
||||
|
||||
|
||||
|
@ -67,8 +67,8 @@ def size_checked_iter(response, image_meta, expected_size, image_iter,
|
||||
'bytes_written': bytes_written})
|
||||
LOG.error(msg)
|
||||
raise exception.DaisyException(_("Corrupt image download for "
|
||||
"image %(image_id)s") %
|
||||
{'image_id': image_id})
|
||||
"image %(image_id)s") %
|
||||
{'image_id': image_id})
|
||||
|
||||
|
||||
def image_send_notification(bytes_written, expected_size, image_meta, request,
|
||||
@ -218,3 +218,9 @@ def get_thread_pool(lock_name, size=1024):
|
||||
return wsgi.get_asynchronous_eventlet_pool(size=size)
|
||||
|
||||
return _get_thread_pool
|
||||
|
||||
|
||||
def get_pxe_mac(host_detail):
|
||||
pxe_macs = [interface['mac'] for interface in host_detail['interfaces']
|
||||
if interface['is_deployment']]
|
||||
return pxe_macs
|
||||
|
@ -1,30 +1,29 @@
|
||||
|
||||
import subprocess
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.backends.tecs import config
|
||||
from daisy.api.backends.tecs import config as role_service
|
||||
from oslo_log import log as logging
|
||||
import webob.exc
|
||||
from webob.exc import HTTPBadRequest
|
||||
from daisy.common import exception
|
||||
from daisy.common import utils
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONFIG_MAP = {
|
||||
'cinder_config': '/etc/cinder/cinder.conf',
|
||||
'cinder_api_paste_ini': '/etc/cinder/api-paste.ini',
|
||||
'glance_api_config': '/etc/glance/glance-api.conf',
|
||||
'glance_api_paste_ini': '/etc/glance/glance-api-paste.ini',
|
||||
}
|
||||
|
||||
|
||||
class config_clushshell():
|
||||
|
||||
""" Class for clush backend."""
|
||||
def __init__(self, req, role_id):
|
||||
if not req and not role_id:
|
||||
LOG.error("<<<config_clushshell:push_config input params is invalid.>>>")
|
||||
return
|
||||
|
||||
def __init__(self, req):
|
||||
self.context = req.context
|
||||
self.role_id = role_id
|
||||
|
||||
self.CLUSH_CMD = "clush -S -w %(management_ip)s \"%(sub_command)s\""
|
||||
self.SUB_COMMAND = "openstack-config --set %(config_file)s %(section)s %(key)s %(value)s"
|
||||
self.CLUSH_CMD = 'clush -S -w %(management_ip)s "%(sub_command)s"'
|
||||
self.SUB_COMMAND_SET = "openstack-config --set %(config_file)s"\
|
||||
" %(section)s %(key)s '%(value)s'"
|
||||
self.SUB_COMMAND_DEL = "openstack-config --del %(config_file)s"\
|
||||
" %(section)s %(key)s"
|
||||
|
||||
def _openstack_set_config(self, host_ip, config_set):
|
||||
"""
|
||||
@ -37,107 +36,259 @@ class config_clushshell():
|
||||
LOG.debug('<<<FUN:_openstack_set_config input params invalid.>>>')
|
||||
return
|
||||
|
||||
sub_command_by_one_host = []
|
||||
config_cmd = []
|
||||
for config in config_set['config']:
|
||||
if config['config_version'] == config['running_version']:
|
||||
continue
|
||||
|
||||
config_file = registry.get_config_file_metadata(self.context, config['config_file_id'])
|
||||
sub_command_by_one_host.append(
|
||||
self.SUB_COMMAND % \
|
||||
{'config_file':config_file['name'] ,'section':config['section'],
|
||||
'key':config['key'], 'value':config['value']})
|
||||
config_file = registry.get_config_file_metadata(
|
||||
self.context, config['config_file_id'])
|
||||
if config['value']:
|
||||
value = utils.translate_quotation_marks_for_shell(
|
||||
config['value'])
|
||||
config_cmd.append(self.SUB_COMMAND_SET %
|
||||
{'config_file': config_file['name'],
|
||||
'section': config['section'],
|
||||
'key': config['key'],
|
||||
'value': value})
|
||||
else:
|
||||
# if value is empty, delete or comment it.
|
||||
config_cmd.append(self.SUB_COMMAND_DEL %
|
||||
{'config_file': config_file['name'],
|
||||
'section': config['section'],
|
||||
'key': config['key']})
|
||||
|
||||
try:
|
||||
sub_command_by_one_host = ";".join(sub_command_by_one_host)
|
||||
clush_cmd = self.CLUSH_CMD % {'management_ip':host_ip, 'sub_command':sub_command_by_one_host}
|
||||
subprocess.check_output(clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
for cmd in config_cmd:
|
||||
clush_cmd = self.CLUSH_CMD % {
|
||||
'management_ip': host_ip, 'sub_command': cmd}
|
||||
subprocess.check_output(
|
||||
clush_cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
msg = ("<<<Host %s excute clush failed:%s!>>>" % (host_ip, e.output.strip()))
|
||||
msg = ("<<<Host %s excute clush failed:%s.>>>" %
|
||||
(host_ip, e.output.strip()))
|
||||
LOG.exception(msg)
|
||||
raise webob.exc.HTTPServerError(explanation=msg)
|
||||
else:
|
||||
msg = ("<<<Host %s excute clush successful!>>>" % host_ip)
|
||||
msg = ("<<<Complete to push configs for host %s.>>>" % host_ip)
|
||||
LOG.info(msg)
|
||||
config['running_version'] = config['config_version']
|
||||
|
||||
def push_config(self):
|
||||
# if push_status = None, we will push configs
|
||||
# to all hosts in the role
|
||||
def push_role_configs(self, role_id, push_status):
|
||||
"""
|
||||
Push config to remote host.
|
||||
:param req: http req
|
||||
:param role_id: host role id
|
||||
:return:
|
||||
"""
|
||||
self.role_info = registry.get_role_metadata(self.context, self.role_id)
|
||||
if not self.role_info or not self.role_info.get('config_set_id'):
|
||||
LOG.error("<<<config_clushshell:push_config,get_role_metadata failed.>>>")
|
||||
role_info = registry.get_role_metadata(self.context, role_id)
|
||||
if not role_info.get('config_set_id'):
|
||||
LOG.info("<<<No config_set configed for role '%s'>>>"
|
||||
% role_info['name'])
|
||||
return
|
||||
|
||||
config_set = registry.get_config_set_metadata(self.context, self.role_info['config_set_id'])
|
||||
if not config_set or not config_set.has_key('config'):
|
||||
LOG.info("<<<config_clushshell:push_config,get_config_set_metadata failed.>>>")
|
||||
config_set = registry.get_config_set_metadata(
|
||||
self.context, role_info['config_set_id'])
|
||||
if not config_set:
|
||||
LOG.info("<<<Get config_set failed for role '%s'.>>>"
|
||||
% role_info['name'])
|
||||
return
|
||||
else:
|
||||
if 'config' not in config_set:
|
||||
LOG.info("<<<No configs get for role '%s'.>>>"
|
||||
% role_info['name'])
|
||||
return
|
||||
|
||||
config_set['config'] = \
|
||||
[config for config in config_set['config']
|
||||
if config.has_key('config_version') and config.has_key('running_version')
|
||||
and config['config_version'] != config['running_version']]
|
||||
config_set['config'] = [config for config in config_set['config']
|
||||
if config.get('config_version', 0) !=
|
||||
config.get('running_version', 0)]
|
||||
|
||||
if not config_set['config']:
|
||||
LOG.info('<<<No config need to be modified, within the scope of the hosts in role_id:%s.>>>' %
|
||||
self.role_id)
|
||||
LOG.info("<<<No config need to push for role '%s'.>>>"
|
||||
% role_info['name'])
|
||||
return
|
||||
|
||||
self.role_hosts = registry.get_role_host_metadata(self.context, self.role_id)
|
||||
self.role_hosts = registry.get_role_host_metadata(
|
||||
self.context, role_id)
|
||||
|
||||
total_host_count = 0
|
||||
if push_status:
|
||||
for r_host in self.role_hosts:
|
||||
if r_host['status'] == push_status:
|
||||
total_host_count += 1
|
||||
else:
|
||||
total_host_count = len(self.role_hosts)
|
||||
|
||||
if total_host_count > 0:
|
||||
LOG.info("Begin to push config for role '%s'"
|
||||
% role_info['name'])
|
||||
else:
|
||||
return
|
||||
current_count = 0
|
||||
all_host_config_sets = []
|
||||
# all_host_config_sets = []
|
||||
for role_host in self.role_hosts:
|
||||
host = registry.get_host_metadata(self.context, role_host['host_id'])
|
||||
#change by 10166727--------start-------------
|
||||
host_ip=[]
|
||||
host = registry.get_host_metadata(
|
||||
self.context, role_host['host_id'])
|
||||
if push_status and role_host['status'] != push_status:
|
||||
LOG.debug("<<<Status of host '%s' is not '%s',"
|
||||
" don't push configs.>>>"
|
||||
% (role_host['host_id'], push_status))
|
||||
continue
|
||||
|
||||
host_management_ip = ''
|
||||
for interface in host['interfaces']:
|
||||
find_flag=interface['ip'].find(':')
|
||||
if find_flag<0:
|
||||
host_ip=[interface['ip']]
|
||||
else:
|
||||
ip_list_tmp=interface['ip'].split(",")
|
||||
for ip_list in ip_list_tmp:
|
||||
if ip_list.split(':')[0] == "MANAGEMENT":
|
||||
host_ip=[str(ip_list.split(':')[1])]
|
||||
#change by 10166727--------end---------------
|
||||
if not host_ip:
|
||||
continue
|
||||
host_ip = host_ip[0]
|
||||
if ('assigned_networks' in interface and
|
||||
interface['assigned_networks']):
|
||||
for assigned_network in interface['assigned_networks']:
|
||||
if (assigned_network['name'] == 'MANAGEMENT' and
|
||||
'ip' in assigned_network):
|
||||
host_management_ip = assigned_network['ip']
|
||||
|
||||
if 0 != subprocess.call('/var/lib/daisy/tecs/trustme.sh %s %s' % (host_ip, 'ossdbg1'),
|
||||
shell=True,
|
||||
stderr=subprocess.STDOUT):
|
||||
raise Exception("trustme.sh error!")
|
||||
if not config_set.has_key("config"):
|
||||
if not host_management_ip:
|
||||
msg = "Can't find management ip for host %s"\
|
||||
% role_host['host_id']
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
root_passwd = 'ossdbg1'
|
||||
daisy_cmn.trust_me([host_management_ip], root_passwd)
|
||||
|
||||
self._openstack_set_config(host_management_ip, config_set)
|
||||
|
||||
self._role_service_restart(role_info, host_management_ip)
|
||||
|
||||
current_count += 1
|
||||
role_info['config_set_update_progress'] =\
|
||||
round(current_count * 1.0 / total_host_count, 2) * 100
|
||||
registry.update_role_metadata(
|
||||
self.context, role_id, role_info)
|
||||
|
||||
all_config_sets = []
|
||||
for config in config_set['config']:
|
||||
config['running_version'] = config['config_version']
|
||||
all_config_sets.append(config_set)
|
||||
registry.update_configs_metadata_by_role_hosts(
|
||||
self.context, all_config_sets)
|
||||
|
||||
def _host_service_restart(self, host_ip, components_name):
|
||||
params = {'limit': '200', 'filters': {}}
|
||||
try:
|
||||
services = registry.get_services_detail(self.context,
|
||||
**params)
|
||||
components = registry.get_components_detail(self.context,
|
||||
**params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg)
|
||||
|
||||
components_id = [comp['id'] for comp in components
|
||||
for comp_name in components_name
|
||||
if comp['name'] == comp_name]
|
||||
|
||||
for service in services:
|
||||
if service['component_id'] not in components_id:
|
||||
continue
|
||||
|
||||
self._openstack_set_config(host_ip, config_set)
|
||||
all_host_config_sets.append(config_set)
|
||||
registry.update_configs_metadata_by_role_hosts(self.context, all_host_config_sets)
|
||||
services_name = role_service.service_map.get(service['name'])
|
||||
if not services_name:
|
||||
msg = "Can't find service for '%s'" % service
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
LOG.debug("Update config for host:%s successfully!" % host_ip)
|
||||
for service_name in services_name.split(','):
|
||||
active_service = "clush -S -w %s 'systemctl is-active\
|
||||
%s'" % (host_ip, service_name)
|
||||
if 0 == utils.simple_subprocess_call(active_service):
|
||||
restart_service = "clush -S -w %s 'systemctl restart\
|
||||
%s'" % (host_ip, service_name)
|
||||
LOG.info("Restart service %s after pushing config"
|
||||
% service_name)
|
||||
if 0 != utils.simple_subprocess_call(restart_service):
|
||||
msg = "Service %s restart failed on host '%s'."\
|
||||
% (service_name, host_ip)
|
||||
LOG.error(msg)
|
||||
|
||||
self._host_service_restart(host_ip)
|
||||
current_count +=1
|
||||
self.role_info['config_set_update_progress'] = round(current_count*1.0/len(self.role_hosts), 2)*100
|
||||
registry.update_role_metadata(self.context, self.role_id, self.role_info)
|
||||
# now i don't known how to find component id by config file,
|
||||
# so add you must tell me, and it can be deleted if i can find it
|
||||
# in future.
|
||||
def push_host_configs(self, host_id, components_name):
|
||||
"""
|
||||
Push config to remote host.
|
||||
:param req: http req
|
||||
:param host_id: host id
|
||||
:return:
|
||||
"""
|
||||
host_detail = registry.get_host_metadata(self.context, host_id)
|
||||
|
||||
def _host_service_restart(self,host_ip):
|
||||
if not host_detail.get('config_set_id'):
|
||||
LOG.info("<<<No config_set configed for host '%s'.>>>"
|
||||
% host_id)
|
||||
return
|
||||
|
||||
config_set =\
|
||||
registry.get_config_set_metadata(self.context,
|
||||
host_detail['config_set_id'])
|
||||
if not config_set:
|
||||
LOG.info("<<<Get config_set failed for host '%s'.>>>"
|
||||
% host_id)
|
||||
return
|
||||
else:
|
||||
if 'config' not in config_set:
|
||||
LOG.info("<<<No configs get for host '%s'.>>>" % host_id)
|
||||
return
|
||||
|
||||
config_set['config'] = [config for config in config_set['config']
|
||||
if config.get('config_version', 0) !=
|
||||
config.get('running_version', 0)]
|
||||
|
||||
if not config_set['config']:
|
||||
LOG.info("<<<No config need to push for host '%s'.>>>"
|
||||
% host_id)
|
||||
return
|
||||
|
||||
host_management_ip = ''
|
||||
for interface in host_detail['interfaces']:
|
||||
if ('assigned_networks' in interface and
|
||||
interface['assigned_networks']):
|
||||
for assigned_network in interface['assigned_networks']:
|
||||
if (assigned_network['name'] == 'MANAGEMENT' and
|
||||
'ip' in assigned_network):
|
||||
host_management_ip = assigned_network['ip']
|
||||
|
||||
if not host_management_ip:
|
||||
msg = "Can't find management ip for host %s"\
|
||||
% host_detail['host_id']
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
root_passwd = 'ossdbg1'
|
||||
daisy_cmn.trust_me([host_management_ip], root_passwd)
|
||||
|
||||
self._openstack_set_config(host_management_ip, config_set)
|
||||
|
||||
self._host_service_restart(host_management_ip, components_name)
|
||||
|
||||
all_config_sets = []
|
||||
for config in config_set['config']:
|
||||
config['running_version'] = config['config_version']
|
||||
all_config_sets.append(config_set)
|
||||
registry.update_configs_metadata_by_role_hosts(self.context,
|
||||
all_config_sets)
|
||||
|
||||
def _role_service_restart(self, role_info, host_ip):
|
||||
""" """
|
||||
for service in self.role_info['service_name']:
|
||||
for service_detail_name in config.service_map.get(service).split(','):
|
||||
cmd = ""
|
||||
if self.role_info['name'] == "CONTROLLER_HA":
|
||||
cmd = "clush -S -w %s [ `systemctl is-active %s` != 'active' ] && systemctl restart %s" % \
|
||||
(host_ip, service_detail_name, service_detail_name)
|
||||
else:
|
||||
cmd = "clush -S -w %s systemctl restart %s" % (host_ip, service_detail_name)
|
||||
if 0 != subprocess.call(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
|
||||
LOG.error("Service %s restart failed in host:%s." % (service_detail_name, host_ip))
|
||||
for service in role_info['service_name']:
|
||||
services_name = role_service.service_map.get(service)
|
||||
if not services_name:
|
||||
msg = "Can't find service for '%s'" % service
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
|
||||
for service_name in services_name.split(','):
|
||||
active_service = "clush -S -w %s 'systemctl is-active\
|
||||
%s'" % (host_ip, service_name)
|
||||
if 0 == utils.simple_subprocess_call(active_service):
|
||||
restart_service = "clush -S -w %s 'systemctl restart\
|
||||
%s'" % (host_ip, service_name)
|
||||
LOG.info("Restart service %s after pushing config"
|
||||
% service_name)
|
||||
if 0 != utils.simple_subprocess_call(restart_service):
|
||||
msg = "Service %s restart failed on host '%s'."\
|
||||
% (service_name, host_ip)
|
||||
LOG.error(msg)
|
||||
|
@ -1,16 +1,24 @@
|
||||
from daisy.api.configset.clush import config_clushshell
|
||||
|
||||
|
||||
class configBackend():
|
||||
def __init__(self, type, req, role_id):
|
||||
|
||||
def __init__(self, type, req):
|
||||
self.type = type
|
||||
self._instance = None
|
||||
|
||||
|
||||
if type == "clushshell":
|
||||
self._instance = config_clushshell(req, role_id)
|
||||
self._instance = config_clushshell(req)
|
||||
elif type == "puppet":
|
||||
pass
|
||||
|
||||
def push_config(self):
|
||||
self._instance.push_config()
|
||||
|
||||
|
||||
|
||||
# if push_status = None, we will push configs
|
||||
# to all hosts in the role
|
||||
def push_config_by_roles(self, role_ids, push_status=None):
|
||||
for role_id in role_ids:
|
||||
self._instance.push_role_configs(role_id, push_status)
|
||||
|
||||
def push_config_by_hosts(self, host_ids, component_names=[]):
|
||||
for host_id in host_ids:
|
||||
self._instance.push_host_configs(host_id,
|
||||
component_names)
|
||||
|
@ -24,10 +24,12 @@ from neutronclient.v2_0 import client as clientv20
|
||||
from daisy.common import exception
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class network(object):
|
||||
"""
|
||||
network config
|
||||
"""
|
||||
|
||||
def __init__(self, req, neutron_host, keystone_host, cluster_id):
|
||||
registry.configure_registry_client()
|
||||
auth_url = 'http://' + keystone_host + ':35357/v2.0'
|
||||
@ -49,10 +51,12 @@ class network(object):
|
||||
except exception.Invalid as e:
|
||||
LOG.exception(e.msg)
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
LOG.info("<<<CLUSTER:%s,NEUTRON HOST:%s,KEYSTOEN:%s>>>", cluster, neutron_host, keystone_host)
|
||||
if 'logic_networks' in cluster and cluster['logic_networks'] is not None:
|
||||
LOG.info("<<<CLUSTER:%s,NEUTRON HOST:%s,KEYSTOEN:%s>>>",
|
||||
cluster, neutron_host, keystone_host)
|
||||
if 'logic_networks' in cluster and cluster[
|
||||
'logic_networks'] is not None:
|
||||
self.nets = cluster['logic_networks']
|
||||
#self._flat_network_uniqueness_check()
|
||||
# self._flat_network_uniqueness_check()
|
||||
if 'routers' in cluster and cluster['routers'] is not None:
|
||||
self.routers = cluster['routers']
|
||||
else:
|
||||
@ -83,7 +87,9 @@ class network(object):
|
||||
for router in self.routers:
|
||||
router_id = self._router_create(router['name'])
|
||||
if 'external_logic_network' in router:
|
||||
body = {'network_id': self.name_mappings[router['external_logic_network']]}
|
||||
body = {
|
||||
'network_id': self.name_mappings[
|
||||
router['external_logic_network']]}
|
||||
self.neutron.add_gateway_router(router_id, body)
|
||||
if 'subnets' in router:
|
||||
for i in router['subnets']:
|
||||
@ -92,7 +98,8 @@ class network(object):
|
||||
|
||||
def _net_subnet_same_router_check(self, ex_network, subnet):
|
||||
for router in self.routers:
|
||||
if 'external_logic_network' in router and router['external_logic_network'] == ex_network:
|
||||
if 'external_logic_network' in router and router[
|
||||
'external_logic_network'] == ex_network:
|
||||
if 'subnets' in router:
|
||||
for i in router['subnets']:
|
||||
if i == subnet:
|
||||
@ -155,18 +162,25 @@ class network(object):
|
||||
for net in self.nets:
|
||||
body = {}
|
||||
if net['type'] == 'external':
|
||||
body['network'] = {'name': net['name'],
|
||||
'router:external': True,
|
||||
'provider:network_type': net['segmentation_type']}
|
||||
body['network'] = {
|
||||
'name': net['name'],
|
||||
'router:external': True,
|
||||
'provider:network_type': net['segmentation_type']}
|
||||
if net['segmentation_type'].strip() == 'flat':
|
||||
body['network']['provider:physical_network'] = net['physnet_name']
|
||||
body['network']['provider:physical_network'] = net[
|
||||
'physnet_name']
|
||||
elif net['segmentation_type'].strip() == 'vxlan':
|
||||
if 'segmentation_id' in net and net['segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net['segmentation_id']
|
||||
if 'segmentation_id' in net and net[
|
||||
'segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net[
|
||||
'segmentation_id']
|
||||
else:
|
||||
if 'segmentation_id' in net and net['segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net['segmentation_id']
|
||||
body['network']['provider:physical_network'] = net['physnet_name']
|
||||
if 'segmentation_id' in net and net[
|
||||
'segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net[
|
||||
'segmentation_id']
|
||||
body['network']['provider:physical_network'] = net[
|
||||
'physnet_name']
|
||||
if net['shared']:
|
||||
body['network']['shared'] = True
|
||||
else:
|
||||
@ -175,21 +189,28 @@ class network(object):
|
||||
self.name_mappings[net['name']] = external['network']['id']
|
||||
last_create_subnet = []
|
||||
for subnet in net['subnets']:
|
||||
if self._net_subnet_same_router_check(net['name'], subnet['name']):
|
||||
if self._net_subnet_same_router_check(
|
||||
net['name'], subnet['name']):
|
||||
last_create_subnet.append(subnet)
|
||||
else:
|
||||
subnet_id = self._subnet_check_and_create(external['network']['id'], subnet)
|
||||
subnet_id = self._subnet_check_and_create(
|
||||
external['network']['id'], subnet)
|
||||
self.name_mappings[subnet['name']] = subnet_id
|
||||
for subnet in last_create_subnet:
|
||||
subnet_id = self._subnet_check_and_create(external['network']['id'], subnet)
|
||||
subnet_id = self._subnet_check_and_create(
|
||||
external['network']['id'], subnet)
|
||||
self.name_mappings[subnet['name']] = subnet_id
|
||||
else:
|
||||
body['network'] = {'name': net['name'],
|
||||
'provider:network_type': net['segmentation_type']}
|
||||
body['network'] = {
|
||||
'name': net['name'],
|
||||
'provider:network_type': net['segmentation_type']}
|
||||
if net['segmentation_type'].strip() == 'vlan':
|
||||
body['network']['provider:physical_network'] = net['physnet_name']
|
||||
if 'segmentation_id' in net and net['segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net['segmentation_id']
|
||||
body['network']['provider:physical_network'] = net[
|
||||
'physnet_name']
|
||||
if 'segmentation_id' in net and net[
|
||||
'segmentation_id'] is not None:
|
||||
body['network']['provider:segmentation_id'] = net[
|
||||
'segmentation_id']
|
||||
if net['shared']:
|
||||
body['network']['shared'] = True
|
||||
else:
|
||||
@ -197,6 +218,7 @@ class network(object):
|
||||
inner = self.neutron.create_network(body)
|
||||
self.name_mappings[net['name']] = inner['network']['id']
|
||||
for subnet in net['subnets']:
|
||||
subnet_id = self._subnet_check_and_create(inner['network']['id'], subnet)
|
||||
subnet_id = self._subnet_check_and_create(
|
||||
inner['network']['id'], subnet)
|
||||
self.name_mappings[subnet['name']] = subnet_id
|
||||
self._router_link()
|
||||
|
@ -13,9 +13,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
SUPPORTED_FILTERS = ['name', 'status','cluster_id','id','host_id', 'role_id', 'auto_scale','container_format', 'disk_format',
|
||||
SUPPORTED_FILTERS = ['name', 'status', 'cluster_id', 'id',
|
||||
'host_id', 'role_id',
|
||||
'auto_scale', 'container_format', 'disk_format',
|
||||
'min_ram', 'min_disk', 'size_min', 'size_max',
|
||||
'is_public', 'changes-since', 'protected']
|
||||
'is_public', 'changes-since', 'protected', 'type']
|
||||
|
||||
SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
|
||||
|
||||
|
312
code/daisy/daisy/api/v1/backup_restore.py
Executable file
312
code/daisy/daisy/api/v1/backup_restore.py
Executable file
@ -0,0 +1,312 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/hosts endpoint for Daisy v1 API
|
||||
"""
|
||||
import datetime
|
||||
import os
|
||||
import subprocess
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
SUPPORTED_PARAMS = daisy.api.v1.SUPPORTED_PARAMS
|
||||
SUPPORTED_FILTERS = daisy.api.v1.SUPPORTED_FILTERS
|
||||
ACTIVE_IMMUTABLE = daisy.api.v1.ACTIVE_IMMUTABLE
|
||||
BACK_PATH = '/home/daisy_backup/'
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for hosts resource in Daisy v1 API
|
||||
|
||||
The hosts resource API is a RESTful web service for host data. The API
|
||||
is as follows::
|
||||
|
||||
GET /hosts -- Returns a set of brief metadata about hosts
|
||||
GET /hosts/detail -- Returns a set of detailed metadata about
|
||||
hosts
|
||||
HEAD /hosts/<ID> -- Return metadata about an host with id <ID>
|
||||
GET /hosts/<ID> -- Return host data for host with id <ID>
|
||||
POST /hosts -- Store host data and return metadata about the
|
||||
newly-stored host
|
||||
PUT /hosts/<ID> -- Update host metadata and/or upload host
|
||||
data for a previously-reserved host
|
||||
DELETE /hosts/<ID> -- Delete the host with id <ID>
|
||||
"""
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
registry.configure_registry_client()
|
||||
self.policy = policy.Enforcer()
|
||||
if property_utils.is_property_protection_enabled():
|
||||
self.prop_enforcer = property_utils.PropertyRules(self.policy)
|
||||
else:
|
||||
self.prop_enforcer = None
|
||||
|
||||
def _enforce(self, req, action, target=None):
|
||||
"""Authorize an action against our policies"""
|
||||
if target is None:
|
||||
target = {}
|
||||
try:
|
||||
self.policy.enforce(req.context, action, target)
|
||||
except exception.Forbidden:
|
||||
raise HTTPForbidden()
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""
|
||||
Return a dictionary of query param filters from the request
|
||||
|
||||
:param req: the Request object coming from the wsgi layer
|
||||
:retval a dict of key/value filters
|
||||
"""
|
||||
query_filters = {}
|
||||
for param in req.params:
|
||||
if param in SUPPORTED_FILTERS:
|
||||
query_filters[param] = req.params.get(param)
|
||||
if not filters.validate(param, query_filters[param]):
|
||||
raise HTTPBadRequest(_('Bad value passed to filter '
|
||||
'%(filter)s got %(val)s')
|
||||
% {'filter': param,
|
||||
'val': query_filters[param]})
|
||||
return query_filters
|
||||
|
||||
def _get_query_params(self, req):
|
||||
"""
|
||||
Extracts necessary query params from request.
|
||||
|
||||
:param req: the WSGI Request object
|
||||
:retval dict of parameters that can be used by registry client
|
||||
"""
|
||||
params = {'filters': self._get_filters(req)}
|
||||
|
||||
for PARAM in SUPPORTED_PARAMS:
|
||||
if PARAM in req.params:
|
||||
params[PARAM] = req.params.get(PARAM)
|
||||
return params
|
||||
|
||||
def hostname(self):
|
||||
if os.name == 'posix':
|
||||
host = os.popen('echo $HOSTNAME')
|
||||
try:
|
||||
return host.read()
|
||||
finally:
|
||||
host.close()
|
||||
else:
|
||||
return 'Unkwon hostname'
|
||||
|
||||
def check_file_format(self, req, file_meta):
|
||||
if not os.path.exists(file_meta.get('backup_file_path', '')):
|
||||
msg = 'File not exists!'
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if not file_meta['backup_file_path'].endswith('.tar.gz'):
|
||||
msg = 'File format not supported! .tar.gz format is required!'
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
@utils.mutating
|
||||
def backup(self, req):
|
||||
"""
|
||||
Backup daisy data..
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if backup failed
|
||||
"""
|
||||
version = self.version(req, {'type': 'internal'})
|
||||
date_str = filter(lambda x: x.isdigit(),
|
||||
str(datetime.datetime.now())[:19])
|
||||
backup_file_name = '{0}_{1}_{2}.tar.gz'.format(
|
||||
self.hostname().strip(), date_str, version['daisy_version'])
|
||||
|
||||
scripts = [
|
||||
'test -d {0}daisy_tmp||mkdir -p {0}daisy_tmp'.format(BACK_PATH),
|
||||
'echo {0}>{1}daisy_tmp/version.conf'.format(
|
||||
version['daisy_version'], BACK_PATH),
|
||||
'cp /home/daisy_install/daisy.conf {0}/daisy_tmp'.format(
|
||||
BACK_PATH),
|
||||
'mysqldump --all-databases > {0}daisy_tmp/database.sql'.format(
|
||||
BACK_PATH),
|
||||
'tar -zcvf {0}{1} -C {0} daisy_tmp >/dev/null 2>&1'.format(
|
||||
BACK_PATH, backup_file_name),
|
||||
'chmod 777 {0} {0}{1}'.format(BACK_PATH, backup_file_name),
|
||||
'rm -rf {0}daisy_tmp'.format(BACK_PATH)
|
||||
]
|
||||
|
||||
tecs_cmn.run_scrip(scripts, msg='Backup file failed!')
|
||||
return {"backup_file": BACK_PATH + backup_file_name}
|
||||
|
||||
@utils.mutating
|
||||
def restore(self, req, file_meta):
|
||||
"""
|
||||
Restore daisy data.
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param file_meta: The daisy backup file path
|
||||
:raises HTTPBadRequest if restore failed
|
||||
"""
|
||||
self.check_file_format(req, file_meta)
|
||||
restore_scripts = [
|
||||
'test -d {0} || mkdir {0}'.format(BACK_PATH),
|
||||
'test -d {0} || mkdir {0}'.format('/home/daisy_install/'),
|
||||
'tar -zxvf {1} -C {0}>/dev/null 2>&1'.format(
|
||||
BACK_PATH, file_meta['backup_file_path']),
|
||||
'mysql < {0}daisy_tmp/database.sql'.format(BACK_PATH),
|
||||
'cp {0}daisy_tmp/daisy.conf /home/daisy_install/'.format(
|
||||
BACK_PATH),
|
||||
'rm -rf {0}daisy_tmp'.format(BACK_PATH)
|
||||
]
|
||||
tecs_cmn.run_scrip(restore_scripts, msg='Restore failed!')
|
||||
LOG.info('Restore successfully')
|
||||
|
||||
@utils.mutating
|
||||
def get_backup_file_version(self, req, file_meta):
|
||||
"""
|
||||
Get version of daisy backup file.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if can't get version of backup file
|
||||
"""
|
||||
self.check_file_format(req, file_meta)
|
||||
scripts = [
|
||||
'test -d {0} || mkdir {0}'.format(BACK_PATH),
|
||||
'tar -zxvf {0} -C {1}>/dev/null 2>&1'.format(
|
||||
file_meta['backup_file_path'], BACK_PATH)
|
||||
]
|
||||
|
||||
tecs_cmn.run_scrip(scripts, msg='Decompression file failed!')
|
||||
|
||||
try:
|
||||
version = subprocess.check_output(
|
||||
'cat {0}daisy_tmp/version.conf'.format(BACK_PATH),
|
||||
shell=True, stderr=subprocess.STDOUT).strip()
|
||||
except:
|
||||
msg = 'Error occurred when running scripts to get version of' \
|
||||
' backup file!'
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
tecs_cmn.run_scrip(['rm -rf {0}daisy_tmp'.format(BACK_PATH)])
|
||||
return {"backup_file_version": version}
|
||||
|
||||
@utils.mutating
|
||||
def version(self, req, version):
|
||||
"""
|
||||
Get version of daisy.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
|
||||
:raises HTTPBadRequest if can't get version of daisy
|
||||
"""
|
||||
if version.get('type') == 'internal':
|
||||
scripts = "rpm -q python-daisy | awk -F'-' '{print $3\"-\"$4}'"
|
||||
else:
|
||||
# reserve for external version
|
||||
return {"daisy_version": '1.0.0-1.1.0'}
|
||||
try:
|
||||
version = subprocess.check_output(scripts, shell=True,
|
||||
stderr=subprocess.STDOUT).strip()
|
||||
except:
|
||||
msg = 'Error occurred when running scripts to get version of daisy'
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
daisy_version = filter(lambda x: not x.isalpha(), version)[:-1]
|
||||
return {"daisy_version": daisy_version}
|
||||
|
||||
|
||||
class BackupRestoreDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
def _deserialize(self, request):
|
||||
result = {}
|
||||
result['file_meta'] = utils.get_dict_meta(request)
|
||||
return result
|
||||
|
||||
def backup(self, request):
|
||||
return {}
|
||||
|
||||
def restore(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def get_backup_file_version(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def version(self, request):
|
||||
result = {}
|
||||
result['version'] = utils.get_dict_meta(request)
|
||||
return result
|
||||
|
||||
|
||||
class BackupRestoreSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
|
||||
def backup(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
def restore(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
def get_backup_file_version(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
def version(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Version resource factory method"""
|
||||
deserializer = BackupRestoreDeserializer()
|
||||
serializer = BackupRestoreSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
@ -38,6 +38,7 @@ from daisy.common import wsgi
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from functools import reduce
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -53,15 +54,16 @@ CONF.import_opt('disk_formats', 'daisy.common.config', group='image_format')
|
||||
CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
CLUSTER_DEFAULT_NETWORKS = ['PUBLIC', 'DEPLOYMENT', 'PRIVATE', 'EXTERNAL',
|
||||
'STORAGE', 'VXLAN', 'MANAGEMENT']
|
||||
CLUSTER_DEFAULT_NETWORKS = ['PUBLICAPI', 'DEPLOYMENT', 'DATAPLANE', 'EXTERNAL',
|
||||
'STORAGE', 'MANAGEMENT']
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for clusters resource in Daisy v1 API
|
||||
|
||||
The clusters resource API is a RESTful web service for cluster data. The API
|
||||
is as follows::
|
||||
The clusters resource API is a RESTful web service for cluster data.
|
||||
The API is as follows::
|
||||
|
||||
GET /clusters -- Returns a set of brief metadata about clusters
|
||||
GET /clusters -- Returns a set of detailed metadata about
|
||||
@ -86,57 +88,74 @@ class Controller(controller.BaseController):
|
||||
cluster_id = kwargs.get('id', None)
|
||||
errmsg = (_("I'm params checker."))
|
||||
|
||||
LOG.debug(_("Params check for cluster-add or cluster-update begin!"))
|
||||
|
||||
LOG.debug(
|
||||
_("Params check for cluster-add or cluster-update begin!"))
|
||||
|
||||
def check_params_range(param, type=None):
|
||||
'''
|
||||
param : input a list ,such as [start, end]
|
||||
check condition: start must less than end, and existed with pair
|
||||
check condition: start must less than end,
|
||||
and existed with pair
|
||||
return True of False
|
||||
'''
|
||||
if len(param) != 2:
|
||||
msg = '%s range must be existed in pairs.' % type
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if param[0] == None or param[0] == '':
|
||||
if param[0] is None or param[0] == '':
|
||||
msg = 'The start value of %s range can not be None.' % type
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if param[1] == None:
|
||||
if param[1] is None:
|
||||
msg = 'The end value of %s range can not be None.' % type
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if int(param[0]) > int(param[1]):
|
||||
msg = 'The start value of the %s range must be less than the end value.' % type
|
||||
msg = 'The start value of the %s range must be less ' \
|
||||
'than the end value.' % type
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if type not in ['vni']:
|
||||
if int(param[0]) < 0 or int(param[0]) > 4096:
|
||||
msg = 'Invalid value of the start value(%s) of the %s range .' % (param[0], type)
|
||||
msg = 'Invalid value of the start value(%s) of ' \
|
||||
'the %s range .' % (param[
|
||||
0], type)
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if int(param[1]) < 0 or int(param[1]) > 4096:
|
||||
msg = 'Invalid value of the end value(%s) of the %s range .' % (param[1], type)
|
||||
msg = 'Invalid value of the end value(%s) of ' \
|
||||
'the %s range .' % (param[
|
||||
1], type)
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
else:
|
||||
if int(param[0]) < 0 or int(param[0]) > 16777216:
|
||||
msg = 'Invalid value of the start value(%s) of the %s range .' % (param[0], type)
|
||||
msg = 'Invalid value of the start value(%s) of ' \
|
||||
'the %s range .' % (param[
|
||||
0], type)
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if int(param[1]) < 0 or int(param[1]) > 16777216:
|
||||
msg = 'Invalid value of the end value(%s) of the %s range .' % (param[1], type)
|
||||
msg = 'Invalid value of the end value(%s) of ' \
|
||||
'the %s range .' % (param[
|
||||
1], type)
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
return True
|
||||
|
||||
|
||||
def _check_auto_scale(req, cluster_meta):
|
||||
if cluster_meta.has_key('auto_scale') and cluster_meta['auto_scale'] =='1':
|
||||
meta = { "auto_scale":'1' }
|
||||
params = { 'filters': meta }
|
||||
clusters = registry.get_clusters_detail(req.context, **params)
|
||||
if 'auto_scale' in cluster_meta and cluster_meta[
|
||||
'auto_scale'] == '1':
|
||||
meta = {"auto_scale": '1'}
|
||||
params = {'filters': meta}
|
||||
clusters = registry.get_clusters_detail(
|
||||
req.context, **params)
|
||||
if clusters:
|
||||
if cluster_id:
|
||||
temp_cluster = [cluster for cluster in clusters if cluster['id'] !=cluster_id]
|
||||
temp_cluster = [
|
||||
cluster for cluster in clusters if
|
||||
cluster['id'] != cluster_id]
|
||||
if temp_cluster:
|
||||
errmsg = (_("already exist cluster auto_scale is true"))
|
||||
raise HTTPBadRequest(explanation=errmsg)
|
||||
errmsg = (
|
||||
_("already exist cluster "
|
||||
"auto_scale is true"))
|
||||
raise HTTPBadRequest(explanation=errmsg)
|
||||
else:
|
||||
errmsg = (_("already exist cluster auto_scale is true"))
|
||||
errmsg = (
|
||||
_("already exist cluster auto_scale is true"))
|
||||
raise HTTPBadRequest(explanation=errmsg)
|
||||
|
||||
|
||||
def _ip_into_int(ip):
|
||||
"""
|
||||
@ -144,7 +163,8 @@ class Controller(controller.BaseController):
|
||||
:param ip: ip string
|
||||
:return: decimalism integer
|
||||
"""
|
||||
return reduce(lambda x, y: (x<<8)+y, map(int, ip.split('.')))
|
||||
return reduce(lambda x, y: (x << 8) + y,
|
||||
map(int, ip.split('.')))
|
||||
|
||||
def _is_in_network_range(ip, network):
|
||||
"""
|
||||
@ -155,9 +175,13 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
network = network.split('/')
|
||||
mask = ~(2**(32 - int(network[1])) - 1)
|
||||
return (_ip_into_int(ip) & mask) == (_ip_into_int(network[0]) & mask)
|
||||
return (
|
||||
_ip_into_int(ip) & mask) == (
|
||||
_ip_into_int(
|
||||
network[0]) & mask)
|
||||
|
||||
def _check_param_nonull_and_valid(values_set, keys_set, valids_set={}):
|
||||
def _check_param_nonull_and_valid(
|
||||
values_set, keys_set, valids_set={}):
|
||||
"""
|
||||
Check operation params is not null and valid.
|
||||
:param values_set: Params set.
|
||||
@ -167,10 +191,10 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
for k in keys_set:
|
||||
v = values_set.get(k, None)
|
||||
if type(v) == type(True) and v == None:
|
||||
if isinstance(v, type(True)) and v is None:
|
||||
errmsg = (_("Segment %s can't be None." % k))
|
||||
raise HTTPBadRequest(explanation=errmsg)
|
||||
elif type(v) != type(True) and not v:
|
||||
elif not isinstance(v, type(True)) and not v:
|
||||
errmsg = (_("Segment %s can't be None." % k))
|
||||
raise HTTPBadRequest(explanation=errmsg)
|
||||
|
||||
@ -183,15 +207,18 @@ class Controller(controller.BaseController):
|
||||
def _get_network_detail(req, cluster_id, networks_list):
|
||||
all_network_list = []
|
||||
if cluster_id:
|
||||
all_network_list = registry.get_networks_detail(req.context, cluster_id)
|
||||
all_network_list = registry.get_networks_detail(
|
||||
req.context, cluster_id)
|
||||
|
||||
if networks_list:
|
||||
for net_id in networks_list:
|
||||
network_detail = registry.get_network_metadata(req.context, net_id)
|
||||
network_detail = registry.get_network_metadata(
|
||||
req.context, net_id)
|
||||
all_network_list.append(network_detail)
|
||||
|
||||
all_private_network_list = \
|
||||
[network for network in all_network_list if network['network_type'] == "PRIVATE"]
|
||||
all_private_network_list = [
|
||||
network for network in all_network_list if network[
|
||||
'network_type'] == "DATAPLANE"]
|
||||
return all_private_network_list
|
||||
|
||||
def _check_cluster_add_parameters(req, cluster_meta):
|
||||
@ -201,123 +228,92 @@ class Controller(controller.BaseController):
|
||||
:param cluster_meta: params set
|
||||
:return:error message
|
||||
"""
|
||||
if cluster_meta.has_key('nodes'):
|
||||
if 'nodes' in cluster_meta:
|
||||
orig_keys = list(eval(cluster_meta['nodes']))
|
||||
for host_id in orig_keys:
|
||||
controller._raise_404_if_host_deleted(req, host_id)
|
||||
|
||||
if cluster_meta.has_key('networks'):
|
||||
if 'networks' in cluster_meta:
|
||||
orig_keys = list(eval(cluster_meta['networks']))
|
||||
network_with_same_name = []
|
||||
for network_id in orig_keys:
|
||||
network_name = controller._raise_404_if_network_deleted(req, network_id)
|
||||
network_name = \
|
||||
controller._raise_404_if_network_deleted(
|
||||
req, network_id)
|
||||
if network_name in CLUSTER_DEFAULT_NETWORKS:
|
||||
return (_("Network name %s of %s already exits"
|
||||
" in the cluster, please check." %
|
||||
(network_name, network_id)))
|
||||
if network_name in network_with_same_name:
|
||||
return (_("Network name can't be same with each other in 'networks[]', "
|
||||
return (_("Network name can't be same with "
|
||||
"each other in 'networks[]', "
|
||||
"please check."))
|
||||
network_with_same_name.append(network_name)
|
||||
|
||||
# checkout network_params--------------------------------------------------
|
||||
# checkout network_params
|
||||
if cluster_meta.get('networking_parameters', None):
|
||||
networking_parameters = eval(cluster_meta['networking_parameters'])
|
||||
_check_param_nonull_and_valid(networking_parameters,
|
||||
['segmentation_type'])
|
||||
segmentation_type_set = networking_parameters['segmentation_type'].split(",")
|
||||
for segmentation_type in segmentation_type_set:
|
||||
if segmentation_type not in ['vlan', 'vxlan', 'flat', 'gre']:
|
||||
return (_("Segmentation_type of networking_parameters is not valid."))
|
||||
if segmentation_type =='vxlan':
|
||||
_check_param_nonull_and_valid(networking_parameters,['vni_range'])
|
||||
elif segmentation_type =='gre':
|
||||
_check_param_nonull_and_valid(networking_parameters,['gre_id_range'])
|
||||
networking_parameters =\
|
||||
eval(cluster_meta['networking_parameters'])
|
||||
|
||||
vlan_range = networking_parameters.get("vlan_range", None)
|
||||
vni_range = networking_parameters.get("vni_range", None)
|
||||
gre_id_range = networking_parameters.get("gre_id_range", None)
|
||||
#if (vlan_range and len(vlan_range) != 2) \
|
||||
# or (vni_range and len(vni_range) != 2) \
|
||||
# or (gre_id_range and len(gre_id_range) != 2):
|
||||
# return (_("Range params must be pair."))
|
||||
if vlan_range:
|
||||
check_params_range(vlan_range, 'vlan')
|
||||
if vni_range:
|
||||
check_params_range(vni_range, 'vni')
|
||||
if gre_id_range:
|
||||
check_params_range(gre_id_range, 'gre_id')
|
||||
|
||||
# check logic_networks--------------------------------------------------
|
||||
subnet_name_set = [] # record all subnets's name
|
||||
logic_network_name_set = [] # record all logic_network's name
|
||||
# check logic_networks
|
||||
subnet_name_set = [] # record all subnets's name
|
||||
logic_network_name_set = [] # record all logic_network's name
|
||||
subnets_in_logic_network = {}
|
||||
external_logic_network_name = []
|
||||
if cluster_meta.get('logic_networks', None):
|
||||
# get physnet_name list
|
||||
all_private_cluster_networks_list = _get_network_detail(
|
||||
req, cluster_id,
|
||||
cluster_meta.get('networks', None)
|
||||
if not isinstance(cluster_meta.get('networks', None), unicode)
|
||||
else eval(cluster_meta.get('networks', None)))
|
||||
req, cluster_id, cluster_meta.get(
|
||||
'networks', None) if not isinstance(
|
||||
cluster_meta.get(
|
||||
'networks', None), unicode) else eval(
|
||||
cluster_meta.get(
|
||||
'networks', None)))
|
||||
if not all_private_cluster_networks_list:
|
||||
LOG.info("Private network is empty in db, it lead logical network config invalid.")
|
||||
physnet_name_set = [net['name'] for net in all_private_cluster_networks_list]
|
||||
LOG.info(
|
||||
"Private network is empty in db, it lead "
|
||||
"logical network config invalid.")
|
||||
physnet_name_set = [net['name']
|
||||
for net in
|
||||
all_private_cluster_networks_list]
|
||||
|
||||
logic_networks = eval(cluster_meta['logic_networks'])
|
||||
for logic_network in logic_networks:
|
||||
subnets_in_logic_network[logic_network['name']] = []
|
||||
|
||||
# We force setting the physnet_name of flat logical network to 'flat'.
|
||||
if logic_network.get('segmentation_type', None) == "flat":
|
||||
if logic_network['physnet_name'] != "physnet1" or logic_network['type'] != "external":
|
||||
LOG.info("When 'segmentation_type' is flat the 'physnet_name' and 'type' segmentation"
|
||||
"must be 'physnet1'' and 'external'', but got '%s' and '%s'.We have changed"
|
||||
"it to the valid value.")
|
||||
# We force setting the physnet_name of flat logical
|
||||
# network to 'flat'.
|
||||
if logic_network.get(
|
||||
'segmentation_type', None) == "flat":
|
||||
if logic_network['physnet_name'] != "physnet1" or \
|
||||
logic_network[
|
||||
'type'] != "external":
|
||||
LOG.info(
|
||||
"When 'segmentation_type' is flat the "
|
||||
"'physnet_name' and 'type' segmentation"
|
||||
"must be 'physnet1'' and 'external'', "
|
||||
"but got '%s' and '%s'.We have changed"
|
||||
"it to the valid value.")
|
||||
logic_network['physnet_name'] = "physnet1"
|
||||
logic_network['type'] = "external"
|
||||
physnet_name_set.append("physnet1")
|
||||
|
||||
_check_param_nonull_and_valid(
|
||||
logic_network,
|
||||
['name', 'type', 'physnet_name', 'segmentation_type', 'shared', 'segmentation_id'],
|
||||
{'segmentation_type' : networking_parameters['segmentation_type'],
|
||||
'physnet_name' : ','.join(physnet_name_set),
|
||||
'type' : ','.join(["external", "internal"])})
|
||||
['name', 'type', 'physnet_name',
|
||||
'segmentation_type', 'shared', 'segmentation_id'],
|
||||
{'segmentation_type': networking_parameters[
|
||||
'segmentation_type'],
|
||||
'physnet_name': ','.join(physnet_name_set),
|
||||
'type': ','.join(["external", "internal"])})
|
||||
|
||||
if logic_network['type'] == "external":
|
||||
external_logic_network_name.append(logic_network['name'])
|
||||
external_logic_network_name.append(
|
||||
logic_network['name'])
|
||||
|
||||
logic_network_name_set.append(logic_network['name'])
|
||||
|
||||
# By segmentation_type check segmentation_id is in range
|
||||
segmentation_id = logic_network.get('segmentation_id', None)
|
||||
if segmentation_id:
|
||||
err = "Segmentation_id is out of private network %s of %s.Vaild range is [%s, %s]."
|
||||
segmentation_type = logic_network.get('segmentation_type', None)
|
||||
if 0 == cmp(segmentation_type, "vlan"):
|
||||
private_vlan_range = \
|
||||
[(net['vlan_start'], net['vlan_end'])
|
||||
for net in all_private_cluster_networks_list
|
||||
if logic_network['physnet_name'] == net['name']]
|
||||
|
||||
if private_vlan_range and \
|
||||
not private_vlan_range[0][0] or \
|
||||
not private_vlan_range[0][1]:
|
||||
return (_("Private network plane %s don't config the 'vlan_start' or "
|
||||
"'vlan_end' parameter."))
|
||||
|
||||
if int(segmentation_id) not in range(private_vlan_range[0][0], private_vlan_range[0][1]):
|
||||
return (_(err % ("vlan_range", logic_network['physnet_name'],
|
||||
private_vlan_range[0][0], private_vlan_range[0][1])))
|
||||
elif 0 == cmp(segmentation_type, "vxlan") and vni_range:
|
||||
if int(segmentation_id) not in range(vni_range[0], vni_range[1]):
|
||||
return (_("Segmentation_id is out of vni_range."))
|
||||
elif 0 == cmp(segmentation_type, "gre") and gre_id_range:
|
||||
if int(segmentation_id) not in range(gre_id_range[0], gre_id_range[1]):
|
||||
return (_("Segmentation_id is out of gre_id_range."))
|
||||
|
||||
# checkout subnets params--------------------------------------------------
|
||||
# checkout subnets params------------------------------
|
||||
if logic_network.get('subnets', None):
|
||||
subnet_data = logic_network['subnets']
|
||||
for subnet in subnet_data:
|
||||
@ -325,49 +321,78 @@ class Controller(controller.BaseController):
|
||||
subnet,
|
||||
['name', 'cidr'])
|
||||
subnet_name_set.append(subnet['name'])
|
||||
# By cidr check floating_ranges is in range and not overlap
|
||||
#---------------start-----
|
||||
if subnet['gateway'] and not _is_in_network_range(subnet['gateway'], subnet['cidr']):
|
||||
# By cidr check floating_ranges is in range
|
||||
# and not overlap
|
||||
# ---------------start-----
|
||||
if subnet['gateway'] and not \
|
||||
_is_in_network_range(
|
||||
subnet['gateway'], subnet['cidr']):
|
||||
return (_("Wrong gateway format."))
|
||||
if subnet['floating_ranges']:
|
||||
inter_ip = lambda x: '.'.join([str(x/(256**i)%256) for i in range(3,-1,-1)])
|
||||
inter_ip = lambda x: '.'.join(
|
||||
[str(x / (256**i) % 256) for i in
|
||||
range(3, -1, -1)])
|
||||
floating_ranges_with_int_ip = list()
|
||||
sorted_floating_ranges = list()
|
||||
sorted_floating_ranges_with_int_ip = list()
|
||||
for floating_ip in subnet['floating_ranges']:
|
||||
for floating_ip in subnet[
|
||||
'floating_ranges']:
|
||||
if len(floating_ip) != 2:
|
||||
return (_("Floating ip must be paris."))
|
||||
return (
|
||||
_("Floating ip must "
|
||||
"be paris."))
|
||||
ip_start = _ip_into_int(floating_ip[0])
|
||||
ip_end = _ip_into_int(floating_ip[1])
|
||||
if ip_start > ip_end:
|
||||
return (_("Wrong floating ip format."))
|
||||
floating_ranges_with_int_ip.append([ip_start, ip_end])
|
||||
sorted_floating_ranges_with_int_ip = sorted(floating_ranges_with_int_ip, key=lambda x : x[0])
|
||||
for ip_range in sorted_floating_ranges_with_int_ip:
|
||||
return (
|
||||
_("Wrong floating ip format."))
|
||||
floating_ranges_with_int_ip.append(
|
||||
[ip_start, ip_end])
|
||||
sorted_floating_ranges_with_int_ip = \
|
||||
sorted(floating_ranges_with_int_ip,
|
||||
key=lambda x: x[0])
|
||||
for ip_range in \
|
||||
sorted_floating_ranges_with_int_ip:
|
||||
ip_start = inter_ip(ip_range[0])
|
||||
ip_end = inter_ip(ip_range[1])
|
||||
sorted_floating_ranges.append([ip_start, ip_end])
|
||||
sorted_floating_ranges.append(
|
||||
[ip_start, ip_end])
|
||||
|
||||
last_rang_ip = []
|
||||
for floating in sorted_floating_ranges:
|
||||
if not _is_in_network_range(floating[0], subnet['cidr']) \
|
||||
or not _is_in_network_range(floating[1], subnet['cidr']):
|
||||
return (_("Floating ip or gateway is out of range cidr."))
|
||||
if not _is_in_network_range(
|
||||
floating[0],
|
||||
subnet['cidr']) or not \
|
||||
_is_in_network_range(
|
||||
floating[1], subnet['cidr']):
|
||||
return (
|
||||
_("Floating ip or gateway "
|
||||
"is out of range cidr."))
|
||||
|
||||
err_list = [err for err in last_rang_ip if _ip_into_int(floating[0]) < err]
|
||||
err_list = [
|
||||
err for err in last_rang_ip if
|
||||
_ip_into_int(
|
||||
floating[0]) < err]
|
||||
if last_rang_ip and 0 < len(err_list):
|
||||
return (_("Between floating ip range can not be overlap."))
|
||||
last_rang_ip.append(_ip_into_int(floating[1]))
|
||||
subnets_in_logic_network[logic_network['name']].append(subnet['name'])
|
||||
return (
|
||||
_("Between floating ip range "
|
||||
"can not be overlap."))
|
||||
last_rang_ip.append(
|
||||
_ip_into_int(floating[1]))
|
||||
subnets_in_logic_network[logic_network[
|
||||
'name']].append(subnet['name'])
|
||||
|
||||
# check external logical network uniqueness
|
||||
if len(external_logic_network_name) > 1:
|
||||
return (_("External logical network is uniqueness in the cluster.Got %s." %
|
||||
",".join(external_logic_network_name)))
|
||||
return (_("External logical network is uniqueness "
|
||||
"in the cluster.Got %s." %
|
||||
",".join(external_logic_network_name)))
|
||||
|
||||
# check logic_network_name uniqueness
|
||||
if len(logic_network_name_set) != len(set(logic_network_name_set)):
|
||||
return (_("Logic network name segment is repetition."))
|
||||
if len(logic_network_name_set) != len(
|
||||
set(logic_network_name_set)):
|
||||
return (_("Logic network name segment "
|
||||
"is repetition."))
|
||||
|
||||
# check subnet_name uniqueness
|
||||
if len(subnet_name_set) != len(set(subnet_name_set)):
|
||||
@ -375,36 +400,47 @@ class Controller(controller.BaseController):
|
||||
|
||||
cluster_meta['logic_networks'] = unicode(logic_networks)
|
||||
|
||||
# check routers--------------------------------------------------
|
||||
# check routers------------------------------------------------
|
||||
subnet_name_set_deepcopy = copy.deepcopy(subnet_name_set)
|
||||
router_name_set = [] # record all routers name
|
||||
router_name_set = [] # record all routers name
|
||||
if cluster_meta.get('routers', None):
|
||||
router_data = eval(cluster_meta['routers'])
|
||||
for router in router_data:
|
||||
for router in router_data:
|
||||
_check_param_nonull_and_valid(router, ['name'])
|
||||
|
||||
# check relevance logic_network is valid
|
||||
external_logic_network_data = router.get('external_logic_network', None)
|
||||
external_logic_network_data = router.get(
|
||||
'external_logic_network', None)
|
||||
if external_logic_network_data and \
|
||||
external_logic_network_data not in logic_network_name_set:
|
||||
return (_("Logic_network %s is not valid range." % external_logic_network_data))
|
||||
external_logic_network_data not in \
|
||||
logic_network_name_set:
|
||||
return (_("Logic_network %s is not valid range." %
|
||||
external_logic_network_data))
|
||||
router_name_set.append(router['name'])
|
||||
|
||||
# check relevance subnets is valid
|
||||
for subnet in router.get('subnets', []):
|
||||
if subnet not in subnet_name_set:
|
||||
return (_("Subnet %s is not valid range." % subnet))
|
||||
return (
|
||||
_("Subnet %s is not valid range." %
|
||||
subnet))
|
||||
|
||||
# subnet cann't relate with two routers
|
||||
if subnet not in subnet_name_set_deepcopy:
|
||||
return (_("The subnet can't be related with multiple routers."))
|
||||
return (
|
||||
_("The subnet can't be related with "
|
||||
"multiple routers."))
|
||||
subnet_name_set_deepcopy.remove(subnet)
|
||||
|
||||
if external_logic_network_data and \
|
||||
subnets_in_logic_network[external_logic_network_data] and \
|
||||
set(subnets_in_logic_network[external_logic_network_data]). \
|
||||
subnets_in_logic_network[
|
||||
external_logic_network_data] and \
|
||||
set(subnets_in_logic_network[
|
||||
external_logic_network_data]). \
|
||||
issubset(set(router['subnets'])):
|
||||
return (_("Logic network's subnets is all related with a router, it's not allowed."))
|
||||
return (
|
||||
_("Logic network's subnets is all related"
|
||||
" with a router, it's not allowed."))
|
||||
|
||||
# check subnet_name uniqueness
|
||||
if len(router_name_set) != len(set(router_name_set)):
|
||||
@ -413,10 +449,13 @@ class Controller(controller.BaseController):
|
||||
_check_auto_scale(req, cluster_meta)
|
||||
check_result = _check_cluster_add_parameters(req, cluster_meta)
|
||||
if 0 != cmp(check_result, errmsg):
|
||||
LOG.exception(_("Params check for cluster-add or cluster-update is failed!"))
|
||||
LOG.exception(
|
||||
_("Params check for cluster-add or cluster-update "
|
||||
"is failed!"))
|
||||
raise HTTPBadRequest(explanation=check_result)
|
||||
|
||||
LOG.debug(_("Params check for cluster-add or cluster-update is done!"))
|
||||
LOG.debug(
|
||||
_("Params check for cluster-add or cluster-update is done!"))
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
||||
@ -448,7 +487,8 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_network_deleted(self, req, network_id):
|
||||
network = self.get_network_meta_or_404(req, network_id)
|
||||
if network['deleted']:
|
||||
msg = _("Network with identifier %s has been deleted.") % network_id
|
||||
msg = _("Network with identifier %s has been deleted.") % \
|
||||
network_id
|
||||
raise HTTPNotFound(msg)
|
||||
return network.get('name', None)
|
||||
|
||||
@ -500,9 +540,10 @@ class Controller(controller.BaseController):
|
||||
if not cluster_name:
|
||||
raise ValueError('cluster name is null!')
|
||||
cluster_name_split = cluster_name.split('_')
|
||||
for cluster_name_info in cluster_name_split :
|
||||
for cluster_name_info in cluster_name_split:
|
||||
if not cluster_name_info.isalnum():
|
||||
raise ValueError('cluster name must be numbers or letters or underscores !')
|
||||
raise ValueError(
|
||||
'cluster name must be numbers or letters or underscores !')
|
||||
if cluster_meta.get('nodes', None):
|
||||
orig_keys = list(eval(cluster_meta['nodes']))
|
||||
for host_id in orig_keys:
|
||||
@ -514,11 +555,15 @@ class Controller(controller.BaseController):
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if node.get('interfaces', None):
|
||||
interfaces = node['interfaces']
|
||||
input_host_pxe_info = [interface for interface in interfaces
|
||||
if interface.get('is_deployment', None) == 1]
|
||||
if not input_host_pxe_info and node.get('os_status',None) != 'active':
|
||||
msg = _("The host %s has more than one dhcp server, "
|
||||
"please choose one interface for deployment") % host_id
|
||||
input_host_pxe_info = [
|
||||
interface for interface in interfaces if interface.get(
|
||||
'is_deployment', None) == 1]
|
||||
if not input_host_pxe_info and node.get(
|
||||
'os_status', None) != 'active':
|
||||
msg = _(
|
||||
"The host %s has more than one dhcp server, "
|
||||
"please choose one interface for deployment") % \
|
||||
host_id
|
||||
raise HTTPServerError(explanation=msg)
|
||||
print cluster_name
|
||||
print cluster_meta
|
||||
@ -537,7 +582,7 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'delete_cluster')
|
||||
|
||||
#cluster = self.get_cluster_meta_or_404(req, id)
|
||||
# cluster = self.get_cluster_meta_or_404(req, id)
|
||||
print "delete_cluster:%s" % id
|
||||
try:
|
||||
registry.delete_cluster_metadata(req.context, id)
|
||||
@ -556,14 +601,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("cluster %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("cluster %(id)s could not be deleted because "
|
||||
"it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('cluster.delete', cluster)
|
||||
# self.notifier.info('cluster.delete', cluster)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -619,26 +665,31 @@ class Controller(controller.BaseController):
|
||||
:retval Returns the updated cluster information as a mapping
|
||||
"""
|
||||
self._enforce(req, 'update_cluster')
|
||||
if cluster_meta.has_key('nodes'):
|
||||
if 'nodes' in cluster_meta:
|
||||
orig_keys = list(eval(cluster_meta['nodes']))
|
||||
for host_id in orig_keys:
|
||||
self._raise_404_if_host_deleted(req, host_id)
|
||||
node = registry.get_host_metadata(req.context, host_id)
|
||||
if node['status'] == 'in-cluster':
|
||||
host_cluster = registry.get_host_clusters(req.context, host_id)
|
||||
host_cluster = registry.get_host_clusters(
|
||||
req.context, host_id)
|
||||
if host_cluster[0]['cluster_id'] != id:
|
||||
msg = _("Forbidden to add host %s with status "
|
||||
"'in-cluster' in another cluster") % host_id
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
if node.get('interfaces', None):
|
||||
interfaces = node['interfaces']
|
||||
input_host_pxe_info = [interface for interface in interfaces
|
||||
if interface.get('is_deployment', None) == 1]
|
||||
if not input_host_pxe_info and node.get('os_status', None) != 'active':
|
||||
msg = _("The host %s has more than one dhcp server, "
|
||||
"please choose one interface for deployment") % host_id
|
||||
input_host_pxe_info = [
|
||||
interface for interface in interfaces if interface.get(
|
||||
'is_deployment', None) == 1]
|
||||
if not input_host_pxe_info and node.get(
|
||||
'os_status', None) != 'active':
|
||||
msg = _(
|
||||
"The host %s has more than one dhcp server, "
|
||||
"please choose one interface for deployment") % \
|
||||
host_id
|
||||
raise HTTPServerError(explanation=msg)
|
||||
if cluster_meta.has_key('networks'):
|
||||
if 'networks' in cluster_meta:
|
||||
orig_keys = list(eval(cluster_meta['networks']))
|
||||
for network_id in orig_keys:
|
||||
self._raise_404_if_network_deleted(req, network_id)
|
||||
@ -687,6 +738,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'cluster_meta': cluster_meta}
|
||||
|
||||
|
||||
class ProjectDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -701,6 +753,7 @@ class ProjectDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_cluster(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class ProjectSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -727,6 +780,7 @@ class ProjectSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(cluster=cluster_meta))
|
||||
return response
|
||||
|
||||
def get_cluster(self, response, result):
|
||||
cluster_meta = result['cluster_meta']
|
||||
response.status = 201
|
||||
@ -734,9 +788,9 @@ class ProjectSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(cluster=cluster_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Projects resource factory method"""
|
||||
deserializer = ProjectDeserializer()
|
||||
serializer = ProjectSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -52,21 +52,25 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for components resource in Daisy v1 API
|
||||
|
||||
The components resource API is a RESTful web service for component data. The API
|
||||
is as follows::
|
||||
The components resource API is a RESTful web service for component data.
|
||||
The API is as follows::
|
||||
|
||||
GET /components -- Returns a set of brief metadata about components
|
||||
GET /components/detail -- Returns a set of detailed metadata about
|
||||
components
|
||||
HEAD /components/<ID> -- Return metadata about an component with id <ID>
|
||||
GET /components/<ID> -- Return component data for component with id <ID>
|
||||
HEAD /components/<ID> --
|
||||
Return metadata about an component with id <ID>
|
||||
GET /components/<ID> --
|
||||
Return component data for component with id <ID>
|
||||
POST /components -- Store component data and return metadata about the
|
||||
newly-stored component
|
||||
PUT /components/<ID> -- Update component metadata and/or upload component
|
||||
PUT /components/<ID> --
|
||||
Update component metadata and/or upload component
|
||||
data for a previously-reserved component
|
||||
DELETE /components/<ID> -- Delete the component with id <ID>
|
||||
"""
|
||||
@ -132,15 +136,16 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-component-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_component')
|
||||
#component_id=component_meta["id"]
|
||||
#component_owner=component_meta["owner"]
|
||||
# component_id=component_meta["id"]
|
||||
# component_owner=component_meta["owner"]
|
||||
component_name = component_meta["name"]
|
||||
component_description = component_meta["description"]
|
||||
#print component_id
|
||||
#print component_owner
|
||||
# print component_id
|
||||
# print component_owner
|
||||
print component_name
|
||||
print component_description
|
||||
component_meta = registry.add_component_metadata(req.context, component_meta)
|
||||
component_meta = registry.add_component_metadata(
|
||||
req.context, component_meta)
|
||||
|
||||
return {'component_meta': component_meta}
|
||||
|
||||
@ -156,7 +161,7 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'delete_component')
|
||||
|
||||
#component = self.get_component_meta_or_404(req, id)
|
||||
# component = self.get_component_meta_or_404(req, id)
|
||||
print "delete_component:%s" % id
|
||||
try:
|
||||
registry.delete_component_metadata(req.context, id)
|
||||
@ -175,14 +180,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("component %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("component %(id)s could not be "
|
||||
"deleted because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('component.delete', component)
|
||||
# self.notifier.info('component.delete', component)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -280,6 +286,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'component_meta': component_meta}
|
||||
|
||||
|
||||
class ComponentDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -294,6 +301,7 @@ class ComponentDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_component(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class ComponentSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -313,6 +321,7 @@ class ComponentSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(component=component_meta))
|
||||
return response
|
||||
|
||||
def get_component(self, response, result):
|
||||
component_meta = result['component_meta']
|
||||
response.status = 201
|
||||
@ -320,9 +329,9 @@ class ComponentSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(component=component_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Components resource factory method"""
|
||||
deserializer = ComponentDeserializer()
|
||||
serializer = ComponentSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -52,21 +52,28 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for config_files resource in Daisy v1 API
|
||||
|
||||
The config_files resource API is a RESTful web service for config_file data. The API
|
||||
The config_files resource API is a RESTful web service
|
||||
for config_file data. The API
|
||||
is as follows::
|
||||
|
||||
GET /config_files -- Returns a set of brief metadata about config_files
|
||||
GET /config_files --
|
||||
Returns a set of brief metadata about config_files
|
||||
GET /config_files/detail -- Returns a set of detailed metadata about
|
||||
config_files
|
||||
HEAD /config_files/<ID> -- Return metadata about an config_file with id <ID>
|
||||
GET /config_files/<ID> -- Return config_file data for config_file with id <ID>
|
||||
POST /config_files -- Store config_file data and return metadata about the
|
||||
HEAD /config_files/<ID> --
|
||||
Return metadata about an config_file with id <ID>
|
||||
GET /config_files/<ID> --
|
||||
Return config_file data for config_file with id <ID>
|
||||
POST /config_files --
|
||||
Store config_file data and return metadata about the
|
||||
newly-stored config_file
|
||||
PUT /config_files/<ID> -- Update config_file metadata and/or upload config_file
|
||||
PUT /config_files/<ID> --
|
||||
Update config_file metadata and/or upload config_file
|
||||
data for a previously-reserved config_file
|
||||
DELETE /config_files/<ID> -- Delete the config_file with id <ID>
|
||||
"""
|
||||
@ -132,13 +139,14 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-config_file-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_config_file')
|
||||
#config_file_id=config_file_meta["id"]
|
||||
# config_file_id=config_file_meta["id"]
|
||||
config_file_name = config_file_meta["name"]
|
||||
config_file_description = config_file_meta["description"]
|
||||
#print config_file_id
|
||||
# print config_file_id
|
||||
print config_file_name
|
||||
print config_file_description
|
||||
config_file_meta = registry.add_config_file_metadata(req.context, config_file_meta)
|
||||
config_file_meta = registry.add_config_file_metadata(
|
||||
req.context, config_file_meta)
|
||||
|
||||
return {'config_file_meta': config_file_meta}
|
||||
|
||||
@ -171,14 +179,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("config_file %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("config_file %(id)s could not be "
|
||||
"deleted because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('config_file.delete', config_file)
|
||||
# self.notifier.info('config_file.delete', config_file)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -215,7 +224,8 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'get_config_files')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
config_files = registry.get_config_files_detail(req.context, **params)
|
||||
config_files = registry.get_config_files_detail(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(config_files=config_files)
|
||||
@ -241,9 +251,8 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
try:
|
||||
config_file_meta = registry.update_config_file_metadata(req.context,
|
||||
id,
|
||||
config_file_meta)
|
||||
config_file_meta = registry.update_config_file_metadata(
|
||||
req.context, id, config_file_meta)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update config_file metadata. Got error: %s") %
|
||||
@ -276,6 +285,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'config_file_meta': config_file_meta}
|
||||
|
||||
|
||||
class Config_fileDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -290,6 +300,7 @@ class Config_fileDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_config_file(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class Config_fileSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -317,9 +328,9 @@ class Config_fileSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(config_file=config_file_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""config_files resource factory method"""
|
||||
deserializer = Config_fileDeserializer()
|
||||
serializer = Config_fileSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -53,21 +53,26 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for config_sets resource in Daisy v1 API
|
||||
|
||||
The config_sets resource API is a RESTful web service for config_set data. The API
|
||||
is as follows::
|
||||
The config_sets resource API is a RESTful web service for config_set data.
|
||||
The API is as follows::
|
||||
|
||||
GET /config_sets -- Returns a set of brief metadata about config_sets
|
||||
GET /config_sets/detail -- Returns a set of detailed metadata about
|
||||
config_sets
|
||||
HEAD /config_sets/<ID> -- Return metadata about an config_set with id <ID>
|
||||
GET /config_sets/<ID> -- Return config_set data for config_set with id <ID>
|
||||
POST /config_sets -- Store config_set data and return metadata about the
|
||||
HEAD /config_sets/<ID> --
|
||||
Return metadata about an config_set with id <ID>
|
||||
GET /config_sets/<ID> --
|
||||
Return config_set data for config_set with id <ID>
|
||||
POST /config_sets --
|
||||
Store config_set data and return metadata about the
|
||||
newly-stored config_set
|
||||
PUT /config_sets/<ID> -- Update config_set metadata and/or upload config_set
|
||||
PUT /config_sets/<ID> --
|
||||
Update config_set metadata and/or upload config_set
|
||||
data for a previously-reserved config_set
|
||||
DELETE /config_sets/<ID> -- Delete the config_set with id <ID>
|
||||
"""
|
||||
@ -125,7 +130,8 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("cluster with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
@utils.mutating
|
||||
@ -139,13 +145,14 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-config_set-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_config_set')
|
||||
#config_set_id=config_set_meta["id"]
|
||||
# config_set_id=config_set_meta["id"]
|
||||
config_set_name = config_set_meta["name"]
|
||||
config_set_description = config_set_meta["description"]
|
||||
#print config_set_id
|
||||
# print config_set_id
|
||||
print config_set_name
|
||||
print config_set_description
|
||||
config_set_meta = registry.add_config_set_metadata(req.context, config_set_meta)
|
||||
config_set_meta = registry.add_config_set_metadata(
|
||||
req.context, config_set_meta)
|
||||
|
||||
return {'config_set_meta': config_set_meta}
|
||||
|
||||
@ -171,21 +178,20 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.Forbidden as e:
|
||||
msg = (_("Forbidden to delete config_set: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
LOG.warn(e)
|
||||
raise HTTPForbidden(explanation=e,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("config_set %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("config_set %(id)s could not be "
|
||||
"deleted because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('config_set.delete', config_set)
|
||||
# self.notifier.info('config_set.delete', config_set)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -222,7 +228,8 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'get_config_sets')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
config_sets = registry.get_config_sets_detail(req.context, **params)
|
||||
config_sets = registry.get_config_sets_detail(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(config_sets=config_sets)
|
||||
@ -248,9 +255,8 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
try:
|
||||
config_set_meta = registry.update_config_set_metadata(req.context,
|
||||
id,
|
||||
config_set_meta)
|
||||
config_set_meta = registry.update_config_set_metadata(
|
||||
req.context, id, config_set_meta)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update config_set metadata. Got error: %s") %
|
||||
@ -282,48 +288,51 @@ class Controller(controller.BaseController):
|
||||
self.notifier.info('config_set.update', config_set_meta)
|
||||
|
||||
return {'config_set_meta': config_set_meta}
|
||||
|
||||
def _raise_404_if_role_exist(self,req,config_set_meta):
|
||||
role_id_list=[]
|
||||
|
||||
def _raise_404_if_role_exist(self, req, config_set_meta):
|
||||
role_id_list = []
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
for role in roles:
|
||||
for role_name in eval(config_set_meta['role']):
|
||||
if role['cluster_id'] == config_set_meta['cluster'] and role['name'] == role_name:
|
||||
if role['cluster_id'] == config_set_meta[
|
||||
'cluster'] and role['name'] == role_name:
|
||||
role_id_list.append(role['id'])
|
||||
break
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role_id_list
|
||||
|
||||
@utils.mutating
|
||||
def cluster_config_set_update(self, req, config_set_meta):
|
||||
if config_set_meta.has_key('cluster'):
|
||||
if 'cluster' in config_set_meta:
|
||||
orig_cluster = str(config_set_meta['cluster'])
|
||||
self._raise_404_if_cluster_deleted(req, orig_cluster)
|
||||
try:
|
||||
if config_set_meta.get('role',None):
|
||||
role_id_list=self._raise_404_if_role_exist(req,config_set_meta)
|
||||
if config_set_meta.get('role', None):
|
||||
role_id_list = self._raise_404_if_role_exist(
|
||||
req, config_set_meta)
|
||||
if len(role_id_list) == len(eval(config_set_meta['role'])):
|
||||
for role_id in role_id_list:
|
||||
backend=manager.configBackend('clushshell', req, role_id)
|
||||
backend.push_config()
|
||||
backend = manager.configBackend('clushshell', req)
|
||||
backend.push_config_by_roles(role_id_list)
|
||||
else:
|
||||
msg = "the role is not exist"
|
||||
LOG.error(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
else:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
role_id_list = []
|
||||
for role in roles:
|
||||
if role['cluster_id'] == config_set_meta['cluster']:
|
||||
backend=manager.configBackend('clushshell', req, role['id'])
|
||||
backend.push_config()
|
||||
|
||||
role_id_list.append(role['id'])
|
||||
backend = manager.configBackend('clushshell', req)
|
||||
backend.push_config_by_roles(role_id_list)
|
||||
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
config_status={"status":"config successful"}
|
||||
return {'config_set':config_status}
|
||||
|
||||
config_status = {"status": "config successful"}
|
||||
return {'config_set': config_status}
|
||||
else:
|
||||
msg = "the cluster is not exist"
|
||||
LOG.error(msg)
|
||||
@ -332,18 +341,22 @@ class Controller(controller.BaseController):
|
||||
@utils.mutating
|
||||
def cluster_config_set_progress(self, req, config_set_meta):
|
||||
role_list = []
|
||||
if config_set_meta.has_key('cluster'):
|
||||
if 'cluster' in config_set_meta:
|
||||
orig_cluster = str(config_set_meta['cluster'])
|
||||
self._raise_404_if_cluster_deleted(req, orig_cluster)
|
||||
try:
|
||||
if config_set_meta.get('role',None):
|
||||
role_id_list=self._raise_404_if_role_exist(req,config_set_meta)
|
||||
if config_set_meta.get('role', None):
|
||||
role_id_list = self._raise_404_if_role_exist(
|
||||
req, config_set_meta)
|
||||
if len(role_id_list) == len(eval(config_set_meta['role'])):
|
||||
for role_id in role_id_list:
|
||||
role_info = {}
|
||||
role_meta=registry.get_role_metadata(req.context, role_id)
|
||||
role_info['role-name']=role_meta['name']
|
||||
role_info['config_set_update_progress']=role_meta['config_set_update_progress']
|
||||
role_meta = registry.get_role_metadata(
|
||||
req.context, role_id)
|
||||
role_info['role-name'] = role_meta['name']
|
||||
role_info['config_set_update_progress'] = \
|
||||
role_meta[
|
||||
'config_set_update_progress']
|
||||
role_list.append(role_info)
|
||||
else:
|
||||
msg = "the role is not exist"
|
||||
@ -354,19 +367,21 @@ class Controller(controller.BaseController):
|
||||
for role in roles:
|
||||
if role['cluster_id'] == config_set_meta['cluster']:
|
||||
role_info = {}
|
||||
role_info['role-name']=role['name']
|
||||
role_info['config_set_update_progress']=role['config_set_update_progress']
|
||||
role_info['role-name'] = role['name']
|
||||
role_info['config_set_update_progress'] = role[
|
||||
'config_set_update_progress']
|
||||
role_list.append(role_info)
|
||||
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role_list
|
||||
|
||||
|
||||
else:
|
||||
msg = "the cluster is not exist"
|
||||
LOG.error(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
|
||||
class Config_setDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -387,6 +402,7 @@ class Config_setDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def cluster_config_set_progress(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class Config_setSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -426,9 +442,9 @@ class Config_setSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(config_set=result))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""config_sets resource factory method"""
|
||||
deserializer = Config_setDeserializer()
|
||||
serializer = Config_setSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -52,6 +52,7 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for configs resource in Daisy v1 API
|
||||
@ -120,32 +121,40 @@ class Controller(controller.BaseController):
|
||||
if PARAM in req.params:
|
||||
params[PARAM] = req.params.get(PARAM)
|
||||
return params
|
||||
|
||||
def _raise_404_if_config_set_delete(self, req, config_set_id):
|
||||
config_set = self.get_config_set_meta_or_404(req, config_set_id)
|
||||
if config_set['deleted']:
|
||||
msg = _("config_set with identifier %s has been deleted.") % config_set_id
|
||||
msg = _("config_set with identifier %s has been deleted.") % \
|
||||
config_set_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _raise_404_if_config_file_delete(self, req, config_file_id):
|
||||
config_file = self.get_config_file_meta_or_404(req, config_file_id)
|
||||
if config_file['deleted']:
|
||||
msg = _("config_file with identifier %s has been deleted.") % config_file_id
|
||||
msg = _(
|
||||
"config_file with identifier %s has been deleted.") % \
|
||||
config_file_id
|
||||
raise HTTPNotFound(msg)
|
||||
def _raise_404_if_role_exist(self,req,config_meta):
|
||||
role_id=""
|
||||
|
||||
def _raise_404_if_role_exist(self, req, config_meta):
|
||||
role_id = ""
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context)
|
||||
for role in roles:
|
||||
if role['cluster_id'] == config_meta['cluster'] and role['name'] == config_meta['role']:
|
||||
role_id=role['id']
|
||||
if role['cluster_id'] == config_meta[
|
||||
'cluster'] and role['name'] == config_meta['role']:
|
||||
role_id = role['id']
|
||||
break
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return role_id
|
||||
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("cluster with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
@utils.mutating
|
||||
@ -159,19 +168,57 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-config-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_config')
|
||||
|
||||
if config_meta.has_key('cluster'):
|
||||
orig_cluster = str(config_meta['cluster'])
|
||||
self._raise_404_if_cluster_deleted(req, orig_cluster)
|
||||
|
||||
if config_meta.has_key('role'):
|
||||
role_id=self._raise_404_if_role_exist(req,config_meta)
|
||||
if not role_id:
|
||||
msg = "the role name is not exist"
|
||||
|
||||
if ('role' in config_meta and
|
||||
'host_id' in config_meta):
|
||||
msg = "role name and host id only have one"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
elif 'role' in config_meta:
|
||||
# the first way to add config
|
||||
# when have 'role', config_set will be ignore
|
||||
if config_meta.get('cluster'):
|
||||
orig_cluster = str(config_meta['cluster'])
|
||||
self._raise_404_if_cluster_deleted(req, orig_cluster)
|
||||
else:
|
||||
msg = "cluster must be given when add config for role"
|
||||
LOG.error(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
if config_meta['role']:
|
||||
role_id = self._raise_404_if_role_exist(req, config_meta)
|
||||
if not role_id:
|
||||
msg = "the role name is not exist"
|
||||
LOG.error(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
else:
|
||||
msg = "the role name can't be empty"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
elif 'host_id' in config_meta:
|
||||
# the second way to add config
|
||||
# when have 'host_id', config_set will be ignore
|
||||
if config_meta['host_id']:
|
||||
self.get_host_meta_or_404(req, config_meta['host_id'])
|
||||
else:
|
||||
msg = "the host id can't be empty"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
elif 'config_set' in config_meta:
|
||||
# the third way to add config
|
||||
if config_meta['config_set']:
|
||||
self.get_config_set_meta_or_404(req,
|
||||
config_meta['config_set'])
|
||||
else:
|
||||
msg = "config set id can't be empty"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
else:
|
||||
msg = "no way to add config"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
config_meta = registry.config_interface_metadata(req.context, config_meta)
|
||||
config_meta = registry.config_interface_metadata(
|
||||
req.context, config_meta)
|
||||
return config_meta
|
||||
|
||||
@utils.mutating
|
||||
@ -204,14 +251,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("config %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("config %(id)s could not be "
|
||||
"deleted because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('config.delete', config)
|
||||
# self.notifier.info('config.delete', config)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -253,6 +301,7 @@ class Controller(controller.BaseController):
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(configs=configs)
|
||||
|
||||
|
||||
class ConfigDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -263,10 +312,11 @@ class ConfigDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
def add_config(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def delete_config(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class ConfigSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -293,9 +343,9 @@ class ConfigSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(config=config_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""configs resource factory method"""
|
||||
deserializer = ConfigDeserializer()
|
||||
serializer = ConfigSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -27,6 +27,7 @@ _ = i18n._
|
||||
|
||||
|
||||
class BaseController(object):
|
||||
|
||||
def get_image_meta_or_404(self, request, image_id):
|
||||
"""
|
||||
Grabs the image metadata for an image with a supplied
|
||||
@ -101,6 +102,7 @@ class BaseController(object):
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
|
||||
def get_component_meta_or_404(self, request, component_id):
|
||||
"""
|
||||
Grabs the component metadata for an component with a supplied
|
||||
@ -175,7 +177,7 @@ class BaseController(object):
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
|
||||
|
||||
def get_network_meta_or_404(self, request, network_id):
|
||||
"""
|
||||
Grabs the network metadata for an network with a supplied
|
||||
@ -199,7 +201,7 @@ class BaseController(object):
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
content_type='text/plain')
|
||||
|
||||
def get_active_image_meta_or_error(self, request, image_id):
|
||||
"""
|
||||
@ -242,7 +244,7 @@ class BaseController(object):
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type='text/plain')
|
||||
|
||||
|
||||
def get_config_file_meta_or_404(self, request, config_file_id):
|
||||
"""
|
||||
Grabs the config_file metadata for an config_file with a supplied
|
||||
@ -291,7 +293,7 @@ class BaseController(object):
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
content_type='text/plain')
|
||||
|
||||
def get_config_meta_or_404(self, request, config_id):
|
||||
"""
|
||||
@ -342,7 +344,7 @@ class BaseController(object):
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
|
||||
|
||||
def get_cinder_volume_meta_or_404(self, request, id):
|
||||
"""
|
||||
Grabs the config metadata for an config with a supplied
|
||||
@ -366,4 +368,4 @@ class BaseController(object):
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=request,
|
||||
content_type='text/plain')
|
||||
content_type='text/plain')
|
||||
|
@ -16,19 +16,15 @@
|
||||
"""
|
||||
/hosts endpoint for Daisy v1 API
|
||||
"""
|
||||
import time
|
||||
import traceback
|
||||
import ast
|
||||
import webob.exc
|
||||
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPServerError
|
||||
from webob.exc import HTTPNotFound
|
||||
from webob.exc import HTTPConflict
|
||||
from webob import Response
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
|
||||
@ -43,10 +39,6 @@ import daisy.registry.client.v1.api as registry
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -56,13 +48,15 @@ _LW = i18n._LW
|
||||
SUPPORTED_PARAMS = daisy.api.v1.SUPPORTED_PARAMS
|
||||
SUPPORTED_FILTERS = daisy.api.v1.SUPPORTED_FILTERS
|
||||
ACTIVE_IMMUTABLE = daisy.api.v1.ACTIVE_IMMUTABLE
|
||||
SERVICE_DISK_SERVICE = ('db', 'glance', 'dbbackup', 'mongodb', 'nova')
|
||||
DISK_LOCATION = ('local', 'share')
|
||||
CINDER_VOLUME_BACKEND_PARAMS = ('management_ips', 'data_ips','pools',
|
||||
SERVICE_DISK_SERVICE = ('db', 'glance', 'db_backup', 'mongodb', 'nova')
|
||||
DISK_LOCATION = ('local', 'share', 'share_cluster')
|
||||
PROTOCOL_TYPE = ('FIBER', 'ISCSI', 'CEPH')
|
||||
CINDER_VOLUME_BACKEND_PARAMS = ('management_ips', 'data_ips', 'pools',
|
||||
'volume_driver', 'volume_type',
|
||||
'role_id', 'user_name','user_pwd')
|
||||
'role_id', 'user_name', 'user_pwd')
|
||||
CINDER_VOLUME_BACKEND_DRIVER = ['KS3200_IPSAN', 'KS3200_FCSAN',
|
||||
'FUJISTU_ETERNUS']
|
||||
'FUJITSU_ETERNUS', 'HP3PAR_FCSAN']
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
@ -82,6 +76,7 @@ class Controller(controller.BaseController):
|
||||
data for a previously-reserved host
|
||||
DELETE /hosts/<ID> -- Delete the host with id <ID>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
registry.configure_registry_client()
|
||||
@ -99,7 +94,7 @@ class Controller(controller.BaseController):
|
||||
self.policy.enforce(req.context, action, target)
|
||||
except exception.Forbidden:
|
||||
raise HTTPForbidden()
|
||||
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""
|
||||
Return a dictionary of query param filters from the request
|
||||
@ -146,39 +141,57 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_service_disk_deleted(self, req, service_disk_id):
|
||||
service_disk = self.get_service_disk_meta_or_404(req, service_disk_id)
|
||||
if service_disk is None or service_disk['deleted']:
|
||||
msg = _("service_disk with identifier %s has been deleted.") % service_disk_id
|
||||
msg = _(
|
||||
"service_disk with identifier %s has been deleted.") % \
|
||||
service_disk_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _default_value_set(self, disk_meta):
|
||||
if (not disk_meta.has_key('disk_location') or
|
||||
not disk_meta['disk_location'] or
|
||||
disk_meta['disk_location'] == ''):
|
||||
disk_meta['disk_location'] = 'local'
|
||||
if not disk_meta.has_key('lun'):
|
||||
disk_meta['lun'] = 0
|
||||
if not disk_meta.has_key('size'):
|
||||
disk_meta['size'] = -1
|
||||
|
||||
def _unique_service_in_role(self, req, disk_meta):
|
||||
def _default_value_set(self, disk_meta):
|
||||
if ('disk_location' not in disk_meta or
|
||||
not disk_meta['disk_location'] or
|
||||
disk_meta['disk_location'] == ''):
|
||||
disk_meta['disk_location'] = 'local'
|
||||
if 'lun' not in disk_meta:
|
||||
disk_meta['lun'] = 0
|
||||
if 'size' not in disk_meta:
|
||||
disk_meta['size'] = -1
|
||||
if 'protocol_type' not in disk_meta:
|
||||
disk_meta['protocol_type'] = 'ISCSI'
|
||||
|
||||
def _unique_service_in_role(self, req, disk_meta):
|
||||
params = {'filters': {'role_id': disk_meta['role_id']}}
|
||||
service_disks = registry.list_service_disk_metadata(req.context, **params)
|
||||
for service_disk in service_disks:
|
||||
if service_disk['service'] == disk_meta['service']:
|
||||
msg = "disk service %s has existed in role %s" %(disk_meta['service'], disk_meta['role_id'])
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
service_disks = registry.list_service_disk_metadata(
|
||||
req.context, **params)
|
||||
if disk_meta['disk_location'] == 'share_cluster':
|
||||
for disk in service_disks:
|
||||
if disk['service'] == disk_meta['service'] and \
|
||||
disk['disk_location'] != 'share_cluster':
|
||||
id = disk['id']
|
||||
registry.delete_service_disk_metadata(req.context, id)
|
||||
else:
|
||||
for service_disk in service_disks:
|
||||
if service_disk['disk_location'] == 'share_cluster' and \
|
||||
service_disk['service'] == disk_meta['service']:
|
||||
id = service_disk['id']
|
||||
registry.delete_service_disk_metadata(req.context, id)
|
||||
elif service_disk['service'] == disk_meta['service']:
|
||||
msg = "disk service %s has existed in role %s" % (
|
||||
disk_meta['service'], disk_meta['role_id'])
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
def _service_disk_add_meta_valid(self, req, disk_meta):
|
||||
if not disk_meta.has_key('role_id'):
|
||||
if 'role_id' not in disk_meta:
|
||||
msg = "'role_id' must be given"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
self._raise_404_if_role_deleted(req,disk_meta['role_id'])
|
||||
self._raise_404_if_role_deleted(req, disk_meta['role_id'])
|
||||
|
||||
if not disk_meta.has_key('service'):
|
||||
if 'service' not in disk_meta:
|
||||
msg = "'service' must be given"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
@ -187,20 +200,22 @@ class Controller(controller.BaseController):
|
||||
if disk_meta['service'] not in SERVICE_DISK_SERVICE:
|
||||
msg = "service '%s' is not supported" % disk_meta['service']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if disk_meta['disk_location'] not in DISK_LOCATION:
|
||||
msg = "disk_location %s is not supported" % disk_meta['disk_location']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if disk_meta['disk_location'] == 'share' and not disk_meta.has_key('data_ips'):
|
||||
msg = "'data_ips' must be given when disk_location is share"
|
||||
msg = "disk_location %s is not supported" % disk_meta[
|
||||
'disk_location']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if disk_meta['disk_location'] in ['share', 'share_cluster'] \
|
||||
and 'data_ips' not in disk_meta:
|
||||
msg = "'data_ips' must be given when disk_location was not local"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if disk_meta['lun'] < 0:
|
||||
msg = "'lun' should not be less than 0"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
@ -218,48 +233,65 @@ class Controller(controller.BaseController):
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
self._unique_service_in_role(req, disk_meta)
|
||||
|
||||
if disk_meta.get('protocol_type', None) \
|
||||
and disk_meta['protocol_type'] not in PROTOCOL_TYPE:
|
||||
msg = "protocol type %s is not supported" % disk_meta[
|
||||
'protocol_type']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
self._unique_service_in_role(req, disk_meta)
|
||||
|
||||
def _service_disk_update_meta_valid(self, req, id, disk_meta):
|
||||
orig_disk_meta = self.get_service_disk_meta_or_404(req, id)
|
||||
if disk_meta.has_key('role_id'):
|
||||
self._raise_404_if_role_deleted(req,disk_meta['role_id'])
|
||||
if 'role_id' in disk_meta:
|
||||
self._raise_404_if_role_deleted(req, disk_meta['role_id'])
|
||||
|
||||
if disk_meta.has_key('service'):
|
||||
if 'service' in disk_meta:
|
||||
if disk_meta['service'] not in SERVICE_DISK_SERVICE:
|
||||
msg = "service '%s' is not supported" % disk_meta['service']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if disk_meta.has_key('disk_location'):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if 'disk_location' in disk_meta:
|
||||
if disk_meta['disk_location'] not in DISK_LOCATION:
|
||||
msg = "disk_location '%s' is not supported" % disk_meta['disk_location']
|
||||
msg = "disk_location '%s' is not supported" % disk_meta[
|
||||
'disk_location']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if (disk_meta['disk_location'] == 'share' and
|
||||
not disk_meta.has_key('data_ips') and
|
||||
not orig_disk_meta['data_ips']):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if (disk_meta['disk_location'] == 'share' and
|
||||
'data_ips' not in disk_meta and
|
||||
not orig_disk_meta['data_ips']):
|
||||
msg = "'data_ips' must be given when disk_location is share"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if disk_meta.has_key('size'):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
if 'size' in disk_meta:
|
||||
disk_meta['size'] = ast.literal_eval(str(disk_meta['size']))
|
||||
if not isinstance(disk_meta['size'], int):
|
||||
msg = "'size' is not integer"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if disk_meta['size'] < -1:
|
||||
msg = "'size' is invalid"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
|
||||
if disk_meta.get('protocol_type', None) \
|
||||
and disk_meta['protocol_type'] not in PROTOCOL_TYPE:
|
||||
msg = "protocol type %s is not supported" % disk_meta[
|
||||
'protocol_type']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
@utils.mutating
|
||||
def service_disk_add(self, req, disk_meta):
|
||||
"""
|
||||
@ -269,19 +301,19 @@ class Controller(controller.BaseController):
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
|
||||
|
||||
self._enforce(req, 'service_disk_add')
|
||||
self._default_value_set(disk_meta)
|
||||
self._service_disk_add_meta_valid(req, disk_meta)
|
||||
service_disk_meta = registry.add_service_disk_metadata(req.context, disk_meta)
|
||||
service_disk_meta = registry.add_service_disk_metadata(
|
||||
req.context, disk_meta)
|
||||
return {'disk_meta': service_disk_meta}
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def service_disk_delete(self, req, id):
|
||||
"""
|
||||
Deletes a service_disk from Daisy.
|
||||
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param image_meta: Mapping of metadata about service_disk
|
||||
|
||||
@ -305,7 +337,8 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("service_disk %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("service_disk %(id)s could not be deleted "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
@ -319,9 +352,8 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'service_disk_update')
|
||||
self._service_disk_update_meta_valid(req, id, disk_meta)
|
||||
try:
|
||||
service_disk_meta = registry.update_service_disk_metadata(req.context,
|
||||
id,
|
||||
disk_meta)
|
||||
service_disk_meta = registry.update_service_disk_metadata(
|
||||
req.context, id, disk_meta)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update role metadata. Got error: %s") %
|
||||
@ -353,7 +385,6 @@ class Controller(controller.BaseController):
|
||||
self.notifier.info('role.update', service_disk_meta)
|
||||
|
||||
return {'disk_meta': service_disk_meta}
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def service_disk_detail(self, req, id):
|
||||
@ -374,53 +405,61 @@ class Controller(controller.BaseController):
|
||||
def service_disk_list(self, req):
|
||||
self._enforce(req, 'service_disk_list')
|
||||
params = self._get_query_params(req)
|
||||
filters=params.get('filters',None)
|
||||
filters = params.get('filters', None)
|
||||
if 'role_id' in filters:
|
||||
role_id=filters['role_id']
|
||||
role_id = filters['role_id']
|
||||
self._raise_404_if_role_deleted(req, role_id)
|
||||
try:
|
||||
service_disks = registry.list_service_disk_metadata(req.context, **params)
|
||||
service_disks = registry.list_service_disk_metadata(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(disk_meta=service_disks)
|
||||
|
||||
|
||||
def _cinder_volume_list(self, req, params):
|
||||
try:
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(req.context, **params)
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return cinder_volumes
|
||||
|
||||
def _is_cinder_volume_repeat(self, req, array_disk_info, update_id = None):
|
||||
cinder_volume_id = None
|
||||
|
||||
def _is_cinder_volume_repeat(self, req, array_disk_info, update_id=None):
|
||||
params = {'filters': {}}
|
||||
|
||||
|
||||
if update_id:
|
||||
cinder_volume_metal = self.get_cinder_volume_meta_or_404(req, update_id)
|
||||
new_management_ips = array_disk_info.get('management_ips', cinder_volume_metal['management_ips']).split(",")
|
||||
new_pools = array_disk_info.get('pools', cinder_volume_metal['pools']).split(",")
|
||||
cinder_volume_metal = self.get_cinder_volume_meta_or_404(
|
||||
req, update_id)
|
||||
new_management_ips = array_disk_info.get(
|
||||
'management_ips', cinder_volume_metal[
|
||||
'management_ips']).split(",")
|
||||
new_pools = array_disk_info.get(
|
||||
'pools', cinder_volume_metal['pools']).split(",")
|
||||
else:
|
||||
new_management_ips = array_disk_info['management_ips'].split(",")
|
||||
new_pools = array_disk_info['pools'].split(",")
|
||||
|
||||
|
||||
org_cinder_volumes = self._cinder_volume_list(req, params)
|
||||
for cinder_volume in org_cinder_volumes:
|
||||
if (set(cinder_volume['management_ips'].split(",")) == set(new_management_ips) and
|
||||
set(cinder_volume['pools'].split(",")) == set(new_pools)):
|
||||
if (set(cinder_volume['management_ips'].split(",")) == set(
|
||||
new_management_ips) and
|
||||
set(cinder_volume['pools'].split(",")) == set(new_pools)):
|
||||
if cinder_volume['id'] != update_id:
|
||||
msg = 'cinder_volume array disks conflict with cinder_volume %s' % cinder_volume['id']
|
||||
msg = 'cinder_volume array disks ' \
|
||||
'conflict with cinder_volume %s' % cinder_volume[
|
||||
'id']
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
|
||||
def _get_cinder_volume_backend_index(self, req, disk_array):
|
||||
params = {'filters': {}}
|
||||
cinder_volumes = self._cinder_volume_list(req, params)
|
||||
index = 1
|
||||
while True:
|
||||
backend_index = "%s-%s" %(disk_array['volume_driver'], index)
|
||||
backend_index = "%s-%s" % (disk_array['volume_driver'], index)
|
||||
flag = True
|
||||
for cinder_volume in cinder_volumes:
|
||||
if backend_index == cinder_volume['backend_index']:
|
||||
index=index+1
|
||||
index = index + 1
|
||||
flag = False
|
||||
break
|
||||
if flag:
|
||||
@ -437,46 +476,52 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
self._enforce(req, 'cinder_volume_add')
|
||||
if not disk_meta.has_key('role_id'):
|
||||
if 'role_id' not in disk_meta:
|
||||
msg = "'role_id' must be given"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
self._raise_404_if_role_deleted(req,disk_meta['role_id'])
|
||||
self._raise_404_if_role_deleted(req, disk_meta['role_id'])
|
||||
|
||||
disk_arrays = eval(disk_meta['disk_array'])
|
||||
for disk_array in disk_arrays:
|
||||
for key in disk_array.keys():
|
||||
if (key not in CINDER_VOLUME_BACKEND_PARAMS and
|
||||
key != 'data_ips'):
|
||||
key != 'data_ips'):
|
||||
msg = "'%s' must be given for cinder volume config" % key
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if disk_array['volume_driver'] not in CINDER_VOLUME_BACKEND_DRIVER:
|
||||
msg = "volume_driver %s is not supported" % disk_array['volume_driver']
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if disk_array[
|
||||
'volume_driver'] not in CINDER_VOLUME_BACKEND_DRIVER:
|
||||
msg = "volume_driver %s is not supported" % disk_array[
|
||||
'volume_driver']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if (disk_array['volume_driver'] == 'FUJISTU_ETERNUS' and
|
||||
(not disk_array.has_key('data_ips') or
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if (disk_array['volume_driver'] == 'FUJITSU_ETERNUS' and
|
||||
('data_ips' not in disk_array or
|
||||
not disk_array['data_ips'])):
|
||||
msg = "data_ips must be given when using FUJISTU Disk Array"
|
||||
msg = "data_ips must be given " \
|
||||
"when using FUJITSU Disk Array"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
self._is_cinder_volume_repeat(req, disk_array)
|
||||
disk_array['role_id'] = disk_meta['role_id']
|
||||
disk_array['backend_index'] = self._get_cinder_volume_backend_index(req, disk_array)
|
||||
cinder_volumes = registry.add_cinder_volume_metadata(req.context, disk_array)
|
||||
disk_array['backend_index'] = \
|
||||
self._get_cinder_volume_backend_index(
|
||||
req, disk_array)
|
||||
cinder_volumes = registry.add_cinder_volume_metadata(
|
||||
req.context, disk_array)
|
||||
return {'disk_meta': cinder_volumes}
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def cinder_volume_delete(self, req, id):
|
||||
"""
|
||||
Deletes a service_disk from Daisy.
|
||||
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param image_meta: Mapping of metadata about service_disk
|
||||
|
||||
@ -500,7 +545,8 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("cindre volume %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("cindre volume %(id)s could not "
|
||||
"be deleted because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
@ -510,20 +556,21 @@ class Controller(controller.BaseController):
|
||||
return Response(body='', status=200)
|
||||
|
||||
def _is_data_ips_valid(self, req, update_id, update_meta):
|
||||
orgin_cinder_volume = self.get_cinder_volume_meta_or_404(req, update_id)
|
||||
orgin_cinder_volume = self.get_cinder_volume_meta_or_404(
|
||||
req, update_id)
|
||||
|
||||
new_driver = update_meta.get('volume_driver',
|
||||
orgin_cinder_volume['volume_driver'])
|
||||
if new_driver != 'FUJISTU_ETERNUS':
|
||||
new_driver = update_meta.get('volume_driver',
|
||||
orgin_cinder_volume['volume_driver'])
|
||||
if new_driver != 'FUJITSU_ETERNUS':
|
||||
return
|
||||
|
||||
new_data_ips = update_meta.get('data_ips',
|
||||
orgin_cinder_volume['data_ips'])
|
||||
orgin_cinder_volume['data_ips'])
|
||||
if not new_data_ips:
|
||||
msg = "data_ips must be given when using FUJISTU Disk Array"
|
||||
msg = "data_ips must be given when using FUJITSU Disk Array"
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
@utils.mutating
|
||||
def cinder_volume_update(self, req, id, disk_meta):
|
||||
@ -531,28 +578,29 @@ class Controller(controller.BaseController):
|
||||
if key not in CINDER_VOLUME_BACKEND_PARAMS:
|
||||
msg = "'%s' must be given for cinder volume config" % key
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if disk_meta.has_key('role_id'):
|
||||
self._raise_404_if_role_deleted(req,disk_meta['role_id'])
|
||||
if (disk_meta.has_key('volume_driver') and
|
||||
disk_meta['volume_driver'] not in CINDER_VOLUME_BACKEND_DRIVER):
|
||||
msg = "volume_driver %s is not supported" % disk_meta['volume_driver']
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if 'role_id' in disk_meta:
|
||||
self._raise_404_if_role_deleted(req, disk_meta['role_id'])
|
||||
if ('volume_driver' in disk_meta and disk_meta[
|
||||
'volume_driver'] not in CINDER_VOLUME_BACKEND_DRIVER):
|
||||
msg = "volume_driver %s is not supported" % disk_meta[
|
||||
'volume_driver']
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
self._is_cinder_volume_repeat(req, disk_meta, id)
|
||||
self._is_data_ips_valid(req, id, disk_meta)
|
||||
|
||||
try:
|
||||
cinder_volume_meta = registry.update_cinder_volume_metadata(req.context,
|
||||
id,
|
||||
disk_meta)
|
||||
cinder_volume_meta = registry.update_cinder_volume_metadata(
|
||||
req.context, id, disk_meta)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update cinder_volume metadata. Got error: %s") %
|
||||
utils.exception_to_str(e))
|
||||
msg = (
|
||||
_("Failed to update cinder_volume metadata. Got error: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
@ -580,7 +628,7 @@ class Controller(controller.BaseController):
|
||||
self.notifier.info('cinder_volume.update', cinder_volume_meta)
|
||||
|
||||
return {'disk_meta': cinder_volume_meta}
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def cinder_volume_detail(self, req, id):
|
||||
"""
|
||||
@ -595,17 +643,17 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'cinder_volume_detail')
|
||||
cinder_volume_meta = self.get_cinder_volume_meta_or_404(req, id)
|
||||
return {'disk_meta': cinder_volume_meta}
|
||||
|
||||
|
||||
def cinder_volume_list(self, req):
|
||||
self._enforce(req, 'cinder_volume_list')
|
||||
params = self._get_query_params(req)
|
||||
filters=params.get('filters',None)
|
||||
filters = params.get('filters', None)
|
||||
if 'role_id' in filters:
|
||||
role_id=filters['role_id']
|
||||
role_id = filters['role_id']
|
||||
self._raise_404_if_role_deleted(req, role_id)
|
||||
cinder_volumes = self._cinder_volume_list(req, params)
|
||||
return dict(disk_meta=cinder_volumes)
|
||||
|
||||
|
||||
|
||||
class DiskArrayDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
@ -614,19 +662,20 @@ class DiskArrayDeserializer(wsgi.JSONRequestDeserializer):
|
||||
result = {}
|
||||
result["disk_meta"] = utils.get_dict_meta(request)
|
||||
return result
|
||||
|
||||
|
||||
def service_disk_add(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def service_disk_update(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def cinder_volume_add(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def cinder_volume_update(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
|
||||
class DiskArraySerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -634,33 +683,30 @@ class DiskArraySerializer(wsgi.JSONResponseSerializer):
|
||||
self.notifier = notifier.Notifier()
|
||||
|
||||
def service_disk_add(self, response, result):
|
||||
disk_meta = result['disk_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def service_disk_update(self, response, result):
|
||||
disk_meta = result['disk_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def cinder_volume_add(self, response, result):
|
||||
disk_meta = result['disk_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def cinder_volume_update(self, response, result):
|
||||
disk_meta = result['disk_meta']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Image members resource factory method"""
|
||||
deserializer = DiskArrayDeserializer()
|
||||
|
@ -24,8 +24,8 @@ from webob.exc import HTTPConflict
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPNotFound
|
||||
from webob import Response
|
||||
import copy
|
||||
import json
|
||||
|
||||
# import json
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
@ -41,7 +41,7 @@ import daisy.registry.client.v1.api as registry
|
||||
from daisy.registry.api.v1 import template
|
||||
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
@ -64,21 +64,26 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for Templates resource in Daisy v1 API
|
||||
|
||||
The HostTemplates resource API is a RESTful web Template for Template data. The API
|
||||
is as follows::
|
||||
The HostTemplates resource API is a RESTful web Template for Template data.
|
||||
The API is as follows::
|
||||
|
||||
GET /HostTemplates -- Returns a set of brief metadata about Templates
|
||||
GET /HostTemplates/detail -- Returns a set of detailed metadata about
|
||||
HostTemplates
|
||||
HEAD /HostTemplates/<ID> -- Return metadata about an Template with id <ID>
|
||||
GET /HostTemplates/<ID> -- Return Template data for Template with id <ID>
|
||||
POST /HostTemplates -- Store Template data and return metadata about the
|
||||
HEAD /HostTemplates/<ID> --
|
||||
Return metadata about an Template with id <ID>
|
||||
GET /HostTemplates/<ID> --
|
||||
Return Template data for Template with id <ID>
|
||||
POST /HostTemplates --
|
||||
Store Template data and return metadata about the
|
||||
newly-stored Template
|
||||
PUT /HostTemplates/<ID> -- Update Template metadata and/or upload Template
|
||||
PUT /HostTemplates/<ID> --
|
||||
Update Template metadata and/or upload Template
|
||||
data for a previously-reserved Template
|
||||
DELETE /HostTemplates/<ID> -- Delete the Template with id <ID>
|
||||
"""
|
||||
@ -136,8 +141,9 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("Cluster with identifier %s has been deleted.") % cluster_id
|
||||
raise webob.exc.HTTPNotFound(msg)
|
||||
msg = _("Cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
@utils.mutating
|
||||
def add_template(self, req, host_template):
|
||||
@ -150,9 +156,9 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-Template-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_host_template')
|
||||
template_name = host_template["name"]
|
||||
|
||||
host_template = registry.add_host_template_metadata(req.context, host_template)
|
||||
|
||||
host_template = registry.add_host_template_metadata(
|
||||
req.context, host_template)
|
||||
|
||||
return {'host_template': template}
|
||||
|
||||
@ -167,7 +173,7 @@ class Controller(controller.BaseController):
|
||||
:retval Returns the updated image information as a mapping
|
||||
"""
|
||||
self._enforce(req, 'update_host_template')
|
||||
#orig_Template_meta = self.get_Template_meta_or_404(req, id)
|
||||
# orig_Template_meta = self.get_Template_meta_or_404(req, id)
|
||||
'''
|
||||
if orig_Template_meta['deleted']:
|
||||
msg = _("Forbidden to update deleted Template.")
|
||||
@ -176,9 +182,8 @@ class Controller(controller.BaseController):
|
||||
content_type="text/plain")
|
||||
'''
|
||||
try:
|
||||
host_template = registry.update_host_template_metadata(req.context,
|
||||
template_id,
|
||||
host_template)
|
||||
host_template = registry.update_host_template_metadata(
|
||||
req.context, template_id, host_template)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update template metadata. Got error: %s") %
|
||||
@ -210,47 +215,51 @@ class Controller(controller.BaseController):
|
||||
self.notifier.info('host_template.update', host_template)
|
||||
|
||||
return {'host_template': host_template}
|
||||
|
||||
|
||||
def _filter_params(self, host_meta):
|
||||
for key in host_meta.keys():
|
||||
if key=="id" or key=="updated_at" or key=="deleted_at" or key=="created_at" or key=="deleted":
|
||||
if key == "id" or key == "updated_at" or key == "deleted_at" or \
|
||||
key == "created_at" or key == "deleted":
|
||||
del host_meta[key]
|
||||
if host_meta.has_key("memory"):
|
||||
if "memory" in host_meta:
|
||||
del host_meta['memory']
|
||||
|
||||
if host_meta.has_key("system"):
|
||||
|
||||
if "system" in host_meta:
|
||||
del host_meta['system']
|
||||
|
||||
if host_meta.has_key("disks"):
|
||||
del host_meta['disks']
|
||||
|
||||
if host_meta.has_key("os_status"):
|
||||
del host_meta['os_status']
|
||||
|
||||
if host_meta.has_key("status"):
|
||||
del host_meta['status']
|
||||
if "disks" in host_meta:
|
||||
del host_meta['disks']
|
||||
|
||||
if host_meta.has_key("messages"):
|
||||
del host_meta['messages']
|
||||
|
||||
if host_meta.has_key("cpu"):
|
||||
if "os_status" in host_meta:
|
||||
del host_meta['os_status']
|
||||
|
||||
if "status" in host_meta:
|
||||
del host_meta['status']
|
||||
|
||||
if "messages" in host_meta:
|
||||
del host_meta['messages']
|
||||
|
||||
if "cpu" in host_meta:
|
||||
del host_meta['cpu']
|
||||
|
||||
if host_meta.has_key("ipmi_addr"):
|
||||
if "ipmi_addr" in host_meta:
|
||||
del host_meta['ipmi_addr']
|
||||
|
||||
if host_meta.has_key("interfaces"):
|
||||
if "interfaces" in host_meta:
|
||||
for interface in host_meta['interfaces']:
|
||||
for key in interface.keys():
|
||||
if key=="id" or key=="updated_at" or key=="deleted_at" \
|
||||
or key=="created_at" or key=="deleted" or key=="current_speed" \
|
||||
or key=="max_speed" or key=="host_id" or key=="state":
|
||||
if key == "id" or key == "updated_at" or \
|
||||
key == "deleted_at" \
|
||||
or key == "created_at" or key == "deleted" or \
|
||||
key == "current_speed" \
|
||||
or key == "max_speed" or key == "host_id" or \
|
||||
key == "state":
|
||||
del interface[key]
|
||||
for assigned_network in interface['assigned_networks']:
|
||||
if assigned_network.has_key("ip"):
|
||||
assigned_network['ip'] = ""
|
||||
return host_meta
|
||||
|
||||
if "ip" in assigned_network:
|
||||
assigned_network['ip'] = ""
|
||||
return host_meta
|
||||
|
||||
@utils.mutating
|
||||
def get_host_template_detail(self, req, template_id):
|
||||
"""
|
||||
@ -263,7 +272,8 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'get_host_template_detail')
|
||||
try:
|
||||
host_template = registry.host_template_detail_metadata(req.context, template_id)
|
||||
host_template = registry.host_template_detail_metadata(
|
||||
req.context, template_id)
|
||||
return {'host_template': host_template}
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find host template: %s") %
|
||||
@ -280,30 +290,33 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("host template %(id)s could not be get because it is in use: "
|
||||
"%(exc)s") % {"id": template_id, "exc": utils.exception_to_str(e)})
|
||||
msg = (_("host template %(id)s could not be get "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": template_id,
|
||||
"exc": utils.exception_to_str(e)})
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('host.delete', host)
|
||||
# self.notifier.info('host.delete', host)
|
||||
return Response(body='', status=200)
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def get_host_template_lists(self, req):
|
||||
self._enforce(req, 'get_template_lists')
|
||||
params = self._get_query_params(req)
|
||||
template_meta = {}
|
||||
try:
|
||||
host_template_lists = registry.host_template_lists_metadata(req.context, **params)
|
||||
host_template_lists = registry.host_template_lists_metadata(
|
||||
req.context, **params)
|
||||
if host_template_lists and host_template_lists[0]:
|
||||
template_meta = json.loads(host_template_lists[0]['hosts'])
|
||||
return {'host_template': template_meta}
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(host_template=host_template_lists)
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def host_to_template(self, req, host_template):
|
||||
"""
|
||||
@ -315,21 +328,32 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'host_to_template')
|
||||
if host_template.get('host_id', None):
|
||||
origin_host_meta = self.get_host_meta_or_404(req, host_template['host_id'])
|
||||
origin_host_meta = self.get_host_meta_or_404(
|
||||
req, host_template['host_id'])
|
||||
host_meta = self._filter_params(origin_host_meta)
|
||||
if host_template.get('host_template_name', None) and host_template.get('cluster_name', None):
|
||||
if host_template.get(
|
||||
'host_template_name',
|
||||
None) and host_template.get(
|
||||
'cluster_name',
|
||||
None):
|
||||
host_meta['name'] = host_template['host_template_name']
|
||||
host_meta['description'] = host_template.get('description', None)
|
||||
params = {'filters':{'cluster_name':host_template['cluster_name']}}
|
||||
templates = registry.host_template_lists_metadata(req.context, **params)
|
||||
if templates and templates[0]:
|
||||
host_meta['description'] = host_template.get(
|
||||
'description', None)
|
||||
params = {
|
||||
'filters': {
|
||||
'cluster_name': host_template['cluster_name']}}
|
||||
templates = registry.host_template_lists_metadata(
|
||||
req.context, **params)
|
||||
if templates and templates[0]:
|
||||
had_host_template = False
|
||||
if templates[0]['hosts']:
|
||||
templates[0]['hosts'] = json.loads(templates[0]['hosts'])
|
||||
templates[0]['hosts'] = json.loads(
|
||||
templates[0]['hosts'])
|
||||
else:
|
||||
templates[0]['hosts'] = []
|
||||
for index in range(len(templates[0]['hosts'])):
|
||||
if host_template['host_template_name'] == templates[0]['hosts'][index]['name']:
|
||||
if host_template['host_template_name'] == templates[
|
||||
0]['hosts'][index]['name']:
|
||||
had_host_template = True
|
||||
templates[0]['hosts'][index] = host_meta
|
||||
break
|
||||
@ -337,12 +361,15 @@ class Controller(controller.BaseController):
|
||||
host_meta['name'] = host_template['host_template_name']
|
||||
templates[0]['hosts'].append(host_meta)
|
||||
templates[0]['hosts'] = json.dumps(templates[0]['hosts'])
|
||||
host_template = registry.update_host_template_metadata(req.context,
|
||||
templates[0]['id'],
|
||||
templates[0])
|
||||
host_template = registry.update_host_template_metadata(
|
||||
req.context, templates[0]['id'], templates[0])
|
||||
else:
|
||||
param = {"cluster_name": host_template['cluster_name'], "hosts":json.dumps([host_meta])}
|
||||
host_template = registry.add_host_template_metadata(req.context, param)
|
||||
param = {
|
||||
"cluster_name": host_template['cluster_name'],
|
||||
"hosts": json.dumps(
|
||||
[host_meta])}
|
||||
host_template = registry.add_host_template_metadata(
|
||||
req.context, param)
|
||||
return {'host_template': host_template}
|
||||
|
||||
@utils.mutating
|
||||
@ -350,8 +377,9 @@ class Controller(controller.BaseController):
|
||||
if not host_template.get('cluster_name', None):
|
||||
msg = "cluster name is null"
|
||||
raise HTTPNotFound(explanation=msg)
|
||||
params = {'filters':{'cluster_name':host_template['cluster_name']}}
|
||||
templates = registry.host_template_lists_metadata(req.context, **params)
|
||||
params = {'filters': {'cluster_name': host_template['cluster_name']}}
|
||||
templates = registry.host_template_lists_metadata(
|
||||
req.context, **params)
|
||||
hosts_param = []
|
||||
host_template_used = {}
|
||||
if templates and templates[0]:
|
||||
@ -362,66 +390,79 @@ class Controller(controller.BaseController):
|
||||
break
|
||||
if not host_template_used:
|
||||
msg = "not host_template %s" % host_template['host_template_name']
|
||||
raise HTTPNotFound(explanation=msg, request=req, content_type="text/plain")
|
||||
raise HTTPNotFound(
|
||||
explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if host_template.get('host_id', None):
|
||||
self.get_host_meta_or_404(req, host_template['host_id'])
|
||||
else:
|
||||
msg="host_id is not null"
|
||||
raise HTTPBadRequest(explanation = msg)
|
||||
msg = "host_id is not null"
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
host_id = host_template['host_id']
|
||||
params = {'filters':{'name': host_template['cluster_name']}}
|
||||
params = {'filters': {'name': host_template['cluster_name']}}
|
||||
clusters = registry.get_clusters_detail(req.context, **params)
|
||||
if clusters and clusters[0]:
|
||||
host_template_used['cluster'] = clusters[0]['id']
|
||||
if host_template_used.has_key('role') and host_template_used['role']:
|
||||
if 'role' in host_template_used and host_template_used['role']:
|
||||
role_id_list = []
|
||||
host_role_list = []
|
||||
if host_template_used.has_key('cluster'):
|
||||
if 'cluster' in host_template_used:
|
||||
params = self._get_query_params(req)
|
||||
role_list = registry.get_roles_detail(req.context, **params)
|
||||
for role_name in role_list:
|
||||
if role_name['cluster_id'] == host_template_used['cluster']:
|
||||
if role_name['cluster_id'] == host_template_used[
|
||||
'cluster']:
|
||||
host_role_list = list(host_template_used['role'])
|
||||
if role_name['name'] in host_role_list:
|
||||
role_id_list.append(role_name['id'])
|
||||
host_template_used['role'] = role_id_list
|
||||
if host_template_used.has_key('name'):
|
||||
host_template_used['role'] = role_id_list
|
||||
if 'name' in host_template_used:
|
||||
host_template_used.pop('name')
|
||||
if host_template_used.has_key('dmi_uuid'):
|
||||
if 'dmi_uuid' in host_template_used:
|
||||
host_template_used.pop('dmi_uuid')
|
||||
if host_template_used.has_key('ipmi_user'):
|
||||
if 'ipmi_user' in host_template_used:
|
||||
host_template_used.pop('ipmi_user')
|
||||
if host_template_used.has_key('ipmi_passwd'):
|
||||
if 'ipmi_passwd' in host_template_used:
|
||||
host_template_used.pop('ipmi_passwd')
|
||||
if host_template_used.has_key('ipmi_addr'):
|
||||
if 'ipmi_addr' in host_template_used:
|
||||
host_template_used.pop('ipmi_addr')
|
||||
host_template_interfaces = host_template_used.get('interfaces', None)
|
||||
if host_template_interfaces:
|
||||
template_ether_interface = [interface for interface in host_template_interfaces if interface['type'] == "ether" ]
|
||||
template_ether_interface = [
|
||||
interface for interface in host_template_interfaces if
|
||||
interface['type'] == "ether"]
|
||||
orig_host_meta = registry.get_host_metadata(req.context, host_id)
|
||||
orig_host_interfaces = orig_host_meta.get('interfaces', None)
|
||||
temp_orig_host_interfaces = [ interface for interface in orig_host_interfaces if interface['type'] == "ether" ]
|
||||
temp_orig_host_interfaces = [
|
||||
interface for interface in orig_host_interfaces if
|
||||
interface['type'] == "ether"]
|
||||
if len(temp_orig_host_interfaces) != len(template_ether_interface):
|
||||
msg = (_('host_id %s does not match the host_id host_template '
|
||||
'%s.') % (host_id, host_template['host_template_name']))
|
||||
raise HTTPBadRequest(explanation = msg)
|
||||
'%s.') % (host_id,
|
||||
host_template['host_template_name']))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
interface_match_flag = 0
|
||||
for host_template_interface in host_template_interfaces:
|
||||
if host_template_interface['type'] == 'ether':
|
||||
for orig_host_interface in orig_host_interfaces:
|
||||
if orig_host_interface['pci'] == host_template_interface['pci']:
|
||||
if orig_host_interface[
|
||||
'pci'] == host_template_interface['pci']:
|
||||
interface_match_flag += 1
|
||||
host_template_interface['mac'] = orig_host_interface['mac']
|
||||
if host_template_interface.has_key('ip'):
|
||||
host_template_interface[
|
||||
'mac'] = orig_host_interface['mac']
|
||||
if 'ip' in host_template_interface:
|
||||
host_template_interface.pop('ip')
|
||||
if interface_match_flag != len(template_ether_interface):
|
||||
msg = (_('host_id %s does not match the host '
|
||||
'host_template %s.') % (host_id, host_template['host_template_name']))
|
||||
'host_template %s.') % (
|
||||
host_id, host_template['host_template_name']))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
host_template_used['interfaces'] = str(host_template_interfaces)
|
||||
host_template = registry.update_host_metadata(req.context, host_id, host_template_used)
|
||||
host_template = registry.update_host_metadata(
|
||||
req.context, host_id, host_template_used)
|
||||
return {"host_template": host_template}
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def delete_host_template(self, req, host_template):
|
||||
"""
|
||||
@ -437,8 +478,11 @@ class Controller(controller.BaseController):
|
||||
if not host_template.get('cluster_name', None):
|
||||
msg = "cluster name is null"
|
||||
raise HTTPNotFound(explanation=msg)
|
||||
params = {'filters':{'cluster_name':host_template['cluster_name']}}
|
||||
host_templates = registry.host_template_lists_metadata(req.context, **params)
|
||||
params = {
|
||||
'filters': {
|
||||
'cluster_name': host_template['cluster_name']}}
|
||||
host_templates = registry.host_template_lists_metadata(
|
||||
req.context, **params)
|
||||
template_param = []
|
||||
had_host_template = False
|
||||
if host_templates and host_templates[0]:
|
||||
@ -449,18 +493,20 @@ class Controller(controller.BaseController):
|
||||
had_host_template = True
|
||||
break
|
||||
if not had_host_template:
|
||||
msg = "not host template name %s" %host_template['host_template_name']
|
||||
msg = "not host template name %s" % host_template[
|
||||
'host_template_name']
|
||||
raise HTTPNotFound(explanation=msg)
|
||||
else:
|
||||
host_templates[0]['hosts'] = json.dumps(template_param)
|
||||
host_template = registry.update_host_template_metadata(req.context,
|
||||
host_templates[0]['id'],
|
||||
host_templates[0])
|
||||
return {"host_template": host_template}
|
||||
host_template = registry.update_host_template_metadata(
|
||||
req.context, host_templates[0]['id'],
|
||||
host_templates[0])
|
||||
return {"host_template": host_template}
|
||||
else:
|
||||
msg = "host template cluster name %s is null" %host_template['cluster_name']
|
||||
raise HTTPNotFound(explanation=msg)
|
||||
|
||||
msg = "host template cluster name %s is null" % host_template[
|
||||
'cluster_name']
|
||||
raise HTTPNotFound(explanation=msg)
|
||||
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find host template to delete: %s") %
|
||||
utils.exception_to_str(e))
|
||||
@ -476,15 +522,18 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("template %(id)s could not be deleted because it is in use: "
|
||||
"%(exc)s") % {"id": template_id, "exc": utils.exception_to_str(e)})
|
||||
msg = (_("template %(id)s could not be deleted "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": host_template['host_id'],
|
||||
"exc": utils.exception_to_str(e)})
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
return Response(body='', status=200)
|
||||
|
||||
|
||||
|
||||
class HostTemplateDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -492,13 +541,12 @@ class HostTemplateDeserializer(wsgi.JSONRequestDeserializer):
|
||||
result = {}
|
||||
result["host_template"] = utils.get_template_meta(request)
|
||||
return result
|
||||
|
||||
|
||||
def add_host_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def update_host_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def host_to_template(self, request):
|
||||
return self._deserialize(request)
|
||||
@ -509,6 +557,7 @@ class HostTemplateDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def delete_host_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class HostTemplateSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -528,18 +577,20 @@ class HostTemplateSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(host_template=host_template))
|
||||
return response
|
||||
|
||||
def get_host_template_detail(self, response, result):
|
||||
host_template = result['host_template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(host_template=host_template))
|
||||
return response
|
||||
|
||||
def update_host_template(self, response, result):
|
||||
host_template = result['host_template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(host_template=host_template))
|
||||
return response
|
||||
return response
|
||||
|
||||
def host_to_template(self, response, result):
|
||||
host_template = result['host_template']
|
||||
@ -560,7 +611,7 @@ class HostTemplateSerializer(wsgi.JSONResponseSerializer):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(host_template=host_template))
|
||||
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Templates resource factory method"""
|
||||
|
File diff suppressed because it is too large
Load Diff
347
code/daisy/daisy/api/v1/hwms.py
Executable file
347
code/daisy/daisy/api/v1/hwms.py
Executable file
@ -0,0 +1,347 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
/Hwm endpoint for Daisy v1 API
|
||||
"""
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import webob.exc
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPConflict
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPNotFound
|
||||
from webob import Response
|
||||
|
||||
from daisy.api import policy
|
||||
import daisy.api.v1
|
||||
from daisy.api.v1 import controller
|
||||
from daisy.api.v1 import filters
|
||||
from daisy.common import exception
|
||||
from daisy.common import property_utils
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from daisy.registry.api.v1 import hwms
|
||||
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
|
||||
daisy_tecs_path = tecs_cmn.daisy_tecs_path
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
_LI = i18n._LI
|
||||
_LW = i18n._LW
|
||||
|
||||
SUPPORTED_PARAMS = hwms.SUPPORTED_PARAMS
|
||||
SUPPORTED_FILTERS = hwms.SUPPORTED_FILTERS
|
||||
ACTIVE_IMMUTABLE = daisy.api.v1.ACTIVE_IMMUTABLE
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt('disk_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for hwms resource in Daisy v1 API
|
||||
|
||||
The Templates resource API is a RESTful web Template for Template data.
|
||||
The API is as follows::
|
||||
|
||||
GET /Templates -- Returns a set of brief metadata about Templates
|
||||
GET /Templates/detail -- Returns a set of detailed metadata about
|
||||
Templates
|
||||
HEAD /Templates/<ID> -- Return metadata about an Template with id <ID>
|
||||
GET /Templates/<ID> -- Return Template data for Template with id <ID>
|
||||
POST /Templates -- Store Template data and return metadata about the
|
||||
newly-stored Template
|
||||
PUT /Templates/<ID> -- Update Template metadata and/or upload Template
|
||||
data for a previously-reserved Template
|
||||
DELETE /Templates/<ID> -- Delete the Template with id <ID>
|
||||
"""
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
registry.configure_registry_client()
|
||||
self.policy = policy.Enforcer()
|
||||
if property_utils.is_property_protection_enabled():
|
||||
self.prop_enforcer = property_utils.PropertyRules(self.policy)
|
||||
else:
|
||||
self.prop_enforcer = None
|
||||
|
||||
def _enforce(self, req, action, target=None):
|
||||
"""Authorize an action against our policies"""
|
||||
if target is None:
|
||||
target = {}
|
||||
try:
|
||||
self.policy.enforce(req.context, action, target)
|
||||
except exception.Forbidden:
|
||||
raise HTTPForbidden()
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""
|
||||
Return a dictionary of query param filters from the request
|
||||
|
||||
:param req: the Request object coming from the wsgi layer
|
||||
:retval a dict of key/value filters
|
||||
"""
|
||||
query_filters = {}
|
||||
for param in req.params:
|
||||
if param in SUPPORTED_FILTERS:
|
||||
query_filters[param] = req.params.get(param)
|
||||
if not filters.validate(param, query_filters[param]):
|
||||
raise HTTPBadRequest(_('Bad value passed to filter '
|
||||
'%(filter)s got %(val)s')
|
||||
% {'filter': param,
|
||||
'val': query_filters[param]})
|
||||
return query_filters
|
||||
|
||||
def _get_query_params(self, req):
|
||||
"""
|
||||
Extracts necessary query params from request.
|
||||
|
||||
:param req: the WSGI Request object
|
||||
:retval dict of parameters that can be used by registry client
|
||||
"""
|
||||
params = {'filters': self._get_filters(req)}
|
||||
|
||||
for PARAM in SUPPORTED_PARAMS:
|
||||
if PARAM in req.params:
|
||||
params[PARAM] = req.params.get(PARAM)
|
||||
return params
|
||||
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("Cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise webob.exc.HTTPNotFound(msg)
|
||||
|
||||
def get_clusters_hwm_ip(self, req):
|
||||
params = self._get_query_params(req)
|
||||
clusters_hwm_ip = list()
|
||||
clusters = registry.get_clusters_detail(req.context, **params)
|
||||
for cluster in clusters:
|
||||
clusters_hwm_ip.append(cluster.get('hwm_ip'))
|
||||
return clusters_hwm_ip
|
||||
|
||||
@utils.mutating
|
||||
def add_hwm(self, req, hwm):
|
||||
"""
|
||||
Adds a new hwm to Daisy.
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param image_meta: Mapping of metadata about Template
|
||||
|
||||
:raises HTTPBadRequest if x-Template-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_template')
|
||||
hwm = registry.add_hwm_metadata(req.context, hwm)
|
||||
|
||||
return {'hwm': hwm}
|
||||
|
||||
@utils.mutating
|
||||
def update_hwm(self, req, id, hwm):
|
||||
"""
|
||||
Updates an existing hwm with the registry.
|
||||
|
||||
:param request: The WSGI/Webob Request object
|
||||
:param id: The opaque image identifier
|
||||
|
||||
:retval Returns the updated image information as a mapping
|
||||
"""
|
||||
self._enforce(req, 'update_hwm')
|
||||
hwm_meta = registry.hwm_detail_metadata(req.context, id)
|
||||
hwm_ip = hwm_meta['hwm_ip']
|
||||
clusters_hwm_ip = self.get_clusters_hwm_ip(req)
|
||||
if hwm_ip in clusters_hwm_ip:
|
||||
msg = (_("Hwm %s has already used in cluster, "
|
||||
"it can not be update. " % hwm_ip))
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
try:
|
||||
hwm = registry.update_hwm_metadata(req.context, id, hwm)
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update hwm metadata. Got error: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find hwm to update: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPNotFound(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.Forbidden as e:
|
||||
msg = (_("Forbidden to update hwm: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except (exception.Conflict, exception.Duplicate) as e:
|
||||
LOG.warn(utils.exception_to_str(e))
|
||||
raise HTTPConflict(body=_('hwm operation conflicts'),
|
||||
request=req,
|
||||
content_type='text/plain')
|
||||
else:
|
||||
self.notifier.info('hwm.update', hwm)
|
||||
|
||||
return {'hwm': hwm}
|
||||
|
||||
@utils.mutating
|
||||
def delete_hwm(self, req, id):
|
||||
"""
|
||||
delete a existing hwm template with the registry.
|
||||
|
||||
:param request: The WSGI/Webob Request object
|
||||
:param id: The opaque image identifier
|
||||
|
||||
:retval Returns the updated image information as a mapping
|
||||
"""
|
||||
self._enforce(req, 'delete_hwm')
|
||||
hwm_meta = registry.hwm_detail_metadata(req.context, id)
|
||||
hwm_ip = hwm_meta['hwm_ip']
|
||||
clusters_hwm_ip = self.get_clusters_hwm_ip(req)
|
||||
if hwm_ip in clusters_hwm_ip:
|
||||
msg = (_("Hwm %s has already used in cluster, "
|
||||
"it can not be deleted. " % hwm_ip))
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
try:
|
||||
registry.delete_hwm_metadata(req.context, id)
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find hwm to delete: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.error(msg)
|
||||
raise HTTPNotFound(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
except exception.Forbidden as e:
|
||||
msg = (_("Forbidden to delete hwm: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_(
|
||||
"hwm %(id)s could not be deleted because it is in "
|
||||
"use:%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg, request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
def detail(self, req, id):
|
||||
"""
|
||||
delete a existing hwm with the registry.
|
||||
:param request: The WSGI/Webob Request object
|
||||
:param id: The opaque image identifie
|
||||
:retval Returns the updated image information as a mapping
|
||||
"""
|
||||
self._enforce(req, 'detail')
|
||||
context = req.context
|
||||
try:
|
||||
hwm_meta = registry.hwm_detail_metadata(context, id)
|
||||
except exception.NotFound:
|
||||
msg = "Hwm with identifier %s not found" % id
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPNotFound(
|
||||
msg, request=req, content_type='text/plain')
|
||||
except exception.Forbidden:
|
||||
msg = "Forbidden hwm access"
|
||||
LOG.debug(msg)
|
||||
raise webob.exc.HTTPForbidden(msg,
|
||||
request=req,
|
||||
content_type='text/plain')
|
||||
return {'hwm': hwm_meta}
|
||||
|
||||
@utils.mutating
|
||||
def list(self, req):
|
||||
self._enforce(req, 'list')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
hwm_list = registry.hwm_list_metadata(req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(hwm=hwm_list)
|
||||
|
||||
|
||||
class HwmDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
def _deserialize(self, request):
|
||||
result = {}
|
||||
result["hwm"] = utils.get_hwm_meta(request)
|
||||
return result
|
||||
|
||||
def add_hwm(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def update_hwm(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class HwmSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
|
||||
def add_hwm(self, response, result):
|
||||
hwm = result['hwm']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(hwm=hwm))
|
||||
return response
|
||||
|
||||
def delete_hwm(self, response, result):
|
||||
hwm = result['hwm']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(hwm=hwm))
|
||||
return response
|
||||
|
||||
def get_detail(self, response, result):
|
||||
hwm = result['hwm']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(hwm=hwm))
|
||||
return response
|
||||
|
||||
def update_hwm(self, response, result):
|
||||
hwm = result['hwm']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(hwm=hwm))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Templates resource factory method"""
|
||||
deserializer = HwmDeserializer()
|
||||
serializer = HwmSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
@ -905,8 +905,9 @@ class Controller(controller.BaseController):
|
||||
# Once an image is 'active' only an admin can
|
||||
# modify certain core metadata keys
|
||||
for key in ACTIVE_IMMUTABLE:
|
||||
if (orig_status == 'active' and image_meta.get(key) is not None
|
||||
and image_meta.get(key) != orig_image_meta.get(key)):
|
||||
if (orig_status == 'active' and
|
||||
image_meta.get(key) is not None and
|
||||
image_meta.get(key) != orig_image_meta.get(key)):
|
||||
msg = _("Forbidden to modify '%s' of active image.") % key
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
|
@ -17,13 +17,11 @@
|
||||
/hosts endpoint for Daisy v1 API
|
||||
"""
|
||||
import time
|
||||
import traceback
|
||||
import webob.exc
|
||||
|
||||
from oslo_log import log as logging
|
||||
from webob.exc import HTTPBadRequest
|
||||
from webob.exc import HTTPForbidden
|
||||
from webob.exc import HTTPServerError
|
||||
|
||||
from threading import Thread
|
||||
|
||||
@ -44,10 +42,6 @@ import daisy.api.backends.common as daisy_cmn
|
||||
from daisy.api.backends import driver
|
||||
from daisy.api.backends import os as os_handle
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -67,31 +61,40 @@ BACKENDS_UNINSTALL_ORDER = []
|
||||
|
||||
|
||||
def get_deployment_backends(req, cluster_id, backends_order):
|
||||
cluster_roles = daisy_cmn.get_cluster_roles_detail(req,cluster_id)
|
||||
cluster_backends = set([role['deployment_backend'] for role in cluster_roles if daisy_cmn.get_hosts_of_role(req, role['id'])])
|
||||
ordered_backends = [backend for backend in backends_order if backend in cluster_backends]
|
||||
other_backends = [backend for backend in cluster_backends if backend not in backends_order]
|
||||
deployment_backends =ordered_backends + other_backends
|
||||
return deployment_backends
|
||||
|
||||
cluster_roles = daisy_cmn.get_cluster_roles_detail(req, cluster_id)
|
||||
cluster_backends = set([role['deployment_backend']
|
||||
for role in cluster_roles if
|
||||
daisy_cmn.get_hosts_of_role(req, role['id'])])
|
||||
ordered_backends = [
|
||||
backend for backend in backends_order if backend in cluster_backends]
|
||||
other_backends = [
|
||||
backend for backend in cluster_backends if
|
||||
backend not in backends_order]
|
||||
deployment_backends = ordered_backends + other_backends
|
||||
return deployment_backends
|
||||
|
||||
|
||||
class InstallTask(object):
|
||||
"""
|
||||
Class for install OS and TECS.
|
||||
"""
|
||||
""" Definition for install states."""
|
||||
|
||||
def __init__(self, req, cluster_id):
|
||||
self.req = req
|
||||
self.cluster_id = cluster_id
|
||||
|
||||
def _backends_install(self):
|
||||
backends = get_deployment_backends(self.req, self.cluster_id, BACKENDS_INSTALL_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
self.req, self.cluster_id, BACKENDS_INSTALL_ORDER)
|
||||
if not backends:
|
||||
LOG.info(_("No backends need to install."))
|
||||
return
|
||||
for backend in backends:
|
||||
backend_driver = driver.load_deployment_dirver(backend)
|
||||
backend_driver.install(self.req, self.cluster_id)
|
||||
# this will be raise raise all the exceptions of the thread to log file
|
||||
# this will be raise raise all the exceptions of the thread to log file
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self._run()
|
||||
@ -102,43 +105,57 @@ class InstallTask(object):
|
||||
"""
|
||||
Exectue os installation with sync mode.
|
||||
:return:
|
||||
"""
|
||||
"""
|
||||
# get hosts config which need to install OS
|
||||
all_hosts_need_os = os_handle.get_cluster_hosts_config(self.req, self.cluster_id)
|
||||
all_hosts_need_os = os_handle.get_cluster_hosts_config(
|
||||
self.req, self.cluster_id)
|
||||
if all_hosts_need_os:
|
||||
hosts_with_role_need_os = [host_detail for host_detail in all_hosts_need_os if host_detail['status'] == 'with-role']
|
||||
hosts_without_role_need_os = [host_detail for host_detail in all_hosts_need_os if host_detail['status'] != 'with-role']
|
||||
hosts_with_role_need_os = [
|
||||
host_detail for host_detail in all_hosts_need_os if
|
||||
host_detail['status'] == 'with-role']
|
||||
hosts_without_role_need_os = [
|
||||
host_detail for host_detail in all_hosts_need_os if
|
||||
host_detail['status'] != 'with-role']
|
||||
else:
|
||||
LOG.info(_("No host need to install os, begin to install "
|
||||
"backends for cluster %s." % self.cluster_id))
|
||||
LOG.info(_("No host need to install os, begin to install "
|
||||
"backends for cluster %s." % self.cluster_id))
|
||||
self._backends_install()
|
||||
return
|
||||
|
||||
run_once_flag = True
|
||||
# if no hosts with role need os, install backend applications immediately
|
||||
# if no hosts with role need os, install backend applications
|
||||
# immediately
|
||||
if not hosts_with_role_need_os:
|
||||
run_once_flag = False
|
||||
role_hosts_need_os = []
|
||||
LOG.info(_("All of hosts with role is 'active', begin to install "
|
||||
"backend applications for cluster %s first." % self.cluster_id))
|
||||
LOG.info(_("All of hosts with role is 'active', begin to install "
|
||||
"backend applications for cluster %s first." %
|
||||
self.cluster_id))
|
||||
self._backends_install()
|
||||
else:
|
||||
role_hosts_need_os = [host_detail['id'] for host_detail in hosts_with_role_need_os]
|
||||
role_hosts_need_os = [host_detail['id']
|
||||
for host_detail in hosts_with_role_need_os]
|
||||
|
||||
# hosts with role put the head of the list
|
||||
order_hosts_need_os = hosts_with_role_need_os + hosts_without_role_need_os
|
||||
order_hosts_need_os = hosts_with_role_need_os + \
|
||||
hosts_without_role_need_os
|
||||
while order_hosts_need_os:
|
||||
os_install = os_handle.OSInstall(self.req, self.cluster_id)
|
||||
#all os will be installed batch by batch with max_parallel_os_number which was set in daisy-api.conf
|
||||
(order_hosts_need_os,role_hosts_need_os) = os_install.install_os(order_hosts_need_os,role_hosts_need_os)
|
||||
# after a batch of os install over, judge if all role hosts install os completely,
|
||||
# all os will be installed batch by batch with
|
||||
# max_parallel_os_number which was set in daisy-api.conf
|
||||
(order_hosts_need_os, role_hosts_need_os) = os_install.install_os(
|
||||
order_hosts_need_os, role_hosts_need_os)
|
||||
# after a batch of os install over, judge if all
|
||||
# role hosts install os completely,
|
||||
# if role_hosts_need_os is empty, install TECS immediately
|
||||
if run_once_flag and not role_hosts_need_os:
|
||||
run_once_flag = False
|
||||
#wait to reboot os after new os installed
|
||||
# wait to reboot os after new os installed
|
||||
time.sleep(10)
|
||||
LOG.info(_("All hosts with role install successfully, "
|
||||
"begin to install backend applications for cluster %s." % self.cluster_id))
|
||||
"begin to install backend applications "
|
||||
"for cluster %s." %
|
||||
self.cluster_id))
|
||||
self._backends_install()
|
||||
|
||||
|
||||
@ -160,6 +177,7 @@ class Controller(controller.BaseController):
|
||||
data for a previously-reserved host
|
||||
DELETE /hosts/<ID> -- Delete the host with id <ID>
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
registry.configure_registry_client()
|
||||
@ -177,13 +195,14 @@ class Controller(controller.BaseController):
|
||||
self.policy.enforce(req.context, action, target)
|
||||
except exception.Forbidden:
|
||||
raise HTTPForbidden()
|
||||
|
||||
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("Cluster with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("Cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise webob.exc.HTTPNotFound(msg)
|
||||
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""
|
||||
Return a dictionary of query param filters from the request
|
||||
@ -225,19 +244,24 @@ class Controller(controller.BaseController):
|
||||
|
||||
:raises HTTPBadRequest if x-install-cluster is missing
|
||||
"""
|
||||
if 'deployment_interface' in install_meta:
|
||||
os_handle.pxe_server_build(req, install_meta)
|
||||
return {"status": "pxe is installed"}
|
||||
|
||||
cluster_id = install_meta['cluster_id']
|
||||
self._enforce(req, 'install_cluster')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
if install_meta.get("deployment_interface", None):
|
||||
os_handle.pxe_server_build(req, install_meta)
|
||||
return {"status": "pxe is installed"}
|
||||
|
||||
# if have hosts need to install os, TECS installataion executed in InstallTask
|
||||
daisy_cmn.set_role_status_and_progress(
|
||||
req, cluster_id, 'install',
|
||||
{'messages': 'Waiting for TECS installation', 'progress': '0'},
|
||||
'tecs')
|
||||
# if have hosts need to install os,
|
||||
# TECS installataion executed in InstallTask
|
||||
os_install_obj = InstallTask(req, cluster_id)
|
||||
os_install_thread = Thread(target=os_install_obj.run)
|
||||
os_install_thread.start()
|
||||
return {"status":"begin install"}
|
||||
return {"status": "begin install"}
|
||||
|
||||
@utils.mutating
|
||||
def uninstall_cluster(self, req, cluster_id):
|
||||
@ -251,20 +275,24 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'uninstall_cluster')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
for backend in backends:
|
||||
backend_driver = driver.load_deployment_dirver(backend)
|
||||
uninstall_thread = Thread(target=backend_driver.uninstall, args=(req, cluster_id))
|
||||
uninstall_thread = Thread(
|
||||
target=backend_driver.uninstall, args=(
|
||||
req, cluster_id))
|
||||
uninstall_thread.start()
|
||||
return {"status":"begin uninstall"}
|
||||
|
||||
return {"status": "begin uninstall"}
|
||||
|
||||
@utils.mutating
|
||||
def uninstall_progress(self, req, cluster_id):
|
||||
self._enforce(req, 'uninstall_progress')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
|
||||
all_nodes = {}
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
if not backends:
|
||||
LOG.info(_("No backends need to uninstall."))
|
||||
return all_nodes
|
||||
@ -274,7 +302,6 @@ class Controller(controller.BaseController):
|
||||
all_nodes.update(nodes_process)
|
||||
return all_nodes
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def update_cluster(self, req, cluster_id):
|
||||
"""
|
||||
@ -287,29 +314,36 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'update_cluster')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_UPGRADE_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_UPGRADE_ORDER)
|
||||
if not backends:
|
||||
LOG.info(_("No backends need to update."))
|
||||
return {"status":""}
|
||||
return {"status": ""}
|
||||
daisy_cmn.set_role_status_and_progress(
|
||||
req, cluster_id, 'upgrade',
|
||||
{'messages': 'Waiting for TECS upgrading', 'progress': '0'},
|
||||
'tecs')
|
||||
for backend in backends:
|
||||
backend_driver = driver.load_deployment_dirver(backend)
|
||||
update_thread = Thread(target=backend_driver.upgrade, args=(req, cluster_id))
|
||||
backend_driver = driver.load_deployment_dirver(backend)
|
||||
update_thread = Thread(target=backend_driver.upgrade,
|
||||
args=(req, cluster_id))
|
||||
update_thread.start()
|
||||
return {"status":"begin update"}
|
||||
return {"status": "begin update"}
|
||||
|
||||
@utils.mutating
|
||||
def update_progress(self, req, cluster_id):
|
||||
self._enforce(req, 'update_progress')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_UPGRADE_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_UPGRADE_ORDER)
|
||||
all_nodes = {}
|
||||
for backend in backends:
|
||||
backend_driver = driver.load_deployment_dirver(backend)
|
||||
nodes_process = backend_driver.upgrade_progress(req, cluster_id)
|
||||
all_nodes.update(nodes_process)
|
||||
return all_nodes
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def export_db(self, req, install_meta):
|
||||
"""
|
||||
@ -324,7 +358,8 @@ class Controller(controller.BaseController):
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
all_config_files = {}
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_INSTALL_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_INSTALL_ORDER)
|
||||
if not backends:
|
||||
LOG.info(_("No backends need to export."))
|
||||
return all_config_files
|
||||
@ -345,17 +380,18 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'update_disk_array')
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
|
||||
tecs_backend_name = 'tecs'
|
||||
backends = get_deployment_backends(req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
backends = get_deployment_backends(
|
||||
req, cluster_id, BACKENDS_UNINSTALL_ORDER)
|
||||
if tecs_backend_name not in backends:
|
||||
message = "No tecs backend"
|
||||
LOG.info(_(message))
|
||||
else:
|
||||
backend_driver = driver.load_deployment_dirver(tecs_backend_name)
|
||||
message = backend_driver.update_disk_array(req, cluster_id)
|
||||
return {'status':message}
|
||||
|
||||
return {'status': message}
|
||||
|
||||
|
||||
class InstallDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
@ -367,13 +403,14 @@ class InstallDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
def install_cluster(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def export_db(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
def update_disk_array(self, request):
|
||||
return {}
|
||||
|
||||
|
||||
class InstallSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -385,7 +422,7 @@ class InstallSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def export_db(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
@ -397,7 +434,8 @@ class InstallSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Image members resource factory method"""
|
||||
deserializer = InstallDeserializer()
|
||||
|
@ -53,36 +53,38 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_project_deleted(self, req, cluster_id):
|
||||
project = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if project['deleted']:
|
||||
msg = _("Cluster with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("Cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise webob.exc.HTTPNotFound(msg)
|
||||
|
||||
# def get_cluster_hosts(self, req, cluster_id, host_id=None):
|
||||
# """
|
||||
# Return a list of dictionaries indicating the members of the
|
||||
# image, i.e., those tenants the image is shared with.
|
||||
# def get_cluster_hosts(self, req, cluster_id, host_id=None):
|
||||
# """
|
||||
# Return a list of dictionaries indicating the members of the
|
||||
# image, i.e., those tenants the image is shared with.
|
||||
#
|
||||
# :param req: the Request object coming from the wsgi layer
|
||||
# :param image_id: The opaque image identifier
|
||||
# :retval The response body is a mapping of the following form::
|
||||
# :param req: the Request object coming from the wsgi layer
|
||||
# :param image_id: The opaque image identifier
|
||||
# :retval The response body is a mapping of the following form::
|
||||
|
||||
# {'members': [
|
||||
# {'host_id': <HOST>, ...}, ...
|
||||
# ]}
|
||||
# """
|
||||
# self._enforce(req, 'get_cluster_hosts')
|
||||
# self._raise_404_if_project_deleted(req, cluster_id)
|
||||
# {'members': [
|
||||
# {'host_id': <HOST>, ...}, ...
|
||||
# ]}
|
||||
# """
|
||||
# self._enforce(req, 'get_cluster_hosts')
|
||||
# self._raise_404_if_project_deleted(req, cluster_id)
|
||||
#
|
||||
# try:
|
||||
# members = registry.get_cluster_hosts(req.context, cluster_id, host_id)
|
||||
# except exception.NotFound:
|
||||
# msg = _("Project with identifier %s not found") % cluster_id
|
||||
# LOG.warn(msg)
|
||||
# raise webob.exc.HTTPNotFound(msg)
|
||||
# except exception.Forbidden:
|
||||
# msg = _("Unauthorized project access")
|
||||
# LOG.warn(msg)
|
||||
# raise webob.exc.HTTPForbidden(msg)
|
||||
# return dict(members=members)
|
||||
# try:
|
||||
# members = registry.get_cluster_hosts(
|
||||
# req.context, cluster_id, host_id)
|
||||
# except exception.NotFound:
|
||||
# msg = _("Project with identifier %s not found") % cluster_id
|
||||
# LOG.warn(msg)
|
||||
# raise webob.exc.HTTPNotFound(msg)
|
||||
# except exception.Forbidden:
|
||||
# msg = _("Unauthorized project access")
|
||||
# LOG.warn(msg)
|
||||
# raise webob.exc.HTTPForbidden(msg)
|
||||
# return dict(members=members)
|
||||
|
||||
@utils.mutating
|
||||
def delete(self, req, image_id, id):
|
||||
@ -104,7 +106,7 @@ class Controller(controller.BaseController):
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return webob.exc.HTTPNoContent()
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def add_cluster_host(self, req, cluster_id, host_id, body=None):
|
||||
"""
|
||||
@ -113,7 +115,7 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'add_cluster_host')
|
||||
self._raise_404_if_project_deleted(req, cluster_id)
|
||||
self._raise_404_if_host_deleted(req, host_id)
|
||||
|
||||
|
||||
try:
|
||||
registry.add_cluster_host(req.context, cluster_id, host_id)
|
||||
except exception.Invalid as e:
|
||||
@ -127,7 +129,7 @@ class Controller(controller.BaseController):
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return webob.exc.HTTPNoContent()
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def delete_cluster_host(self, req, cluster_id, host_id):
|
||||
"""
|
||||
@ -147,7 +149,7 @@ class Controller(controller.BaseController):
|
||||
raise webob.exc.HTTPNotFound(explanation=e.msg)
|
||||
|
||||
return webob.exc.HTTPNoContent()
|
||||
|
||||
|
||||
def default(self, req, image_id, id, body=None):
|
||||
"""This will cover the missing 'show' and 'create' actions"""
|
||||
raise webob.exc.HTTPMethodNotAllowed()
|
||||
|
@ -36,6 +36,7 @@ from daisy.common import wsgi
|
||||
from daisy import i18n
|
||||
from daisy import notifier
|
||||
import daisy.registry.client.v1.api as registry
|
||||
from functools import reduce
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
@ -52,9 +53,16 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
SUPPORT_NETWORK_TYPE = ('PUBLIC', 'PRIVATE', 'STORAGE', 'MANAGEMENT', 'EXTERNAL', 'DEPLOYMENT', 'VXLAN')
|
||||
SUPPORT_NETWORK_TEMPLATE_TYPE = ('custom', 'template', 'default')
|
||||
SUPPORT_ML2_TYPE = ('ovs', 'sriov(direct)', 'sriov(macvtap)',
|
||||
SUPPORT_NETWORK_TYPE = (
|
||||
'PUBLICAPI',
|
||||
'DATAPLANE',
|
||||
'STORAGE',
|
||||
'MANAGEMENT',
|
||||
'EXTERNAL',
|
||||
'DEPLOYMENT',
|
||||
'HEARTBEAT')
|
||||
SUPPORT_NETWORK_TEMPLATE_TYPE = ('custom', 'template', 'default', 'system')
|
||||
SUPPORT_ML2_TYPE = ('ovs', 'sriov(direct)', 'sriov(macvtap)',
|
||||
'ovs,sriov(direct)', 'ovs,sriov(macvtap)')
|
||||
SUPPORT_NETWORK_CAPABILITY = ('high', 'low')
|
||||
|
||||
@ -99,12 +107,15 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_network_deleted(self, req, network_id):
|
||||
network = self.get_network_meta_or_404(req, network_id)
|
||||
if network['deleted']:
|
||||
msg = _("Network with identifier %s has been deleted.") % network_id
|
||||
msg = _("Network with identifier %s has been deleted.") % \
|
||||
network_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _raise_404_if_cluster_delete(self, req, cluster_id):
|
||||
cluster_id = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster_id['deleted']:
|
||||
msg = _("cluster_id with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("cluster_id with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _get_network_name_by_cluster_id(self, context, cluster_id):
|
||||
@ -114,7 +125,6 @@ class Controller(controller.BaseController):
|
||||
network_name_list.append(network['name'])
|
||||
return network_name_list
|
||||
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""
|
||||
Return a dictionary of query param filters from the request
|
||||
@ -146,7 +156,7 @@ class Controller(controller.BaseController):
|
||||
if PARAM in req.params:
|
||||
params[PARAM] = req.params.get(PARAM)
|
||||
return params
|
||||
|
||||
|
||||
def validate_ip_format(self, ip_str):
|
||||
'''
|
||||
valid ip_str format = '10.43.178.9'
|
||||
@ -157,21 +167,21 @@ class Controller(controller.BaseController):
|
||||
'10.43.1789', invalid format
|
||||
'''
|
||||
valid_fromat = False
|
||||
if ip_str.count('.') == 3 and \
|
||||
all(num.isdigit() and 0<=int(num)<256 for num in ip_str.rstrip().split('.')):
|
||||
if ip_str.count('.') == 3 and all(num.isdigit() and 0 <= int(
|
||||
num) < 256 for num in ip_str.rstrip().split('.')):
|
||||
valid_fromat = True
|
||||
if valid_fromat == False:
|
||||
if not valid_fromat:
|
||||
msg = (_("%s invalid ip format!") % ip_str)
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
def _ip_into_int(self, ip):
|
||||
"""
|
||||
Switch ip string to decimalism integer..
|
||||
:param ip: ip string
|
||||
:return: decimalism integer
|
||||
"""
|
||||
return reduce(lambda x, y: (x<<8)+y, map(int, ip.split('.')))
|
||||
return reduce(lambda x, y: (x << 8) + y, map(int, ip.split('.')))
|
||||
|
||||
def _is_in_network_range(self, ip, network):
|
||||
"""
|
||||
@ -182,9 +192,13 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
network = network.split('/')
|
||||
mask = ~(2**(32 - int(network[1])) - 1)
|
||||
return (self._ip_into_int(ip) & mask) == (self._ip_into_int(network[0]) & mask)
|
||||
return (
|
||||
self._ip_into_int(ip) & mask) == (
|
||||
self._ip_into_int(
|
||||
network[0]) & mask)
|
||||
|
||||
def _verify_uniqueness_of_network_name(self, req, network_list, network_meta, is_update = False):
|
||||
def _verify_uniqueness_of_network_name(
|
||||
self, req, network_list, network_meta, is_update=False):
|
||||
"""
|
||||
Network name is match case and uniqueness in cluster.
|
||||
:param req:
|
||||
@ -192,50 +206,137 @@ class Controller(controller.BaseController):
|
||||
:param network_meta: network plane need be verified
|
||||
:return:
|
||||
"""
|
||||
if not network_list or not network_meta or not network_meta.get('name', None):
|
||||
msg = _("Input params invalid for verifying uniqueness of network name.")
|
||||
if not network_list or not network_meta or not network_meta.get(
|
||||
'name', None):
|
||||
msg = _("Input params invalid for verifying uniqueness of "
|
||||
"network name.")
|
||||
raise HTTPBadRequest(msg, request=req, content_type="text/plain")
|
||||
|
||||
network_name = network_meta['name']
|
||||
for network in network_list['networks']:
|
||||
if (is_update and
|
||||
network_name == network['name'] and
|
||||
network_meta['id'] == network['id']):
|
||||
if (is_update and
|
||||
network_name == network['name'] and
|
||||
network_meta['id'] == network['id']):
|
||||
return
|
||||
|
||||
# network name don't match case
|
||||
network_name_list = [network['name'].lower() for network in
|
||||
network_list['networks'] if network.get('name', None)]
|
||||
network_list['networks'] if
|
||||
network.get('name', None)]
|
||||
if network_name.lower() in network_name_list:
|
||||
msg = _("Name of network isn't match case and %s already exits in the cluster." % network_name)
|
||||
msg = _(
|
||||
"Name of network isn't match case and %s already exits "
|
||||
"in the cluster." %
|
||||
network_name)
|
||||
raise HTTPConflict(msg, request=req, content_type="text/plain")
|
||||
|
||||
if not is_update:
|
||||
# Input networks type can't be same with db record which is all ready exit,
|
||||
# Input networks type can't be same with db record
|
||||
# which is all ready exit,
|
||||
# except PRIVATE network.
|
||||
network_type_exist_list = \
|
||||
[network['network_type'] for network in network_list['networks']
|
||||
if network.get('network_type', None) and network['network_type'] != "PRIVATE"
|
||||
and network['network_type'] != "STORAGE"]
|
||||
if network_meta.get("network_type", None) in network_type_exist_list:
|
||||
msg = _("The %s network plane %s must be only, except PRIVATE network." %
|
||||
(network_meta['network_type'], network_name))
|
||||
[network['network_type'] for network in
|
||||
network_list['networks']
|
||||
if network.get('network_type', None) and
|
||||
network['network_type'] != "DATAPLANE" and
|
||||
network['network_type'] != "STORAGE" and
|
||||
network['network_type'] != "HEARTBEAT"]
|
||||
if network_meta.get(
|
||||
"network_type",
|
||||
None) in network_type_exist_list:
|
||||
msg = _(
|
||||
"The %s network plane %s must be unique, "
|
||||
"except DATAPLANE/STORAGE/HEARTBEAT network." %
|
||||
(network_meta['network_type'], network_name))
|
||||
raise HTTPConflict(msg, request=req, content_type="text/plain")
|
||||
|
||||
def _valid_vlan_range(self, req, network_meta):
|
||||
if ((network_meta.has_key('vlan_start') and not network_meta.has_key('vlan_end')) or
|
||||
(not network_meta.has_key('vlan_start') and network_meta.has_key('vlan_end'))):
|
||||
raise HTTPBadRequest(explanation="vlan-start and vlan-end must be appeared at the same time", request=req)
|
||||
if network_meta.has_key('vlan_start'):
|
||||
if not (int(network_meta['vlan_start']) >= 1 and
|
||||
def _valid_network_range(self, req, network_meta):
|
||||
if (('vlan_start' in network_meta and 'vlan_end' not in
|
||||
network_meta) or (
|
||||
'vlan_start' not in network_meta and
|
||||
'vlan_end' in network_meta)):
|
||||
msg = "vlan-start and vlan-end must be appeared "\
|
||||
"at the same time"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'vlan_start' in network_meta:
|
||||
if not (int(network_meta['vlan_start']) >= 1 and
|
||||
int(network_meta['vlan_start']) <= 4094):
|
||||
raise HTTPBadRequest(explanation="vlan-start must be a integer in '1~4096'", request=req)
|
||||
if network_meta.has_key('vlan_end'):
|
||||
if not (int(network_meta['vlan_end']) >= 1 and
|
||||
msg = "vlan_start must be a integer in 1~4096"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'vlan_end' in network_meta:
|
||||
if not (int(network_meta['vlan_end']) >= 1 and
|
||||
int(network_meta['vlan_end']) <= 4094):
|
||||
raise HTTPBadRequest(explanation="vlan-end must be a integer in '1~4096'", request=req)
|
||||
msg = "vlan_end must be a integer in 1~4096"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if int(network_meta['vlan_start']) > int(network_meta['vlan_end']):
|
||||
raise HTTPBadRequest(explanation="vlan-start must be less than vlan-end", request=req)
|
||||
msg = "vlan_start must be less than vlan_end"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
if (('vni_start' in network_meta and 'vni_end' not in
|
||||
network_meta) or (
|
||||
'vni_start' not in network_meta and
|
||||
'vni_end' in network_meta)):
|
||||
|
||||
msg = "vni_start and vni_end must be appeared at the same time"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'vni_start' in network_meta:
|
||||
if not (int(network_meta['vni_start']) >= 1 and
|
||||
int(network_meta['vni_start']) <= 16777216):
|
||||
msg = "vni_start must be a integer in 1~16777216"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'vni_end' in network_meta:
|
||||
if not (int(network_meta['vni_end']) >= 1 and
|
||||
int(network_meta['vni_end']) <= 16777216):
|
||||
msg = "vni_end must be a integer in 1~16777216"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if int(network_meta['vni_start']) > int(network_meta['vni_end']):
|
||||
msg = "vni_start must be less than vni_end"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
if (('gre_id_start' in network_meta and 'gre_id_end' not in
|
||||
network_meta) or (
|
||||
'gre_id_start' not in network_meta and
|
||||
'gre_id_end' in network_meta)):
|
||||
msg = "gre_id_start and gre_id_end must"\
|
||||
"be appeared at the same time"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'gre_id_start' in network_meta:
|
||||
if not (int(network_meta['gre_id_start']) >= 1 and
|
||||
int(network_meta['gre_id_start']) <= 4094):
|
||||
msg = "gre_id_start must be a integer in 1~4094"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if 'gre_id_end' in network_meta:
|
||||
if not (int(network_meta['gre_id_end']) >= 1 and
|
||||
int(network_meta['gre_id_end']) <= 4094):
|
||||
msg = "gre_id_end must be a integer in 1~4094"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
if int(network_meta['gre_id_start']) >\
|
||||
int(network_meta['gre_id_end']):
|
||||
msg = "gre_id_start must be less than gre_id_end"
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
def _verify_heartbeat_network(self, req, network_list, network_meta):
|
||||
heartbeat_networks = [
|
||||
network for network in network_list['networks'] if network.get(
|
||||
'network_type',
|
||||
None) and network['network_type'] == "HEARTBEAT"]
|
||||
if len(heartbeat_networks) >= 2:
|
||||
raise HTTPBadRequest(
|
||||
explanation="HEARTBEAT network plane number must be "
|
||||
"less than two",
|
||||
request=req)
|
||||
|
||||
@utils.mutating
|
||||
def add_network(self, req, network_meta):
|
||||
@ -248,46 +349,62 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-host-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_network')
|
||||
cluster_id = network_meta.get('cluster_id',None)
|
||||
cluster_id = network_meta.get('cluster_id', None)
|
||||
if cluster_id:
|
||||
self._raise_404_if_cluster_delete(req, cluster_id)
|
||||
network_list = self.detail(req, cluster_id)
|
||||
self._verify_uniqueness_of_network_name(req, network_list, network_meta)
|
||||
self._verify_uniqueness_of_network_name(
|
||||
req, network_list, network_meta)
|
||||
if 'network_type' in network_meta and network_meta[
|
||||
'network_type'] == "HEARTBEAT":
|
||||
self._verify_heartbeat_network(req, network_list, network_meta)
|
||||
# else:
|
||||
# if network_meta.get('type',None) != "template":
|
||||
# raise HTTPBadRequest(explanation="cluster id must be given", request=req)
|
||||
network_name=network_meta.get('name',None)
|
||||
# raise HTTPBadRequest(explanation="cluster id must be given",
|
||||
# request=req)
|
||||
network_name = network_meta.get('name', None)
|
||||
network_name_split = network_name.split('_')
|
||||
for network_name_info in network_name_split :
|
||||
if not network_name_info.isalnum():
|
||||
raise ValueError('network name must be numbers or letters or underscores !')
|
||||
if not network_meta.has_key('network_type'):
|
||||
raise HTTPBadRequest(explanation="network-type must be given", request=req)
|
||||
if network_meta['network_type'] not in SUPPORT_NETWORK_TYPE:
|
||||
raise HTTPBadRequest(explanation="unsupported network-type", request=req)
|
||||
|
||||
|
||||
if (network_meta.has_key('type') and
|
||||
network_meta['type'] not in SUPPORT_NETWORK_TEMPLATE_TYPE):
|
||||
raise HTTPBadRequest(explanation="unsupported type", request=req)
|
||||
|
||||
if (network_meta.has_key('capability') and
|
||||
network_meta['capability'] not in SUPPORT_NETWORK_CAPABILITY):
|
||||
raise HTTPBadRequest(explanation="unsupported capability type", request=req)
|
||||
|
||||
self._valid_vlan_range(req, network_meta)
|
||||
for network_name_info in network_name_split:
|
||||
if not network_name_info.isalnum():
|
||||
raise ValueError(
|
||||
'network name must be numbers or letters or underscores !')
|
||||
if 'network_type' not in network_meta:
|
||||
raise HTTPBadRequest(
|
||||
explanation="network-type must be given",
|
||||
request=req)
|
||||
if network_meta['network_type'] not in SUPPORT_NETWORK_TYPE:
|
||||
raise HTTPBadRequest(
|
||||
explanation="unsupported network-type",
|
||||
request=req)
|
||||
|
||||
if network_meta.get('ip_ranges', None):
|
||||
if ('type' in network_meta and
|
||||
network_meta['type'] not in SUPPORT_NETWORK_TEMPLATE_TYPE):
|
||||
raise HTTPBadRequest(explanation="unsupported type", request=req)
|
||||
|
||||
if ('capability' in network_meta and
|
||||
network_meta['capability'] not in SUPPORT_NETWORK_CAPABILITY):
|
||||
raise HTTPBadRequest(
|
||||
explanation="unsupported capability type",
|
||||
request=req)
|
||||
|
||||
self._valid_network_range(req, network_meta)
|
||||
|
||||
if network_meta.get('ip_ranges', None) and \
|
||||
eval(network_meta['ip_ranges']):
|
||||
cidr = None
|
||||
if not network_meta.has_key('cidr'):
|
||||
msg = (_("When ip range was specified, the CIDR parameter can not be empty."))
|
||||
if 'cidr' not in network_meta:
|
||||
msg = (
|
||||
_("When ip range was specified, the CIDR parameter "
|
||||
"can not be empty."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
else:
|
||||
cidr = network_meta['cidr']
|
||||
cidr_division = cidr.split('/')
|
||||
if len(cidr_division) != 2 or ( cidr_division[1] \
|
||||
and int(cidr_division[1]) > 32 or int(cidr_division[1]) < 0):
|
||||
if len(cidr_division) != 2 or (
|
||||
cidr_division[1] and int(
|
||||
cidr_division[1]) > 32 or int(
|
||||
cidr_division[1]) < 0):
|
||||
msg = (_("Wrong CIDR format."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
@ -299,39 +416,50 @@ class Controller(controller.BaseController):
|
||||
sorted_int_ip_ranges_list = list()
|
||||
for ip_pair in ip_ranges:
|
||||
if ['start', 'end'] != ip_pair.keys():
|
||||
msg = (_("IP range was not start with 'start:' or end with 'end:'."))
|
||||
msg = (
|
||||
_("IP range was not start with 'start:' or "
|
||||
"end with 'end:'."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
ip_start = ip_pair['start']
|
||||
ip_start = ip_pair['start']
|
||||
ip_end = ip_pair['end']
|
||||
self.validate_ip_format(ip_start) #check ip format
|
||||
self.validate_ip_format(ip_start) # check ip format
|
||||
self.validate_ip_format(ip_end)
|
||||
|
||||
|
||||
if not self._is_in_network_range(ip_start, cidr):
|
||||
msg = (_("IP address %s was not in the range of CIDR %s." % (ip_start, cidr)))
|
||||
msg = (
|
||||
_("IP address %s was not in the range "
|
||||
"of CIDR %s." % (ip_start, cidr)))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
if not self._is_in_network_range(ip_end, cidr):
|
||||
msg = (_("IP address %s was not in the range of CIDR %s." % (ip_end, cidr)))
|
||||
msg = (
|
||||
_("IP address %s was not in the range "
|
||||
"of CIDR %s." % (ip_end, cidr)))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
#transform ip format to int when the string format is valid
|
||||
|
||||
# transform ip format to int when the string format is
|
||||
# valid
|
||||
int_ip_start = self._ip_into_int(ip_start)
|
||||
int_ip_end = self._ip_into_int(ip_end)
|
||||
|
||||
|
||||
if int_ip_start > int_ip_end:
|
||||
msg = (_("Wrong ip range format."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
int_ip_ranges_list.append([int_ip_start, int_ip_end])
|
||||
sorted_int_ip_ranges_list = sorted(int_ip_ranges_list, key=lambda x : x[0])
|
||||
|
||||
sorted_int_ip_ranges_list = sorted(
|
||||
int_ip_ranges_list, key=lambda x: x[0])
|
||||
|
||||
for int_ip_range in sorted_int_ip_ranges_list:
|
||||
if last_ip_range_end and last_ip_range_end >= int_ip_range[0]:
|
||||
if last_ip_range_end and last_ip_range_end >= int_ip_range[
|
||||
0]:
|
||||
msg = (_("Between ip ranges can not be overlap."))
|
||||
LOG.warn(msg) # such as "[10, 15], [12, 16]", last_ip_range_end >= int_ip_range[0], this ip ranges were overlap
|
||||
# such as "[10, 15], [12, 16]", last_ip_range_end >=
|
||||
# int_ip_range[0], this ip ranges were overlap
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
else:
|
||||
last_ip_range_end = int_ip_range[1]
|
||||
@ -353,16 +481,33 @@ class Controller(controller.BaseController):
|
||||
'have the same cidr'))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
if network_meta.get('gateway', None) and network_meta.get('cidr', None):
|
||||
if network_meta.get(
|
||||
'gateway',
|
||||
None) and network_meta.get(
|
||||
'cidr',
|
||||
None):
|
||||
gateway = network_meta['gateway']
|
||||
cidr = network_meta['cidr']
|
||||
|
||||
|
||||
self.validate_ip_format(gateway)
|
||||
return_flag = self._is_in_network_range(gateway, cidr)
|
||||
if not return_flag:
|
||||
msg = (_('The gateway %s was not in the same segment with the cidr %s of management network.' % (gateway, cidr)))
|
||||
msg = (
|
||||
_(
|
||||
'The gateway %s was not in the same segment '
|
||||
'with the cidr %s of management network.' %
|
||||
(gateway, cidr)))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
if network_meta.get('cluster_id') and network_meta.get('gateway'):
|
||||
networks = registry.get_networks_detail(req.context, cluster_id)
|
||||
gateways = [network['gateway'] for network in networks
|
||||
if network['name'] != network_meta['name'] and
|
||||
network['gateway']]
|
||||
if gateways:
|
||||
msg = (_('More than one gateway found in cluster.'))
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg)
|
||||
network_meta = registry.add_network_metadata(req.context, network_meta)
|
||||
return {'network_meta': network_meta}
|
||||
|
||||
@ -377,14 +522,16 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-host-name is missing
|
||||
"""
|
||||
self._enforce(req, 'delete_network')
|
||||
#self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
#self._raise_404_if_network_deleted(req, network_id)
|
||||
# self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
# self._raise_404_if_network_deleted(req, network_id)
|
||||
network = self.get_network_meta_or_404(req, network_id)
|
||||
if network['deleted']:
|
||||
msg = _("Network with identifier %s has been deleted.") % network_id
|
||||
msg = _("Network with identifier %s has been deleted.") % \
|
||||
network_id
|
||||
raise HTTPNotFound(msg)
|
||||
if network['type'] != 'custom':
|
||||
msg = _("Type of network was not custom, can not delete this network.")
|
||||
msg = _("Type of network was not custom, can not "
|
||||
"delete this network.")
|
||||
raise HTTPForbidden(msg)
|
||||
try:
|
||||
registry.delete_network_metadata(req.context, network_id)
|
||||
@ -403,14 +550,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("Network %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("Network %(id)s could not be deleted "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('host.delete', host)
|
||||
# self.notifier.info('host.delete', host)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -436,10 +584,19 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'get_all_network')
|
||||
params = self._get_query_params(req)
|
||||
filters = params.get('filters')
|
||||
if filters and filters.get('type'):
|
||||
if filters['type'] not in SUPPORT_NETWORK_TEMPLATE_TYPE:
|
||||
msg = "type '%s' is not support." % filters['type']
|
||||
LOG.error(msg)
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
try:
|
||||
networks = registry.get_all_networks(req.context,**params)
|
||||
networks = registry.get_all_networks(req.context, **params)
|
||||
except Exception:
|
||||
raise HTTPBadRequest(explanation="Get all networks failed.", request=req)
|
||||
raise HTTPBadRequest(
|
||||
explanation="Get all networks failed.",
|
||||
request=req)
|
||||
return dict(networks=networks)
|
||||
|
||||
def detail(self, req, id):
|
||||
@ -458,15 +615,15 @@ class Controller(controller.BaseController):
|
||||
'deleted_at': <TIMESTAMP>|<NONE>,}, ...
|
||||
]}
|
||||
"""
|
||||
cluster_id = self._raise_404_if_cluster_delete(req, id)
|
||||
self._raise_404_if_cluster_delete(req, id)
|
||||
self._enforce(req, 'get_networks')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
networks = registry.get_networks_detail(req.context, id,**params)
|
||||
networks = registry.get_networks_detail(req.context, id, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(networks=networks)
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def update_network(self, req, network_id, network_meta):
|
||||
"""
|
||||
@ -477,14 +634,16 @@ class Controller(controller.BaseController):
|
||||
|
||||
:retval Returns the updated image information as a mapping
|
||||
"""
|
||||
if network_meta.has_key('name'):
|
||||
network_name=network_meta.get('name',None)
|
||||
if 'name' in network_meta:
|
||||
network_name = network_meta.get('name', None)
|
||||
network_name_split = network_name.split('_')
|
||||
for network_name_info in network_name_split :
|
||||
if not network_name_info.isalnum():
|
||||
raise ValueError('network name must be numbers or letters or underscores !')
|
||||
for network_name_info in network_name_split:
|
||||
if not network_name_info.isalnum():
|
||||
raise ValueError(
|
||||
'network name must be numbers or '
|
||||
'letters or underscores !')
|
||||
self._enforce(req, 'update_network')
|
||||
#orig_cluster_meta = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
# orig_cluster_meta = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
orig_network_meta = self.get_network_meta_or_404(req, network_id)
|
||||
# Do not allow any updates on a deleted network.
|
||||
if orig_network_meta['deleted']:
|
||||
@ -492,23 +651,27 @@ class Controller(controller.BaseController):
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
if (network_meta.has_key('network_type') and
|
||||
network_meta['network_type'] not in SUPPORT_NETWORK_TYPE):
|
||||
raise HTTPBadRequest(explanation="unsupported network-type", request=req)
|
||||
if (network_meta.has_key('type') and
|
||||
network_meta['type'] not in SUPPORT_NETWORK_TEMPLATE_TYPE):
|
||||
raise HTTPBadRequest(explanation="unsupported type", request=req)
|
||||
if (network_meta.has_key('type') and
|
||||
network_meta['type'] == 'template'):
|
||||
raise HTTPBadRequest(explanation="network template type is not allowed to update", request=req)
|
||||
|
||||
|
||||
|
||||
if (network_meta.has_key('capability') and
|
||||
network_meta['capability'] not in SUPPORT_NETWORK_CAPABILITY):
|
||||
raise HTTPBadRequest(explanation="unsupported capability type", request=req)
|
||||
if ('network_type' in network_meta and
|
||||
network_meta['network_type'] not in SUPPORT_NETWORK_TYPE):
|
||||
raise HTTPBadRequest(
|
||||
explanation="unsupported network-type",
|
||||
request=req)
|
||||
if ('type' in network_meta and
|
||||
network_meta['type'] not in SUPPORT_NETWORK_TEMPLATE_TYPE):
|
||||
raise HTTPBadRequest(explanation="unsupported type", request=req)
|
||||
if ('type' in network_meta and
|
||||
network_meta['type'] == 'template'):
|
||||
raise HTTPBadRequest(
|
||||
explanation="network template type is not allowed to update",
|
||||
request=req)
|
||||
|
||||
self._valid_vlan_range(req, network_meta)
|
||||
if ('capability' in network_meta and
|
||||
network_meta['capability'] not in SUPPORT_NETWORK_CAPABILITY):
|
||||
raise HTTPBadRequest(
|
||||
explanation="unsupported capability type",
|
||||
request=req)
|
||||
|
||||
self._valid_network_range(req, network_meta)
|
||||
|
||||
network_name = network_meta.get('name', None)
|
||||
cluster_id = orig_network_meta['cluster_id']
|
||||
@ -516,17 +679,20 @@ class Controller(controller.BaseController):
|
||||
network_updated = copy.deepcopy(network_meta)
|
||||
network_updated['id'] = network_id
|
||||
network_type = network_meta.get('network_type', None)
|
||||
network_updated['network_type'] = \
|
||||
orig_network_meta['network_type'] if not network_type else network_type
|
||||
network_updated['network_type'] = orig_network_meta[
|
||||
'network_type'] if not network_type else network_type
|
||||
network_list = self.detail(req, cluster_id)
|
||||
self._verify_uniqueness_of_network_name(req, network_list, network_updated, True)
|
||||
|
||||
self._verify_uniqueness_of_network_name(
|
||||
req, network_list, network_updated, True)
|
||||
|
||||
cidr = network_meta.get('cidr', orig_network_meta['cidr'])
|
||||
vlan_id = network_meta.get('vlan_id', orig_network_meta['vlan_id'])
|
||||
if cidr:
|
||||
cidr_division = cidr.split('/')
|
||||
if len(cidr_division) != 2 or ( cidr_division[1] \
|
||||
and int(cidr_division[1]) > 32 or int(cidr_division[1]) < 0):
|
||||
if len(cidr_division) != 2 or (
|
||||
cidr_division[1] and int(
|
||||
cidr_division[1]) > 32 or int(
|
||||
cidr_division[1]) < 0):
|
||||
msg = (_("Wrong CIDR format."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
@ -549,9 +715,12 @@ class Controller(controller.BaseController):
|
||||
'have the same cidr'))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
if network_meta.get('ip_ranges', None):
|
||||
if network_meta.get('ip_ranges', None) and \
|
||||
eval(network_meta['ip_ranges']):
|
||||
if not cidr:
|
||||
msg = (_("When ip range was specified, the CIDR parameter can not be empty."))
|
||||
msg = (
|
||||
_("When ip range was specified, "
|
||||
"the CIDR parameter can not be empty."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
ip_ranges = eval(network_meta['ip_ranges'])
|
||||
@ -560,53 +729,81 @@ class Controller(controller.BaseController):
|
||||
sorted_int_ip_ranges_list = list()
|
||||
for ip_pair in ip_ranges:
|
||||
if ['start', 'end'] != ip_pair.keys():
|
||||
msg = (_("IP range was not start with 'start:' or end with 'end:'."))
|
||||
msg = (
|
||||
_("IP range was not start with 'start:' "
|
||||
"or end with 'end:'."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
ip_start = ip_pair['start']
|
||||
ip_start = ip_pair['start']
|
||||
ip_end = ip_pair['end']
|
||||
self.validate_ip_format(ip_start) #check ip format
|
||||
self.validate_ip_format(ip_start) # check ip format
|
||||
self.validate_ip_format(ip_end)
|
||||
|
||||
|
||||
if not self._is_in_network_range(ip_start, cidr):
|
||||
msg = (_("IP address %s was not in the range of CIDR %s." % (ip_start, cidr)))
|
||||
msg = (
|
||||
_("IP address %s was not in the "
|
||||
"range of CIDR %s." % (ip_start, cidr)))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
if not self._is_in_network_range(ip_end, cidr):
|
||||
msg = (_("IP address %s was not in the range of CIDR %s." % (ip_end, cidr)))
|
||||
msg = (
|
||||
_("IP address %s was not in the "
|
||||
"range of CIDR %s." % (ip_end, cidr)))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
#transform ip format to int when the string format is valid
|
||||
|
||||
# transform ip format to int when the string format is valid
|
||||
int_ip_start = self._ip_into_int(ip_start)
|
||||
int_ip_end = self._ip_into_int(ip_end)
|
||||
|
||||
|
||||
if int_ip_start > int_ip_end:
|
||||
msg = (_("Wrong ip range format."))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
int_ip_ranges_list.append([int_ip_start, int_ip_end])
|
||||
sorted_int_ip_ranges_list = sorted(int_ip_ranges_list, key=lambda x : x[0])
|
||||
LOG.warn("sorted_int_ip_ranges_list: "% sorted_int_ip_ranges_list)
|
||||
#check ip ranges overlap
|
||||
sorted_int_ip_ranges_list = sorted(
|
||||
int_ip_ranges_list, key=lambda x: x[0])
|
||||
LOG.warn("sorted_int_ip_ranges_list: " % sorted_int_ip_ranges_list)
|
||||
# check ip ranges overlap
|
||||
for int_ip_range in sorted_int_ip_ranges_list:
|
||||
if last_ip_range_end and last_ip_range_end >= int_ip_range[0]:
|
||||
msg = (_("Between ip ranges can not be overlap."))
|
||||
LOG.warn(msg) # such as "[10, 15], [12, 16]", last_ip_range_end >= int_ip_range[0], this ip ranges were overlap
|
||||
# such as "[10, 15], [12, 16]", last_ip_range_end >=
|
||||
# int_ip_range[0], this ip ranges were overlap
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
else:
|
||||
last_ip_range_end = int_ip_range[1]
|
||||
|
||||
if network_meta.get('gateway', orig_network_meta['gateway']) and network_meta.get('cidr', orig_network_meta['cidr']):
|
||||
|
||||
if network_meta.get(
|
||||
'gateway',
|
||||
orig_network_meta['gateway']) and network_meta.get(
|
||||
'cidr',
|
||||
orig_network_meta['cidr']):
|
||||
gateway = network_meta.get('gateway', orig_network_meta['gateway'])
|
||||
cidr = network_meta.get('cidr', orig_network_meta['cidr'])
|
||||
self.validate_ip_format(gateway)
|
||||
return_flag = self._is_in_network_range(gateway, cidr)
|
||||
if not return_flag:
|
||||
msg = (_('The gateway %s was not in the same segment with the cidr %s of management network.' % (gateway, cidr)))
|
||||
msg = (
|
||||
_(
|
||||
'The gateway %s was not in the same '
|
||||
'segment with the cidr %s of management network.' %
|
||||
(gateway, cidr)))
|
||||
raise HTTPBadRequest(explanation=msg)
|
||||
|
||||
# allow one gateway in one cluster
|
||||
if network_meta.get('cluster_id') and (network_meta.get('gateway')):
|
||||
networks = registry.get_networks_detail(req.context, cluster_id)
|
||||
gateways = [network['gateway'] for network in networks
|
||||
if network['name'] != orig_network_meta['name'] and
|
||||
network['gateway']]
|
||||
if gateways:
|
||||
msg = (_('More than one gateway found in cluster.'))
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg)
|
||||
|
||||
try:
|
||||
network_meta = registry.update_network_metadata(req.context,
|
||||
network_id,
|
||||
@ -626,12 +823,8 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.Forbidden as e:
|
||||
msg = (_("Forbidden to update network: %s") %
|
||||
utils.exception_to_str(e))
|
||||
LOG.warn(msg)
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
LOG.warn(e)
|
||||
raise HTTPForbidden(e)
|
||||
except (exception.Conflict, exception.Duplicate) as e:
|
||||
LOG.warn(utils.exception_to_str(e))
|
||||
raise HTTPConflict(body=_('Network operation conflicts'),
|
||||
@ -642,6 +835,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'network_meta': network_meta}
|
||||
|
||||
|
||||
class HostDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -656,6 +850,7 @@ class HostDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_network(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class HostSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -683,9 +878,9 @@ class HostSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(network=network_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Hosts resource factory method"""
|
||||
deserializer = HostDeserializer()
|
||||
serializer = HostSerializer()
|
||||
return wsgi.Resource(Controller(), deserializer, serializer)
|
||||
|
||||
|
@ -46,8 +46,16 @@ SUPPORTED_PARAMS = daisy.api.v1.SUPPORTED_PARAMS
|
||||
SUPPORTED_FILTERS = daisy.api.v1.SUPPORTED_FILTERS
|
||||
ACTIVE_IMMUTABLE = daisy.api.v1.ACTIVE_IMMUTABLE
|
||||
SUPPORTED_DEPLOYMENT_BACKENDS = ('tecs', 'zenic', 'proton')
|
||||
SUPPORTED_ROLE = ('CONTROLLER_LB', 'CONTROLLER_HA', 'COMPUTER', 'ZENIC_CTL', 'ZENIC_NFM',
|
||||
'ZENIC_MDB', 'PROTON', 'CHILD_CELL_1_COMPUTER', 'CONTROLLER_CHILD_CELL_1')
|
||||
SUPPORTED_ROLE = (
|
||||
'CONTROLLER_LB',
|
||||
'CONTROLLER_HA',
|
||||
'COMPUTER',
|
||||
'ZENIC_CTL',
|
||||
'ZENIC_NFM',
|
||||
'ZENIC_MDB',
|
||||
'PROTON',
|
||||
'CHILD_CELL_1_COMPUTER',
|
||||
'CONTROLLER_CHILD_CELL_1')
|
||||
SUPPORT_DISK_LOCATION = ('local', 'share')
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -56,6 +64,7 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for roles resource in Daisy v1 API
|
||||
@ -130,86 +139,97 @@ class Controller(controller.BaseController):
|
||||
if host['deleted']:
|
||||
msg = _("Node with identifier %s has been deleted.") % host_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _raise_404_if_service_deleted(self, req, service_id):
|
||||
service = self.get_service_meta_or_404(req, service_id)
|
||||
if service['deleted']:
|
||||
msg = _("Service with identifier %s has been deleted.") % service_id
|
||||
msg = _("Service with identifier %s has been deleted.") % \
|
||||
service_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _raise_404_if_config_set_deleted(self, req, config_set_id):
|
||||
config_set = self.get_config_set_meta_or_404(req, config_set_id)
|
||||
if config_set['deleted']:
|
||||
msg = _("Config_Set with identifier %s has been deleted.") % config_set_id
|
||||
msg = _("Config_Set with identifier %s has been deleted.") % \
|
||||
config_set_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("cluster with identifier %s has been deleted.") % cluster_id
|
||||
msg = _("cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
def _get_service_name_list(self, req, role_service_id_list):
|
||||
service_name_list = []
|
||||
for service_id in role_service_id_list:
|
||||
service_meta = registry.get_service_metadata(req.context, service_id)
|
||||
service_meta = registry.get_service_metadata(
|
||||
req.context, service_id)
|
||||
service_name_list.append(service_meta['name'])
|
||||
return service_name_list
|
||||
|
||||
|
||||
def _get_host_disk_except_os_disk_by_info(self, host_info):
|
||||
'''
|
||||
type(host_info): <type 'dict'>
|
||||
host_disk_except_os_disk_lists: disk_size , type = int
|
||||
'''
|
||||
#import pdb;pdb.set_trace()
|
||||
# import pdb;pdb.set_trace()
|
||||
host_disk_except_os_disk_lists = 0
|
||||
os_disk_m = host_info.get('root_lv_size', 51200)
|
||||
os_disk_m = host_info.get('root_lv_size', 102400)
|
||||
swap_size_m = host_info.get('swap_lv_size', None)
|
||||
if swap_size_m:
|
||||
swap_size_m = (swap_size_m / 4)*4
|
||||
swap_size_m = (swap_size_m / 4) * 4
|
||||
else:
|
||||
swap_size_m = 0
|
||||
boot_partition_m = 400
|
||||
redundant_partiton_m = 600
|
||||
if not os_disk_m:
|
||||
os_disk_m = 51200
|
||||
#host_disk = 1024
|
||||
os_disk_m = 102400
|
||||
# host_disk = 1024
|
||||
host_disks = host_info.get('disks', None)
|
||||
host_disk_size_m = 0
|
||||
if host_disks:
|
||||
for key, value in host_disks.items():
|
||||
for key, value in host_disks.items():
|
||||
disk_size_b = str(value.get('size', None))
|
||||
disk_size_b_str = disk_size_b.strip().split()[0]
|
||||
if disk_size_b_str:
|
||||
disk_size_b_int = int(disk_size_b_str)
|
||||
disk_size_m = disk_size_b_int//(1024*1024)
|
||||
disk_size_m = disk_size_b_int // (1024 * 1024)
|
||||
host_disk_size_m = host_disk_size_m + disk_size_m
|
||||
host_disk_except_os_disk_lists = host_disk_size_m - os_disk_m - swap_size_m - boot_partition_m - redundant_partiton_m
|
||||
LOG.warn('----start----host_disk_except_os_disk_lists: %s -----end--' % host_disk_except_os_disk_lists)
|
||||
host_disk_except_os_disk_lists = host_disk_size_m - os_disk_m - \
|
||||
swap_size_m - boot_partition_m - redundant_partiton_m
|
||||
LOG.warn(
|
||||
'----start----host_disk_except_os_disk_lists: %s -----end--' %
|
||||
host_disk_except_os_disk_lists)
|
||||
return host_disk_except_os_disk_lists
|
||||
|
||||
|
||||
def _check_host_validity(self, **paras):
|
||||
'''
|
||||
paras['db_lv_size'], paras['glance_lv_size'] , paras['disk_size']
|
||||
paras['db_lv_size'], paras['glance_lv_size'] , paras['disk_size']
|
||||
'''
|
||||
disk_size = paras.get('disk_size', None)
|
||||
LOG.warn('--------disk_size:----- %s'% disk_size)
|
||||
LOG.warn('--------disk_size:----- %s' % disk_size)
|
||||
if disk_size:
|
||||
disk_size_m = int(disk_size)
|
||||
else:
|
||||
disk_size_m = 0
|
||||
if disk_size_m == 0: #Host hard disk size was 0, think that the host does not need to install the system
|
||||
return #Don't need to ckeck the validity of hard disk size
|
||||
|
||||
if disk_size_m == 0: # Host hard disk size was 0,
|
||||
# think that the host does not need to install the system
|
||||
return # Don't need to ckeck the validity of hard disk size
|
||||
|
||||
db_lv_size_m = paras.get('db_lv_size', 300)
|
||||
if db_lv_size_m:
|
||||
db_lv_size_m = int(db_lv_size_m)
|
||||
else:
|
||||
db_lv_size_m = 0
|
||||
|
||||
|
||||
glance_lv_size_m = paras.get('glance_lv_size', 17100)
|
||||
if glance_lv_size_m:
|
||||
glance_lv_size_m = int(glance_lv_size_m)
|
||||
else:
|
||||
glance_lv_size_m = 0
|
||||
|
||||
|
||||
nova_lv_size_m = paras.get('nova_lv_size', 0)
|
||||
if nova_lv_size_m:
|
||||
nova_lv_size_m = int(nova_lv_size_m)
|
||||
@ -217,11 +237,13 @@ class Controller(controller.BaseController):
|
||||
nova_lv_size_m = 0
|
||||
if nova_lv_size_m == -1:
|
||||
nova_lv_size_m = 0
|
||||
glance_lv_size_m = (glance_lv_size_m/4)*4
|
||||
db_lv_size_m = (db_lv_size_m/4)*4
|
||||
nova_lv_size_m = (nova_lv_size_m/4)*4
|
||||
glance_lv_size_m = (glance_lv_size_m / 4) * 4
|
||||
db_lv_size_m = (db_lv_size_m / 4) * 4
|
||||
nova_lv_size_m = (nova_lv_size_m / 4) * 4
|
||||
if glance_lv_size_m + db_lv_size_m + nova_lv_size_m > disk_size_m:
|
||||
msg = _("There isn't enough disk space to specify database or glance or nova disk, please specify database or glance or nova disk size again")
|
||||
msg = _("There isn't enough disk space to specify database or "
|
||||
"glance or nova disk, please specify database or "
|
||||
"glance or nova disk size again")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
@ -236,7 +258,12 @@ class Controller(controller.BaseController):
|
||||
def _check_config_set_id_exist(self, req, config_set_id):
|
||||
self._raise_404_if_config_set_deleted(req, config_set_id)
|
||||
|
||||
def _check_glance_lv_value(self, req, glance_lv_value, role_name, service_name_list):
|
||||
def _check_glance_lv_value(
|
||||
self,
|
||||
req,
|
||||
glance_lv_value,
|
||||
role_name,
|
||||
service_name_list):
|
||||
if int(glance_lv_value) < 0 and int(glance_lv_value) != -1:
|
||||
msg = _("glance_lv_size can't be negative except -1.")
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
@ -250,150 +277,170 @@ class Controller(controller.BaseController):
|
||||
content_type="text/plain")
|
||||
|
||||
def _check_db_lv_size(self, req, db_lv_size, service_name_list):
|
||||
if int(db_lv_size) < 0 and int(db_lv_size) != -1 :
|
||||
if int(db_lv_size) < 0 and int(db_lv_size) != -1:
|
||||
msg = _("The size of database disk can't be negative except -1.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
#Only the role with database service can be formulated the size of a database.
|
||||
if 'mariadb' not in service_name_list and 'mongodb' not in service_name_list:
|
||||
# Only the role with database service can be formulated the size of
|
||||
# a database.
|
||||
if 'mariadb' not in service_name_list and 'mongodb' not in \
|
||||
service_name_list:
|
||||
msg = _('The role without database service is unable '
|
||||
'to specify the size of the database!')
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
def _check_nova_lv_size(self, req, nova_lv_size, role_name):
|
||||
if role_name != "COMPUTER":
|
||||
msg = _("The role is not COMPUTER, it can't set logic "
|
||||
"volume disk for nova.")
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
try:
|
||||
if int(nova_lv_size) < 0 and int(nova_lv_size) != -1:
|
||||
msg = _("The nova_lv_size must be -1 or [0, N).")
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except:
|
||||
msg = _("The nova_lv_size must be -1 or [0, N).")
|
||||
raise HTTPForbidden(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
def _check_all_lv_size(self, req, db_lv_size, glance_lv_size, nova_lv_size,
|
||||
host_id_list, cluster_id, argws):
|
||||
if db_lv_size or glance_lv_size or nova_lv_size:
|
||||
for host_id in host_id_list:
|
||||
host_disk_db_glance_nova_size = self.get_host_disk_db_glance_nova_size(req, host_id, cluster_id)
|
||||
if host_disk_db_glance_nova_size['db_lv_size'] and db_lv_size and \
|
||||
int(db_lv_size) < int(host_disk_db_glance_nova_size['db_lv_size']):
|
||||
argws['db_lv_size'] = host_disk_db_glance_nova_size['db_lv_size']
|
||||
host_disk_db_glance_nova_size = \
|
||||
self.get_host_disk_db_glance_nova_size(
|
||||
req, host_id, cluster_id)
|
||||
if host_disk_db_glance_nova_size['db_lv_size'] and \
|
||||
db_lv_size and int(
|
||||
db_lv_size) < int(host_disk_db_glance_nova_size[
|
||||
'db_lv_size']):
|
||||
argws['db_lv_size'] = host_disk_db_glance_nova_size[
|
||||
'db_lv_size']
|
||||
else:
|
||||
argws['db_lv_size'] = db_lv_size
|
||||
if host_disk_db_glance_nova_size['glance_lv_size'] and glance_lv_size and \
|
||||
int(glance_lv_size) < int(host_disk_db_glance_nova_size['glance_lv_size']):
|
||||
argws['glance_lv_size'] = host_disk_db_glance_nova_size['glance_lv_size']
|
||||
if host_disk_db_glance_nova_size['glance_lv_size'] and \
|
||||
glance_lv_size and int(
|
||||
glance_lv_size) < int(host_disk_db_glance_nova_size[
|
||||
'glance_lv_size']):
|
||||
argws['glance_lv_size'] = host_disk_db_glance_nova_size[
|
||||
'glance_lv_size']
|
||||
else:
|
||||
argws['glance_lv_size'] = glance_lv_size
|
||||
if host_disk_db_glance_nova_size['nova_lv_size'] and nova_lv_size and \
|
||||
int(nova_lv_size) < int(host_disk_db_glance_nova_size['nova_lv_size']):
|
||||
argws['nova_lv_size'] = host_disk_db_glance_nova_size['nova_lv_size']
|
||||
if host_disk_db_glance_nova_size['nova_lv_size'] and \
|
||||
nova_lv_size and int(
|
||||
nova_lv_size) < int(host_disk_db_glance_nova_size[
|
||||
'nova_lv_size']):
|
||||
argws['nova_lv_size'] = host_disk_db_glance_nova_size[
|
||||
'nova_lv_size']
|
||||
else:
|
||||
argws['nova_lv_size'] = nova_lv_size
|
||||
argws['disk_size'] = host_disk_db_glance_nova_size['disk_size']
|
||||
LOG.warn('--------host(%s) check_host_validity argws:----- %s'% (host_id, argws))
|
||||
LOG.warn(
|
||||
'--------host(%s) check_host_validity argws:----- %s' %
|
||||
(host_id, argws))
|
||||
self._check_host_validity(**argws)
|
||||
|
||||
def _check_deployment_backend(self, req, deployment_backend):
|
||||
if deployment_backend not in SUPPORTED_DEPLOYMENT_BACKENDS:
|
||||
msg = "deployment backend '%s' is not supported." % deployment_backend
|
||||
msg = "deployment backend '%s' is not supported." % \
|
||||
deployment_backend
|
||||
raise HTTPBadRequest(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
|
||||
def _check_role_type_in_update_role(self, req, role_type, orig_role_meta):
|
||||
if orig_role_meta['type'].lower() != role_type.lower():
|
||||
msg = _("Role type can not be updated to other type.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
def _check_cluster_id_in_role_update(self, req, role_cluster, orig_role_meta):
|
||||
|
||||
def _check_cluster_id_in_role_update(
|
||||
self, req, role_cluster, orig_role_meta):
|
||||
if orig_role_meta['type'].lower() == 'template':
|
||||
msg = _("The template role does not belong to any cluster.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
orig_role_cluster = orig_role_meta['cluster_id']
|
||||
if orig_role_cluster != role_cluster: #Can not change the cluster which the role belongs to
|
||||
if orig_role_cluster != role_cluster: # Can not change the cluster
|
||||
# which the role belongs to
|
||||
msg = _("Can't update the cluster of the role.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
else:
|
||||
self._raise_404_if_cluster_deleted(req, role_cluster)
|
||||
|
||||
|
||||
def _check_role_name_in_role_update(self, req, role_meta, orig_role_meta):
|
||||
role_name = role_meta['name']
|
||||
cluster_id = role_meta.get('cluster_id', orig_role_meta['cluster_id'])
|
||||
if cluster_id:
|
||||
self.check_cluster_role_name_repetition(req, role_name, cluster_id)
|
||||
else: #role type was template, cluster id was None
|
||||
else: # role type was template, cluster id was None
|
||||
self.check_template_role_name_repetition(req, role_name)
|
||||
|
||||
def _check_all_lv_size_of_nodes_with_role_in_role_update(self, req, role_meta, orig_role_meta,
|
||||
role_host_id_list):
|
||||
#check host with this role at the same time
|
||||
|
||||
def _check_all_lv_size_of_nodes_with_role_in_role_update(
|
||||
self, req, role_meta, orig_role_meta, role_host_id_list):
|
||||
# check host with this role at the same time
|
||||
cluster_id = role_meta.get('cluster_id', None)
|
||||
if not cluster_id: #role with cluster
|
||||
if not cluster_id: # role with cluster
|
||||
cluster_id = orig_role_meta['cluster_id']
|
||||
if not cluster_id: #without cluster id, raise Error
|
||||
if not cluster_id: # without cluster id, raise Error
|
||||
msg = _("The cluster_id parameter can not be None!")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
argws = dict()
|
||||
if role_meta.has_key('db_lv_size'):
|
||||
if 'db_lv_size' in role_meta:
|
||||
db_lv_size = role_meta['db_lv_size']
|
||||
else: #The db_lv_size has been specified before.
|
||||
else: # The db_lv_size has been specified before.
|
||||
db_lv_size = orig_role_meta.get('db_lv_size')
|
||||
if role_meta.has_key('glance_lv_size'):
|
||||
if 'glance_lv_size' in role_meta:
|
||||
glance_lv_size = role_meta['glance_lv_size']
|
||||
else:
|
||||
glance_lv_size = orig_role_meta.get('glance_lv_size')
|
||||
if role_meta.has_key('nova_lv_size'):
|
||||
if 'nova_lv_size' in role_meta:
|
||||
nova_lv_size = role_meta['nova_lv_size']
|
||||
else:
|
||||
nova_lv_size = orig_role_meta.get('nova_lv_size')
|
||||
if role_meta.has_key('nodes'):
|
||||
if 'nodes' in role_meta:
|
||||
host_id_list = list(eval(role_meta['nodes'])) + role_host_id_list
|
||||
else:
|
||||
host_id_list = role_host_id_list
|
||||
self._check_all_lv_size(req, db_lv_size, glance_lv_size,
|
||||
nova_lv_size, host_id_list, cluster_id, argws)
|
||||
|
||||
|
||||
def _check_ntp_server(self, req, role_name):
|
||||
if role_name != 'CONTROLLER_HA':
|
||||
msg = 'The role %s need no ntp_server' % role_name
|
||||
raise HTTPForbidden(explanation=msg)
|
||||
|
||||
|
||||
def _check_role_type_in_role_add(self, req, role_meta):
|
||||
#role_type == None or not template, cluster id must not be None
|
||||
# role_type == None or not template, cluster id must not be None
|
||||
role_type = role_meta['type']
|
||||
if role_type.lower() != 'template':
|
||||
if role_type.lower() != 'template':
|
||||
role_cluster_id = role_meta.get('cluster_id', None)
|
||||
if not role_cluster_id: #add role without cluster id parameter, raise error
|
||||
msg = _("The cluster_id parameter can not be None if role was not a template type.")
|
||||
if not role_cluster_id: # add role without cluster id parameter,
|
||||
# raise error
|
||||
msg = _(
|
||||
"The cluster_id parameter can not be None "
|
||||
"if role was not a template type.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
else: #role_type == template, cluster id is not necessary
|
||||
if role_meta.has_key('cluster_id'):
|
||||
else: # role_type == template, cluster id is not necessary
|
||||
if 'cluster_id' in role_meta:
|
||||
msg = _("Tht template role cannot be added to any cluster.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
def _check_all_lv_size_with_role_in_role_add(self, req, role_meta):
|
||||
cluster_id = role_meta.get('cluster_id', None)
|
||||
if not cluster_id: #without cluster id, raise Error
|
||||
if not cluster_id: # without cluster id, raise Error
|
||||
msg = _("The cluster_id parameter can not be None!")
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
@ -403,87 +450,104 @@ class Controller(controller.BaseController):
|
||||
nova_lv_size = role_meta.get('nova_lv_size', 0)
|
||||
host_id_list = list(eval(role_meta['nodes']))
|
||||
self._check_all_lv_size(req, db_lv_size, glance_lv_size,
|
||||
nova_lv_size, host_id_list, cluster_id, argws)
|
||||
nova_lv_size, host_id_list, cluster_id, argws)
|
||||
|
||||
def get_host_disk_db_glance_nova_size(self, req, host_id, cluster_id):
|
||||
'''
|
||||
return :
|
||||
return :
|
||||
host_disk_db_glance_nova_size['disk_size'] = 1024000
|
||||
host_disk_db_glance_nova_size['db_lv_size'] = 1011
|
||||
host_disk_db_glance_nova_size['glance_lv_size'] = 1011
|
||||
host_disk_db_glance_nova_size['nova_lv_size'] = 1011
|
||||
'''
|
||||
#import pdb;pdb.set_trace()
|
||||
# import pdb;pdb.set_trace()
|
||||
host_disk_db_glance_nova_size = dict()
|
||||
db_lv_size = list()
|
||||
glance_lv_size = list()
|
||||
nova_lv_size= list()
|
||||
disk_size = list()
|
||||
|
||||
nova_lv_size = list()
|
||||
# disk_size = list()
|
||||
|
||||
host_info = self.get_host_meta_or_404(req, host_id)
|
||||
if host_info:
|
||||
if host_info.has_key('deleted') and host_info['deleted']:
|
||||
msg = _("Node with identifier %s has been deleted.") % host_info['id']
|
||||
if 'deleted' in host_info and host_info['deleted']:
|
||||
msg = _("Node with identifier %s has been deleted.") % \
|
||||
host_info[
|
||||
'id']
|
||||
LOG.debug(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
#get host disk infomation
|
||||
# get host disk infomation
|
||||
host_disk = self._get_host_disk_except_os_disk_by_info(host_info)
|
||||
host_disk_db_glance_nova_size['disk_size'] = host_disk
|
||||
#get role_host db/galnce/nova infomation
|
||||
# get role_host db/galnce/nova infomation
|
||||
cluster_info = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if host_info.has_key('cluster'): #host with cluster
|
||||
if 'cluster' in host_info: # host with cluster
|
||||
if host_info['cluster'] != cluster_info['name']:
|
||||
#type(host_info['cluster']) = list, type(cluster_info['name']) = str
|
||||
msg = _("Role and hosts belong to different cluster.")
|
||||
# type(host_info['cluster']) = list,
|
||||
# type(cluster_info['name']) = str
|
||||
msg = _("Role and hosts belong to different cluster.")
|
||||
LOG.debug(msg)
|
||||
raise HTTPNotFound(msg)
|
||||
else:
|
||||
all_roles = registry.get_roles_detail(req.context)
|
||||
cluster_roles = [role for role in all_roles if role['cluster_id'] == cluster_id]
|
||||
#roles infomation saved in cluster_roles
|
||||
if host_info.has_key('role') and host_info['role']: #host with role
|
||||
cluster_roles = [
|
||||
role for role in all_roles if role['cluster_id'] ==
|
||||
cluster_id]
|
||||
# roles infomation saved in cluster_roles
|
||||
if 'role' in host_info and host_info[
|
||||
'role']: # host with role
|
||||
for role in cluster_roles:
|
||||
if role['name'] in host_info['role'] and cluster_roles:
|
||||
if role['name'] in host_info[
|
||||
'role'] and cluster_roles:
|
||||
db_lv_size.append(role.get('db_lv_size', None))
|
||||
glance_lv_size.append(role.get('glance_lv_size', None))
|
||||
nova_lv_size.append(role.get('nova_lv_size', None))
|
||||
|
||||
if db_lv_size:
|
||||
glance_lv_size.append(
|
||||
role.get('glance_lv_size', None))
|
||||
nova_lv_size.append(
|
||||
role.get('nova_lv_size', None))
|
||||
|
||||
if db_lv_size:
|
||||
host_disk_db_glance_nova_size['db_lv_size'] = max(db_lv_size)
|
||||
else: #host without cluster
|
||||
else: # host without cluster
|
||||
host_disk_db_glance_nova_size['db_lv_size'] = 0
|
||||
if glance_lv_size:
|
||||
host_disk_db_glance_nova_size['glance_lv_size'] = max(glance_lv_size)
|
||||
if glance_lv_size:
|
||||
host_disk_db_glance_nova_size[
|
||||
'glance_lv_size'] = max(glance_lv_size)
|
||||
else:
|
||||
host_disk_db_glance_nova_size['glance_lv_size'] = 0
|
||||
if nova_lv_size:
|
||||
if nova_lv_size:
|
||||
host_disk_db_glance_nova_size['nova_lv_size'] = max(nova_lv_size)
|
||||
else:
|
||||
host_disk_db_glance_nova_size['nova_lv_size'] = 0
|
||||
LOG.warn('--------host(%s)disk_db_glance_nova_size:----- %s'% (host_id, host_disk_db_glance_nova_size))
|
||||
LOG.warn('--------host(%s)disk_db_glance_nova_size:----- %s' %
|
||||
(host_id, host_disk_db_glance_nova_size))
|
||||
return host_disk_db_glance_nova_size
|
||||
|
||||
|
||||
def check_cluster_role_name_repetition(self, req, role_name, cluster_id):
|
||||
all_roles = registry.get_roles_detail(req.context)
|
||||
cluster_roles = [role for role in all_roles if role['cluster_id'] == cluster_id]
|
||||
cluster_roles = [role for role in all_roles if role[
|
||||
'cluster_id'] == cluster_id]
|
||||
cluster_roles_name = [role['name'].lower() for role in cluster_roles]
|
||||
if role_name.lower() in cluster_roles_name:
|
||||
msg = _("The role %s has already been in the cluster %s!" % (role_name, cluster_id))
|
||||
if role_name.lower() in cluster_roles_name:
|
||||
msg = _(
|
||||
"The role %s has already been in the cluster %s!" %
|
||||
(role_name, cluster_id))
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
def check_template_role_name_repetition(self, req, role_name):
|
||||
all_roles = registry.get_roles_detail(req.context)
|
||||
template_roles = [role for role in all_roles if role['cluster_id'] == None]
|
||||
template_roles = [
|
||||
role for role in all_roles if role['cluster_id'] is None]
|
||||
template_roles_name = [role['name'].lower() for role in template_roles]
|
||||
if role_name.lower() in template_roles_name:
|
||||
msg = _("The role %s has already been in the the template role." % role_name)
|
||||
msg = _(
|
||||
"The role %s has already been in the the template role." %
|
||||
role_name)
|
||||
LOG.debug(msg)
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
|
||||
def _check_disk_parameters(self, req, role_meta):
|
||||
if (role_meta.has_key('disk_location') and
|
||||
role_meta['disk_location'] not in SUPPORT_DISK_LOCATION):
|
||||
if ('disk_location' in role_meta and
|
||||
role_meta['disk_location'] not in SUPPORT_DISK_LOCATION):
|
||||
msg = _("value of disk_location is not supported.")
|
||||
raise HTTPForbidden(msg)
|
||||
|
||||
@ -496,69 +560,82 @@ class Controller(controller.BaseController):
|
||||
role_service_id_list, role_host_id_list):
|
||||
role_name = orig_role_meta['name']
|
||||
if role_meta.get('type', None):
|
||||
self._check_role_type_in_update_role(req, role_meta['type'], orig_role_meta)
|
||||
if role_meta.has_key('ntp_server'):
|
||||
self._check_role_type_in_update_role(
|
||||
req, role_meta['type'], orig_role_meta)
|
||||
if 'ntp_server' in role_meta:
|
||||
self._check_ntp_server(req, role_name)
|
||||
if role_meta.has_key('nodes'):
|
||||
if 'nodes' in role_meta:
|
||||
self._check_nodes_exist(req, list(eval(role_meta['nodes'])))
|
||||
if role_meta.has_key('services'):
|
||||
if 'services' in role_meta:
|
||||
self._check_services_exist(req, list(eval(role_meta['services'])))
|
||||
role_service_id_list.extend(list(eval(role_meta['services'])))
|
||||
if role_meta.has_key('config_set_id'):
|
||||
self._check_config_set_id_exist(req, str(role_meta['config_set_id']))
|
||||
if role_meta.has_key('cluster_id'):
|
||||
self._check_cluster_id_in_role_update(req, str(role_meta['cluster_id']), orig_role_meta)
|
||||
if role_meta.has_key('name'):
|
||||
self._check_role_name_in_role_update(req, role_meta, orig_role_meta)
|
||||
service_name_list = self._get_service_name_list(req, role_service_id_list)
|
||||
glance_lv_value = role_meta.get('glance_lv_size', orig_role_meta['glance_lv_size'])
|
||||
if 'config_set_id' in role_meta:
|
||||
self._check_config_set_id_exist(
|
||||
req, str(role_meta['config_set_id']))
|
||||
if 'cluster_id' in role_meta:
|
||||
self._check_cluster_id_in_role_update(
|
||||
req, str(role_meta['cluster_id']), orig_role_meta)
|
||||
if 'name' in role_meta:
|
||||
self._check_role_name_in_role_update(
|
||||
req, role_meta, orig_role_meta)
|
||||
service_name_list = self._get_service_name_list(
|
||||
req, role_service_id_list)
|
||||
glance_lv_value = role_meta.get(
|
||||
'glance_lv_size', orig_role_meta['glance_lv_size'])
|
||||
if glance_lv_value:
|
||||
self._check_glance_lv_value(req, glance_lv_value, role_name, service_name_list)
|
||||
self._check_glance_lv_value(
|
||||
req, glance_lv_value, role_name, service_name_list)
|
||||
if role_meta.get('db_lv_size', None) and role_meta['db_lv_size']:
|
||||
self._check_db_lv_size(req, role_meta['db_lv_size'], service_name_list)
|
||||
self._check_db_lv_size(
|
||||
req, role_meta['db_lv_size'], service_name_list)
|
||||
if role_meta.get('nova_lv_size', None):
|
||||
self._check_nova_lv_size(req, role_meta['nova_lv_size'], role_name)
|
||||
if role_meta.has_key('nodes') or role_host_id_list:
|
||||
self._check_all_lv_size_of_nodes_with_role_in_role_update(req, role_meta, orig_role_meta,
|
||||
role_host_id_list)
|
||||
if 'nodes' in role_meta or role_host_id_list:
|
||||
self._check_all_lv_size_of_nodes_with_role_in_role_update(
|
||||
req, role_meta, orig_role_meta, role_host_id_list)
|
||||
self._check_disk_parameters(req, role_meta)
|
||||
if role_meta.has_key('deployment_backend'):
|
||||
self._check_deployment_backend(req, role_meta['deployment_backend'])
|
||||
if 'deployment_backend' in role_meta:
|
||||
self._check_deployment_backend(
|
||||
req, role_meta['deployment_backend'])
|
||||
if role_meta.get('role_type', None):
|
||||
self._check_type_role_reasonable(req, role_meta)
|
||||
|
||||
|
||||
def _check_role_add_parameters(self, req, role_meta, role_service_id_list):
|
||||
role_type = role_meta.get('type', None)
|
||||
role_name = role_meta.get('name', None)
|
||||
if role_meta.get('type', None):
|
||||
self._check_role_type_in_role_add(req, role_meta)
|
||||
if role_meta.has_key('nodes'):
|
||||
if 'nodes' in role_meta:
|
||||
self._check_nodes_exist(req, list(eval(role_meta['nodes'])))
|
||||
if role_meta.has_key('services'):
|
||||
if 'services' in role_meta:
|
||||
self._check_services_exist(req, list(eval(role_meta['services'])))
|
||||
role_service_id_list.extend(list(eval(role_meta['services'])))
|
||||
if role_meta.has_key('config_set_id'):
|
||||
self._check_config_set_id_exist(req, str(role_meta['config_set_id']))
|
||||
if role_meta.has_key('cluster_id'):
|
||||
if 'config_set_id' in role_meta:
|
||||
self._check_config_set_id_exist(
|
||||
req, str(role_meta['config_set_id']))
|
||||
if 'cluster_id' in role_meta:
|
||||
orig_cluster = str(role_meta['cluster_id'])
|
||||
self._raise_404_if_cluster_deleted(req, orig_cluster)
|
||||
self.check_cluster_role_name_repetition(req, role_name, orig_cluster)
|
||||
self.check_cluster_role_name_repetition(
|
||||
req, role_name, orig_cluster)
|
||||
else:
|
||||
self.check_template_role_name_repetition(req, role_name)
|
||||
service_name_list = self._get_service_name_list(req, role_service_id_list)
|
||||
service_name_list = self._get_service_name_list(
|
||||
req, role_service_id_list)
|
||||
glance_lv_value = role_meta.get('glance_lv_size', None)
|
||||
if glance_lv_value:
|
||||
self._check_glance_lv_value(req, glance_lv_value, role_name, service_name_list)
|
||||
self._check_glance_lv_value(
|
||||
req, glance_lv_value, role_name, service_name_list)
|
||||
if role_meta.get('db_lv_size', None) and role_meta['db_lv_size']:
|
||||
self._check_db_lv_size(req, role_meta['db_lv_size'], service_name_list)
|
||||
self._check_db_lv_size(
|
||||
req, role_meta['db_lv_size'], service_name_list)
|
||||
if role_meta.get('nova_lv_size', None):
|
||||
self._check_nova_lv_size(req, role_meta['nova_lv_size'], role_name)
|
||||
if role_meta.has_key('nodes'):
|
||||
if 'nodes' in role_meta:
|
||||
self._check_all_lv_size_with_role_in_role_add(req, role_meta)
|
||||
self._check_disk_parameters(req, role_meta)
|
||||
if role_meta.has_key('deployment_backend'):
|
||||
self._check_deployment_backend(req, role_meta['deployment_backend'])
|
||||
if 'deployment_backend' in role_meta:
|
||||
self._check_deployment_backend(
|
||||
req, role_meta['deployment_backend'])
|
||||
else:
|
||||
role_meta['deployment_backend'] = 'tecs'
|
||||
if role_meta.get('role_type', None):
|
||||
@ -591,7 +668,7 @@ class Controller(controller.BaseController):
|
||||
def delete_role(self, req, id):
|
||||
"""
|
||||
Deletes a role from Daisy.
|
||||
|
||||
|
||||
:param req: The WSGI/Webob Request object
|
||||
:param image_meta: Mapping of metadata about role
|
||||
|
||||
@ -599,7 +676,7 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'delete_role')
|
||||
|
||||
#role = self.get_role_meta_or_404(req, id)
|
||||
# role = self.get_role_meta_or_404(req, id)
|
||||
print "delete_role:%s" % id
|
||||
try:
|
||||
registry.delete_role_metadata(req.context, id)
|
||||
@ -625,7 +702,7 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('role.delete', role)
|
||||
# self.notifier.info('role.delete', role)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -661,11 +738,11 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'get_roles')
|
||||
params = self._get_query_params(req)
|
||||
filters=params.get('filters',None)
|
||||
filters = params.get('filters', None)
|
||||
if 'cluster_id' in filters:
|
||||
cluster_id=filters['cluster_id']
|
||||
cluster_id = filters['cluster_id']
|
||||
self._raise_404_if_cluster_deleted(req, cluster_id)
|
||||
|
||||
|
||||
try:
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
@ -684,13 +761,28 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
orig_role_meta = self.get_role_meta_or_404(req, id)
|
||||
role_service_list = registry.get_role_services(req.context, id)
|
||||
role_service_id_list = [ role_service['service_id'] for role_service in role_service_list ]
|
||||
role_service_id_list = [role_service['service_id']
|
||||
for role_service in role_service_list]
|
||||
role_host_info_list = registry.get_role_host_metadata(req.context, id)
|
||||
role_host_id_list = [role_host['host_id'] for role_host in role_host_info_list]
|
||||
self._check_role_update_parameters(req, role_meta, orig_role_meta, role_service_id_list, role_host_id_list)
|
||||
role_host_id_list = [role_host['host_id']
|
||||
for role_host in role_host_info_list]
|
||||
self._check_role_update_parameters(
|
||||
req,
|
||||
role_meta,
|
||||
orig_role_meta,
|
||||
role_service_id_list,
|
||||
role_host_id_list)
|
||||
|
||||
if orig_role_meta['role_type'] == "CONTROLLER_HA":
|
||||
cluster_meta = {}
|
||||
cluster_meta['public_vip'] = role_meta.get(
|
||||
'public_vip') or role_meta.get('vip')
|
||||
if cluster_meta['public_vip']:
|
||||
cluster_meta = registry.update_cluster_metadata(
|
||||
req.context, orig_role_meta['cluster_id'], cluster_meta)
|
||||
|
||||
self._enforce(req, 'modify_image')
|
||||
#orig_role_meta = self.get_role_meta_or_404(req, id)
|
||||
# orig_role_meta = self.get_role_meta_or_404(req, id)
|
||||
|
||||
# Do not allow any updates on a deleted image.
|
||||
# Fix for LP Bug #1060930
|
||||
@ -735,6 +827,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'role_meta': role_meta}
|
||||
|
||||
|
||||
class RoleDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -749,6 +842,7 @@ class RoleDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_role(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class RoleSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -768,6 +862,7 @@ class RoleSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(role=role_meta))
|
||||
return response
|
||||
|
||||
def get_role(self, response, result):
|
||||
role_meta = result['role_meta']
|
||||
response.status = 201
|
||||
@ -775,6 +870,7 @@ class RoleSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(role=role_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Roles resource factory method"""
|
||||
deserializer = RoleDeserializer()
|
||||
|
@ -14,7 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
#from daisy.api.v1 import images
|
||||
# from daisy.api.v1 import images
|
||||
from daisy.api.v1 import hosts
|
||||
from daisy.api.v1 import clusters
|
||||
from daisy.api.v1 import template
|
||||
@ -29,14 +29,17 @@ from daisy.api.v1 import networks
|
||||
from daisy.api.v1 import install
|
||||
from daisy.api.v1 import disk_array
|
||||
from daisy.api.v1 import host_template
|
||||
from daisy.api.v1 import hwms
|
||||
from daisy.common import wsgi
|
||||
from daisy.api.v1 import backup_restore
|
||||
|
||||
|
||||
class API(wsgi.Router):
|
||||
|
||||
"""WSGI router for Glance v1 API requests."""
|
||||
|
||||
def __init__(self, mapper):
|
||||
reject_method_resource = wsgi.Resource(wsgi.RejectMethodController())
|
||||
wsgi.Resource(wsgi.RejectMethodController())
|
||||
|
||||
'''images_resource = images.create_resource()
|
||||
|
||||
@ -126,7 +129,6 @@ class API(wsgi.Router):
|
||||
controller=members_resource,
|
||||
action="index_shared_images")'''
|
||||
|
||||
|
||||
hosts_resource = hosts.create_resource()
|
||||
|
||||
mapper.connect("/nodes",
|
||||
@ -145,11 +147,17 @@ class API(wsgi.Router):
|
||||
controller=hosts_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/nodes/{id}",
|
||||
controller=hosts_resource,
|
||||
action='get_host',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/hwm_nodes",
|
||||
controller=hosts_resource,
|
||||
action='update_hwm_host',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/discover_host/",
|
||||
controller=hosts_resource,
|
||||
action='discover_host',
|
||||
@ -159,17 +167,17 @@ class API(wsgi.Router):
|
||||
controller=hosts_resource,
|
||||
action='add_discover_host',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/discover/nodes/{id}",
|
||||
controller=hosts_resource,
|
||||
action='delete_discover_host',
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
|
||||
mapper.connect("/discover/nodes",
|
||||
controller=hosts_resource,
|
||||
action='detail_discover_host',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/discover/nodes/{id}",
|
||||
controller=hosts_resource,
|
||||
action='update_discover_host',
|
||||
@ -179,9 +187,43 @@ class API(wsgi.Router):
|
||||
controller=hosts_resource,
|
||||
action='get_discover_host_detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/pxe_discover/nodes",
|
||||
controller=hosts_resource,
|
||||
action='add_pxe_host',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/pxe_discover/nodes/{id}",
|
||||
controller=hosts_resource,
|
||||
action='update_pxe_host',
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
hwms_resource = hwms.create_resource()
|
||||
|
||||
mapper.connect("/hwm",
|
||||
controller=hwms_resource,
|
||||
action='add_hwm',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/hwm/{id}",
|
||||
controller=hwms_resource,
|
||||
action='delete_hwm',
|
||||
conditions={'method': ['DELETE']})
|
||||
mapper.connect("/hwm/{id}",
|
||||
controller=hwms_resource,
|
||||
action='update_hwm',
|
||||
conditions={'method': ['PUT']})
|
||||
mapper.connect("/hwm",
|
||||
controller=hwms_resource,
|
||||
action='list',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/hwm/{id}",
|
||||
controller=hwms_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
clusters_resource = clusters.create_resource()
|
||||
|
||||
|
||||
mapper.connect("/clusters",
|
||||
controller=clusters_resource,
|
||||
action='add_cluster',
|
||||
@ -193,56 +235,54 @@ class API(wsgi.Router):
|
||||
mapper.connect("/clusters/{id}",
|
||||
controller=clusters_resource,
|
||||
action='update_cluster',
|
||||
conditions={'method': ['PUT']})
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
mapper.connect("/clusters",
|
||||
controller=clusters_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/clusters/{id}",
|
||||
controller=clusters_resource,
|
||||
action='get_cluster',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
|
||||
mapper.connect("/clusters/{id}",
|
||||
controller=clusters_resource,
|
||||
action='update_cluster',
|
||||
conditions={'method': ['PUT']})
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
template_resource = template.create_resource()
|
||||
mapper.connect("/template",
|
||||
controller=template_resource,
|
||||
action='add_template',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/template/{template_id}",
|
||||
controller=template_resource,
|
||||
action='update_template',
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
|
||||
|
||||
mapper.connect("/template/{template_id}",
|
||||
controller=template_resource,
|
||||
action='delete_template',
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
|
||||
mapper.connect("/template/lists",
|
||||
controller=template_resource,
|
||||
action='get_template_lists',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/template/{template_id}",
|
||||
controller=template_resource,
|
||||
action='get_template_detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/export_db_to_json",
|
||||
controller=template_resource,
|
||||
action='export_db_to_json',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/import_json_to_template",
|
||||
controller=template_resource,
|
||||
action='import_json_to_template',
|
||||
@ -253,7 +293,6 @@ class API(wsgi.Router):
|
||||
action='import_template_to_db',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
host_template_resource = host_template.create_resource()
|
||||
mapper.connect("/host_template",
|
||||
controller=host_template_resource,
|
||||
@ -262,7 +301,7 @@ class API(wsgi.Router):
|
||||
mapper.connect("/host_template/{template_id}",
|
||||
controller=host_template_resource,
|
||||
action='update_host_template',
|
||||
conditions={'method': ['PUT']})
|
||||
conditions={'method': ['PUT']})
|
||||
mapper.connect("/host_template",
|
||||
controller=host_template_resource,
|
||||
action='delete_host_template',
|
||||
@ -270,11 +309,11 @@ class API(wsgi.Router):
|
||||
mapper.connect("/host_template/lists",
|
||||
controller=host_template_resource,
|
||||
action='get_host_template_lists',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/host_template/{template_id}",
|
||||
controller=host_template_resource,
|
||||
action='get_host_template_detail',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/host_to_template",
|
||||
controller=host_template_resource,
|
||||
action='host_to_template',
|
||||
@ -283,7 +322,7 @@ class API(wsgi.Router):
|
||||
controller=host_template_resource,
|
||||
action='template_to_host',
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
|
||||
components_resource = components.create_resource()
|
||||
mapper.connect("/components",
|
||||
controller=components_resource,
|
||||
@ -296,16 +335,16 @@ class API(wsgi.Router):
|
||||
mapper.connect("/components/detail",
|
||||
controller=components_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/components/{id}",
|
||||
controller=components_resource,
|
||||
action='get_component',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/components/{id}",
|
||||
controller=components_resource,
|
||||
action='update_component',
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
services_resource = services.create_resource()
|
||||
mapper.connect("/services",
|
||||
controller=services_resource,
|
||||
@ -318,15 +357,15 @@ class API(wsgi.Router):
|
||||
mapper.connect("/services/detail",
|
||||
controller=services_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/services/{id}",
|
||||
controller=services_resource,
|
||||
action='get_service',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/services/{id}",
|
||||
controller=services_resource,
|
||||
action='update_service',
|
||||
conditions={'method': ['PUT']})
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
roles_resource = roles.create_resource()
|
||||
mapper.connect("/roles",
|
||||
@ -340,15 +379,15 @@ class API(wsgi.Router):
|
||||
mapper.connect("/roles/detail",
|
||||
controller=roles_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/roles/{id}",
|
||||
controller=roles_resource,
|
||||
action='get_role',
|
||||
conditions={'method': ['GET']})
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect("/roles/{id}",
|
||||
controller=roles_resource,
|
||||
action='update_role',
|
||||
conditions={'method': ['PUT']})
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
members_resource = members.create_resource()
|
||||
mapper.connect("/clusters/{cluster_id}/nodes/{host_id}",
|
||||
@ -359,102 +398,102 @@ class API(wsgi.Router):
|
||||
controller=members_resource,
|
||||
action="delete_cluster_host",
|
||||
conditions={'method': ['DELETE']})
|
||||
# mapper.connect("/clusters/{cluster_id}/nodes/{host_id}",
|
||||
# controller=members_resource,
|
||||
# action="get_cluster_hosts",
|
||||
# conditions={'method': ['GET']})
|
||||
# mapper.connect("/clusters/{cluster_id}/nodes",
|
||||
# controller=members_resource,
|
||||
# action="get_cluster_hosts",
|
||||
# conditions={'method': ['GET']})
|
||||
# mapper.connect("/multi_clusters/nodes/{host_id}",
|
||||
# controller=members_resource,
|
||||
# action="get_host_clusters",
|
||||
# conditions={'method': ['GET']})
|
||||
# mapper.connect("/clusters/{cluster_id}/nodes/{host_id}",
|
||||
# controller=members_resource,
|
||||
# action="get_cluster_hosts",
|
||||
# conditions={'method': ['GET']})
|
||||
# mapper.connect("/clusters/{cluster_id}/nodes",
|
||||
# controller=members_resource,
|
||||
# action="get_cluster_hosts",
|
||||
# conditions={'method': ['GET']})
|
||||
# mapper.connect("/multi_clusters/nodes/{host_id}",
|
||||
# controller=members_resource,
|
||||
# action="get_host_clusters",
|
||||
# conditions={'method': ['GET']})
|
||||
|
||||
config_files_resource = config_files.create_resource()
|
||||
|
||||
mapper.connect("/config_files",
|
||||
controller=config_files_resource,
|
||||
action="add_config_file",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
controller=config_files_resource,
|
||||
action="add_config_file",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/config_files/{id}",
|
||||
controller=config_files_resource,
|
||||
action="delete_config_file",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
controller=config_files_resource,
|
||||
action="delete_config_file",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
mapper.connect("/config_files/{id}",
|
||||
controller=config_files_resource,
|
||||
action="update_config_file",
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
controller=config_files_resource,
|
||||
action="update_config_file",
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
mapper.connect("/config_files/detail",
|
||||
controller=config_files_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
controller=config_files_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/config_files/{id}",
|
||||
controller=config_files_resource,
|
||||
action="get_config_file",
|
||||
conditions=dict(method=["GET"]))
|
||||
controller=config_files_resource,
|
||||
action="get_config_file",
|
||||
conditions=dict(method=["GET"]))
|
||||
config_sets_resource = config_sets.create_resource()
|
||||
|
||||
mapper.connect("/config_sets",
|
||||
controller=config_sets_resource,
|
||||
action="add_config_set",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
controller=config_sets_resource,
|
||||
action="add_config_set",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/config_sets/{id}",
|
||||
controller=config_sets_resource,
|
||||
action="delete_config_set",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
controller=config_sets_resource,
|
||||
action="delete_config_set",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
mapper.connect("/config_sets/{id}",
|
||||
controller=config_sets_resource,
|
||||
action="update_config_set",
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
controller=config_sets_resource,
|
||||
action="update_config_set",
|
||||
conditions={'method': ['PUT']})
|
||||
|
||||
mapper.connect("/config_sets/detail",
|
||||
controller=config_sets_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
controller=config_sets_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/config_sets/{id}",
|
||||
controller=config_sets_resource,
|
||||
action="get_config_set",
|
||||
conditions=dict(method=["GET"]))
|
||||
controller=config_sets_resource,
|
||||
action="get_config_set",
|
||||
conditions=dict(method=["GET"]))
|
||||
mapper.connect("/cluster_config_set_update",
|
||||
controller=config_sets_resource,
|
||||
action="cluster_config_set_update",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
controller=config_sets_resource,
|
||||
action="cluster_config_set_update",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/cluster_config_set_progress",
|
||||
controller=config_sets_resource,
|
||||
action="cluster_config_set_progress",
|
||||
conditions={'method': ['POST']})
|
||||
controller=config_sets_resource,
|
||||
action="cluster_config_set_progress",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
configs_resource = configs.create_resource()
|
||||
|
||||
mapper.connect("/configs",
|
||||
controller=configs_resource,
|
||||
action="add_config",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
controller=configs_resource,
|
||||
action="add_config",
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
mapper.connect("/configs_delete",
|
||||
controller=configs_resource,
|
||||
action="delete_config",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
controller=configs_resource,
|
||||
action="delete_config",
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
mapper.connect("/configs/detail",
|
||||
controller=configs_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
controller=configs_resource,
|
||||
action="detail",
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/configs/{id}",
|
||||
controller=configs_resource,
|
||||
action="get_config",
|
||||
conditions=dict(method=["GET"]))
|
||||
controller=configs_resource,
|
||||
action="get_config",
|
||||
conditions=dict(method=["GET"]))
|
||||
|
||||
networks_resource = networks.create_resource()
|
||||
|
||||
@ -474,16 +513,16 @@ class API(wsgi.Router):
|
||||
controller=networks_resource,
|
||||
action='detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/networks/{id}",
|
||||
controller=networks_resource,
|
||||
action='get_network',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
mapper.connect("/networks",
|
||||
controller=networks_resource,
|
||||
action='get_all_network',
|
||||
conditions={'method': ['GET']})
|
||||
controller=networks_resource,
|
||||
action='get_all_network',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
install_resource = install.create_resource()
|
||||
|
||||
@ -491,12 +530,12 @@ class API(wsgi.Router):
|
||||
controller=install_resource,
|
||||
action='install_cluster',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/export_db",
|
||||
controller=install_resource,
|
||||
action='export_db',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/uninstall/{cluster_id}",
|
||||
controller=install_resource,
|
||||
action='uninstall_cluster',
|
||||
@ -510,23 +549,23 @@ class API(wsgi.Router):
|
||||
controller=install_resource,
|
||||
action='update_cluster',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
|
||||
mapper.connect("/update/{cluster_id}",
|
||||
controller=install_resource,
|
||||
action='update_progress',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/disk_array/{cluster_id}",
|
||||
controller=install_resource,
|
||||
action='update_disk_array',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
#mapper.connect("/update/{cluster_id}/versions/{versions_id}",
|
||||
|
||||
# mapper.connect("/update/{cluster_id}/versions/{versions_id}",
|
||||
# controller=update_resource,
|
||||
# action='update_cluster_version',
|
||||
# conditions={'method': ['POST']})
|
||||
|
||||
array_resource = disk_array.create_resource()
|
||||
|
||||
array_resource = disk_array.create_resource()
|
||||
mapper.connect("/service_disk",
|
||||
controller=array_resource,
|
||||
action='service_disk_add',
|
||||
@ -547,7 +586,7 @@ class API(wsgi.Router):
|
||||
controller=array_resource,
|
||||
action='service_disk_detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
mapper.connect("/cinder_volume",
|
||||
controller=array_resource,
|
||||
action='cinder_volume_add',
|
||||
@ -568,7 +607,23 @@ class API(wsgi.Router):
|
||||
controller=array_resource,
|
||||
action='cinder_volume_detail',
|
||||
conditions={'method': ['GET']})
|
||||
|
||||
|
||||
backup_restore_resource = backup_restore.create_resource()
|
||||
|
||||
mapper.connect("/backup",
|
||||
controller=backup_restore_resource,
|
||||
action='backup',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/restore",
|
||||
controller=backup_restore_resource,
|
||||
action='restore',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/backup_file_version",
|
||||
controller=backup_restore_resource,
|
||||
action='get_backup_file_version',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect("/version",
|
||||
controller=backup_restore_resource,
|
||||
action='version',
|
||||
conditions={'method': ['POST']})
|
||||
super(API, self).__init__(mapper)
|
||||
|
||||
|
||||
|
@ -52,12 +52,13 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for services resource in Daisy v1 API
|
||||
|
||||
The services resource API is a RESTful web service for service data. The API
|
||||
is as follows::
|
||||
The services resource API is a RESTful web service for service data.
|
||||
The API is as follows::
|
||||
|
||||
GET /services -- Returns a set of brief metadata about services
|
||||
GET /services/detail -- Returns a set of detailed metadata about
|
||||
@ -124,7 +125,8 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_component_deleted(self, req, component_id):
|
||||
component = self.get_component_meta_or_404(req, component_id)
|
||||
if component['deleted']:
|
||||
msg = _("Component with identifier %s has been deleted.") % component_id
|
||||
msg = _("Component with identifier %s has been deleted.") % \
|
||||
component_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
@utils.mutating
|
||||
@ -141,7 +143,7 @@ class Controller(controller.BaseController):
|
||||
service_name = service_meta["name"]
|
||||
service_description = service_meta["description"]
|
||||
|
||||
if service_meta.has_key('component_id'):
|
||||
if 'component_id' in service_meta:
|
||||
orig_component_id = str(service_meta['component_id'])
|
||||
self._raise_404_if_component_deleted(req, orig_component_id)
|
||||
|
||||
@ -163,7 +165,7 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'delete_service')
|
||||
|
||||
#service = self.get_service_meta_or_404(req, id)
|
||||
# service = self.get_service_meta_or_404(req, id)
|
||||
print "delete_service:%s" % id
|
||||
try:
|
||||
registry.delete_service_metadata(req.context, id)
|
||||
@ -182,14 +184,15 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("service %(id)s could not be deleted because it is in use: "
|
||||
msg = (_("service %(id)s could not be deleted "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": id, "exc": utils.exception_to_str(e)})
|
||||
LOG.warn(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
#self.notifier.info('service.delete', service)
|
||||
# self.notifier.info('service.delete', service)
|
||||
return Response(body='', status=200)
|
||||
|
||||
@utils.mutating
|
||||
@ -287,6 +290,7 @@ class Controller(controller.BaseController):
|
||||
|
||||
return {'service_meta': service_meta}
|
||||
|
||||
|
||||
class ServiceDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
@ -301,6 +305,7 @@ class ServiceDeserializer(wsgi.JSONRequestDeserializer):
|
||||
def update_service(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class ServiceSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
@ -320,6 +325,7 @@ class ServiceSerializer(wsgi.JSONResponseSerializer):
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(service=service_meta))
|
||||
return response
|
||||
|
||||
def get_service(self, response, result):
|
||||
service_meta = result['service_meta']
|
||||
response.status = 201
|
||||
@ -327,6 +333,7 @@ class ServiceSerializer(wsgi.JSONResponseSerializer):
|
||||
response.body = self.to_json(dict(service=service_meta))
|
||||
return response
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Services resource factory method"""
|
||||
deserializer = ServiceDeserializer()
|
||||
|
@ -42,10 +42,6 @@ from daisy.registry.api.v1 import template
|
||||
|
||||
import daisy.api.backends.tecs.common as tecs_cmn
|
||||
import daisy.api.backends.common as daisy_cmn
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
daisy_tecs_path = tecs_cmn.daisy_tecs_path
|
||||
|
||||
@ -64,12 +60,13 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
group='image_format')
|
||||
CONF.import_opt('image_property_quota', 'daisy.common.config')
|
||||
|
||||
|
||||
class Controller(controller.BaseController):
|
||||
"""
|
||||
WSGI controller for Templates resource in Daisy v1 API
|
||||
|
||||
The Templates resource API is a RESTful web Template for Template data. The API
|
||||
is as follows::
|
||||
The Templates resource API is a RESTful web Template for Template data.
|
||||
The API is as follows::
|
||||
|
||||
GET /Templates -- Returns a set of brief metadata about Templates
|
||||
GET /Templates/detail -- Returns a set of detailed metadata about
|
||||
@ -136,8 +133,9 @@ class Controller(controller.BaseController):
|
||||
def _raise_404_if_cluster_deleted(self, req, cluster_id):
|
||||
cluster = self.get_cluster_meta_or_404(req, cluster_id)
|
||||
if cluster['deleted']:
|
||||
msg = _("Cluster with identifier %s has been deleted.") % cluster_id
|
||||
raise webob.exc.HTTPNotFound(msg)
|
||||
msg = _("Cluster with identifier %s has been deleted.") % \
|
||||
cluster_id
|
||||
raise HTTPNotFound(msg)
|
||||
|
||||
@utils.mutating
|
||||
def add_template(self, req, template):
|
||||
@ -150,8 +148,7 @@ class Controller(controller.BaseController):
|
||||
:raises HTTPBadRequest if x-Template-name is missing
|
||||
"""
|
||||
self._enforce(req, 'add_template')
|
||||
template_name = template["name"]
|
||||
|
||||
|
||||
template = registry.add_template_metadata(req.context, template)
|
||||
|
||||
return {'template': template}
|
||||
@ -169,8 +166,8 @@ class Controller(controller.BaseController):
|
||||
self._enforce(req, 'update_template')
|
||||
try:
|
||||
template = registry.update_template_metadata(req.context,
|
||||
template_id,
|
||||
template)
|
||||
template_id,
|
||||
template)
|
||||
|
||||
except exception.Invalid as e:
|
||||
msg = (_("Failed to update template metadata. Got error: %s") %
|
||||
@ -202,6 +199,7 @@ class Controller(controller.BaseController):
|
||||
self.notifier.info('template.update', template)
|
||||
|
||||
return {'template': template}
|
||||
|
||||
@utils.mutating
|
||||
def delete_template(self, req, template_id):
|
||||
"""
|
||||
@ -230,23 +228,25 @@ class Controller(controller.BaseController):
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("template %(id)s could not be deleted because it is in use: "
|
||||
"%(exc)s") % {"id": template_id, "exc": utils.exception_to_str(e)})
|
||||
msg = (_("template %(id)s could not be deleted "
|
||||
"because it is in use: "
|
||||
"%(exc)s") % {"id": template_id,
|
||||
"exc": utils.exception_to_str(e)})
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
return Response(body='', status=200)
|
||||
|
||||
def _del_general_params(self,param):
|
||||
|
||||
def _del_general_params(self, param):
|
||||
del param['created_at']
|
||||
del param['updated_at']
|
||||
del param['deleted']
|
||||
del param['deleted_at']
|
||||
del param['id']
|
||||
|
||||
def _del_cluster_params(self,cluster):
|
||||
|
||||
def _del_cluster_params(self, cluster):
|
||||
del cluster['networks']
|
||||
del cluster['vlan_start']
|
||||
del cluster['vlan_end']
|
||||
@ -259,7 +259,27 @@ class Controller(controller.BaseController):
|
||||
del cluster['segmentation_type']
|
||||
del cluster['base_mac']
|
||||
del cluster['name']
|
||||
|
||||
|
||||
def _get_cinder_volumes(self, req, role):
|
||||
cinder_volume_params = {'filters': {'role_id': role['id']}}
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(
|
||||
req.context, **cinder_volume_params)
|
||||
for cinder_volume in cinder_volumes:
|
||||
if cinder_volume.get('role_id', None):
|
||||
cinder_volume['role_id'] = role['name']
|
||||
self._del_general_params(cinder_volume)
|
||||
return cinder_volumes
|
||||
|
||||
def _get_services_disk(self, req, role):
|
||||
params = {'filters': {'role_id': role['id']}}
|
||||
services_disk = registry.list_service_disk_metadata(
|
||||
req.context, **params)
|
||||
for service_disk in services_disk:
|
||||
if service_disk.get('role_id', None):
|
||||
service_disk['role_id'] = role['name']
|
||||
self._del_general_params(service_disk)
|
||||
return services_disk
|
||||
|
||||
@utils.mutating
|
||||
def export_db_to_json(self, req, template):
|
||||
"""
|
||||
@ -267,40 +287,45 @@ class Controller(controller.BaseController):
|
||||
:param req: The WSGI/Webob Request object
|
||||
:raises HTTPBadRequest if x-Template-cluster is missing
|
||||
"""
|
||||
cluster_name = template.get('cluster_name',None)
|
||||
type = template.get('type',None)
|
||||
description = template.get('description',None)
|
||||
template_name = template.get('template_name',None)
|
||||
cluster_name = template.get('cluster_name', None)
|
||||
type = template.get('type', None)
|
||||
description = template.get('description', None)
|
||||
template_name = template.get('template_name', None)
|
||||
self._enforce(req, 'export_db_to_json')
|
||||
cinder_volume_list = []
|
||||
service_disk_list = []
|
||||
template_content = {}
|
||||
template_json = {}
|
||||
template_id = ""
|
||||
if not type or type == "tecs":
|
||||
try:
|
||||
params = {'filters': {'name':cluster_name}}
|
||||
params = {'filters': {'name': cluster_name}}
|
||||
clusters = registry.get_clusters_detail(req.context, **params)
|
||||
if clusters:
|
||||
cluster_id = clusters[0]['id']
|
||||
else:
|
||||
msg = "the cluster %s is not exist"%cluster_name
|
||||
msg = "the cluster %s is not exist" % cluster_name
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain")
|
||||
|
||||
params = {'filters': {'cluster_id':cluster_id}}
|
||||
cluster = registry.get_cluster_metadata(req.context, cluster_id)
|
||||
raise HTTPForbidden(
|
||||
explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
params = {'filters': {'cluster_id': cluster_id}}
|
||||
cluster = registry.get_cluster_metadata(
|
||||
req.context, cluster_id)
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
networks = registry.get_networks_detail(req.context, cluster_id,**params)
|
||||
networks = registry.get_networks_detail(
|
||||
req.context, cluster_id, **params)
|
||||
for role in roles:
|
||||
cinder_volume_params = {'filters': {'role_id':role['id']}}
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(req.context, **cinder_volume_params)
|
||||
for cinder_volume in cinder_volumes:
|
||||
if cinder_volume.get('role_id',None):
|
||||
cinder_volume['role_id'] = role['name']
|
||||
self._del_general_params(cinder_volume)
|
||||
cinder_volume_list.append(cinder_volume)
|
||||
if role.get('config_set_id',None):
|
||||
config_set = registry.get_config_set_metadata(req.context, role['config_set_id'])
|
||||
cinder_volumes = self._get_cinder_volumes(req, role)
|
||||
cinder_volume_list += cinder_volumes
|
||||
services_disk = self._get_services_disk(req, role)
|
||||
service_disk_list += services_disk
|
||||
|
||||
if role.get('config_set_id', None):
|
||||
config_set = registry.get_config_set_metadata(
|
||||
req.context, role['config_set_id'])
|
||||
role['config_set_id'] = config_set['name']
|
||||
del role['cluster_id']
|
||||
del role['status']
|
||||
@ -309,16 +334,17 @@ class Controller(controller.BaseController):
|
||||
del role['config_set_update_progress']
|
||||
self._del_general_params(role)
|
||||
for network in networks:
|
||||
network_detail = registry.get_network_metadata(req.context, network['id'])
|
||||
if network_detail.get('ip_ranges',None):
|
||||
network_detail = registry.get_network_metadata(
|
||||
req.context, network['id'])
|
||||
if network_detail.get('ip_ranges', None):
|
||||
network['ip_ranges'] = network_detail['ip_ranges']
|
||||
del network['cluster_id']
|
||||
self._del_general_params(network)
|
||||
if cluster.get('routers',None):
|
||||
if cluster.get('routers', None):
|
||||
for router in cluster['routers']:
|
||||
del router['cluster_id']
|
||||
self._del_general_params(router)
|
||||
if cluster.get('logic_networks',None):
|
||||
if cluster.get('logic_networks', None):
|
||||
for logic_network in cluster['logic_networks']:
|
||||
for subnet in logic_network['subnets']:
|
||||
del subnet['logic_network_id']
|
||||
@ -326,7 +352,7 @@ class Controller(controller.BaseController):
|
||||
self._del_general_params(subnet)
|
||||
del logic_network['cluster_id']
|
||||
self._del_general_params(logic_network)
|
||||
if cluster.get('nodes',None):
|
||||
if cluster.get('nodes', None):
|
||||
del cluster['nodes']
|
||||
self._del_general_params(cluster)
|
||||
self._del_cluster_params(cluster)
|
||||
@ -334,140 +360,226 @@ class Controller(controller.BaseController):
|
||||
template_content['roles'] = roles
|
||||
template_content['networks'] = networks
|
||||
template_content['cinder_volumes'] = cinder_volume_list
|
||||
template_content['services_disk'] = service_disk_list
|
||||
template_json['content'] = json.dumps(template_content)
|
||||
template_json['type'] = 'tecs'
|
||||
template_json['name'] = template_name
|
||||
template_json['description'] = description
|
||||
|
||||
template_host_params = {'cluster_name':cluster_name}
|
||||
template_hosts = registry.host_template_lists_metadata(req.context, **template_host_params)
|
||||
|
||||
template_host_params = {'cluster_name': cluster_name}
|
||||
template_hosts = registry.host_template_lists_metadata(
|
||||
req.context, **template_host_params)
|
||||
if template_hosts:
|
||||
template_json['hosts'] = template_hosts[0]['hosts']
|
||||
else:
|
||||
template_json['hosts'] = "[]"
|
||||
|
||||
template_params = {'filters': {'name':template_name}}
|
||||
template_list = registry.template_lists_metadata(req.context, **template_params)
|
||||
template_params = {'filters': {'name': template_name}}
|
||||
template_list = registry.template_lists_metadata(
|
||||
req.context, **template_params)
|
||||
if template_list:
|
||||
update_template = registry.update_template_metadata(req.context, template_list[0]['id'], template_json)
|
||||
registry.update_template_metadata(
|
||||
req.context, template_list[0]['id'], template_json)
|
||||
template_id = template_list[0]['id']
|
||||
else:
|
||||
add_template = registry.add_template_metadata(req.context, template_json)
|
||||
add_template = registry.add_template_metadata(
|
||||
req.context, template_json)
|
||||
template_id = add_template['id']
|
||||
|
||||
|
||||
if template_id:
|
||||
template_detail = registry.template_detail_metadata(req.context, template_id)
|
||||
template_detail = registry.template_detail_metadata(
|
||||
req.context, template_id)
|
||||
self._del_general_params(template_detail)
|
||||
template_detail['content'] = json.loads(template_detail['content'])
|
||||
template_detail['content'] = json.loads(
|
||||
template_detail['content'])
|
||||
if template_detail['hosts']:
|
||||
template_detail['hosts'] = json.loads(template_detail['hosts'])
|
||||
|
||||
tecs_json = daisy_tecs_path + "%s.json"%template_name
|
||||
template_detail['hosts'] = json.loads(
|
||||
template_detail['hosts'])
|
||||
|
||||
tecs_json = daisy_tecs_path + "%s.json" % template_name
|
||||
cmd = 'rm -rf %s' % (tecs_json,)
|
||||
daisy_cmn.subprocess_call(cmd)
|
||||
with open(tecs_json, "w+") as fp:
|
||||
fp.write(json.dumps(template_detail))
|
||||
json.dump(template_detail, fp, indent=2)
|
||||
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
return {"template":template_detail}
|
||||
|
||||
|
||||
return {"template": template_detail}
|
||||
|
||||
@utils.mutating
|
||||
def import_json_to_template(self, req, template):
|
||||
template_id = ""
|
||||
template = json.loads(template.get('template',None))
|
||||
template = json.loads(template.get('template', None))
|
||||
template_cluster = copy.deepcopy(template)
|
||||
template_name = template_cluster.get('name',None)
|
||||
template_params = {'filters': {'name':template_name}}
|
||||
template_name = template_cluster.get('name', None)
|
||||
template_params = {'filters': {'name': template_name}}
|
||||
try:
|
||||
if template_cluster.get('content',None):
|
||||
template_cluster['content'] = json.dumps(template_cluster['content'])
|
||||
if template_cluster.get('hosts',None):
|
||||
template_cluster['hosts'] = json.dumps(template_cluster['hosts'])
|
||||
if template_cluster.get('content', None):
|
||||
template_cluster['content'] = json.dumps(
|
||||
template_cluster['content'])
|
||||
if template_cluster.get('hosts', None):
|
||||
template_cluster['hosts'] = json.dumps(
|
||||
template_cluster['hosts'])
|
||||
else:
|
||||
template_cluster['hosts'] = "[]"
|
||||
|
||||
template_list = registry.template_lists_metadata(req.context, **template_params)
|
||||
template_cluster['hosts'] = "[]"
|
||||
|
||||
template_list = registry.template_lists_metadata(
|
||||
req.context, **template_params)
|
||||
if template_list:
|
||||
update_template_cluster = registry.update_template_metadata(req.context, template_list[0]['id'], template_cluster)
|
||||
registry.update_template_metadata(
|
||||
req.context, template_list[0]['id'], template_cluster)
|
||||
template_id = template_list[0]['id']
|
||||
else:
|
||||
add_template_cluster = registry.add_template_metadata(req.context, template_cluster)
|
||||
add_template_cluster = registry.add_template_metadata(
|
||||
req.context, template_cluster)
|
||||
template_id = add_template_cluster['id']
|
||||
|
||||
|
||||
if template_id:
|
||||
template_detail = registry.template_detail_metadata(req.context, template_id)
|
||||
template_detail = registry.template_detail_metadata(
|
||||
req.context, template_id)
|
||||
del template_detail['deleted']
|
||||
del template_detail['deleted_at']
|
||||
|
||||
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
|
||||
return {"template":template_detail}
|
||||
|
||||
|
||||
return {"template": template_detail}
|
||||
|
||||
def _import_cinder_volumes_to_db(self, req,
|
||||
template_cinder_volumes, roles):
|
||||
for template_cinder_volume in template_cinder_volumes:
|
||||
has_template_role = False
|
||||
for role in roles:
|
||||
if template_cinder_volume['role_id'] == role['name']:
|
||||
has_template_role = True
|
||||
template_cinder_volume['role_id'] = role['id']
|
||||
break
|
||||
if has_template_role:
|
||||
registry.add_cinder_volume_metadata(req.context,
|
||||
template_cinder_volume)
|
||||
else:
|
||||
msg = "can't find role %s in new cluster when\
|
||||
import cinder_volumes from template"\
|
||||
% template_cinder_volume['role_id']
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
def _import_services_disk_to_db(self, req,
|
||||
template_services_disk, roles):
|
||||
for template_service_disk in template_services_disk:
|
||||
has_template_role = False
|
||||
for role in roles:
|
||||
if template_service_disk['role_id'] == role['name']:
|
||||
has_template_role = True
|
||||
template_service_disk['role_id'] = role['id']
|
||||
break
|
||||
if has_template_role:
|
||||
registry.add_service_disk_metadata(req.context,
|
||||
template_service_disk)
|
||||
else:
|
||||
msg = "can't find role %s in new cluster when\
|
||||
import service_disks from template"\
|
||||
% template_service_disk['role_id']
|
||||
raise HTTPBadRequest(explanation=msg, request=req)
|
||||
|
||||
@utils.mutating
|
||||
def import_template_to_db(self, req, template):
|
||||
cluster_id = ""
|
||||
template_cluster = {}
|
||||
cluster_meta = {}
|
||||
template_meta = copy.deepcopy(template)
|
||||
template_name = template_meta.get('name',None)
|
||||
cluster_name = template_meta.get('cluster',None)
|
||||
template_params = {'filters': {'name':template_name}}
|
||||
template_list = registry.template_lists_metadata(req.context, **template_params)
|
||||
template_name = template_meta.get('name', None)
|
||||
cluster_name = template_meta.get('cluster', None)
|
||||
template_params = {'filters': {'name': template_name}}
|
||||
template_list = registry.template_lists_metadata(
|
||||
req.context, **template_params)
|
||||
if template_list:
|
||||
template_cluster = template_list[0]
|
||||
else:
|
||||
msg = "the template %s is not exist" % template_name
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain")
|
||||
|
||||
raise HTTPForbidden(
|
||||
explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
|
||||
try:
|
||||
template_content = json.loads(template_cluster['content'])
|
||||
template_content_cluster = template_content['cluster']
|
||||
template_content_cluster['name'] = cluster_name
|
||||
template_content_cluster['networking_parameters'] = str(template_content_cluster['networking_parameters'])
|
||||
template_content_cluster['logic_networks'] = str(template_content_cluster['logic_networks'])
|
||||
template_content_cluster['logic_networks'] = template_content_cluster['logic_networks'].replace("\'true\'","True")
|
||||
template_content_cluster['routers'] = str(template_content_cluster['routers'])
|
||||
|
||||
template_content_cluster['networking_parameters'] = str(
|
||||
template_content_cluster['networking_parameters'])
|
||||
template_content_cluster['logic_networks'] = str(
|
||||
template_content_cluster['logic_networks'])
|
||||
template_content_cluster['logic_networks'] = \
|
||||
template_content_cluster[
|
||||
'logic_networks'].replace("\'true\'", "True")
|
||||
template_content_cluster['routers'] = str(
|
||||
template_content_cluster['routers'])
|
||||
|
||||
if template_cluster['hosts']:
|
||||
template_hosts = json.loads(template_cluster['hosts'])
|
||||
template_host_params = {'cluster_name':cluster_name}
|
||||
template_host_list = registry.host_template_lists_metadata(req.context, **template_host_params)
|
||||
template_host_params = {'cluster_name': cluster_name}
|
||||
template_host_list = registry.host_template_lists_metadata(
|
||||
req.context, **template_host_params)
|
||||
if template_host_list:
|
||||
update_template_meta = {"cluster_name": cluster_name, "hosts":json.dumps(template_hosts)}
|
||||
registry.update_host_template_metadata(req.context, template_host_list[0]['id'], update_template_meta)
|
||||
update_template_meta = {
|
||||
"cluster_name": cluster_name,
|
||||
"hosts": json.dumps(template_hosts)}
|
||||
registry.update_host_template_metadata(
|
||||
req.context, template_host_list[0]['id'],
|
||||
update_template_meta)
|
||||
else:
|
||||
template_meta = {"cluster_name": cluster_name, "hosts":json.dumps(template_hosts)}
|
||||
registry.add_host_template_metadata(req.context, template_meta)
|
||||
|
||||
cluster_params = {'filters': {'name':cluster_name}}
|
||||
clusters = registry.get_clusters_detail(req.context, **cluster_params)
|
||||
template_meta = {
|
||||
"cluster_name": cluster_name,
|
||||
"hosts": json.dumps(template_hosts)}
|
||||
registry.add_host_template_metadata(
|
||||
req.context, template_meta)
|
||||
|
||||
cluster_params = {'filters': {'name': cluster_name}}
|
||||
clusters = registry.get_clusters_detail(
|
||||
req.context, **cluster_params)
|
||||
if clusters:
|
||||
msg = "the cluster %s is exist" % clusters[0]['name']
|
||||
LOG.error(msg)
|
||||
raise HTTPForbidden(explanation=msg, request=req, content_type="text/plain")
|
||||
raise HTTPForbidden(
|
||||
explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
cluster_meta = registry.add_cluster_metadata(req.context, template_content['cluster'])
|
||||
if template_content_cluster.get('auto_scale', None) == 1:
|
||||
params = {'filters': ''}
|
||||
clusters_list = registry.get_clusters_detail(
|
||||
req.context, **params)
|
||||
for cluster in clusters_list:
|
||||
if cluster.get('auto_scale', None) == 1:
|
||||
template_content_cluster['auto_scale'] = 0
|
||||
break
|
||||
cluster_meta = registry.add_cluster_metadata(
|
||||
req.context, template_content['cluster'])
|
||||
cluster_id = cluster_meta['id']
|
||||
|
||||
params = {'filters':{}}
|
||||
networks = registry.get_networks_detail(req.context, cluster_id,**params)
|
||||
|
||||
params = {'filters': {}}
|
||||
networks = registry.get_networks_detail(
|
||||
req.context, cluster_id, **params)
|
||||
template_content_networks = template_content['networks']
|
||||
for template_content_network in template_content_networks:
|
||||
template_content_network['ip_ranges'] = str(template_content_network['ip_ranges'])
|
||||
template_content_network['ip_ranges'] = str(
|
||||
template_content_network['ip_ranges'])
|
||||
network_exist = 'false'
|
||||
for network in networks:
|
||||
if template_content_network['name'] == network['name']:
|
||||
update_network_meta = registry.update_network_metadata(req.context, network['id'], template_content_network)
|
||||
registry.update_network_metadata(
|
||||
req.context, network['id'],
|
||||
template_content_network)
|
||||
network_exist = 'true'
|
||||
|
||||
if network_exist == 'false':
|
||||
template_content_network['cluster_id'] = cluster_id
|
||||
add_network_meta = registry.add_network_metadata(req.context, template_content_network)
|
||||
|
||||
params = {'filters': {'cluster_id':cluster_id}}
|
||||
registry.add_network_metadata(
|
||||
req.context, template_content_network)
|
||||
|
||||
params = {'filters': {'cluster_id': cluster_id}}
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
template_content_roles = template_content['roles']
|
||||
for template_content_role in template_content_roles:
|
||||
@ -475,34 +587,25 @@ class Controller(controller.BaseController):
|
||||
del template_content_role['config_set_id']
|
||||
for role in roles:
|
||||
if template_content_role['name'] == role['name']:
|
||||
update_role_meta = registry.update_role_metadata(req.context, role['id'], template_content_role)
|
||||
registry.update_role_metadata(
|
||||
req.context, role['id'], template_content_role)
|
||||
role_exist = 'true'
|
||||
|
||||
|
||||
if role_exist == 'false':
|
||||
template_content_role['cluster_id'] = cluster_id
|
||||
add_role_meta = registry.add_role_metadata(req.context, template_content_role)
|
||||
|
||||
cinder_volumes = registry.list_cinder_volume_metadata(req.context, **params)
|
||||
template_content_cinder_volumes = template_content['cinder_volumes']
|
||||
for template_content_cinder_volume in template_content_cinder_volumes:
|
||||
cinder_volume_exist = 'false'
|
||||
roles = registry.get_roles_detail(req.context, **params)
|
||||
for role in roles:
|
||||
if template_content_cinder_volume['role_id'] == role['name']:
|
||||
template_content_cinder_volume['role_id'] = role['id']
|
||||
|
||||
for cinder_volume in cinder_volumes:
|
||||
if template_content_cinder_volume['role_id'] == cinder_volume['role_id']:
|
||||
update_cinder_volume_meta = registry.update_cinder_volume_metadata(req.context, cinder_volume['id'], template_content_cinder_volume)
|
||||
cinder_volume_exist = 'true'
|
||||
|
||||
if cinder_volume_exist == 'false':
|
||||
add_cinder_volumes = registry.add_cinder_volume_metadata(req.context, template_content_cinder_volume)
|
||||
|
||||
registry.add_role_metadata(
|
||||
req.context, template_content_role)
|
||||
|
||||
self._import_cinder_volumes_to_db(
|
||||
req, template_content['cinder_volumes'], roles)
|
||||
self._import_services_disk_to_db(req,
|
||||
template_content['services_disk'],
|
||||
roles)
|
||||
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return {"template":cluster_meta}
|
||||
|
||||
return {"template": cluster_meta}
|
||||
|
||||
@utils.mutating
|
||||
def get_template_detail(self, req, template_id):
|
||||
"""
|
||||
@ -513,7 +616,8 @@ class Controller(controller.BaseController):
|
||||
"""
|
||||
self._enforce(req, 'get_template_detail')
|
||||
try:
|
||||
template = registry.template_detail_metadata(req.context, template_id)
|
||||
template = registry.template_detail_metadata(
|
||||
req.context, template_id)
|
||||
return {'template': template}
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find template: %s") %
|
||||
@ -531,97 +635,104 @@ class Controller(controller.BaseController):
|
||||
content_type="text/plain")
|
||||
except exception.InUseByStore as e:
|
||||
msg = (_("template %(id)s could not be get because it is in use: "
|
||||
"%(exc)s") % {"id": template_id, "exc": utils.exception_to_str(e)})
|
||||
"%(exc)s") % {"id": template_id,
|
||||
"exc": utils.exception_to_str(e)})
|
||||
LOG.error(msg)
|
||||
raise HTTPConflict(explanation=msg,
|
||||
request=req,
|
||||
content_type="text/plain")
|
||||
else:
|
||||
return Response(body='', status=200)
|
||||
|
||||
|
||||
@utils.mutating
|
||||
def get_template_lists(self, req):
|
||||
self._enforce(req, 'get_template_lists')
|
||||
params = self._get_query_params(req)
|
||||
try:
|
||||
template_lists = registry.template_lists_metadata(req.context, **params)
|
||||
template_lists = registry.template_lists_metadata(
|
||||
req.context, **params)
|
||||
except exception.Invalid as e:
|
||||
raise HTTPBadRequest(explanation=e.msg, request=req)
|
||||
return dict(template=template_lists)
|
||||
|
||||
|
||||
|
||||
class TemplateDeserializer(wsgi.JSONRequestDeserializer):
|
||||
"""Handles deserialization of specific controller method requests."""
|
||||
|
||||
|
||||
def _deserialize(self, request):
|
||||
result = {}
|
||||
result["template"] = utils.get_template_meta(request)
|
||||
return result
|
||||
|
||||
|
||||
def add_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def update_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def export_db_to_json(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def import_json_to_template(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
def import_template_to_db(self, request):
|
||||
return self._deserialize(request)
|
||||
|
||||
|
||||
class TemplateSerializer(wsgi.JSONResponseSerializer):
|
||||
"""Handles serialization of specific controller method responses."""
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.notifier = notifier.Notifier()
|
||||
|
||||
|
||||
def add_template(self, response, result):
|
||||
template = result['template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(template=template))
|
||||
return response
|
||||
|
||||
|
||||
def delete_template(self, response, result):
|
||||
template = result['template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(template=template))
|
||||
return response
|
||||
|
||||
def get_template_detail(self, response, result):
|
||||
template = result['template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(template=template))
|
||||
return response
|
||||
|
||||
def update_template(self, response, result):
|
||||
template = result['template']
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(dict(template=template))
|
||||
return response
|
||||
|
||||
return response
|
||||
|
||||
def export_db_to_json(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def import_json_to_template(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
def import_template_to_db(self, response, result):
|
||||
response.status = 201
|
||||
response.headers['Content-Type'] = 'application/json'
|
||||
response.body = self.to_json(result)
|
||||
return response
|
||||
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Templates resource factory method"""
|
||||
deserializer = TemplateDeserializer()
|
||||
|
@ -32,6 +32,7 @@ _LI = i18n._LI
|
||||
|
||||
|
||||
class ImageActionsController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None,
|
||||
store_api=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
@ -39,7 +40,7 @@ class ImageActionsController(object):
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.store_api = store_api or glance_store
|
||||
self.gateway = daisy.gateway.Gateway(self.db_api, self.store_api,
|
||||
self.notifier, self.policy)
|
||||
self.notifier, self.policy)
|
||||
|
||||
@utils.mutating
|
||||
def deactivate(self, req, image_id):
|
||||
|
@ -33,6 +33,7 @@ _LE = i18n._LE
|
||||
|
||||
|
||||
class ImageDataController(object):
|
||||
|
||||
def __init__(self, db_api=None, store_api=None,
|
||||
policy_enforcer=None, notifier=None,
|
||||
gateway=None):
|
||||
@ -42,7 +43,7 @@ class ImageDataController(object):
|
||||
policy = policy_enforcer or daisy.api.policy.Enforcer()
|
||||
notifier = notifier or daisy.notifier.Notifier()
|
||||
gateway = daisy.gateway.Gateway(db_api, store_api,
|
||||
notifier, policy)
|
||||
notifier, policy)
|
||||
self.gateway = gateway
|
||||
|
||||
def _restore(self, image_repo, image):
|
||||
|
@ -38,6 +38,7 @@ _ = i18n._
|
||||
|
||||
|
||||
class ImageMembersController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None,
|
||||
store_api=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
@ -45,7 +46,7 @@ class ImageMembersController(object):
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.store_api = store_api or glance_store
|
||||
self.gateway = daisy.gateway.Gateway(self.db_api, self.store_api,
|
||||
self.notifier, self.policy)
|
||||
self.notifier, self.policy)
|
||||
|
||||
@utils.mutating
|
||||
def create(self, req, image_id, member_id):
|
||||
@ -250,6 +251,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema or get_schema()
|
||||
|
@ -31,6 +31,7 @@ _ = i18n._
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None,
|
||||
store_api=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
@ -38,7 +39,7 @@ class Controller(object):
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.store_api = store_api or glance_store
|
||||
self.gateway = daisy.gateway.Gateway(self.db_api, self.store_api,
|
||||
self.notifier, self.policy)
|
||||
self.notifier, self.policy)
|
||||
|
||||
@utils.mutating
|
||||
def update(self, req, image_id, tag_value):
|
||||
@ -85,6 +86,7 @@ class Controller(object):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def update(self, response, result):
|
||||
response.status_int = 204
|
||||
|
||||
|
@ -46,6 +46,7 @@ CONF.import_opt('container_formats', 'daisy.common.config',
|
||||
|
||||
|
||||
class ImagesController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None,
|
||||
store_api=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
@ -53,7 +54,7 @@ class ImagesController(object):
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.store_api = store_api or glance_store
|
||||
self.gateway = daisy.gateway.Gateway(self.db_api, self.store_api,
|
||||
self.notifier, self.policy)
|
||||
self.notifier, self.policy)
|
||||
|
||||
@utils.mutating
|
||||
def create(self, req, image, extra_properties, tags):
|
||||
@ -188,8 +189,8 @@ class ImagesController(object):
|
||||
self._do_add_locations(image, path[1], value)
|
||||
else:
|
||||
if ((hasattr(image, path_root) or
|
||||
path_root in image.extra_properties)
|
||||
and json_schema_version == 4):
|
||||
path_root in image.extra_properties) and
|
||||
json_schema_version == 4):
|
||||
msg = _("Property %s already present.")
|
||||
raise webob.exc.HTTPConflict(msg % path_root)
|
||||
if hasattr(image, path_root):
|
||||
@ -681,6 +682,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema or get_schema()
|
||||
|
@ -48,13 +48,14 @@ CONF = cfg.CONF
|
||||
|
||||
|
||||
class NamespaceController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.gateway = daisy.gateway.Gateway(db_api=self.db_api,
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
self.ns_schema_link = '/v2/schemas/metadefs/namespace'
|
||||
self.obj_schema_link = '/v2/schemas/metadefs/object'
|
||||
self.tag_schema_link = '/v2/schemas/metadefs/tag'
|
||||
@ -486,6 +487,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema
|
||||
@ -781,20 +783,20 @@ def get_collection_schema():
|
||||
|
||||
|
||||
def get_namespace_href(namespace):
|
||||
base_href = '/v2/metadefs/namespaces/%s' % namespace.namespace
|
||||
return base_href
|
||||
base_href = '/v2/metadefs/namespaces/%s' % namespace.namespace
|
||||
return base_href
|
||||
|
||||
|
||||
def get_object_href(namespace_name, metadef_object):
|
||||
base_href = ('/v2/metadefs/namespaces/%s/objects/%s' %
|
||||
(namespace_name, metadef_object.name))
|
||||
return base_href
|
||||
base_href = ('/v2/metadefs/namespaces/%s/objects/%s' %
|
||||
(namespace_name, metadef_object.name))
|
||||
return base_href
|
||||
|
||||
|
||||
def get_tag_href(namespace_name, metadef_tag):
|
||||
base_href = ('/v2/metadefs/namespaces/%s/tags/%s' %
|
||||
(namespace_name, metadef_tag.name))
|
||||
return base_href
|
||||
base_href = ('/v2/metadefs/namespaces/%s/tags/%s' %
|
||||
(namespace_name, metadef_tag.name))
|
||||
return base_href
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
@ -42,13 +42,14 @@ CONF = cfg.CONF
|
||||
|
||||
|
||||
class MetadefObjectsController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.gateway = daisy.gateway.Gateway(db_api=self.db_api,
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
self.obj_schema_link = '/v2/schemas/metadefs/object'
|
||||
|
||||
def create(self, req, metadata_object, namespace):
|
||||
@ -294,6 +295,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema or get_schema()
|
||||
@ -324,9 +326,9 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
|
||||
def get_object_href(namespace_name, metadef_object):
|
||||
base_href = ('/v2/metadefs/namespaces/%s/objects/%s' %
|
||||
(namespace_name, metadef_object.name))
|
||||
return base_href
|
||||
base_href = ('/v2/metadefs/namespaces/%s/objects/%s' %
|
||||
(namespace_name, metadef_object.name))
|
||||
return base_href
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
@ -40,13 +40,14 @@ _LI = i18n._LI
|
||||
|
||||
|
||||
class NamespacePropertiesController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.gateway = daisy.gateway.Gateway(db_api=self.db_api,
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
|
||||
def _to_dict(self, model_property_type):
|
||||
# Convert the model PropertyTypes dict to a JSON encoding
|
||||
@ -213,6 +214,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema
|
||||
@ -288,7 +290,7 @@ def get_collection_schema():
|
||||
# individual property schema inside property collections
|
||||
namespace_properties_schema.required.remove('name')
|
||||
return daisy.schema.DictCollectionSchema('properties',
|
||||
namespace_properties_schema)
|
||||
namespace_properties_schema)
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
@ -40,13 +40,14 @@ _LI = i18n._LI
|
||||
|
||||
|
||||
class ResourceTypeController(object):
|
||||
|
||||
def __init__(self, db_api=None, policy_enforcer=None, notifier=None):
|
||||
self.db_api = db_api or daisy.db.get_api()
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.gateway = daisy.gateway.Gateway(db_api=self.db_api,
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
|
||||
def index(self, req):
|
||||
try:
|
||||
@ -167,6 +168,7 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
||||
|
||||
|
||||
class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
|
||||
def __init__(self, schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.schema = schema
|
||||
@ -253,7 +255,7 @@ def get_schema():
|
||||
def get_collection_schema():
|
||||
resource_type_schema = get_schema()
|
||||
return daisy.schema.CollectionSchema('resource_type_associations',
|
||||
resource_type_schema)
|
||||
resource_type_schema)
|
||||
|
||||
|
||||
def create_resource():
|
||||
|
@ -46,8 +46,8 @@ class TagsController(object):
|
||||
self.policy = policy_enforcer or policy.Enforcer()
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.gateway = daisy.gateway.Gateway(db_api=self.db_api,
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
notifier=self.notifier,
|
||||
policy_enforcer=self.policy)
|
||||
self.tag_schema_link = '/v2/schemas/metadefs/tag'
|
||||
|
||||
def create(self, req, namespace, tag_name):
|
||||
|
@ -53,7 +53,7 @@ class TasksController(object):
|
||||
self.notifier = notifier or daisy.notifier.Notifier()
|
||||
self.store_api = store_api or glance_store
|
||||
self.gateway = daisy.gateway.Gateway(self.db_api, self.store_api,
|
||||
self.notifier, self.policy)
|
||||
self.notifier, self.policy)
|
||||
|
||||
def create(self, req, task):
|
||||
task_factory = self.gateway.get_task_factory(req.context)
|
||||
@ -229,8 +229,8 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
||||
def __init__(self, task_schema=None, partial_task_schema=None):
|
||||
super(ResponseSerializer, self).__init__()
|
||||
self.task_schema = task_schema or get_task_schema()
|
||||
self.partial_task_schema = (partial_task_schema
|
||||
or _get_partial_task_schema())
|
||||
self.partial_task_schema = (partial_task_schema or
|
||||
_get_partial_task_schema())
|
||||
|
||||
def _inject_location_header(self, response, task):
|
||||
location = self._get_task_location(task)
|
||||
|
@ -27,6 +27,17 @@ import sys
|
||||
import eventlet
|
||||
|
||||
from daisy.common import utils
|
||||
import glance_store
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import exception
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
from daisy.openstack.common import systemd
|
||||
|
||||
# Monkey patch socket, time, select, threads
|
||||
eventlet.patcher.monkey_patch(all=False, socket=True, time=True,
|
||||
@ -40,17 +51,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
import glance_store
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import exception
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
from daisy.openstack.common import systemd
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group("profiler", "daisy.common.wsgi")
|
||||
|
@ -31,8 +31,9 @@ period, we automatically sweep it up.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import cleaner
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -42,8 +43,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import cleaner
|
||||
|
||||
CONF = config.CONF
|
||||
logging.register_options(CONF)
|
||||
|
@ -19,16 +19,16 @@
|
||||
A simple cache management utility for daisy.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import functools
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from daisy.common import utils
|
||||
from daisy.common import exception
|
||||
import daisy.image_cache.client
|
||||
from daisy.version import version_info as version
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -38,10 +38,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from daisy.common import exception
|
||||
import daisy.image_cache.client
|
||||
from daisy.version import version_info as version
|
||||
|
||||
|
||||
SUCCESS = 0
|
||||
FAILURE = 1
|
||||
|
@ -24,6 +24,11 @@ images to be pretched.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glance_store
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import prefetcher
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -33,11 +38,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
import glance_store
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import prefetcher
|
||||
|
||||
CONF = config.CONF
|
||||
logging.register_options(CONF)
|
||||
|
@ -25,6 +25,8 @@ import os
|
||||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import pruner
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -34,8 +36,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.image_cache import pruner
|
||||
|
||||
CONF = config.CONF
|
||||
logging.register_options(CONF)
|
||||
|
@ -30,6 +30,12 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import units
|
||||
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
||||
from six.moves import range
|
||||
from daisy.common import config
|
||||
from daisy import i18n
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -39,13 +45,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import units
|
||||
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
||||
from six.moves import range
|
||||
|
||||
from daisy.common import config
|
||||
from daisy import i18n
|
||||
|
||||
_ = i18n._
|
||||
|
||||
|
@ -29,15 +29,6 @@ from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(possible_topdir, 'daisy', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db.sqlalchemy import migration
|
||||
from oslo_log import log as logging
|
||||
@ -52,6 +43,14 @@ from daisy.db.sqlalchemy import api as db_api
|
||||
from daisy.db.sqlalchemy import metadata
|
||||
from daisy import i18n
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(possible_topdir, 'daisy', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -23,8 +23,14 @@ Reference implementation server for Daisy orchestration
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import eventlet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from daisy.common import exception
|
||||
from daisy.common import config
|
||||
from daisy.openstack.common import loopingcall
|
||||
from daisy.orchestration.manager import OrchestrationManager
|
||||
import six
|
||||
|
||||
# Monkey patch socket and time
|
||||
eventlet.patcher.monkey_patch(all=False, socket=True, time=True, thread=True)
|
||||
@ -37,23 +43,12 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'daisy', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
from daisy.common import exception
|
||||
from daisy.common import config
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
from daisy.openstack.common import systemd
|
||||
from daisy.openstack.common import loopingcall
|
||||
from daisy.orchestration.manager import OrchestrationManager
|
||||
|
||||
CONF = cfg.CONF
|
||||
scale_opts = [
|
||||
cfg.StrOpt('auto_scale_interval', default=60,
|
||||
help='Number of seconds between two checkings to compute auto scale status'),
|
||||
help='Number of seconds between two '
|
||||
'checkings to compute auto scale status'),
|
||||
]
|
||||
CONF.register_opts(scale_opts, group='orchestration')
|
||||
logging.register_options(CONF)
|
||||
@ -62,10 +57,11 @@ logging.register_options(CONF)
|
||||
def fail(returncode, e):
|
||||
sys.stderr.write("ERROR: %s\n" % six.text_type(e))
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
config.parse_args()
|
||||
logging.setup(CONF,'daisy')
|
||||
logging.setup(CONF, 'daisy')
|
||||
timer = loopingcall.FixedIntervalLoopingCall(
|
||||
OrchestrationManager.find_auto_scale_cluster)
|
||||
timer.start(float(CONF.orchestration.auto_scale_interval)).wait()
|
||||
|
@ -25,6 +25,16 @@ import os
|
||||
import sys
|
||||
|
||||
import eventlet
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
from daisy.openstack.common import systemd
|
||||
|
||||
# Monkey patch socket and time
|
||||
eventlet.patcher.monkey_patch(all=False, socket=True, time=True, thread=True)
|
||||
@ -37,16 +47,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'daisy', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import utils
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
from daisy.openstack.common import systemd
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group("profiler", "daisy.common.wsgi")
|
||||
|
@ -21,6 +21,13 @@ Glance Scrub Service
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glance_store
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.openstack.common import systemd
|
||||
from daisy import scrubber
|
||||
|
||||
# If ../glance/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@ -30,14 +37,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
import glance_store
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.openstack.common import systemd
|
||||
from daisy import scrubber
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
logging.register_options(CONF)
|
||||
|
@ -27,6 +27,15 @@ import sys
|
||||
import eventlet
|
||||
|
||||
from daisy.common import utils
|
||||
from oslo.config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import exception
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
|
||||
# Monkey patch socket, time, select, threads
|
||||
eventlet.patcher.monkey_patch(socket=True, time=True, select=True,
|
||||
@ -40,15 +49,6 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from oslo.config import cfg
|
||||
from oslo_log import log as logging
|
||||
import osprofiler.notifier
|
||||
import osprofiler.web
|
||||
|
||||
from daisy.common import config
|
||||
from daisy.common import exception
|
||||
from daisy.common import wsgi
|
||||
from daisy import notifier
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group("profiler", "daisy.common.wsgi")
|
||||
|
@ -399,6 +399,7 @@ class PropertyDefinition(AttributeDefinition):
|
||||
|
||||
class RelationDefinition(AttributeDefinition):
|
||||
"""A base class for Attributes defining cross-artifact relations"""
|
||||
|
||||
def __init__(self, internal=False, **kwargs):
|
||||
self.internal = internal
|
||||
kwargs.setdefault('mutable', False)
|
||||
@ -482,6 +483,7 @@ class ArtifactPropertyDescriptor(object):
|
||||
|
||||
class ArtifactAttributes(object):
|
||||
"""A container class storing description of Artifact Type attributes"""
|
||||
|
||||
def __init__(self):
|
||||
self.properties = {}
|
||||
self.dependencies = {}
|
||||
|
@ -121,7 +121,7 @@ class SemVerString(String):
|
||||
|
||||
super(SemVerString,
|
||||
self).__init__(validators=[(validate,
|
||||
"Invalid semver string")],
|
||||
"Invalid semver string")],
|
||||
**kwargs)
|
||||
|
||||
|
||||
@ -436,7 +436,7 @@ class ArtifactReference(declarative.RelationDefinition):
|
||||
if artifact.type_name not in type_names:
|
||||
return False
|
||||
if (type_version is not None and
|
||||
artifact.type_version != type_version):
|
||||
artifact.type_version != type_version):
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -477,6 +477,7 @@ class ArtifactReferenceList(declarative.ListAttributeDefinition,
|
||||
|
||||
class Blob(object):
|
||||
"""A Binary object being part of the Artifact"""
|
||||
|
||||
def __init__(self, size=0, locations=None, checksum=None, item_key=None):
|
||||
"""Initializes a new Binary Object for an Artifact
|
||||
|
||||
|
@ -48,6 +48,7 @@ CONF.register_opts(plugins_opts)
|
||||
|
||||
|
||||
class ArtifactsPluginLoader(object):
|
||||
|
||||
def __init__(self, namespace):
|
||||
self.mgr = enabled.EnabledExtensionManager(
|
||||
check_func=self._gen_check_func(),
|
||||
|
@ -44,6 +44,7 @@ _ = i18n._
|
||||
|
||||
|
||||
class BaseStrategy(object):
|
||||
|
||||
def __init__(self):
|
||||
self.auth_token = None
|
||||
# TODO(sirp): Should expose selecting public/internal/admin URL.
|
||||
@ -62,6 +63,7 @@ class BaseStrategy(object):
|
||||
|
||||
|
||||
class NoAuthStrategy(BaseStrategy):
|
||||
|
||||
def authenticate(self):
|
||||
pass
|
||||
|
||||
|
@ -27,6 +27,7 @@ _FATAL_EXCEPTION_FORMAT_ERRORS = False
|
||||
|
||||
|
||||
class RedirectException(Exception):
|
||||
|
||||
def __init__(self, url):
|
||||
self.url = urlparse.urlparse(url)
|
||||
|
||||
@ -336,13 +337,16 @@ class TaskException(DaisyException):
|
||||
class BadTaskConfiguration(DaisyException):
|
||||
message = _("Task was not configured properly")
|
||||
|
||||
|
||||
class InstallException(DaisyException):
|
||||
message = _("Cluster installtation raise exception")
|
||||
|
||||
|
||||
class InstallTimeoutException(DaisyException):
|
||||
message = _(
|
||||
"Time out, during install TECS components to cluster %(cluster_id)s")
|
||||
|
||||
|
||||
class TaskNotFound(TaskException, NotFound):
|
||||
message = _("Task with the given id %(task_id)s was not found")
|
||||
|
||||
@ -566,23 +570,32 @@ class InvalidJsonPatchPath(JsonPatchException):
|
||||
class InvalidNetworkConfig(DaisyException):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidIP(DaisyException):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class OSInstallFailed(DaisyException):
|
||||
message = _("os installtation failed.")
|
||||
|
||||
|
||||
|
||||
class IMPIOprationFailed(DaisyException):
|
||||
message = _("ipmi command failed.")
|
||||
|
||||
|
||||
|
||||
class ThreadBinException(DaisyException):
|
||||
|
||||
def __init__(self, *args):
|
||||
super(ThreadBinException, self).__init__(*args)
|
||||
|
||||
|
||||
|
||||
class SubprocessCmdFailed(DaisyException):
|
||||
message = _("suprocess command failed.")
|
||||
|
||||
|
||||
|
||||
class DeleteConstrainted(DaisyException):
|
||||
message = _("delete is not allowed.")
|
||||
|
||||
|
||||
class TrustMeFailed(DaisyException):
|
||||
message = _("Trust me script failed.")
|
||||
|
@ -251,8 +251,8 @@ class RPCClient(client.BaseClient):
|
||||
# checking if content contains the '_error' key,
|
||||
# verify if it is an instance of dict - since the
|
||||
# RPC call may have returned something different.
|
||||
if self.raise_exc and (isinstance(content, dict)
|
||||
and '_error' in content):
|
||||
if self.raise_exc and (isinstance(content, dict) and
|
||||
'_error' in content):
|
||||
error = content['_error']
|
||||
try:
|
||||
exc_cls = imp.import_class(error['cls'])
|
||||
|
@ -12,11 +12,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__all__ = [
|
||||
'run',
|
||||
]
|
||||
|
||||
from oslo_concurrency import lockutils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
@ -28,6 +23,9 @@ from daisy.common.scripts import utils as script_utils
|
||||
from daisy.common import store_utils
|
||||
from daisy.common import utils as common_utils
|
||||
from daisy import i18n
|
||||
__all__ = [
|
||||
'run',
|
||||
]
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -150,7 +148,7 @@ def set_image_data(image, uri, task_id):
|
||||
data_iter = None
|
||||
try:
|
||||
LOG.info(_LI("Task %(task_id)s: Got image data uri %(data_uri)s to be "
|
||||
"imported") % {"data_uri": uri, "task_id": task_id})
|
||||
"imported") % {"data_uri": uri, "task_id": task_id})
|
||||
data_iter = script_utils.get_image_data_iter(uri)
|
||||
image.set_data(data_iter)
|
||||
except Exception as e:
|
||||
|
@ -12,7 +12,12 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import urllib2
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy import i18n
|
||||
__all__ = [
|
||||
'get_task',
|
||||
'unpack_task_input',
|
||||
@ -22,14 +27,6 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
import urllib2
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy import i18n
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
@ -100,7 +97,7 @@ def validate_location_uri(location):
|
||||
"source of image data.")
|
||||
# NOTE: raise Exception and let the encompassing block save
|
||||
# the error msg in the task.message.
|
||||
raise StandardError(msg)
|
||||
raise Exception(msg)
|
||||
|
||||
else:
|
||||
# TODO(nikhil): add other supported uris
|
||||
|
@ -25,6 +25,7 @@ _ = i18n._
|
||||
|
||||
|
||||
class DBVersion(object):
|
||||
|
||||
def __init__(self, components_long, prerelease, build):
|
||||
"""
|
||||
Creates a DBVersion object out of 3 component fields. This initializer
|
||||
@ -54,8 +55,8 @@ class DBVersion(object):
|
||||
other.version == self.version)
|
||||
|
||||
def __ne__(self, other):
|
||||
return (not isinstance(other, DBVersion)
|
||||
or self.version != other.version)
|
||||
return (not isinstance(other, DBVersion) or
|
||||
self.version != other.version)
|
||||
|
||||
def __composite_values__(self):
|
||||
long_version = _version_to_long(self.version)
|
||||
|
@ -63,6 +63,7 @@ def is_multiple_swift_store_accounts_enabled():
|
||||
|
||||
|
||||
class SwiftParams(object):
|
||||
|
||||
def __init__(self):
|
||||
if is_multiple_swift_store_accounts_enabled():
|
||||
self.params = self._load_config()
|
||||
@ -71,8 +72,8 @@ class SwiftParams(object):
|
||||
|
||||
def _form_default_params(self):
|
||||
default = {}
|
||||
if (CONF.swift_store_user and CONF.swift_store_key
|
||||
and CONF.swift_store_auth_address):
|
||||
if (CONF.swift_store_user and CONF.swift_store_key and
|
||||
CONF.swift_store_auth_address):
|
||||
default['user'] = CONF.swift_store_user
|
||||
default['key'] = CONF.swift_store_key
|
||||
default['auth_address'] = CONF.swift_store_auth_address
|
||||
|
@ -21,6 +21,7 @@ System-level utilities and helper functions.
|
||||
"""
|
||||
|
||||
import errno
|
||||
from functools import reduce
|
||||
|
||||
try:
|
||||
from eventlet import sleep
|
||||
@ -46,9 +47,11 @@ from oslo_utils import netutils
|
||||
from oslo_utils import strutils
|
||||
import six
|
||||
from webob import exc
|
||||
import ConfigParser
|
||||
|
||||
from daisy.common import exception
|
||||
from daisy import i18n
|
||||
from ironicclient import client as ironic_client
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
@ -73,6 +76,11 @@ IMAGE_META_HEADERS = ['x-image-meta-location', 'x-image-meta-size',
|
||||
|
||||
DAISY_TEST_SOCKET_FD_STR = 'DAISY_TEST_SOCKET_FD'
|
||||
|
||||
DISCOVER_DEFAULTS = {
|
||||
'listen_port': '5050',
|
||||
'ironic_url': 'http://127.0.0.1:6385/v1',
|
||||
}
|
||||
|
||||
|
||||
def chunkreadable(iter, chunk_size=65536):
|
||||
"""
|
||||
@ -135,6 +143,7 @@ MAX_COOP_READER_BUFFER_SIZE = 134217728 # 128M seems like a sane buffer limit
|
||||
|
||||
|
||||
class CooperativeReader(object):
|
||||
|
||||
"""
|
||||
An eventlet thread friendly class for reading in image data.
|
||||
|
||||
@ -144,6 +153,7 @@ class CooperativeReader(object):
|
||||
starvation, ie allows all threads to be scheduled periodically rather than
|
||||
having the same thread be continuously active.
|
||||
"""
|
||||
|
||||
def __init__(self, fd):
|
||||
"""
|
||||
:param fd: Underlying image file object
|
||||
@ -223,10 +233,12 @@ class CooperativeReader(object):
|
||||
|
||||
|
||||
class LimitingReader(object):
|
||||
|
||||
"""
|
||||
Reader designed to fail when reading image data past the configured
|
||||
allowable amount.
|
||||
"""
|
||||
|
||||
def __init__(self, data, limit):
|
||||
"""
|
||||
:param data: Underlying image data object
|
||||
@ -330,72 +342,91 @@ def get_image_meta_from_headers(response):
|
||||
result[key] = strutils.bool_from_string(result[key])
|
||||
return result
|
||||
|
||||
|
||||
def get_host_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_hwm_meta(response):
|
||||
result = {}
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_cluster_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_component_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_service_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_template_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_role_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_config_file_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_config_set_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_config_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
def get_network_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
def get_dict_meta(response):
|
||||
|
||||
def get_network_meta(response):
|
||||
result = {}
|
||||
for key,value in response.json.items():
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def get_dict_meta(response):
|
||||
result = {}
|
||||
for key, value in response.json.items():
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def create_mashup_dict(image_meta):
|
||||
"""
|
||||
Returns a dictionary-like mashup of the image core properties
|
||||
@ -434,6 +465,7 @@ def safe_remove(path):
|
||||
|
||||
|
||||
class PrettyTable(object):
|
||||
|
||||
"""Creates an ASCII art table for use in bin/glance
|
||||
|
||||
Example:
|
||||
@ -442,6 +474,7 @@ class PrettyTable(object):
|
||||
--- ----------------- ------------ -----
|
||||
122 image 22 0
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.columns = []
|
||||
|
||||
@ -506,8 +539,9 @@ def get_terminal_size():
|
||||
|
||||
try:
|
||||
height_width = struct.unpack('hh', fcntl.ioctl(sys.stderr.fileno(),
|
||||
termios.TIOCGWINSZ,
|
||||
struct.pack('HH', 0, 0)))
|
||||
termios.TIOCGWINSZ,
|
||||
struct.pack(
|
||||
'HH', 0, 0)))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -802,3 +836,254 @@ def get_search_plugins():
|
||||
ext_manager = stevedore.extension.ExtensionManager(
|
||||
namespace, invoke_on_load=True)
|
||||
return ext_manager.extensions
|
||||
|
||||
|
||||
def get_host_min_mac(host_interfaces):
|
||||
if not isinstance(host_interfaces, list):
|
||||
host_interfaces = eval(host_interfaces)
|
||||
macs = [interface['mac'] for interface in host_interfaces
|
||||
if interface['type'] == 'ether' and interface['mac']]
|
||||
min_mac = min(macs)
|
||||
return min_mac
|
||||
|
||||
|
||||
def ip_into_int(ip):
|
||||
"""
|
||||
Switch ip string to decimalism integer..
|
||||
:param ip: ip string
|
||||
:return: decimalism integer
|
||||
"""
|
||||
return reduce(lambda x, y: (x << 8) + y, map(int, ip.split('.')))
|
||||
|
||||
|
||||
def is_ip_in_cidr(ip, cidr):
|
||||
"""
|
||||
Check ip is in cidr
|
||||
:param ip: Ip will be checked, like:192.168.1.2.
|
||||
:param cidr: Ip range,like:192.168.0.0/24.
|
||||
:return: If ip in cidr, return True, else return False.
|
||||
"""
|
||||
network = cidr.split('/')
|
||||
mask = ~(2**(32 - int(network[1])) - 1)
|
||||
return (ip_into_int(ip) & mask) == (ip_into_int(network[0]) & mask)
|
||||
|
||||
|
||||
def is_ip_in_ranges(ip, ip_ranges):
|
||||
"""
|
||||
Check ip is in range
|
||||
: ip: Ip will be checked, like:192.168.1.2.
|
||||
: ip_ranges : Ip ranges, like:
|
||||
[{'start':'192.168.0.10', 'end':'192.168.0.20'}
|
||||
{'start':'192.168.0.50', 'end':'192.168.0.60'}]
|
||||
:return: If ip in ip_ranges, return True, else return False.
|
||||
"""
|
||||
for ip_range in ip_ranges:
|
||||
start_ip_int = ip_into_int(ip_range['start'])
|
||||
end_ip_int = ip_into_int(ip_range['end'])
|
||||
ip_int = ip_into_int(ip)
|
||||
if ip_int >= start_ip_int and ip_int <= end_ip_int:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_ironicclient(): # pragma: no cover
|
||||
"""Get Ironic client instance."""
|
||||
config_discoverd = ConfigParser.ConfigParser(defaults=DISCOVER_DEFAULTS)
|
||||
config_discoverd.read("/etc/ironic-discoverd/discoverd.conf")
|
||||
ironic_url = config_discoverd.get("discoverd", "ironic_url")
|
||||
args = {'os_auth_token': 'fake',
|
||||
'ironic_url': ironic_url}
|
||||
return ironic_client.get_client(1, **args)
|
||||
|
||||
|
||||
def get_host_hw_info(host_interface):
|
||||
host_hw_config = {}
|
||||
ironicclient = get_ironicclient()
|
||||
if host_interface:
|
||||
min_mac = get_host_min_mac(host_interface)
|
||||
try:
|
||||
host_obj = ironicclient.physical_node.get(min_mac)
|
||||
host_hw_config = dict([(f, getattr(host_obj, f, ''))
|
||||
for f in ['system', 'memory', 'cpu',
|
||||
'disks', 'interfaces',
|
||||
'pci', 'devices']])
|
||||
except Exception:
|
||||
LOG.exception(_LE("Unable to find ironic data %s")
|
||||
% Exception)
|
||||
return host_hw_config
|
||||
|
||||
|
||||
def get_dvs_interfaces(host_interfaces):
|
||||
dvs_interfaces = []
|
||||
if not isinstance(host_interfaces, list):
|
||||
host_interfaces = eval(host_interfaces)
|
||||
for interface in host_interfaces:
|
||||
if not isinstance(interface, dict):
|
||||
interface = eval(interface)
|
||||
if ('vswitch_type' in interface and
|
||||
interface['vswitch_type'] == 'dvs'):
|
||||
dvs_interfaces.append(interface)
|
||||
|
||||
return dvs_interfaces
|
||||
|
||||
|
||||
def get_clc_pci_info(pci_info):
|
||||
clc_pci = []
|
||||
flag1 = 'Intel Corporation Coleto Creek PCIe Endpoint'
|
||||
flag2 = '8086:0435'
|
||||
for pci in pci_info:
|
||||
if flag1 in pci or flag2 in pci:
|
||||
clc_pci.append(pci.split()[0])
|
||||
return clc_pci
|
||||
|
||||
|
||||
def cpu_str_to_list(spec):
|
||||
"""Parse a CPU set specification.
|
||||
|
||||
:param spec: cpu set string eg "1-4,^3,6"
|
||||
|
||||
Each element in the list is either a single
|
||||
CPU number, a range of CPU numbers, or a
|
||||
caret followed by a CPU number to be excluded
|
||||
from a previous range.
|
||||
|
||||
:returns: a set of CPU indexes
|
||||
"""
|
||||
|
||||
cpusets = []
|
||||
if not spec:
|
||||
return cpusets
|
||||
|
||||
cpuset_ids = set()
|
||||
cpuset_reject_ids = set()
|
||||
for rule in spec.split(','):
|
||||
rule = rule.strip()
|
||||
# Handle multi ','
|
||||
if len(rule) < 1:
|
||||
continue
|
||||
# Note the count limit in the .split() call
|
||||
range_parts = rule.split('-', 1)
|
||||
if len(range_parts) > 1:
|
||||
# So, this was a range; start by converting the parts to ints
|
||||
try:
|
||||
start, end = [int(p.strip()) for p in range_parts]
|
||||
except ValueError:
|
||||
raise exception.Invalid(_("Invalid range expression %r")
|
||||
% rule)
|
||||
# Make sure it's a valid range
|
||||
if start > end:
|
||||
raise exception.Invalid(_("Invalid range expression %r")
|
||||
% rule)
|
||||
# Add available CPU ids to set
|
||||
cpuset_ids |= set(range(start, end + 1))
|
||||
elif rule[0] == '^':
|
||||
# Not a range, the rule is an exclusion rule; convert to int
|
||||
try:
|
||||
cpuset_reject_ids.add(int(rule[1:].strip()))
|
||||
except ValueError:
|
||||
raise exception.Invalid(_("Invalid exclusion "
|
||||
"expression %r") % rule)
|
||||
else:
|
||||
# OK, a single CPU to include; convert to int
|
||||
try:
|
||||
cpuset_ids.add(int(rule))
|
||||
except ValueError:
|
||||
raise exception.Invalid(_("Invalid inclusion "
|
||||
"expression %r") % rule)
|
||||
|
||||
# Use sets to handle the exclusion rules for us
|
||||
cpuset_ids -= cpuset_reject_ids
|
||||
cpusets = list(cpuset_ids)
|
||||
cpusets.sort()
|
||||
return cpusets
|
||||
|
||||
|
||||
def cpu_list_to_str(cpu_list):
|
||||
"""Parse a CPU list to string.
|
||||
|
||||
:param cpu_list: eg "[1,2,3,4,6,7]"
|
||||
|
||||
:returns: a string of CPU ranges, eg 1-4,6,7
|
||||
"""
|
||||
spec = ''
|
||||
if not cpu_list:
|
||||
return spec
|
||||
|
||||
cpu_list.sort()
|
||||
count = 0
|
||||
group_cpus = []
|
||||
tmp_cpus = []
|
||||
for cpu in cpu_list:
|
||||
if count == 0:
|
||||
init = cpu
|
||||
tmp_cpus.append(cpu)
|
||||
else:
|
||||
if cpu == (init + count):
|
||||
tmp_cpus.append(cpu)
|
||||
else:
|
||||
group_cpus.append(tmp_cpus)
|
||||
tmp_cpus = []
|
||||
count = 0
|
||||
init = cpu
|
||||
tmp_cpus.append(cpu)
|
||||
count += 1
|
||||
|
||||
group_cpus.append(tmp_cpus)
|
||||
|
||||
for group in group_cpus:
|
||||
if len(group) > 2:
|
||||
group_spec = ("%s-%s" % (group[0], group[0]+len(group)-1))
|
||||
else:
|
||||
group_str = [str(num) for num in group]
|
||||
group_spec = ','.join(group_str)
|
||||
if spec:
|
||||
spec += ',' + group_spec
|
||||
else:
|
||||
spec = group_spec
|
||||
|
||||
return spec
|
||||
|
||||
|
||||
def simple_subprocess_call(cmd):
|
||||
return_code = subprocess.call(cmd,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
return return_code
|
||||
|
||||
|
||||
def translate_quotation_marks_for_shell(orig_str):
|
||||
translated_str = ''
|
||||
quotation_marks = '"'
|
||||
quotation_marks_count = orig_str.count(quotation_marks)
|
||||
if quotation_marks_count > 0:
|
||||
replace_marks = '\\"'
|
||||
translated_str = orig_str.replace(quotation_marks, replace_marks)
|
||||
else:
|
||||
translated_str = orig_str
|
||||
return translated_str
|
||||
|
||||
|
||||
def get_numa_node_cpus(host_cpu):
|
||||
numa = {}
|
||||
if 'numa_node0' in host_cpu:
|
||||
numa['numa_node0'] = cpu_str_to_list(host_cpu['numa_node0'])
|
||||
if 'numa_node1' in host_cpu:
|
||||
numa['numa_node1'] = cpu_str_to_list(host_cpu['numa_node1'])
|
||||
return numa
|
||||
|
||||
|
||||
def get_numa_node_from_cpus(numa, str_cpus):
|
||||
numa_nodes = []
|
||||
|
||||
cpu_list = cpu_str_to_list(str_cpus)
|
||||
for cpu in cpu_list:
|
||||
if cpu in numa['numa_node0']:
|
||||
numa_nodes.append(0)
|
||||
if cpu in numa['numa_node1']:
|
||||
numa_nodes.append(1)
|
||||
|
||||
numa_nodes = list(set(numa_nodes))
|
||||
numa_nodes.sort()
|
||||
return numa_nodes
|
||||
|
392
code/daisy/daisy/common/vcpu_pin.py
Executable file
392
code/daisy/daisy/common/vcpu_pin.py
Executable file
@ -0,0 +1,392 @@
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# Copyright 2014 SoftLayer Technologies, Inc.
|
||||
# Copyright 2015 Mirantis, Inc
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
System-level utilities and helper functions.
|
||||
"""
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from webob import exc
|
||||
|
||||
from daisy.common import utils
|
||||
from daisy import i18n
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
_ = i18n._
|
||||
_LE = i18n._LE
|
||||
|
||||
|
||||
def get_total_cpus_for_numa(numa_cpus):
|
||||
all_cpus = []
|
||||
for value in numa_cpus.values():
|
||||
all_cpus.extend(value)
|
||||
return all_cpus
|
||||
|
||||
|
||||
def get_default_os_num(host_roles_name):
|
||||
if (('CONTROLLER_LB' in host_roles_name or
|
||||
'CONTROLLER_HA' in host_roles_name) and
|
||||
'COMPUTER' in host_roles_name):
|
||||
# host with role of CONTOLLER and COMPUTER,
|
||||
# isolate 4 cpu cores default for OS and TECS
|
||||
os_cpu_num = 4
|
||||
elif 'COMPUTER' in host_roles_name:
|
||||
# host with role of COMPUTER only,
|
||||
# isolate 2 cpu cores default for OS and TECS
|
||||
os_cpu_num = 2
|
||||
elif ('CONTROLLER_LB' in host_roles_name or
|
||||
'CONTROLLER_HA' in host_roles_name):
|
||||
# host with role of CONTOLLER only,
|
||||
# don't isolate cpu for OS and TECS
|
||||
os_cpu_num = 0
|
||||
else:
|
||||
os_cpu_num = 0
|
||||
|
||||
return os_cpu_num
|
||||
|
||||
|
||||
def pci_get_cpu_sets(numa_cpus, pci_info, device_numa_node):
|
||||
high_pci_cpu_set = {}
|
||||
msg = ''
|
||||
return_code = 0
|
||||
status = {'rc': 0, 'msg': ''}
|
||||
|
||||
if not numa_cpus:
|
||||
msg = "The architecture of CPU does not supported"
|
||||
LOG.info(msg)
|
||||
return_code = 0
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, high_pci_cpu_set)
|
||||
|
||||
# get Intel Corporation Coleto Creek PCIe Endpoint
|
||||
clc_pci_lines = utils.get_clc_pci_info(pci_info)
|
||||
if not clc_pci_lines:
|
||||
msg = "No CLC card in system"
|
||||
LOG.info(msg)
|
||||
return_code = 0
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, high_pci_cpu_set)
|
||||
|
||||
high_pci_cpusets = []
|
||||
for clc_pci_line in clc_pci_lines:
|
||||
numa_node = device_numa_node['0000:' + clc_pci_line]
|
||||
numa_key = 'numa_node' + str(numa_node)
|
||||
if numa_key not in numa_cpus:
|
||||
msg = "Can't find numa_node '%s' for CLC" % numa_node
|
||||
return_code = 1
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, high_pci_cpu_set)
|
||||
high_pci_cpusets += numa_cpus[numa_key]
|
||||
|
||||
high_pci_cpu_set['high'] = list(set(high_pci_cpusets))
|
||||
total_cpus = get_total_cpus_for_numa(numa_cpus)
|
||||
high_pci_cpu_set['low'] =\
|
||||
list(set(total_cpus) - set(high_pci_cpu_set['high']))
|
||||
LOG.debug("high_pci_cpu_set:%s" % high_pci_cpu_set)
|
||||
|
||||
return (status, high_pci_cpu_set)
|
||||
|
||||
|
||||
# if numa codes are not same, return -1
|
||||
def get_numa_by_nic(nic_info, device_numa_node):
|
||||
numa = []
|
||||
try:
|
||||
for nic in nic_info:
|
||||
numa.append(device_numa_node[nic['bus']])
|
||||
|
||||
numa = list(set(numa))
|
||||
numa_info = (-1 if len(numa) > 1 else numa[0])
|
||||
except Exception:
|
||||
numa_info = -1
|
||||
|
||||
return numa_info
|
||||
|
||||
|
||||
def dvs_get_cpu_sets(dic_numas, nic_info, device_numa_node, cpu_num=4):
|
||||
dvs_cpu_set = []
|
||||
total_cpus = []
|
||||
high_cpu_set = []
|
||||
low_cpu_set = []
|
||||
cpu_set = {}
|
||||
msg = ''
|
||||
return_code = 0
|
||||
status = {}
|
||||
|
||||
if not dic_numas:
|
||||
msg = "The architecture of CPU not supported"
|
||||
LOG.info(msg)
|
||||
return_code = 1
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, cpu_set)
|
||||
|
||||
numa_node = get_numa_by_nic(nic_info, device_numa_node)
|
||||
if numa_node < 0:
|
||||
msg = 'Invalid numa node:%s' % numa_node
|
||||
LOG.info(msg)
|
||||
return_code = 3
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, cpu_set)
|
||||
|
||||
numa_key = "numa_node%s" % numa_node
|
||||
if numa_key not in dic_numas:
|
||||
msg = "Can't find numa node '%s' for DVS" % numa_node
|
||||
return_code = 4
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, cpu_set)
|
||||
|
||||
if len(dic_numas[numa_key]) < (cpu_num + 1):
|
||||
msg = "CPU on %s is not enough" % numa_key
|
||||
LOG.info(msg)
|
||||
return_code = 5
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
return (status, cpu_set)
|
||||
|
||||
total_cpus = get_total_cpus_for_numa(dic_numas)
|
||||
LOG.debug("total_cpu:%s" % total_cpus)
|
||||
|
||||
# sort
|
||||
dic_numas[numa_key] = sorted(dic_numas[numa_key], reverse=True)
|
||||
for i in dic_numas[numa_key][0:cpu_num]:
|
||||
dvs_cpu_set.append(i)
|
||||
|
||||
high_cpu_set = dic_numas[numa_key]
|
||||
low_cpu_set =\
|
||||
list(set(total_cpus).difference(set(dic_numas[numa_key])))
|
||||
LOG.debug("cpu used by dvs:%s" % dvs_cpu_set)
|
||||
LOG.debug("low_cpu_set:%s" % low_cpu_set)
|
||||
LOG.debug("high_cpu_set:%s" % high_cpu_set)
|
||||
|
||||
cpu_set['dvs'] = dvs_cpu_set
|
||||
cpu_set['high'] = high_cpu_set
|
||||
cpu_set['low'] = low_cpu_set
|
||||
LOG.debug("cpu_set:%s" % cpu_set)
|
||||
|
||||
msg = 'Success'
|
||||
status['rc'] = return_code
|
||||
status['msg'] = msg
|
||||
LOG.debug("status:%s" % status)
|
||||
|
||||
return (status, cpu_set)
|
||||
|
||||
|
||||
def get_dvs_cpusets(numa_cpus, host_detail, host_hw_info):
|
||||
dvs_nics_name = []
|
||||
dvs_interfaces = utils.get_dvs_interfaces(host_detail['interfaces'])
|
||||
for dvs_interface in dvs_interfaces:
|
||||
if dvs_interface['type'] == 'ether':
|
||||
dvs_nics_name.append(dvs_interface['name'])
|
||||
if dvs_interface['type'] == 'bond':
|
||||
if dvs_interface.get('slaves', None):
|
||||
dvs_nics_name.extend(dvs_interface['slaves'])
|
||||
elif dvs_interface.get('slave1', None) and \
|
||||
dvs_interface.get('slave2', None):
|
||||
slave_list = []
|
||||
slave_list.append(dvs_interface['slave1'])
|
||||
slave_list.append(dvs_interface['slave2'])
|
||||
dvs_nics_name.extend(slave_list)
|
||||
|
||||
dvs_cpusets = {}
|
||||
if dvs_nics_name:
|
||||
nics_info = [{'name': nic_name, 'bus': interface['pci']}
|
||||
for nic_name in dvs_nics_name
|
||||
for interface in host_hw_info['interfaces'].values()
|
||||
if nic_name == interface['name']]
|
||||
dvs_cpu_num = 4
|
||||
device_numa = {}
|
||||
for device in host_hw_info['devices'].values():
|
||||
device_numa.update(device)
|
||||
LOG.info("DVS netcard info: '%s'" % nics_info)
|
||||
(status, dvs_cpusets) = \
|
||||
dvs_get_cpu_sets(numa_cpus,
|
||||
nics_info,
|
||||
device_numa,
|
||||
dvs_cpu_num)
|
||||
if status['rc'] != 0:
|
||||
msg = "Get dvs cpu sets for host '%s' failed,\
|
||||
detail error is '%s'"\
|
||||
% (host_detail['name'], status['msg'])
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
return dvs_cpusets
|
||||
|
||||
|
||||
def get_pci_cpusets(numa_cpus, host_hw_info):
|
||||
device_numa = {}
|
||||
for device in host_hw_info['devices'].values():
|
||||
device_numa.update(device)
|
||||
|
||||
(status, pci_cpusets) = pci_get_cpu_sets(numa_cpus,
|
||||
host_hw_info['pci'].values(),
|
||||
device_numa)
|
||||
if status['rc'] != 0:
|
||||
LOG.error(status['msg'])
|
||||
raise exc.HTTPBadRequest(explanation=status['msg'])
|
||||
|
||||
return pci_cpusets
|
||||
|
||||
|
||||
def allocate_os_cpus(roles_name, pci_cpusets, dvs_cpusets):
|
||||
os_cpus = []
|
||||
if not dvs_cpusets and not pci_cpusets:
|
||||
return os_cpus
|
||||
|
||||
os_cpu_num = get_default_os_num(roles_name)
|
||||
if os_cpu_num == 0:
|
||||
return os_cpus
|
||||
|
||||
os_available_cpuset = []
|
||||
if ((pci_cpusets and pci_cpusets.get('high')) and
|
||||
(not dvs_cpusets or not dvs_cpusets.get('high'))):
|
||||
# if only pci exist, get OS cores from pci lowset
|
||||
cpus_low = pci_cpusets.get('low', [])
|
||||
cpus_high = pci_cpusets.get('high', [])
|
||||
|
||||
if dvs_cpusets and dvs_cpusets.get('high'):
|
||||
# if only dvs exist, get OS cores from dvs lowset.
|
||||
# if pci and dvs exist at the same time,
|
||||
# get OS cores from lowset from dvs lowset.
|
||||
cpus_low = list(set(dvs_cpusets.get('low', [])) -
|
||||
set(dvs_cpusets.get('dvs', [])))
|
||||
|
||||
cpus_high = list(set(dvs_cpusets.get('high', [])) -
|
||||
set(dvs_cpusets.get('dvs', [])))
|
||||
|
||||
cpus_low.sort()
|
||||
cpus_high.sort()
|
||||
os_available_cpuset = cpus_low + cpus_high
|
||||
if not os_available_cpuset:
|
||||
return os_cpus
|
||||
|
||||
if (len(os_available_cpuset) < os_cpu_num):
|
||||
msg = 'cpus are not enough'
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
# cpu core 0 must give OS
|
||||
cpu0 = 0
|
||||
if cpu0 in os_available_cpuset:
|
||||
os_available_cpuset.remove(cpu0)
|
||||
os_available_cpuset = [cpu0] + os_available_cpuset
|
||||
|
||||
os_cpus = os_available_cpuset[:os_cpu_num]
|
||||
return os_cpus
|
||||
|
||||
|
||||
# when config role 'COMPUTER', allocate cpus for CLC
|
||||
def allocate_clc_cpus(host_detail):
|
||||
pci_cpu_sets = {}
|
||||
if 'COMPUTER' not in host_detail.get('role', []):
|
||||
return pci_cpu_sets
|
||||
|
||||
host_interfaces = host_detail.get('interfaces')
|
||||
if host_interfaces:
|
||||
host_hw_info = utils.get_host_hw_info(host_interfaces)
|
||||
else:
|
||||
return pci_cpu_sets
|
||||
|
||||
host_id = host_detail.get('id')
|
||||
clc_pci = utils.get_clc_pci_info(host_hw_info['pci'].values())
|
||||
if not clc_pci:
|
||||
return pci_cpu_sets
|
||||
else:
|
||||
LOG.info("CLC card pci number: '%s'" % clc_pci)
|
||||
numa_cpus = utils.get_numa_node_cpus(host_hw_info.get('cpu', {}))
|
||||
if not numa_cpus or not numa_cpus['numa_node0']:
|
||||
msg = "No NUMA CPU found from of host '%s'" % host_id
|
||||
LOG.info(msg)
|
||||
return pci_cpu_sets
|
||||
LOG.info("Get CLC cpusets of host '%s'" % host_id)
|
||||
pci_cpu_sets = get_pci_cpusets(numa_cpus, host_hw_info)
|
||||
if not pci_cpu_sets or not pci_cpu_sets.get('high'):
|
||||
msg = "Can't get CLC cpusets of host '%s'" % host_id
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
return pci_cpu_sets
|
||||
|
||||
|
||||
# when config DVS on network plane mapping, allocate cpus for dvs
|
||||
def allocate_dvs_cpus(host_detail):
|
||||
dvs_cpu_sets = {}
|
||||
host_interfaces = host_detail.get('interfaces')
|
||||
if not host_interfaces:
|
||||
return dvs_cpu_sets
|
||||
|
||||
dvs_interfaces = utils.get_dvs_interfaces(host_interfaces)
|
||||
if not dvs_interfaces:
|
||||
return dvs_cpu_sets
|
||||
|
||||
host_id = host_detail.get('id')
|
||||
host_hw_info = utils.get_host_hw_info(host_interfaces)
|
||||
numa_cpus = utils.get_numa_node_cpus(host_hw_info.get('cpu', {}))
|
||||
if not numa_cpus or not numa_cpus['numa_node0']:
|
||||
msg = "No NUMA CPU found from of host '%s'" % host_id
|
||||
LOG.info(msg)
|
||||
return dvs_cpu_sets
|
||||
|
||||
LOG.info("Get dvs cpusets of host '%s'" % host_id)
|
||||
dvs_cpu_sets = get_dvs_cpusets(numa_cpus,
|
||||
host_detail,
|
||||
host_hw_info)
|
||||
if not dvs_cpu_sets or not dvs_cpu_sets.get('high'):
|
||||
msg = "Can't get dvs high cpusets of host '%s'" % host_id
|
||||
LOG.error(msg)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
return dvs_cpu_sets
|
||||
|
||||
|
||||
def allocate_cpus(host_detail):
|
||||
host_cpu_sets = {'dvs_high_cpuset': '',
|
||||
'pci_high_cpuset': '',
|
||||
'suggest_dvs_cpus': '',
|
||||
'suggest_os_cpus': ''}
|
||||
|
||||
dvs_cpusets = allocate_dvs_cpus(host_detail)
|
||||
pci_cpusets = allocate_clc_cpus(host_detail)
|
||||
|
||||
# no CLC and no DVS
|
||||
if (not pci_cpusets and not dvs_cpusets):
|
||||
return host_cpu_sets
|
||||
|
||||
host_roles_name = host_detail.get('role', [])
|
||||
os_cpus = allocate_os_cpus(host_roles_name,
|
||||
pci_cpusets,
|
||||
dvs_cpusets)
|
||||
|
||||
host_cpu_sets['dvs_high_cpuset'] =\
|
||||
utils.cpu_list_to_str(dvs_cpusets.get('high', []))
|
||||
host_cpu_sets['pci_high_cpuset'] =\
|
||||
utils.cpu_list_to_str(pci_cpusets.get('high', []))
|
||||
host_cpu_sets['suggest_dvs_cpus'] =\
|
||||
utils.cpu_list_to_str(dvs_cpusets.get('dvs', []))
|
||||
host_cpu_sets['suggest_os_cpus'] = utils.cpu_list_to_str(os_cpus)
|
||||
|
||||
LOG.info("NUMA CPU usage for host %s: %s"
|
||||
% (host_detail['id'], host_cpu_sets))
|
||||
|
||||
return host_cpu_sets
|
@ -244,6 +244,7 @@ class Server(object):
|
||||
This class requires initialize_glance_store set to True if
|
||||
glance store needs to be initialized.
|
||||
"""
|
||||
|
||||
def __init__(self, threads=1000, initialize_glance_store=False):
|
||||
os.umask(0o27) # ensure files are created with the correct privileges
|
||||
self._logger = logging.getLogger("eventlet.wsgi.server")
|
||||
@ -638,6 +639,7 @@ class APIMapper(routes.Mapper):
|
||||
|
||||
|
||||
class RejectMethodController(object):
|
||||
|
||||
def reject(self, req, allowed_methods, *args, **kwargs):
|
||||
LOG.debug("The method %s is not allowed for this resource" %
|
||||
req.environ['REQUEST_METHOD'])
|
||||
|
@ -40,7 +40,7 @@ class WSMEModelTransformer(object):
|
||||
for name in names:
|
||||
value = getattr(db_entity, name, None)
|
||||
if value is not None:
|
||||
if type(value) == datetime:
|
||||
if isinstance(value, datetime):
|
||||
iso_datetime_value = timeutils.isotime(value)
|
||||
values.update({name: iso_datetime_value})
|
||||
else:
|
||||
|
@ -52,8 +52,8 @@ class ImageAsAnArtifact(v1_1.ImageAsAnArtifact):
|
||||
if service['name'] == 'glance')
|
||||
try:
|
||||
client = daisyclient.Client(version=2,
|
||||
endpoint=glance_endpoint,
|
||||
token=context.auth_token)
|
||||
endpoint=glance_endpoint,
|
||||
token=context.auth_token)
|
||||
legacy_image = client.images.get(self.legacy_image_id)
|
||||
except Exception:
|
||||
raise exception.InvalidArtifactPropertyValue(
|
||||
|
@ -607,4 +607,3 @@ def artifact_publish(client, artifact_id,
|
||||
return client.artifact_publish(artifact_id=artifact_id,
|
||||
type_name=type_name,
|
||||
type_version=type_version)
|
||||
|
||||
|
@ -272,8 +272,8 @@ def _filter_images(images, filters, context,
|
||||
elif visibility == 'private':
|
||||
if image['is_public']:
|
||||
continue
|
||||
if not (has_ownership or (context.is_admin
|
||||
and not admin_as_user)):
|
||||
if not (has_ownership or (context.is_admin and not
|
||||
admin_as_user)):
|
||||
continue
|
||||
elif visibility == 'shared':
|
||||
if not is_member:
|
||||
@ -387,8 +387,8 @@ def _image_get(context, image_id, force_show_deleted=False, status=None):
|
||||
LOG.warn(_LW('Could not find image %s') % image_id)
|
||||
raise exception.NotFound()
|
||||
|
||||
if image['deleted'] and not (force_show_deleted
|
||||
or context.can_see_deleted):
|
||||
if image['deleted'] and not (force_show_deleted or
|
||||
context.can_see_deleted):
|
||||
LOG.warn(_LW('Unable to get deleted image'))
|
||||
raise exception.NotFound()
|
||||
|
||||
@ -625,7 +625,7 @@ def _image_locations_delete_all(context, image_id, delete_time=None):
|
||||
delete_time=delete_time)
|
||||
|
||||
for i, loc in enumerate(DATA['locations']):
|
||||
if image_id == loc['image_id'] and loc['deleted'] == False:
|
||||
if image_id == loc['image_id'] and loc['deleted'] is False:
|
||||
del DATA['locations'][i]
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user