Merge lp:~javier.collado/utah/bug1178367 into lp:utah

Proposed by Javier Collado
Status: Merged
Merged at revision: 904
Proposed branch: lp:~javier.collado/utah/bug1178367
Merge into: lp:utah
Diff against target: 680 lines (+78/-348)
6 files modified
debian/changelog (+2/-0)
debian/control (+1/-9)
debian/rules (+1/-9)
examples/run_utah_tests.py (+2/-108)
tests/test_parser.py (+72/-0)
utah/parser.py (+0/-222)
To merge this branch: bzr merge lp:~javier.collado/utah/bug1178367
Reviewer Review Type Date Requested Status
Andy Doan (community) Approve
Review via email: mp+163339@code.launchpad.net

Description of the change

This branch fixes the parsing of the gigabytes option and adds a few test cases
to verify this.

Besides this, the `utah.parser` module and the `utah-parser` package are
removed since they aren't used anymore. The `utah.parser` module is now used to
have there the parser for the utah server script since that makes unit testing
easier.

To post a comment you must log in.
Revision history for this message
Andy Doan (doanac) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2013-05-09 23:36:07 +0000
+++ debian/changelog 2013-05-10 16:56:25 +0000
@@ -8,6 +8,8 @@
8 * Apply retry strategy to install UTAH client package (LP: #1175732)8 * Apply retry strategy to install UTAH client package (LP: #1175732)
9 * Added phoenix manpage (LP: #1067704)9 * Added phoenix manpage (LP: #1067704)
10 * Apply all overrides in tslist.run to the test cases (LP: #1178238)10 * Apply all overrides in tslist.run to the test cases (LP: #1178238)
11 * Set disksizes default directly instead of via argparse (LP:
12 #1178367)
1113
12 -- Javier Collado <javier.collado@canonical.com> Tue, 07 May 2013 16:06:48 +020014 -- Javier Collado <javier.collado@canonical.com> Tue, 07 May 2013 16:06:48 +0200
1315
1416
=== modified file 'debian/control'
--- debian/control 2013-05-08 14:45:47 +0000
+++ debian/control 2013-05-10 16:56:25 +0000
@@ -23,8 +23,7 @@
2323
24Package: utah-all24Package: utah-all
25Architecture: all25Architecture: all
26Depends: ${misc:Depends}, ${python:Depends}, utah-bamboofeeder, utah-cobbler,26Depends: ${misc:Depends}, ${python:Depends}, utah-bamboofeeder, utah-cobbler
27 utah-parser
28Description: Ubuntu Test Automation Harness Complete Package27Description: Ubuntu Test Automation Harness Complete Package
29 Automation framework for testing in Ubuntu, all sections28 Automation framework for testing in Ubuntu, all sections
3029
@@ -59,10 +58,3 @@
59Depends: ${misc:Depends}, ${python:Depends}58Depends: ${misc:Depends}, ${python:Depends}
60Description: Ubuntu Test Automation Harness Common Files59Description: Ubuntu Test Automation Harness Common Files
61 Automation framework for testing in Ubuntu, common files60 Automation framework for testing in Ubuntu, common files
62
63Package: utah-parser
64Architecture: all
65Depends: ${misc:Depends}, ${python:Depends},
66 python-jsonschema (>= 1.3~), python-yaml, utah-common
67Description: Ubuntu Test Automation Harness Parser
68 Automation framework for testing in Ubuntu, result parser
6961
=== modified file 'debian/rules'
--- debian/rules 2013-05-08 13:28:00 +0000
+++ debian/rules 2013-05-10 16:56:25 +0000
@@ -34,18 +34,14 @@
3434
35override_dh_auto_install:35override_dh_auto_install:
36 # utah and utah-client both live in the utah directory36 # utah and utah-client both live in the utah directory
37 # utah-parser lives in that tree as well
38 # utah should only install the provisioning subdirectory, and utah-client should install everything else37 # utah should only install the provisioning subdirectory, and utah-client should install everything else
39 # except parser.py, which is now its own package38 # except __init__.py, which is now in the common package
40 # and __init__.py, which is now in the common package
41 # The baremetal subdirectory in the provisioning directory is now 3 packages39 # The baremetal subdirectory in the provisioning directory is now 3 packages
42 # If we just use dh_auto_install, all packages will get everything40 # If we just use dh_auto_install, all packages will get everything
43 # We start by building the whole thing41 # We start by building the whole thing
44 set -e && for pyvers in $(PYVERS); do python$$pyvers setup.py install --install-layout=deb --root=$(CURDIR); done42 set -e && for pyvers in $(PYVERS); do python$$pyvers setup.py install --install-layout=deb --root=$(CURDIR); done
45 # Next, we move the built provisioning directory aside for later use43 # Next, we move the built provisioning directory aside for later use
46 mv build/*/utah/provisioning .44 mv build/*/utah/provisioning .
47 # Same with parser.py
48 mv build/*/utah/parser.py .
49 # And __init__.py45 # And __init__.py
50 mv build/*/utah/__init__.py .46 mv build/*/utah/__init__.py .
51 # Now we install into the utah-client directory, since provisioning is removed, using --skip-build to not rebuild it47 # Now we install into the utah-client directory, since provisioning is removed, using --skip-build to not rebuild it
@@ -58,10 +54,6 @@
58 mv build/*/utah/provisioning/baremetal .54 mv build/*/utah/provisioning/baremetal .
59 # Now we install just the provisioning directory, again using --skip-build into the utah package tree55 # Now we install just the provisioning directory, again using --skip-build into the utah package tree
60 set -e && for pyvers in $(PYVERS); do python$$pyvers setup.py install --skip-build --install-layout=deb --root=$(CURDIR)/debian/utah; done56 set -e && for pyvers in $(PYVERS); do python$$pyvers setup.py install --skip-build --install-layout=deb --root=$(CURDIR)/debian/utah; done
61 # And now we put back the parser and install that
62 rm -r build/*/utah/*
63 mv parser.py build/*/utah
64 set -e && for pyvers in $(PYVERS); do python$$pyvers setup.py install --skip-build --install-layout=deb --root=$(CURDIR)/debian/utah-parser; done
65 # And now we put back the init file and install that57 # And now we put back the init file and install that
66 rm -r build/*/utah/*58 rm -r build/*/utah/*
67 mv __init__.py build/*/utah59 mv __init__.py build/*/utah
6860
=== modified file 'examples/run_utah_tests.py'
--- examples/run_utah_tests.py 2013-05-01 23:57:13 +0000
+++ examples/run_utah_tests.py 2013-05-10 16:56:25 +0000
@@ -17,8 +17,6 @@
1717
18"""Provision a machine a run a test."""18"""Provision a machine a run a test."""
1919
20
21import argparse
22import logging20import logging
23import os21import os
24import sys22import sys
@@ -31,16 +29,15 @@
31from utah.cleanup import cleanup29from utah.cleanup import cleanup
32from utah.exceptions import UTAHException30from utah.exceptions import UTAHException
33from utah.group import check_user_group, print_group_error_message31from utah.group import check_user_group, print_group_error_message
32from utah.parser import get_parser, parse_args # NOQA
34from utah.provisioning.ssh import ProvisionedMachine33from utah.provisioning.ssh import ProvisionedMachine
35from utah.provisioning.vm import TinySQLiteInventory34from utah.provisioning.vm import TinySQLiteInventory
36from utah.run import (35from utah.run import (
37 configure_logging,36 configure_logging,
38 master_runlist_argument,
39 run_tests,37 run_tests,
40 ReturnCodes,38 ReturnCodes,
41)39)
42from utah.timeout import timeout, UTAHTimeout40from utah.timeout import timeout, UTAHTimeout
43from utah.url import url_argument
4441
4542
46MISSING = []43MISSING = []
@@ -59,108 +56,6 @@
59 MISSING.append('baremetal')56 MISSING.append('baremetal')
6057
6158
62def get_parser():
63 parser = argparse.ArgumentParser(
64 description=('Provision a machine '
65 'and run one or more UTAH runlists there.\n\n'
66 'The appropriate run_*.py script will be called, '
67 'depending on the parameters passed.'),
68 epilog=("For example:\n"
69 "Provision a VM using a precise server image "
70 "with i386 architecture and run the given runlist\n"
71 "\t%(prog)s -s precise -t server -a i386 \\\n"
72 "\t\t/usr/share/utah/client/examples/master.run"),
73 formatter_class=argparse.RawDescriptionHelpFormatter)
74 parser.add_argument('-m', '--machinetype', metavar='MACHINETYPE',
75 choices=('physical', 'virtual'),
76 default=config.machinetype,
77 help='Type of machine to provision (%(choices)s) '
78 '(Default is %(default)s)')
79 parser.add_argument('-v', '--variant',
80 default=config.variant,
81 help='Variant of architecture, i.e., armel, armhf')
82 parser.add_argument('--skip-provisioning', action='store_true',
83 help='Reuse a system that is already provisioned '
84 '(name argument must be passed)')
85 parser.add_argument('runlist', metavar='runlist',
86 type=master_runlist_argument,
87 help='URLs of runlist files to run')
88 parser.add_argument('-s', '--series', metavar='SERIES',
89 choices=config.serieschoices,
90 default=config.series,
91 help='Series to use for installation (%(choices)s) '
92 '(Default is %(default)s)')
93 parser.add_argument('-t', '--type', metavar='TYPE',
94 choices=('desktop', 'server', 'mini', 'alternate'),
95 default=config.installtype,
96 help='Install type to use for installation '
97 '(%(choices)s) (Default is %(default)s)')
98 parser.add_argument('-a', '--arch', metavar='ARCH',
99 choices=('i386', 'amd64', 'arm'),
100 default=config.arch,
101 help='Architecture to use for installation '
102 '(%(choices)s) (Default is %(default)s)')
103 parser.add_argument('-n', '--no-destroy', action='store_true',
104 help='Preserve VM after tests have run')
105 parser.add_argument('-d', '--debug', action='store_true',
106 help='Enable debug logging')
107 parser.add_argument('-j', '--json', action='store_true',
108 help='Enable json logging (default is YAML)')
109 parser.add_argument('-f', '--files', action='append',
110 help='File or directory to copy from test system ')
111 parser.add_argument('-o', '--outdir',
112 help=('Directory to store locally copied files '
113 '(Default is {}/machine-name)'
114 .format(config.logpath)))
115 parser.add_argument('--dumplogs', action='store_true',
116 help='Write client output logs to standard out')
117 parser.add_argument('--outputpreseed', action='store_true',
118 help='Copy preseed to logs directory and list as '
119 'log file in output')
120 parser.add_argument('-i', '--image', type=url_argument,
121 default=config.image,
122 help='Image/ISO file to use for installation')
123 parser.add_argument('-p', '--preseed', type=url_argument,
124 default=config.preseed,
125 help='Preseed file to use for installation')
126 parser.add_argument('-b', '--boot',
127 default=config.boot,
128 help='Boot arguments for initial installation')
129 parser.add_argument('--rewrite',
130 choices=('all', 'minimal', 'casperonly', 'none'),
131 default=config.rewrite,
132 help='Set level of automatic configuration rewriting '
133 '(Default is %(default)s)')
134 parser.add_argument('-k', '--kernel', type=url_argument,
135 default=config.kernel,
136 help='Kernel file to use for installation')
137 parser.add_argument('-r', '--initrd', type=url_argument,
138 default=config.initrd,
139 help='InitRD file to use for installation')
140 parser.add_argument('--name',
141 default=config.name,
142 help='Name of machine to provision')
143 parser.add_argument('-e', '--emulator',
144 default=config.emulator,
145 help='Emulator to use (kvm and qemu are supported, '
146 'kvm will be favored if available)')
147 parser.add_argument('-x', '--xml', type=url_argument,
148 default=config.xml,
149 help='XML VM definition file '
150 '(Default is %(default)s)')
151 parser.add_argument('-g', '--gigabytes', action='append',
152 default=config.disksizes,
153 help='Size in gigabytes of virtual disk, '
154 'specify more than once for multiple disks '
155 '(Default is %(default)s)')
156 parser.add_argument('--diskbus', metavar='DISKBUS',
157 choices=('virtio', 'sata', 'ide'),
158 default=config.diskbus,
159 help='Disk bus to use for customvm installation '
160 '(%(choices)s) (Default is %(default)s)')
161 return parser
162
163
164def _get_machine(args):59def _get_machine(args):
165 if args.skip_provisioning:60 if args.skip_provisioning:
166 # TBD: Inventory should be used to verify machine61 # TBD: Inventory should be used to verify machine
@@ -210,8 +105,7 @@
210105
211106
212def run_utah_tests(args=None):107def run_utah_tests(args=None):
213 if args is None:108 args = parse_args()
214 args = get_parser().parse_args()
215109
216 if not check_user_group():110 if not check_user_group():
217 print_group_error_message(__file__)111 print_group_error_message(__file__)
218112
=== added file 'tests/test_parser.py'
--- tests/test_parser.py 1970-01-01 00:00:00 +0000
+++ tests/test_parser.py 2013-05-10 16:56:25 +0000
@@ -0,0 +1,72 @@
1# Ubuntu Testing Automation Harness
2# Copyright 2013 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16"""Unit tests for the utah.parser module."""
17
18import unittest
19
20from mock import patch, DEFAULT
21
22from utah import config
23from utah.parser import parse_args
24
25
26class TestParser(unittest.TestCase):
27
28 """Tests that command line parsing works as expected."""
29
30 def parse_args_wrapper(self, argv):
31 """A wrapper to ensure that runlist argument passes validation.
32
33 :param argv: Command line arguments to be tested
34 :type argv: list
35 :returns: Parse arguments
36 :rtype: `argparse.Namespace`
37
38 """
39 with patch.multiple('utah.run',
40 url_argument=DEFAULT,
41 parse_yaml_file=DEFAULT) as patches:
42 patches['url_argument'].return_value = '<local_runlist_file>'
43 patches['parse_yaml_file'].return_value = {
44 'testsuites': [
45 {'name': 'test_suite_name',
46 'fetch_method': 'dev',
47 'fetch_location': '<fetch_location>',
48 },
49 ]
50 }
51 return parse_args(argv)
52
53 def test_gigabytes_default(self):
54 """Verify that gigabytes is set to default value if not passed."""
55 args = self.parse_args_wrapper(['<runlist_file>'])
56 self.assertEqual(args.gigabytes, config.disksizes)
57
58 def test_gigabytes_one_argument(self):
59 """Verify that gigabytes is set to the argument passed."""
60 gigabytes = '3'
61 args = self.parse_args_wrapper(['--gigabytes', gigabytes,
62 '<runlist_file>'])
63 self.assertEqual(args.gigabytes, [gigabytes])
64
65 def test_gigabytes_multiple_arguments(self):
66 """Verify that gigabytes is set to the arguments passed."""
67 gigabytes = ['3', '5', '7']
68 args = self.parse_args_wrapper(['--gigabytes', gigabytes[0],
69 '--gigabytes', gigabytes[1],
70 '--gigabytes', gigabytes[2],
71 '<runlist_file>'])
72 self.assertEqual(args.gigabytes, gigabytes)
073
=== added file 'utah/parser.py'
--- utah/parser.py 1970-01-01 00:00:00 +0000
+++ utah/parser.py 2013-05-10 16:56:25 +0000
@@ -0,0 +1,149 @@
1# Ubuntu Testing Automation Harness
2# Copyright 2012 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16"""Command line parser for the utah server script."""
17
18import argparse
19import sys
20
21from utah import config
22from utah.run import master_runlist_argument
23from utah.url import url_argument
24
25
26def parse_args(argv=None):
27 """Parse command line arguments.
28
29 :param argv: Command line arguments to be parsed
30 :type argv: list
31 :returns: Parse arguments
32 :rtype: `argparse.Namespace`
33
34 """
35
36 if argv is None:
37 argv = sys.argv[1:]
38
39 args = get_parser().parse_args(argv)
40 if args.gigabytes is None:
41 args.gigabytes = config.disksizes
42 return args
43
44
45def get_parser():
46 """Get command line parser.
47
48 :returns: Parser object
49 :rtype: `argparse.ArgumentParser`
50
51 """
52 parser = argparse.ArgumentParser(
53 description=('Provision a machine '
54 'and run one or more UTAH runlists there.\n\n'
55 'The appropriate run_*.py script will be called, '
56 'depending on the parameters passed.'),
57 epilog=("For example:\n"
58 "Provision a VM using a precise server image "
59 "with i386 architecture and run the given runlist\n"
60 "\t%(prog)s -s precise -t server -a i386 \\\n"
61 "\t\t/usr/share/utah/client/examples/master.run"),
62 formatter_class=argparse.RawDescriptionHelpFormatter)
63 parser.add_argument('-m', '--machinetype', metavar='MACHINETYPE',
64 choices=('physical', 'virtual'),
65 default=config.machinetype,
66 help='Type of machine to provision (%(choices)s) '
67 '(Default is %(default)s)')
68 parser.add_argument('-v', '--variant',
69 default=config.variant,
70 help='Variant of architecture, i.e., armel, armhf')
71 parser.add_argument('--skip-provisioning', action='store_true',
72 help='Reuse a system that is already provisioned '
73 '(name argument must be passed)')
74 parser.add_argument('runlist', metavar='runlist',
75 type=master_runlist_argument,
76 help='URLs of runlist files to run')
77 parser.add_argument('-s', '--series', metavar='SERIES',
78 choices=config.serieschoices,
79 default=config.series,
80 help='Series to use for installation (%(choices)s) '
81 '(Default is %(default)s)')
82 parser.add_argument('-t', '--type', metavar='TYPE',
83 choices=('desktop', 'server', 'mini', 'alternate'),
84 default=config.installtype,
85 help='Install type to use for installation '
86 '(%(choices)s) (Default is %(default)s)')
87 parser.add_argument('-a', '--arch', metavar='ARCH',
88 choices=('i386', 'amd64', 'arm'),
89 default=config.arch,
90 help='Architecture to use for installation '
91 '(%(choices)s) (Default is %(default)s)')
92 parser.add_argument('-n', '--no-destroy', action='store_true',
93 help='Preserve VM after tests have run')
94 parser.add_argument('-d', '--debug', action='store_true',
95 help='Enable debug logging')
96 parser.add_argument('-j', '--json', action='store_true',
97 help='Enable json logging (default is YAML)')
98 parser.add_argument('-f', '--files', action='append',
99 help='File or directory to copy from test system ')
100 parser.add_argument('-o', '--outdir',
101 help=('Directory to store locally copied files '
102 '(Default is {}/machine-name)'
103 .format(config.logpath)))
104 parser.add_argument('--dumplogs', action='store_true',
105 help='Write client output logs to standard out')
106 parser.add_argument('--outputpreseed', action='store_true',
107 help='Copy preseed to logs directory and list as '
108 'log file in output')
109 parser.add_argument('-i', '--image', type=url_argument,
110 default=config.image,
111 help='Image/ISO file to use for installation')
112 parser.add_argument('-p', '--preseed', type=url_argument,
113 default=config.preseed,
114 help='Preseed file to use for installation')
115 parser.add_argument('-b', '--boot',
116 default=config.boot,
117 help='Boot arguments for initial installation')
118 parser.add_argument('--rewrite',
119 choices=('all', 'minimal', 'casperonly', 'none'),
120 default=config.rewrite,
121 help='Set level of automatic configuration rewriting '
122 '(Default is %(default)s)')
123 parser.add_argument('-k', '--kernel', type=url_argument,
124 default=config.kernel,
125 help='Kernel file to use for installation')
126 parser.add_argument('-r', '--initrd', type=url_argument,
127 default=config.initrd,
128 help='InitRD file to use for installation')
129 parser.add_argument('--name',
130 default=config.name,
131 help='Name of machine to provision')
132 parser.add_argument('-e', '--emulator',
133 default=config.emulator,
134 help='Emulator to use (kvm and qemu are supported, '
135 'kvm will be favored if available)')
136 parser.add_argument('-x', '--xml', type=url_argument,
137 default=config.xml,
138 help='XML VM definition file '
139 '(Default is %(default)s)')
140 parser.add_argument('-g', '--gigabytes', action='append',
141 help='Size in gigabytes of virtual disk, '
142 'specify more than once for multiple disks '
143 '(Default is {})'.format(config.disksizes))
144 parser.add_argument('--diskbus', metavar='DISKBUS',
145 choices=('virtio', 'sata', 'ide'),
146 default=config.diskbus,
147 help='Disk bus to use for customvm installation '
148 '(%(choices)s) (Default is %(default)s)')
149 return parser
0150
=== removed file 'utah/parser.py'
--- utah/parser.py 2013-04-03 21:17:26 +0000
+++ utah/parser.py 1970-01-01 00:00:00 +0000
@@ -1,222 +0,0 @@
1# Ubuntu Testing Automation Harness
2# Copyright 2012 Canonical Ltd.
3
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License version 3, as published
6# by the Free Software Foundation.
7
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranties of
10# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11# PURPOSE. See the GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License along
14# with this program. If not, see <http://www.gnu.org/licenses/>.
15
16"""UTAH Client log parser."""
17
18
19import argparse
20import jsonschema
21import logging
22import urllib2
23import yaml
24
25
26class ParserError(Exception):
27
28 """Module level parse error exception."""
29
30 pass
31
32
33class UTAHParser(object):
34
35 """UTAH Client result parser class."""
36
37 COMMAND_SCHEMA = {
38 'type': 'object',
39 'properties': {
40 'cmd_type': {'type': 'string'},
41 'command': {'type': 'string'},
42 'returncode': {'type': 'integer'},
43 'start_time': {'type': 'string'},
44 'stderr': {'type': 'string'},
45 'stdout': {'type': 'string'},
46 'testcase': {'type': 'string'},
47 'testsuite': {'type': 'string'},
48 'time_delta': {'type': 'string'},
49 'user': {'type': 'string'},
50 },
51 }
52
53 CLIENT_OUTPUT_SCHEMA = {
54 'type': 'object',
55 'properties': {
56 'runlist': {
57 'type': 'string',
58 'required': True,
59 },
60 'ran_at': {
61 'type': 'string',
62 'required': True,
63 },
64 'commands': {
65 'type': 'array',
66 'items': {'type': COMMAND_SCHEMA},
67 'required': True,
68 },
69 'fetch_errors': {
70 'type': 'integer',
71 'required': True,
72 },
73 'errors': {
74 'type': 'integer',
75 'required': True,
76 },
77 'failures': {
78 'type': 'integer',
79 'required': True,
80 },
81 'passes': {
82 'type': 'integer',
83 'required': True,
84 },
85 'uname': {
86 'type': 'array',
87 'items': {'type': 'string'},
88 'required': True,
89 },
90 'media-info': {
91 'type': 'string',
92 'required': True,
93 },
94 'install_type': {
95 'type': 'string',
96 'required': True,
97 },
98 'arch': {
99 'type': 'string',
100 'required': True,
101 },
102 'release': {
103 'type': 'string',
104 'required': True,
105 },
106 'build_number': {
107 'type': 'string',
108 'required': True,
109 },
110 },
111 }
112
113 def parse(self, logdata, as_string=False):
114 """Parse utah client results.
115
116 :param logdata:
117 should be either a filename or a handle to a file object.
118
119 :returns: the parsed yaml data or None.
120
121 :raises: ParserError on exceptions.
122
123 """
124
125 if as_string:
126 return self._parse_string(logdata)
127 elif isinstance(logdata, str):
128 return self._parse_logfile(logdata)
129 else:
130 return self._parse_stream(logdata)
131
132 def _parse_stream(self, stream):
133 """Parse client output from stream.
134
135 :returns: validated decoded YAML data.
136
137 :raises: ParseError
138
139 """
140 try:
141 data = yaml.load(stream)
142 except yaml.YAMLError as e:
143 logging.error(e)
144 raise ParserError(e.message)
145
146 # Allow empty yaml files
147 if data is None:
148 return data
149
150 try:
151 jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
152 except jsonschema.ValidationError as e:
153 logging.error(e)
154 raise ParserError(e.message)
155
156 return data
157
158 def _parse_logfile(self, logfile):
159 """Parse client output log.
160
161 :returns: validated decoded YAML data.
162
163 :raises: ParseError
164
165 """
166 data = None
167
168 if logfile.startswith('http'):
169 try:
170 fp = urllib2.urlopen(logfile)
171 except IOError as err:
172 raise ParserError(
173 'IOError when downloading {}: {}'
174 .format(logfile, err))
175 except urllib2.ContentTooShortError as err:
176 raise ParserError(
177 'Error when downloading {} (probably interrupted): {}'
178 .format(logfile, err))
179 data = self._parse_stream(fp)
180 else:
181 with open(logfile, 'r') as fp:
182 data = self._parse_stream(fp)
183
184 return data
185
186 def _parse_string(self, log_data):
187 """Parse client data from a string.
188
189 :returns: validated decoded YAML data.
190
191 :raises: ParseError
192
193 """
194 try:
195 data = yaml.load(log_data)
196
197 # Allow empty yaml files
198 if data is None:
199 return data
200 except yaml.YAMLError as e:
201 logging.error(e)
202 raise ParserError(e.message)
203
204 try:
205 jsonschema.validate(data, self.CLIENT_OUTPUT_SCHEMA)
206 except jsonschema.ValidationError as e:
207 logging.error(e)
208 raise ParserError(e.message)
209
210 return data
211
212
213if __name__ == "__main__":
214 arg_parser = argparse.ArgumentParser(description='phoenix bootstrapper')
215 arg_parser.add_argument('logfile', metavar='LOGFILE', type=str,
216 help='log file to parse')
217
218 args = arg_parser.parse_args()
219
220 parser = UTAHParser()
221 data = parser.parse(args.logfile)
222 print(data)

Subscribers

People subscribed via source and target branches