Rework shell execution
This commit is contained in:
parent
5fd489739b
commit
dd612ee676
|
@ -1,10 +1,9 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import logging
|
||||
from logging import debug, info, warning
|
||||
from logging import debug, info, warning, DEBUG, basicConfig
|
||||
from subprocess import Popen, PIPE
|
||||
import yaml
|
||||
from subprocess import call, Popen, PIPE
|
||||
from shutil import rmtree
|
||||
from tempfile import mkstemp, mkdtemp
|
||||
from socket import inet_ntoa
|
||||
|
@ -15,9 +14,40 @@ import re
|
|||
LOG_FILE = '/tmp/compute_post_deployment.log'
|
||||
ASTUTE_PATH = '/etc/astute.yaml'
|
||||
ACCESS_SECTION = 'xenserver-fuel-plugin'
|
||||
XENAPI_URL = 'https://pypi.python.org/packages/source/X/XenAPI/XenAPI-1.2.tar.gz'
|
||||
XENAPI_URL = \
|
||||
'https://pypi.python.org/packages/source/X/XenAPI/XenAPI-1.2.tar.gz'
|
||||
|
||||
logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG)
|
||||
basicConfig(filename=LOG_FILE, level=DEBUG)
|
||||
|
||||
|
||||
def execute(*cmd):
|
||||
cmd = map(str, cmd)
|
||||
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
|
||||
|
||||
out = proc.stdout.readlines()
|
||||
err = proc.stderr.readlines()
|
||||
|
||||
(out, err, cmd) = map(' '.join, [out, err, cmd])
|
||||
|
||||
info(cmd)
|
||||
if out:
|
||||
debug(out)
|
||||
if err:
|
||||
warning(err)
|
||||
|
||||
return (out, err, cmd)
|
||||
|
||||
|
||||
def ssh(host, username, password, *cmd):
|
||||
cmd = map(str, cmd)
|
||||
|
||||
return execute(*(['sshpass', '-p', password, 'ssh',
|
||||
'%s@%s' % (username, host)] + cmd))
|
||||
|
||||
|
||||
def scp(host, username, password, target_path, filename):
|
||||
return execute('sshpass', '-p', '"%s"' % password, 'scp', filename,
|
||||
'%s@%s:%s' % (username, host, target_path))
|
||||
|
||||
|
||||
def get_astute(astute_path):
|
||||
|
@ -32,188 +62,150 @@ def get_astute(astute_path):
|
|||
def get_access(astute, access_section):
|
||||
if not access_section in astute:
|
||||
warning('%s not found' % access_section)
|
||||
return None
|
||||
return None, None
|
||||
|
||||
access = astute[access_section]
|
||||
info('username: {username}'.format(**access))
|
||||
info('password: {password}'.format(**access))
|
||||
return access
|
||||
return access['username'], access['password']
|
||||
|
||||
|
||||
def get_endpoints(astute):
|
||||
_endpoints = astute['network_scheme']['endpoints']
|
||||
endpoints = astute['network_scheme']['endpoints']
|
||||
endpoints = dict([(
|
||||
k.replace('br-', ''),
|
||||
_endpoints[k]['IP'][0]
|
||||
) for k in _endpoints])
|
||||
endpoints[k]['IP'][0]
|
||||
) for k in endpoints])
|
||||
|
||||
info('storage network: {storage}'.format(**endpoints))
|
||||
info('mgmt network: {mgmt}'.format(**endpoints))
|
||||
return endpoints
|
||||
|
||||
|
||||
def init_eth(dev_no):
|
||||
eth = 'eth%s' % dev_no
|
||||
def init_eth(eth):
|
||||
if not eth in netifaces.interfaces():
|
||||
warning('%s not found' % eth)
|
||||
return
|
||||
return None
|
||||
|
||||
info('%s found' % eth)
|
||||
call(['dhclient', eth])
|
||||
call(['ifconfig', eth])
|
||||
execute('dhclient', eth)
|
||||
execute('ifconfig', eth)
|
||||
fname = '/etc/network/interfaces.d/ifcfg-' + eth
|
||||
s = \
|
||||
"""auto {eth}
|
||||
iface {eth} inet dhcp
|
||||
""".format(eth=eth)
|
||||
s = 'auto {eth}\niface {eth} inet dhcp'.format(eth=eth)
|
||||
with open(fname, 'w') as f:
|
||||
f.write(s)
|
||||
info('%s created' % fname)
|
||||
call(['ifdown', eth])
|
||||
call(['ifup', eth])
|
||||
execute('ifdown', eth)
|
||||
execute('ifup', eth)
|
||||
addr = netifaces.ifaddresses(eth).get(2)
|
||||
if addr is not None:
|
||||
if addr:
|
||||
local_ip = addr[0]['addr']
|
||||
ip = '.'.join(local_ip.split('.')[:-1] + ['1'])
|
||||
info('%s : %s' % (eth, ip))
|
||||
return ip
|
||||
xs_ip = '.'.join(local_ip.split('.')[:-1] + ['1'])
|
||||
info('HIMN on %s : %s' % (eth, xs_ip))
|
||||
return xs_ip
|
||||
else:
|
||||
warning('%s not found' % access_section)
|
||||
warning('HIMN failed to get IP address from XenServer')
|
||||
return None
|
||||
|
||||
|
||||
def install_xenapi_sdk(xenapi_url):
|
||||
xenapi_zipball = mkstemp()[1]
|
||||
xenapi_sources = mkdtemp()
|
||||
|
||||
call(['wget', '-qO', xenapi_zipball, xenapi_url])
|
||||
info('%s downloaded' % (xenapi_url))
|
||||
execute('wget', '-qO', xenapi_zipball, xenapi_url)
|
||||
|
||||
call(['tar', '-zxf', xenapi_zipball, '-C', xenapi_sources])
|
||||
execute('tar', '-zxf', xenapi_zipball, '-C', xenapi_sources)
|
||||
subdirs = os.listdir(xenapi_sources)
|
||||
if (len(subdirs) != 1) or (not subdirs[0].startswith('XenAPI')):
|
||||
warning('fail to extract %s' % xenapi_url)
|
||||
return
|
||||
info('%s extracted' % (subdirs[0]))
|
||||
|
||||
src = os.path.join(xenapi_sources, subdirs[0], 'XenAPI.py')
|
||||
dest = '/usr/lib/python2.7/dist-packages'
|
||||
call(['cp', src, dest])
|
||||
info('XenAPI.py deployed')
|
||||
execute('cp', src, dest)
|
||||
|
||||
os.remove(xenapi_zipball)
|
||||
rmtree(xenapi_sources)
|
||||
|
||||
|
||||
def create_novacompute_conf(access, ip):
|
||||
template = """[DEFAULT]
|
||||
compute_driver=xenapi.XenAPIDriver
|
||||
[xenserver]
|
||||
connection_url=http://%s
|
||||
connection_username="%s"
|
||||
connection_password="%s"
|
||||
"""
|
||||
s = template % (ip, access['username'], access['password'])
|
||||
with open('/etc/nova/nova-compute.conf', 'w') as f:
|
||||
def create_novacompute_conf(himn, username, password):
|
||||
template = '\n'.join([
|
||||
'[DEFAULT]',
|
||||
'compute_driver=xenapi.XenAPIDriver',
|
||||
'[xenserver]',
|
||||
'connection_url=http://%s',
|
||||
'connection_username="%s"',
|
||||
'connection_password="%s"'
|
||||
])
|
||||
|
||||
s = template % (himn, username, password)
|
||||
fname = '/etc/nova/nova-compute.conf'
|
||||
with open(fname, 'w') as f:
|
||||
f.write(s)
|
||||
info('nova-compute.conf created')
|
||||
info('%s created' % fname)
|
||||
|
||||
|
||||
def restart_nova_services():
|
||||
_run('stop nova-compute')
|
||||
_run('start nova-compute')
|
||||
info('nova-compute restarted')
|
||||
_run('stop nova-network')
|
||||
_run('start nova-network')
|
||||
info('nova-network restarted')
|
||||
execute('stop', 'nova-compute')
|
||||
execute('start', 'nova-compute')
|
||||
execute('stop', 'nova-network')
|
||||
execute('start', 'nova-network')
|
||||
|
||||
|
||||
def _ssh(host, access, cmd):
|
||||
ssh = Popen(['sshpass', '-p', access['password'], 'ssh',
|
||||
'%s@%s' % (access['username'], host), cmd],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
s = ssh.stdout.readlines()
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
def _scp(host, access, path, filename):
|
||||
ssh = Popen(['sshpass', '-p', access['password'], 'scp',
|
||||
'%s@%s:%s' % (access['username'], host, path), filename],
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
s = ssh.stdout.readlines()
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
def _run(cmd):
|
||||
ssh = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
|
||||
s = ssh.stdout.readlines()
|
||||
return '\n'.join(s)
|
||||
|
||||
|
||||
def route_to_himn(endpoints, himn_ip, access):
|
||||
route_list = _ssh(himn_ip, access, 'route -n')
|
||||
netmask = lambda cidr: inet_ntoa(pack(
|
||||
def route_to_himn(endpoints, himn, username, password):
|
||||
(out, err, cmd) = ssh(himn, username, password, 'route -n')
|
||||
_netmask = lambda cidr: inet_ntoa(pack(
|
||||
'>I', 0xffffffff ^ (1 << 32 - int(cidr)) - 1))
|
||||
routed = lambda ip, mask: re.search(r'%s\s+%s\s+%s\s+' % (
|
||||
_routed = lambda ip, mask, gw: re.search(r'%s\s+%s\s+%s\s+' % (
|
||||
ip.replace('.', r'\.'),
|
||||
himn_ip.replace('.', r'\.'),
|
||||
gw.replace('.', r'\.'),
|
||||
mask
|
||||
), route_list)
|
||||
), out)
|
||||
_route = lambda ip, mask, gw: ssh(
|
||||
himn, username, password, 'route', 'add', '-net', ip, 'netmask',
|
||||
mask, 'gw', gw)
|
||||
|
||||
storage_network = endpoints.get('storage')
|
||||
if storage_network:
|
||||
storage_ip, storage_cidr = storage_network.split('/')
|
||||
storage_netmask = netmask(storage_cidr)
|
||||
if not routed(storage_ip, storage_netmask):
|
||||
_ssh(himn_ip, access, 'route add -net %s netmask %s gw %s' %
|
||||
(storage_ip, storage_netmask, himn_ip))
|
||||
info('storage network %s/%s routed to %s' %
|
||||
(storage_ip, storage_netmask, himn_ip))
|
||||
else:
|
||||
info('storage network ip is missing')
|
||||
|
||||
mgmt_network = endpoints.get('mgmt')
|
||||
if mgmt_network:
|
||||
mgmt_ip, mgmt_cidr = mgmt_network.split('/')
|
||||
mgmt_netmask = netmask(mgmt_cidr)
|
||||
if not routed(mgmt_ip, mgmt_netmask):
|
||||
_ssh(himn_ip, access, 'route add -net %s netmask %s gw %s' %
|
||||
(mgmt_ip, mgmt_netmask, himn_ip))
|
||||
info('mgmt network %s/%s routed to %s' %
|
||||
(mgmt_ip, mgmt_netmask, himn_ip))
|
||||
else:
|
||||
info('mgmt network ip is missing')
|
||||
nets = ['storage', 'mgmt']
|
||||
for net in nets:
|
||||
endpoint = endpoints.get(net)
|
||||
if endpoint:
|
||||
ip, cidr = endpoint.split('/')
|
||||
netmask = _netmask(cidr)
|
||||
if not _routed(ip, netmask, himn):
|
||||
_route(ip, netmask, himn)
|
||||
else:
|
||||
info('%s network ip is missing' % net)
|
||||
|
||||
|
||||
def install_suppack(himn_ip, access):
|
||||
def install_suppack(himn, username, password):
|
||||
# TODO: check exists
|
||||
_scp(himn_ip, access, '/tmp/', 'novaplugins.iso')
|
||||
info('novaplugins.iso copied')
|
||||
_ssh(himn_ip, access, 'xe-install-supplemental-pack /tmp/novaplugins.iso')
|
||||
info('novaplugins.iso installed')
|
||||
_ssh(himn_ip, access, 'rm /tmp/novaplugins.iso')
|
||||
info('novaplugins.iso removed')
|
||||
scp(himn, username, password, '/tmp/', 'novaplugins.iso')
|
||||
ssh(himn, username, password,
|
||||
'xe-install-supplemental-pack', '/tmp/novaplugins.iso')
|
||||
ssh(himn, username, password, 'rm', '/tmp/novaplugins.iso')
|
||||
|
||||
|
||||
def forward_from_himn(eth_no):
|
||||
if _run('iptables -S | grep eth%s' % eth_no):
|
||||
_run('iptables -A FORWARD -i eth%s -j ACCEPT' % eth_no)
|
||||
_run("sed -i 's/#net.ipv4.ip_forward/net.ipv4.ip_forward/g' "
|
||||
"/etc/sysctl.conf")
|
||||
_run('sysctl -p /etc/sysctl.conf')
|
||||
_run('iptables -t nat -A POSTROUTING -o eth%s -j MASQUERADE' % eth_no)
|
||||
def forward_from_himn(eth):
|
||||
(out, err, cmd) = execute('iptables', '-S')
|
||||
if eth in out:
|
||||
execute('iptables', '-A', 'FORWARD', '-i', eth, '-j', 'ACCEPT')
|
||||
execute('sed', '-i', 's/#net.ipv4.ip_forward/net.ipv4.ip_forward/g',
|
||||
'/etc/sysctl.conf')
|
||||
execute('sysctl', '-p', '/etc/sysctl.conf')
|
||||
execute('iptables', '-t', 'nat', '-A', 'POSTROUTING', '-o', eth,
|
||||
'-j', 'MASQUERADE')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
eth_no = 2
|
||||
eth = 'eth2'
|
||||
install_xenapi_sdk(XENAPI_URL)
|
||||
astute = get_astute(ASTUTE_PATH)
|
||||
if astute:
|
||||
access = get_access(astute, ACCESS_SECTION)
|
||||
username, password = get_access(astute, ACCESS_SECTION)
|
||||
endpoints = get_endpoints(astute)
|
||||
himn_ip = init_eth(eth_no)
|
||||
if access and endpoints and himn_ip:
|
||||
route_to_himn(endpoints, himn_ip, access)
|
||||
install_suppack(himn_ip, access)
|
||||
forward_from_himn(eth_no)
|
||||
create_novacompute_conf(access, himn_ip)
|
||||
himn = init_eth(eth)
|
||||
if username and password and endpoints and himn:
|
||||
route_to_himn(endpoints, himn, username, password)
|
||||
install_suppack(himn, username, password)
|
||||
forward_from_himn(eth)
|
||||
create_novacompute_conf(himn, username, password)
|
||||
restart_nova_services()
|
||||
|
|
|
@ -16,14 +16,14 @@
|
|||
parameters:
|
||||
timeout: 300
|
||||
- role: ['compute']
|
||||
stage: post_deployment
|
||||
stage: post_deployment/50
|
||||
type: shell
|
||||
parameters:
|
||||
cmd: ./compute_post_deployment.py
|
||||
timeout: 60
|
||||
- role: ['controller']
|
||||
stage: post_deployment
|
||||
timeout: 300
|
||||
- role: ['primary-controller', 'controller']
|
||||
stage: post_deployment/100
|
||||
type: shell
|
||||
parameters:
|
||||
cmd: ./controller_post_deployment.sh
|
||||
timeout: 60
|
||||
timeout: 300
|
Loading…
Reference in New Issue