Fix Eoan.
Moved to pure Python where clib conflicts arose in using command line tools. Fixed erroneous assumptions about the presence and reliability of a $HOME variable while running init. Added tests specific to eoan, disco and xenial. They are not yet part of the gate. Change-Id: I2fc74fcc2ae9876442bb87a3446aef48d0428f2f
This commit is contained in:
parent
5404a261aa
commit
cb940157ab
|
@ -8,8 +8,9 @@ description: |
|
||||||
grade: stable
|
grade: stable
|
||||||
confinement: classic
|
confinement: classic
|
||||||
environment:
|
environment:
|
||||||
LD_LIBRARY_PATH: $SNAP/lib:$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET
|
# Edit the following lines with tools/update_path.py
|
||||||
PATH: $SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:/snap/core18/current/bin:$PATH
|
LD_LIBRARY_PATH: $SNAP/lib:$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio
|
||||||
|
PATH: $SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH
|
||||||
LC_ALL: C
|
LC_ALL: C
|
||||||
OS_PLACEMENT_CONFIG_DIR: $SNAP/etc/nova/
|
OS_PLACEMENT_CONFIG_DIR: $SNAP/etc/nova/
|
||||||
|
|
||||||
|
@ -219,8 +220,6 @@ apps:
|
||||||
libvirtd:
|
libvirtd:
|
||||||
command: libvirtd
|
command: libvirtd
|
||||||
daemon: simple
|
daemon: simple
|
||||||
environment:
|
|
||||||
LD_LIBRARY_PATH: $SNAP/lib:$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio
|
|
||||||
virtlogd:
|
virtlogd:
|
||||||
command: virtlogd
|
command: virtlogd
|
||||||
daemon: simple
|
daemon: simple
|
||||||
|
|
|
@ -72,10 +72,11 @@ class Framework(unittest.TestCase):
|
||||||
|
|
||||||
self.MACHINE = petname.generate()
|
self.MACHINE = petname.generate()
|
||||||
self.PREFIX = ['multipass', 'exec', self.MACHINE, '--']
|
self.PREFIX = ['multipass', 'exec', self.MACHINE, '--']
|
||||||
|
distro = os.environ.get('DISTRO') or self.DISTRO
|
||||||
|
|
||||||
check('sudo', 'snap', 'install', '--classic', '--edge', 'multipass')
|
check('sudo', 'snap', 'install', '--classic', '--edge', 'multipass')
|
||||||
|
|
||||||
check('multipass', 'launch', '--cpus', '2', '--mem', '8G', self.DISTRO,
|
check('multipass', 'launch', '--cpus', '2', '--mem', '8G', distro,
|
||||||
'--name', self.MACHINE)
|
'--name', self.MACHINE)
|
||||||
check('multipass', 'copy-files', self.SNAP, '{}:'.format(self.MACHINE))
|
check('multipass', 'copy-files', self.SNAP, '{}:'.format(self.MACHINE))
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@ Web IDE.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
import xvfbwrapper
|
import xvfbwrapper
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
|
@ -50,7 +52,7 @@ class TestBasics(Framework):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
launch = '/snap/bin/microstack.launch'
|
launch = '/snap/bin/microstack.launch'
|
||||||
# openstack = '/snap/bin/microstack.openstack'
|
openstack = '/snap/bin/microstack.openstack'
|
||||||
|
|
||||||
print("Testing microstack.launch ...")
|
print("Testing microstack.launch ...")
|
||||||
|
|
||||||
|
@ -66,6 +68,55 @@ class TestBasics(Framework):
|
||||||
# Endpoints should not contain localhost
|
# Endpoints should not contain localhost
|
||||||
self.assertFalse("localhost" in endpoints)
|
self.assertFalse("localhost" in endpoints)
|
||||||
|
|
||||||
|
if 'multipass' in self.PREFIX:
|
||||||
|
# Verify that microstack.launch completed successfully
|
||||||
|
# Skip these tests in the gate, as they are not reliable there.
|
||||||
|
# TODO: fix these in the gate!
|
||||||
|
|
||||||
|
# Ping the instance
|
||||||
|
ip = None
|
||||||
|
servers = check_output(*self.PREFIX, openstack,
|
||||||
|
'server', 'list', '--format', 'json')
|
||||||
|
servers = json.loads(servers)
|
||||||
|
for server in servers:
|
||||||
|
if server['Name'] == 'breakfast':
|
||||||
|
ip = server['Networks'].split(",")[1].strip()
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertTrue(ip)
|
||||||
|
|
||||||
|
pings = 1
|
||||||
|
max_pings = 600 # ~10 minutes!
|
||||||
|
while not call(*self.PREFIX, 'ping', '-c1', '-w1', ip):
|
||||||
|
pings += 1
|
||||||
|
if pings > max_pings:
|
||||||
|
self.assertFalse(True, msg='Max pings reached!')
|
||||||
|
|
||||||
|
print("Testing instances' ability to connect to the Internet")
|
||||||
|
# Test Internet connectivity
|
||||||
|
attempts = 1
|
||||||
|
max_attempts = 300 # ~10 minutes!
|
||||||
|
username = check_output(*self.PREFIX, 'whoami')
|
||||||
|
|
||||||
|
while not call(
|
||||||
|
*self.PREFIX,
|
||||||
|
'ssh',
|
||||||
|
'-oStrictHostKeyChecking=no',
|
||||||
|
'-i', '/home/{}/.ssh/id_microstack'.format(username),
|
||||||
|
'cirros@{}'.format(ip),
|
||||||
|
'--', 'ping', '-c1', '91.189.94.250'):
|
||||||
|
attempts += 1
|
||||||
|
if attempts > max_attempts:
|
||||||
|
self.assertFalse(
|
||||||
|
True,
|
||||||
|
msg='Unable to access the Internet!')
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Artificial wait, to allow for stuff to settle for the GUI test.
|
||||||
|
# TODO: get rid of this, when we drop the ping tests back int.
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
if 'multipass' in self.PREFIX:
|
if 'multipass' in self.PREFIX:
|
||||||
print("Opening {}:80 up to the outside world".format(
|
print("Opening {}:80 up to the outside world".format(
|
||||||
self.HORIZON_IP))
|
self.HORIZON_IP))
|
||||||
|
|
|
@ -291,12 +291,10 @@ class RabbitMq(Question):
|
||||||
|
|
||||||
(actions may have already been run, in which case we fail silently).
|
(actions may have already been run, in which case we fail silently).
|
||||||
"""
|
"""
|
||||||
# Add Erlang HOME to env.
|
|
||||||
env = dict(**_env)
|
|
||||||
env['HOME'] = '{SNAP_COMMON}/lib/rabbitmq'.format(**_env)
|
|
||||||
# Configure RabbitMQ
|
# Configure RabbitMQ
|
||||||
call('rabbitmqctl', 'add_user', 'openstack', 'rabbitmq', env=env)
|
call('microstack.rabbitmqctl', 'add_user', 'openstack', 'rabbitmq')
|
||||||
shell('rabbitmqctl set_permissions openstack ".*" ".*" ".*"', env=env)
|
shell(
|
||||||
|
'microstack.rabbitmqctl set_permissions openstack ".*" ".*" ".*"')
|
||||||
|
|
||||||
def yes(self, answer: str) -> None:
|
def yes(self, answer: str) -> None:
|
||||||
log.info('Waiting for RabbitMQ to start ...')
|
log.info('Waiting for RabbitMQ to start ...')
|
||||||
|
@ -692,20 +690,18 @@ class KeyPair(Question):
|
||||||
def yes(self, answer: str) -> None:
|
def yes(self, answer: str) -> None:
|
||||||
|
|
||||||
if 'microstack' not in check_output('openstack', 'keypair', 'list'):
|
if 'microstack' not in check_output('openstack', 'keypair', 'list'):
|
||||||
|
user = check_output('logname')
|
||||||
|
home = '/home/{}'.format(user) # TODO make more portable!
|
||||||
|
|
||||||
log.info('Creating microstack keypair (~/.ssh/{})'.format(answer))
|
log.info('Creating microstack keypair (~/.ssh/{})'.format(answer))
|
||||||
check('mkdir', '-p', '{HOME}/.ssh'.format(**_env))
|
check('mkdir', '-p', '{home}/.ssh'.format(home=home))
|
||||||
check('chmod', '700', '{HOME}/.ssh'.format(**_env))
|
check('chmod', '700', '{home}/.ssh'.format(home=home))
|
||||||
id_ = check_output('openstack', 'keypair', 'create', 'microstack')
|
id_ = check_output('openstack', 'keypair', 'create', 'microstack')
|
||||||
id_path = '{HOME}/.ssh/{answer}'.format(
|
id_path = '{home}/.ssh/{answer}'.format(home=home, answer=answer)
|
||||||
HOME=_env['HOME'],
|
|
||||||
answer=answer
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(id_path, 'w') as file_:
|
with open(id_path, 'w') as file_:
|
||||||
file_.write(id_)
|
file_.write(id_)
|
||||||
check('chmod', '600', id_path)
|
check('chmod', '600', id_path)
|
||||||
# TODO: too many assumptions in the below. Make it portable!
|
|
||||||
user = _env['HOME'].split("/")[2]
|
|
||||||
check('chown', '{}:{}'.format(user, user), id_path)
|
check('chown', '{}:{}'.format(user, user), id_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ from typing import Dict, List
|
||||||
import netaddr
|
import netaddr
|
||||||
import netifaces
|
import netifaces
|
||||||
import pymysql
|
import pymysql
|
||||||
|
import socket
|
||||||
import wget
|
import wget
|
||||||
|
|
||||||
from init.config import Env, log
|
from init.config import Env, log
|
||||||
|
@ -107,16 +108,12 @@ def shell(cmd: str, env: Dict = _env) -> int:
|
||||||
"""
|
"""
|
||||||
proc = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
|
proc = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT, bufsize=1,
|
stderr=subprocess.STDOUT, bufsize=1,
|
||||||
universal_newlines=True, shell=True,
|
universal_newlines=True, shell=True)
|
||||||
executable='/snap/core18/current/bin/bash')
|
|
||||||
for line in iter(proc.stdout.readline, ''):
|
for line in iter(proc.stdout.readline, ''):
|
||||||
log.debug(line)
|
log.debug(line)
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode:
|
if proc.returncode:
|
||||||
raise subprocess.CalledProcessError(
|
raise subprocess.CalledProcessError(proc.returncode, cmd)
|
||||||
"Command '{}' returned non-zero exit status {}".format(
|
|
||||||
cmd,
|
|
||||||
proc.returncode))
|
|
||||||
return proc.returncode
|
return proc.returncode
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +138,8 @@ def sql(cmd: str) -> None:
|
||||||
def nc_wait(addr: str, port: str) -> None:
|
def nc_wait(addr: str, port: str) -> None:
|
||||||
"""Wait for a service to be answering on a port."""
|
"""Wait for a service to be answering on a port."""
|
||||||
print('Waiting for {}:{}'.format(addr, port))
|
print('Waiting for {}:{}'.format(addr, port))
|
||||||
while not call('nc', '-z', addr, port):
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
while sock.connect_ex((addr, int(port))) != 0:
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
"""Update LD_LIBRARY_PATH and PATH snapcraft.yaml in the current
|
||||||
|
working directory.
|
||||||
|
|
||||||
|
Editing the lines in question directly in snapcraft.yaml is pretty
|
||||||
|
terrible, as the lines are long, and we cannot break them up into a
|
||||||
|
normal yaml string w/ a | and still get snapcraft's variable
|
||||||
|
expansion. (Or, if we can, I don't know what magic invocation will do
|
||||||
|
so.)
|
||||||
|
|
||||||
|
This script will not check in the new snapcraft.yaml. You should
|
||||||
|
inspect the updates and check in the file yourself!
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
LD_LIBRARY_PATH = (
|
||||||
|
'$SNAP/lib',
|
||||||
|
'$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET',
|
||||||
|
'$SNAP/usr/lib',
|
||||||
|
'$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET',
|
||||||
|
'$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio',
|
||||||
|
# '/snap/core18/current/lib',
|
||||||
|
# '/snap/core18/current/lib/$SNAPCRAFT_ARCH_TRIPLET',
|
||||||
|
# '/snap/core18/current/lib/systemd',
|
||||||
|
# '/snap/core18/current/usr/lib',
|
||||||
|
# '/snap/core18/current/var/lib',
|
||||||
|
# '/snap/core18/current/usr/lib/$SNAPCRAFT_ARCH_TRIPLET',
|
||||||
|
)
|
||||||
|
PATH = (
|
||||||
|
'$SNAP/usr/sbin',
|
||||||
|
'$SNAP/usr/bin',
|
||||||
|
'$SNAP/sbin',
|
||||||
|
'$SNAP/bin',
|
||||||
|
# '/snap/core18/current/bin',
|
||||||
|
# '/snap/core18/current/usr/sbin',
|
||||||
|
# '/snap/core18/current/usr/bin',
|
||||||
|
# '/snap/core18/current/sbin',
|
||||||
|
'$PATH'
|
||||||
|
)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Replace PATH and LD_LIBRARY_PATH with lists above.
|
||||||
|
|
||||||
|
This is dead simple code that relies on there being one setting
|
||||||
|
for LD_LIBRARY_PATH and PATH. It needs to be updated to be made
|
||||||
|
smarter if more instances are added.
|
||||||
|
|
||||||
|
Note that it would be nice if we could just read and write the
|
||||||
|
yaml, but we'd chomp comments if we did so. And we like our
|
||||||
|
comments!
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not os.path.isfile('./snapcraft.yaml'):
|
||||||
|
print('Cannot file snapcraft.yaml in the current working dir!')
|
||||||
|
print('Exiting.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print('snapcraft.yaml found in the current working dir. '
|
||||||
|
'Updating LD_LIBRARY_PATH and PATH ...')
|
||||||
|
|
||||||
|
libs = ':'.join(LD_LIBRARY_PATH)
|
||||||
|
path_ = ':'.join(PATH)
|
||||||
|
|
||||||
|
with open('./snapcraft.yaml', 'r') as source:
|
||||||
|
with open('./snapcraft.yaml.updated', 'w') as dest:
|
||||||
|
lines = source.readlines()
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith(' LD_LIBRARY_PATH: '):
|
||||||
|
line = ' LD_LIBRARY_PATH: {}\n'.format(libs)
|
||||||
|
if line.startswith(' PATH: '):
|
||||||
|
line = ' PATH: {}\n'.format(path_)
|
||||||
|
|
||||||
|
dest.write(line)
|
||||||
|
|
||||||
|
shutil.move('./snapcraft.yaml.updated', './snapcraft.yaml')
|
||||||
|
|
||||||
|
print('File updated! Please manually inspect the changes '
|
||||||
|
'and commit them via git.')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
32
tox.ini
32
tox.ini
|
@ -53,6 +53,38 @@ commands =
|
||||||
flake8 {toxinidir}/tests/
|
flake8 {toxinidir}/tests/
|
||||||
{toxinidir}/tests/test_basic.py
|
{toxinidir}/tests/test_basic.py
|
||||||
|
|
||||||
|
[testenv:eoan]
|
||||||
|
# Just run basic_test.sh, with multipass support, on eoan.
|
||||||
|
# TODO: refactor so that there isn't so much copypasta here and below.
|
||||||
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
|
setenv =
|
||||||
|
MULTIPASS=true
|
||||||
|
DISTRO=eoan
|
||||||
|
|
||||||
|
commands =
|
||||||
|
{toxinidir}/tools/basic_setup.sh
|
||||||
|
flake8 {toxinidir}/tests/
|
||||||
|
{toxinidir}/tests/test_basic.py
|
||||||
|
|
||||||
|
[testenv:disco]
|
||||||
|
# Just run basic_test.sh, with multipass support, on disco.
|
||||||
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
|
setenv =
|
||||||
|
MULTIPASS=true
|
||||||
|
DISTRO=disco
|
||||||
|
|
||||||
|
[testenv:xenial]
|
||||||
|
# Just run basic_test.sh, with multipass support, on xenial.
|
||||||
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
|
setenv =
|
||||||
|
MULTIPASS=true
|
||||||
|
DISTRO=xenial
|
||||||
|
|
||||||
|
commands =
|
||||||
|
{toxinidir}/tools/basic_setup.sh
|
||||||
|
flake8 {toxinidir}/tests/
|
||||||
|
{toxinidir}/tests/test_basic.py
|
||||||
|
|
||||||
[testenv:cluster]
|
[testenv:cluster]
|
||||||
# Test out clustering!
|
# Test out clustering!
|
||||||
# Requires multipass.
|
# Requires multipass.
|
||||||
|
|
Loading…
Reference in New Issue