mirror of https://github.com/apache/cloudstack.git
Tests for update_config.py
These are failing on my machine with cloud.log lines like 2014-08-07 14:34:09,509 Add dev eth2 table Table_eth2 10.0.2.0/24 2014-08-07 14:34:09,511 Address 10.0.2.106/24 on device eth2 not configured 2014-08-07 14:34:10,513 Device eth2 cannot be configured - device was not found I think it's correct that they are failing -- this is work in progress.
This commit is contained in:
parent
295e2caff0
commit
712fa9c92c
|
|
@ -43,6 +43,8 @@ except (NameError, ImportError):
|
|||
return output
|
||||
subprocess.check_output = check_output
|
||||
|
||||
import logging
|
||||
logging.getLogger('paramiko.transport').setLevel(logging.WARNING)
|
||||
|
||||
from vagrant import Vagrant
|
||||
from unittest import TestCase
|
||||
|
|
@ -57,6 +59,7 @@ from StringIO import StringIO
|
|||
from nose.plugins.attrib import attr
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
|
||||
_defaultVagrantDir = os.path.abspath(os.path.join(
|
||||
|
|
@ -180,7 +183,36 @@ class SystemVMTestCase(TestCase):
|
|||
# env.host_string = self._env_host_string_orig
|
||||
|
||||
|
||||
def has_line(location, line):
|
||||
def has_line(location, line, ctx=3):
|
||||
with hide("everything"):
|
||||
text = run('cat "%s"' % location)
|
||||
return text.find(line) >= 0
|
||||
text_len = len(text)
|
||||
pos = text.find(line)
|
||||
if pos < 0:
|
||||
return False, ''
|
||||
start = end = pos
|
||||
newlines = 0
|
||||
while start > 0:
|
||||
if text[start] == '\n':
|
||||
newlines += 1
|
||||
if newlines > ctx:
|
||||
break
|
||||
start -= 1
|
||||
newlines = 0
|
||||
while end < text_len:
|
||||
if text[end] == '\n':
|
||||
newlines += 1
|
||||
if newlines > ctx:
|
||||
break
|
||||
end += 1
|
||||
context = '...\n' + text[start:end].strip() + '\n...'
|
||||
return True, context
|
||||
|
||||
|
||||
def print_doc(name, data, target=None):
|
||||
if target is None:
|
||||
target = sys.stdout
|
||||
print >>target, " ", "-" * 4, name, "-" * max(68-4-2-len(name), 0)
|
||||
for line in data.split('\n'):
|
||||
print >>target, " ", line
|
||||
print >>target, " ", "-" * 68
|
||||
|
|
|
|||
|
|
@ -17,35 +17,38 @@
|
|||
|
||||
"""Example of using paramiko and envassert for systemvm tests."""
|
||||
|
||||
from nose.plugins.attrib import attr
|
||||
# from nose.plugins.attrib import attr
|
||||
from envassert import file, package, user
|
||||
from cuisine import file_write
|
||||
try:
|
||||
from . import SystemVMTestCase, has_line
|
||||
from . import SystemVMTestCase, has_line, print_doc
|
||||
except (ImportError, ValueError):
|
||||
from systemvm import SystemVMTestCase, has_line
|
||||
from systemvm import SystemVMTestCase, has_line, print_doc
|
||||
|
||||
|
||||
class HelloSystemVMTestCase(SystemVMTestCase):
|
||||
@attr(tags=["systemvm"], required_hardware="true")
|
||||
def test_hello_systemvm_paramiko(self):
|
||||
# @attr(tags=["systemvm"], required_hardware="true")
|
||||
def disabled_hello_systemvm_paramiko(self):
|
||||
"""Test we can connect to the systemvm over ssh, low-level with paramiko"""
|
||||
stdin, stdout, stderr = self.sshClient.exec_command('echo hello')
|
||||
result = stdout.read().strip()
|
||||
self.assertEqual('hello', result)
|
||||
|
||||
@attr(tags=["systemvm"], required_hardware="true")
|
||||
def test_hello_systemvm_envassert(self):
|
||||
# @attr(tags=["systemvm"], required_hardware="true")
|
||||
def disabled_test_hello_systemvm_envassert(self):
|
||||
"""Test we can run envassert assertions on the systemvm"""
|
||||
assert file.exists('/etc/hosts')
|
||||
|
||||
for packageName in ['dnsmasq', 'haproxy', 'keepalived', 'curl']:
|
||||
assert package.installed(packageName)
|
||||
assert package.installed(packageName), 'package %s should be installed' % packageName
|
||||
|
||||
assert user.exists('cloud')
|
||||
assert user.exists('cloud'), 'user cloud should exist'
|
||||
|
||||
@attr(tags=["systemvm"], required_hardware="true")
|
||||
def test_hello_systemvm_cuisine(self):
|
||||
# @attr(tags=["systemvm"], required_hardware="true")
|
||||
def disabled_hello_systemvm_cuisine(self):
|
||||
"""Test we can run cuisine on the systemvm"""
|
||||
file_write('/tmp/run_cuisine', '\n\nsuccess!\n')
|
||||
assert has_line('/tmp/run_cuisine', 'success!')
|
||||
found, context = has_line('/tmp/run_cuisine', 'success!')
|
||||
if not found:
|
||||
print_doc('/tmp/cuisine', context)
|
||||
assert found, '/tmp/run_cuisine should contain "success!"'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
|
||||
"""Basic integration test that runs update_config.py."""
|
||||
|
||||
from nose.plugins.attrib import attr
|
||||
from cuisine import file_write, run
|
||||
from fabric.api import hide
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
|
||||
try:
|
||||
from . import SystemVMTestCase, has_line, print_doc
|
||||
except (ImportError, ValueError):
|
||||
from systemvm import SystemVMTestCase, has_line, print_doc
|
||||
|
||||
|
||||
def deep_copy(obj):
|
||||
return json.loads(json.dumps(obj))
|
||||
|
||||
|
||||
class UpdateConfigTestCase(SystemVMTestCase):
|
||||
basic_config = {
|
||||
"ip_address": [
|
||||
{
|
||||
"public_ip": "10.0.2.102",
|
||||
"source_nat": True,
|
||||
"add": True,
|
||||
"one_to_one_nat": False,
|
||||
"first_i_p": False,
|
||||
"gateway": "10.0.2.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"vif_mac_address": "06:cb:aa:00:00:03",
|
||||
"nic_dev_id": 1,
|
||||
"new_nic": False
|
||||
}
|
||||
],
|
||||
"type": "ips"
|
||||
}
|
||||
|
||||
def update_config(self, config):
|
||||
config_json = json.dumps(config, indent=2)
|
||||
print_doc('config.json', config_json)
|
||||
file_write('/etc/cloudstack/update_config_test.json', config_json)
|
||||
with hide("everything"):
|
||||
result = run("python /opt/cloud/bin/update_config.py update_config_test.json",
|
||||
timeout=600, warn_only=True)
|
||||
print result
|
||||
assert result.succeeded, 'update_config.py ran without errors'
|
||||
assert result.find("Convergence is achieved") >= 0, 'update_config.py should report convergence'
|
||||
|
||||
def clear_log(self):
|
||||
tstamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
run("test -f /var/log/cloud.log && mv /var/log/cloud.log /var/log/cloud.log.%s || true" % tstamp)
|
||||
|
||||
def setUp(self):
|
||||
super(UpdateConfigTestCase, self).setUp()
|
||||
self.clear_log()
|
||||
|
||||
def check_no_errors(self):
|
||||
# todo config update should exit 1 on convergence errors!
|
||||
found, context = has_line('/var/log/cloud.log', 'cannot be configured')
|
||||
if found:
|
||||
print_doc('/var/log/cloud.log', context)
|
||||
assert not found, 'cloud.log should not contain "cannot be configured"'
|
||||
|
||||
@attr(tags=["systemvm"], required_hardware="true")
|
||||
def test_basic_config(self):
|
||||
self.update_config(self.basic_config)
|
||||
self.check_no_errors()
|
||||
# should be able to run twice with same config
|
||||
self.clear_log()
|
||||
self.update_config(self.basic_config)
|
||||
self.check_no_errors()
|
||||
|
||||
@attr(tags=["systemvm"], required_hardware="true")
|
||||
def test_various_random_ip_addresses(self):
|
||||
r = random.Random()
|
||||
r.seed()
|
||||
for i in range(0, 10):
|
||||
# todo need to know what kind of configurations are valid!
|
||||
config = deep_copy(self.basic_config)
|
||||
ip_address = deep_copy(self.basic_config["ip_address"][0])
|
||||
ip_address["public_ip"] = "10.0.2.%d" % (i + 103,)
|
||||
ip_address["source_nat"] = r.choice((True, False))
|
||||
ip_address["add"] = r.choice((True, False))
|
||||
ip_address["one_to_one_nat"] = r.choice((True, False))
|
||||
ip_address["first_i_p"] = r.choice((True, False))
|
||||
ip_address["nic_dev_id"] = r.choice((0, 1, 2))
|
||||
if ip_address["nic_dev_id"] > 0:
|
||||
ip_address["new_nic"] = True
|
||||
else:
|
||||
ip_address["new_nic"] = False
|
||||
config["ip_address"].append(ip_address)
|
||||
# runs a bunch of times adding an IP address each time
|
||||
self.update_config(config)
|
||||
self.check_no_errors()
|
||||
self.clear_log()
|
||||
# run again with just the basic config; this should remove the IP addresses?
|
||||
self.update_config(self.basic_config)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import unittest
|
||||
unittest.main()
|
||||
|
|
@ -78,8 +78,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|||
'config/opt' => '/opt',
|
||||
'config/root' => '/root',
|
||||
'config/var' => '/var',
|
||||
'vpn/etc' => '/etc',
|
||||
'vpn/opt' => '/opt',
|
||||
# cannot have two rsyncs pointing to the same dir
|
||||
# 'vpn/etc' => '/etc',
|
||||
# 'vpn/opt' => '/opt',
|
||||
'xe' => '/usr/sbin'
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue