Skip to content

Commit 712fa9c

Browse files
lsimonswilderrodrigues
authored andcommitted
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.
1 parent 295e2ca commit 712fa9c

File tree

4 files changed

+172
-16
lines changed

4 files changed

+172
-16
lines changed

test/systemvm/__init__.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def check_output(*popenargs, **kwargs):
4343
return output
4444
subprocess.check_output = check_output
4545

46+
import logging
47+
logging.getLogger('paramiko.transport').setLevel(logging.WARNING)
4648

4749
from vagrant import Vagrant
4850
from unittest import TestCase
@@ -57,6 +59,7 @@ def check_output(*popenargs, **kwargs):
5759
from nose.plugins.attrib import attr
5860

5961
import os.path
62+
import sys
6063

6164

6265
_defaultVagrantDir = os.path.abspath(os.path.join(
@@ -180,7 +183,36 @@ def setUp(self):
180183
# env.host_string = self._env_host_string_orig
181184

182185

183-
def has_line(location, line):
186+
def has_line(location, line, ctx=3):
184187
with hide("everything"):
185188
text = run('cat "%s"' % location)
186-
return text.find(line) >= 0
189+
text_len = len(text)
190+
pos = text.find(line)
191+
if pos < 0:
192+
return False, ''
193+
start = end = pos
194+
newlines = 0
195+
while start > 0:
196+
if text[start] == '\n':
197+
newlines += 1
198+
if newlines > ctx:
199+
break
200+
start -= 1
201+
newlines = 0
202+
while end < text_len:
203+
if text[end] == '\n':
204+
newlines += 1
205+
if newlines > ctx:
206+
break
207+
end += 1
208+
context = '...\n' + text[start:end].strip() + '\n...'
209+
return True, context
210+
211+
212+
def print_doc(name, data, target=None):
213+
if target is None:
214+
target = sys.stdout
215+
print >>target, " ", "-" * 4, name, "-" * max(68-4-2-len(name), 0)
216+
for line in data.split('\n'):
217+
print >>target, " ", line
218+
print >>target, " ", "-" * 68

test/systemvm/test_hello_systemvm.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,38 @@
1717

1818
"""Example of using paramiko and envassert for systemvm tests."""
1919

20-
from nose.plugins.attrib import attr
20+
# from nose.plugins.attrib import attr
2121
from envassert import file, package, user
2222
from cuisine import file_write
2323
try:
24-
from . import SystemVMTestCase, has_line
24+
from . import SystemVMTestCase, has_line, print_doc
2525
except (ImportError, ValueError):
26-
from systemvm import SystemVMTestCase, has_line
26+
from systemvm import SystemVMTestCase, has_line, print_doc
2727

2828

2929
class HelloSystemVMTestCase(SystemVMTestCase):
30-
@attr(tags=["systemvm"], required_hardware="true")
31-
def test_hello_systemvm_paramiko(self):
30+
# @attr(tags=["systemvm"], required_hardware="true")
31+
def disabled_hello_systemvm_paramiko(self):
3232
"""Test we can connect to the systemvm over ssh, low-level with paramiko"""
3333
stdin, stdout, stderr = self.sshClient.exec_command('echo hello')
3434
result = stdout.read().strip()
3535
self.assertEqual('hello', result)
3636

37-
@attr(tags=["systemvm"], required_hardware="true")
38-
def test_hello_systemvm_envassert(self):
37+
# @attr(tags=["systemvm"], required_hardware="true")
38+
def disabled_test_hello_systemvm_envassert(self):
3939
"""Test we can run envassert assertions on the systemvm"""
4040
assert file.exists('/etc/hosts')
4141

4242
for packageName in ['dnsmasq', 'haproxy', 'keepalived', 'curl']:
43-
assert package.installed(packageName)
43+
assert package.installed(packageName), 'package %s should be installed' % packageName
4444

45-
assert user.exists('cloud')
45+
assert user.exists('cloud'), 'user cloud should exist'
4646

47-
@attr(tags=["systemvm"], required_hardware="true")
48-
def test_hello_systemvm_cuisine(self):
47+
# @attr(tags=["systemvm"], required_hardware="true")
48+
def disabled_hello_systemvm_cuisine(self):
4949
"""Test we can run cuisine on the systemvm"""
5050
file_write('/tmp/run_cuisine', '\n\nsuccess!\n')
51-
assert has_line('/tmp/run_cuisine', 'success!')
51+
found, context = has_line('/tmp/run_cuisine', 'success!')
52+
if not found:
53+
print_doc('/tmp/cuisine', context)
54+
assert found, '/tmp/run_cuisine should contain "success!"'
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
"""Basic integration test that runs update_config.py."""
19+
20+
from nose.plugins.attrib import attr
21+
from cuisine import file_write, run
22+
from fabric.api import hide
23+
import json
24+
import random
25+
import datetime
26+
27+
try:
28+
from . import SystemVMTestCase, has_line, print_doc
29+
except (ImportError, ValueError):
30+
from systemvm import SystemVMTestCase, has_line, print_doc
31+
32+
33+
def deep_copy(obj):
34+
return json.loads(json.dumps(obj))
35+
36+
37+
class UpdateConfigTestCase(SystemVMTestCase):
38+
basic_config = {
39+
"ip_address": [
40+
{
41+
"public_ip": "10.0.2.102",
42+
"source_nat": True,
43+
"add": True,
44+
"one_to_one_nat": False,
45+
"first_i_p": False,
46+
"gateway": "10.0.2.1",
47+
"netmask": "255.255.255.0",
48+
"vif_mac_address": "06:cb:aa:00:00:03",
49+
"nic_dev_id": 1,
50+
"new_nic": False
51+
}
52+
],
53+
"type": "ips"
54+
}
55+
56+
def update_config(self, config):
57+
config_json = json.dumps(config, indent=2)
58+
print_doc('config.json', config_json)
59+
file_write('/etc/cloudstack/update_config_test.json', config_json)
60+
with hide("everything"):
61+
result = run("python /opt/cloud/bin/update_config.py update_config_test.json",
62+
timeout=600, warn_only=True)
63+
print result
64+
assert result.succeeded, 'update_config.py ran without errors'
65+
assert result.find("Convergence is achieved") >= 0, 'update_config.py should report convergence'
66+
67+
def clear_log(self):
68+
tstamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
69+
run("test -f /var/log/cloud.log && mv /var/log/cloud.log /var/log/cloud.log.%s || true" % tstamp)
70+
71+
def setUp(self):
72+
super(UpdateConfigTestCase, self).setUp()
73+
self.clear_log()
74+
75+
def check_no_errors(self):
76+
# todo config update should exit 1 on convergence errors!
77+
found, context = has_line('/var/log/cloud.log', 'cannot be configured')
78+
if found:
79+
print_doc('/var/log/cloud.log', context)
80+
assert not found, 'cloud.log should not contain "cannot be configured"'
81+
82+
@attr(tags=["systemvm"], required_hardware="true")
83+
def test_basic_config(self):
84+
self.update_config(self.basic_config)
85+
self.check_no_errors()
86+
# should be able to run twice with same config
87+
self.clear_log()
88+
self.update_config(self.basic_config)
89+
self.check_no_errors()
90+
91+
@attr(tags=["systemvm"], required_hardware="true")
92+
def test_various_random_ip_addresses(self):
93+
r = random.Random()
94+
r.seed()
95+
for i in range(0, 10):
96+
# todo need to know what kind of configurations are valid!
97+
config = deep_copy(self.basic_config)
98+
ip_address = deep_copy(self.basic_config["ip_address"][0])
99+
ip_address["public_ip"] = "10.0.2.%d" % (i + 103,)
100+
ip_address["source_nat"] = r.choice((True, False))
101+
ip_address["add"] = r.choice((True, False))
102+
ip_address["one_to_one_nat"] = r.choice((True, False))
103+
ip_address["first_i_p"] = r.choice((True, False))
104+
ip_address["nic_dev_id"] = r.choice((0, 1, 2))
105+
if ip_address["nic_dev_id"] > 0:
106+
ip_address["new_nic"] = True
107+
else:
108+
ip_address["new_nic"] = False
109+
config["ip_address"].append(ip_address)
110+
# runs a bunch of times adding an IP address each time
111+
self.update_config(config)
112+
self.check_no_errors()
113+
self.clear_log()
114+
# run again with just the basic config; this should remove the IP addresses?
115+
self.update_config(self.basic_config)
116+
117+
118+
if __name__ == '__main__':
119+
import unittest
120+
unittest.main()

tools/vagrant/systemvm/Vagrantfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
7878
'config/opt' => '/opt',
7979
'config/root' => '/root',
8080
'config/var' => '/var',
81-
'vpn/etc' => '/etc',
82-
'vpn/opt' => '/opt',
81+
# cannot have two rsyncs pointing to the same dir
82+
# 'vpn/etc' => '/etc',
83+
# 'vpn/opt' => '/opt',
8384
'xe' => '/usr/sbin'
8485
}
8586

0 commit comments

Comments
 (0)