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
|
||||
confinement: classic
|
||||
environment:
|
||||
LD_LIBRARY_PATH: $SNAP/lib:$SNAP/lib/$SNAPCRAFT_ARCH_TRIPLET:$SNAP/usr/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET
|
||||
PATH: $SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:/snap/core18/current/bin:$PATH
|
||||
# Edit the following lines with tools/update_path.py
|
||||
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
|
||||
OS_PLACEMENT_CONFIG_DIR: $SNAP/etc/nova/
|
||||
|
||||
@ -219,8 +220,6 @@ apps:
|
||||
libvirtd:
|
||||
command: libvirtd
|
||||
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:
|
||||
command: virtlogd
|
||||
daemon: simple
|
||||
|
@ -72,10 +72,11 @@ class Framework(unittest.TestCase):
|
||||
|
||||
self.MACHINE = petname.generate()
|
||||
self.PREFIX = ['multipass', 'exec', self.MACHINE, '--']
|
||||
distro = os.environ.get('DISTRO') or self.DISTRO
|
||||
|
||||
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)
|
||||
check('multipass', 'copy-files', self.SNAP, '{}:'.format(self.MACHINE))
|
||||
|
||||
|
@ -14,8 +14,10 @@ Web IDE.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
import xvfbwrapper
|
||||
from selenium import webdriver
|
||||
@ -50,7 +52,7 @@ class TestBasics(Framework):
|
||||
|
||||
"""
|
||||
launch = '/snap/bin/microstack.launch'
|
||||
# openstack = '/snap/bin/microstack.openstack'
|
||||
openstack = '/snap/bin/microstack.openstack'
|
||||
|
||||
print("Testing microstack.launch ...")
|
||||
|
||||
@ -66,6 +68,55 @@ class TestBasics(Framework):
|
||||
# Endpoints should not contain localhost
|
||||
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:
|
||||
print("Opening {}:80 up to the outside world".format(
|
||||
self.HORIZON_IP))
|
||||
|
@ -291,12 +291,10 @@ class RabbitMq(Question):
|
||||
|
||||
(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
|
||||
call('rabbitmqctl', 'add_user', 'openstack', 'rabbitmq', env=env)
|
||||
shell('rabbitmqctl set_permissions openstack ".*" ".*" ".*"', env=env)
|
||||
call('microstack.rabbitmqctl', 'add_user', 'openstack', 'rabbitmq')
|
||||
shell(
|
||||
'microstack.rabbitmqctl set_permissions openstack ".*" ".*" ".*"')
|
||||
|
||||
def yes(self, answer: str) -> None:
|
||||
log.info('Waiting for RabbitMQ to start ...')
|
||||
@ -692,20 +690,18 @@ class KeyPair(Question):
|
||||
def yes(self, answer: str) -> None:
|
||||
|
||||
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))
|
||||
check('mkdir', '-p', '{HOME}/.ssh'.format(**_env))
|
||||
check('chmod', '700', '{HOME}/.ssh'.format(**_env))
|
||||
check('mkdir', '-p', '{home}/.ssh'.format(home=home))
|
||||
check('chmod', '700', '{home}/.ssh'.format(home=home))
|
||||
id_ = check_output('openstack', 'keypair', 'create', 'microstack')
|
||||
id_path = '{HOME}/.ssh/{answer}'.format(
|
||||
HOME=_env['HOME'],
|
||||
answer=answer
|
||||
)
|
||||
id_path = '{home}/.ssh/{answer}'.format(home=home, answer=answer)
|
||||
|
||||
with open(id_path, 'w') as file_:
|
||||
file_.write(id_)
|
||||
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)
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@ from typing import Dict, List
|
||||
import netaddr
|
||||
import netifaces
|
||||
import pymysql
|
||||
import socket
|
||||
import wget
|
||||
|
||||
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,
|
||||
stderr=subprocess.STDOUT, bufsize=1,
|
||||
universal_newlines=True, shell=True,
|
||||
executable='/snap/core18/current/bin/bash')
|
||||
universal_newlines=True, shell=True)
|
||||
for line in iter(proc.stdout.readline, ''):
|
||||
log.debug(line)
|
||||
proc.wait()
|
||||
if proc.returncode:
|
||||
raise subprocess.CalledProcessError(
|
||||
"Command '{}' returned non-zero exit status {}".format(
|
||||
cmd,
|
||||
proc.returncode))
|
||||
raise subprocess.CalledProcessError(proc.returncode, cmd)
|
||||
return proc.returncode
|
||||
|
||||
|
||||
@ -141,7 +138,8 @@ def sql(cmd: str) -> None:
|
||||
def nc_wait(addr: str, port: str) -> None:
|
||||
"""Wait for a service to be answering on a 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)
|
||||
|
||||
|
||||
|
85
tools/update_path.py
Executable file
85
tools/update_path.py
Executable file
@ -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/
|
||||
{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]
|
||||
# Test out clustering!
|
||||
# Requires multipass.
|
||||
|
Loading…
x
Reference in New Issue
Block a user