summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDina Belova <dbelova@mirantis.com>2016-11-04 09:11:56 -0700
committerDina Belova <dbelova@mirantis.com>2016-11-07 13:07:15 -0800
commitfc46d7d2f62ca198ad0cd0866845ec2b68bc071f (patch)
treeb626b6443b10bd71bed45ab798e095bac6468a5d
parentf39d24bf07ea1abac5d6fbeddf05d57ed596fc15 (diff)
First commit with initial WG information added
Notes
Notes (review): Code-Review+2: Clint 'SpamapS' Byrum <clint@fewbar.com> Workflow+1: Clint 'SpamapS' Byrum <clint@fewbar.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Thu, 17 Nov 2016 14:45:12 +0000 Reviewed-on: https://review.openstack.org/393837 Project: openstack/arch-wg Branch: refs/heads/master
-rw-r--r--.gitignore7
-rw-r--r--.testr.conf4
-rw-r--r--README.rst24
-rw-r--r--doc/source/conf.py436
-rw-r--r--doc/source/index.rst140
-rw-r--r--requirements.txt6
-rw-r--r--setup.cfg20
-rw-r--r--setup.py27
-rw-r--r--test-requirements.txt6
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/test_fake.py18
-rw-r--r--tox.ini22
12 files changed, 710 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9e61f57
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
1doc/build/
2.tox/
3.idea
4AUTHORS
5ChangeLog
6.testrepository/
7*.pyc
diff --git a/.testr.conf b/.testr.conf
new file mode 100644
index 0000000..1641f86
--- /dev/null
+++ b/.testr.conf
@@ -0,0 +1,4 @@
1[DEFAULT]
2test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
3test_id_option=--load-list $IDFILE
4test_list_option=--list
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..4b4f425
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,24 @@
1==========================
2Architecture Working Group
3==========================
4
5This repository if for storing Architecture Working Group resources,
6investigation documents and methodologies. All documents are in RST format and
7located in `doc/source/` sub-folder.
8
9Building
10========
11
12Prerequisites
13-------------
14
15To get started, you need to install all necessary tools:
16 * `virtualenv`
17 * `pip` (use the latest from `https://bootstrap.pypa.io/get-pip.py`)
18 * `tox`
19 * system dependencies: `libjpeg-dev`
20
21Run the build
22-------------
23
24 $ tox
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644
index 0000000..f953a90
--- /dev/null
+++ b/doc/source/conf.py
@@ -0,0 +1,436 @@
1# -*- coding: utf-8 -*-
2#
3# scale_rnd documentation build configuration file, created by
4# sphinx-quickstart on Mon Nov 23 13:22:23 2015.
5#
6# This file is execfile()d with the current directory set to its
7# containing dir.
8#
9# Note that not all possible configuration values are present in this
10# autogenerated file.
11#
12# All configuration values have a default; values that are commented out
13# serve to show the default.
14
15import sys
16import os
17
18# If extensions (or modules to document with autodoc) are in another directory,
19# add these directories to sys.path here. If the directory is relative to the
20# documentation root, use os.path.abspath to make it absolute, like shown here.
21sys.path.insert(0, os.path.abspath('../..'))
22
23# -- General configuration ------------------------------------------------
24
25# If your documentation needs a minimal Sphinx version, state it here.
26#needs_sphinx = '1.0'
27
28# Add any Sphinx extension module names here, as strings. They can be
29# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
30# ones.
31extensions = [
32 'rst2pdf.pdfbuilder',
33 'sphinx.ext.autodoc',
34 'sphinxcontrib.httpdomain',
35 'oslosphinx',
36]
37
38# Add any paths that contain templates here, relative to this directory.
39templates_path = ['_templates']
40
41# The suffix of source filenames.
42source_suffix = '.rst'
43
44# The encoding of source files.
45#source_encoding = 'utf-8-sig'
46
47# The master toctree document.
48master_doc = 'index'
49
50# General information about the project.
51project = u'Performance Docs'
52copyright = u'2015, OpenStack Foundation'
53
54# The version info for the project you're documenting, acts as replacement for
55# |version| and |release|, also used in various other places throughout the
56# built documents.
57#
58# The short X.Y version.
59version = '0.1'
60# The full version, including alpha/beta/rc tags.
61release = '0.1'
62
63# The language for content autogenerated by Sphinx. Refer to documentation
64# for a list of supported languages.
65#language = None
66
67# There are two options for replacing |today|: either, you set today to some
68# non-false value, then it is used:
69#today = ''
70# Else, today_fmt is used as the format for a strftime call.
71#today_fmt = '%B %d, %Y'
72
73# List of patterns, relative to source directory, that match files and
74# directories to ignore when looking for source files.
75exclude_patterns = []
76
77# The reST default role (used for this markup: `text`) to use for all
78# documents.
79#default_role = None
80
81# If true, '()' will be appended to :func: etc. cross-reference text.
82#add_function_parentheses = True
83
84# If true, the current module name will be prepended to all description
85# unit titles (such as .. function::).
86#add_module_names = True
87
88# If true, sectionauthor and moduleauthor directives will be shown in the
89# output. They are ignored by default.
90#show_authors = False
91
92# The name of the Pygments (syntax highlighting) style to use.
93pygments_style = 'sphinx'
94
95# A list of ignored prefixes for module index sorting.
96#modindex_common_prefix = []
97
98# If true, keep warnings as "system message" paragraphs in the built documents.
99#keep_warnings = False
100
101
102# -- Options for HTML output ----------------------------------------------
103
104# on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org
105on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
106
107# The theme to use for HTML and HTML Help pages. See the documentation for
108# a list of builtin themes.
109
110# Theme options are theme-specific and customize the look and feel of a theme
111# further. For a list of options available for each theme, see the
112# documentation.
113#html_theme_options = {}
114
115# Add any paths that contain custom themes here, relative to this directory.
116#html_theme_path = []
117
118# The name for this set of Sphinx documents. If None, it defaults to
119# "<project> v<release> documentation".
120#html_title = None
121
122# A shorter title for the navigation bar. Default is the same as html_title.
123#html_short_title = None
124
125# The name of an image file (relative to this directory) to place at the top
126# of the sidebar.
127#html_logo = None
128
129# The name of an image file (within the static path) to use as favicon of the
130# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
131# pixels large.
132#html_favicon = None
133
134# Add any paths that contain custom static files (such as style sheets) here,
135# relative to this directory. They are copied after the builtin static files,
136# so a file named "default.css" will overwrite the builtin "default.css".
137html_static_path = ['_static']
138
139# Add any extra paths that contain custom files (such as robots.txt or
140# .htaccess) here, relative to this directory. These files are copied
141# directly to the root of the documentation.
142#html_extra_path = []
143
144# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
145# using the given strftime format.
146#html_last_updated_fmt = '%b %d, %Y'
147
148# If true, SmartyPants will be used to convert quotes and dashes to
149# typographically correct entities.
150#html_use_smartypants = True
151
152# Custom sidebar templates, maps document names to template names.
153#html_sidebars = {}
154
155# Additional templates that should be rendered to pages, maps page names to
156# template names.
157#html_additional_pages = {}
158
159# If false, no module index is generated.
160#html_domain_indices = True
161
162# If false, no index is generated.
163#html_use_index = True
164
165# If true, the index is split into individual pages for each letter.
166#html_split_index = False
167
168# If true, links to the reST sources are added to the pages.
169#html_show_sourcelink = True
170
171# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
172#html_show_sphinx = True
173
174# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
175#html_show_copyright = True
176
177# If true, an OpenSearch description file will be output, and all pages will
178# contain a <link> tag referring to it. The value of this option must be the
179# base URL from which the finished HTML is served.
180#html_use_opensearch = ''
181
182# This is the file name suffix for HTML files (e.g. ".xhtml").
183#html_file_suffix = None
184
185# Output file base name for HTML help builder.
186htmlhelp_basename = 'performance_docs'
187
188
189# -- Options for LaTeX output ---------------------------------------------
190
191latex_elements = {
192# The paper size ('letterpaper' or 'a4paper').
193#'papersize': 'letterpaper',
194
195# The font size ('10pt', '11pt' or '12pt').
196#'pointsize': '10pt',
197
198# Additional stuff for the LaTeX preamble.
199#'preamble': '',
200}
201
202# Grouping the document tree into LaTeX files. List of tuples
203# (source start file, target name, title,
204# author, documentclass [howto, manual, or own class]).
205latex_documents = [
206 ('index', 'performance_docs.tex', u'Performance Documentation',
207 u'OpenStack Foundation', 'manual'),
208]
209
210# The name of an image file (relative to this directory) to place at the top of
211# the title page.
212#latex_logo = None
213
214# For "manual" documents, if this is true, then toplevel headings are parts,
215# not chapters.
216#latex_use_parts = False
217
218# If true, show page references after internal links.
219#latex_show_pagerefs = False
220
221# If true, show URL addresses after external links.
222#latex_show_urls = False
223
224# Documents to append as an appendix to all manuals.
225#latex_appendices = []
226
227# If false, no module index is generated.
228#latex_domain_indices = True
229
230
231# -- Options for manual page output ---------------------------------------
232
233# One entry per manual page. List of tuples
234# (source start file, name, description, authors, manual section).
235man_pages = [
236 ('index', 'performance_docs', u'Performance Documentation',
237 [u'OpenStack Foundation'], 1)
238]
239
240# If true, show URL addresses after external links.
241#man_show_urls = False
242
243
244# -- Options for Texinfo output -------------------------------------------
245
246# Grouping the document tree into Texinfo files. List of tuples
247# (source start file, target name, title, author,
248# dir menu entry, description, category)
249texinfo_documents = [
250 ('index', 'performance_docs', u'Performance Documentation',
251 u'OpenStack Foundation', 'performance_docs', 'OpenStack performance testing plans, results and investigations.',
252 'Miscellaneous'),
253]
254
255# Documents to append as an appendix to all manuals.
256#texinfo_appendices = []
257
258# If false, no module index is generated.
259#texinfo_domain_indices = True
260
261# How to display URL addresses: 'footnote', 'no', or 'inline'.
262#texinfo_show_urls = 'footnote'
263
264# If true, do not generate a @detailmenu in the "Top" node's menu.
265#texinfo_no_detailmenu = False
266
267
268# -- Options for Epub output ----------------------------------------------
269
270# Bibliographic Dublin Core info.
271epub_title = u'performance_docs'
272epub_author = u'OpenStack Foundation'
273epub_publisher = u'OpenStack Foundation'
274epub_copyright = u'2015, OpenStack Foundation'
275
276# The basename for the epub file. It defaults to the project name.
277#epub_basename = u'scale_rnd'
278
279# The HTML theme for the epub output. Since the default themes are not optimized
280# for small screen space, using the same theme for HTML and epub output is
281# usually not wise. This defaults to 'epub', a theme designed to save visual
282# space.
283#epub_theme = 'epub'
284
285# The language of the text. It defaults to the language option
286# or en if the language is not set.
287#epub_language = ''
288
289# The scheme of the identifier. Typical schemes are ISBN or URL.
290#epub_scheme = ''
291
292# The unique identifier of the text. This can be a ISBN number
293# or the project homepage.
294#epub_identifier = ''
295
296# A unique identification for the text.
297#epub_uid = ''
298
299# A tuple containing the cover image and cover page html template filenames.
300#epub_cover = ()
301
302# A sequence of (type, uri, title) tuples for the guide element of content.opf.
303#epub_guide = ()
304
305# HTML files that should be inserted before the pages created by sphinx.
306# The format is a list of tuples containing the path and title.
307#epub_pre_files = []
308
309# HTML files shat should be inserted after the pages created by sphinx.
310# The format is a list of tuples containing the path and title.
311#epub_post_files = []
312
313# A list of files that should not be packed into the epub file.
314epub_exclude_files = ['search.html']
315
316# The depth of the table of contents in toc.ncx.
317#epub_tocdepth = 3
318
319# Allow duplicate toc entries.
320#epub_tocdup = True
321
322# Choose between 'default' and 'includehidden'.
323#epub_tocscope = 'default'
324
325# Fix unsupported image types using the PIL.
326#epub_fix_images = False
327
328# Scale large images.
329#epub_max_image_width = 0
330
331# How to display URL addresses: 'footnote', 'no', or 'inline'.
332#epub_show_urls = 'inline'
333
334# If false, no index is generated.
335#epub_use_index = True
336
337
338# -- Options for PDF output --------------------------------------------------
339
340# Grouping the document tree into PDF files. List of tuples
341# (source start file, target name, title, author, options).
342#
343# If there is more than one author, separate them with \\.
344# For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor'
345#
346# The options element is a dictionary that lets you override
347# this config per-document.
348# For example,
349# ('index', u'MyProject', u'My Project', u'Author Name',
350# dict(pdf_compressed = True))
351# would mean that specific document would be compressed
352# regardless of the global pdf_compressed setting.
353
354pdf_documents = [
355 ('index', 'openstack_performance_docs', 'Performance Documentation', 'OpenStack Foundation'),
356]
357
358# A comma-separated list of custom stylesheets. Example:
359pdf_stylesheets = ['pdf']
360
361# A list of folders to search for stylesheets. Example:
362pdf_style_path = ['.', '_styles', 'source/_styles', 'doc/source/_styles']
363
364# Create a compressed PDF
365# Use True/False or 1/0
366# Example: compressed=True
367#pdf_compressed = False
368
369# A colon-separated list of folders to search for fonts. Example:
370# pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/']
371
372# Language to be used for hyphenation support
373#pdf_language = "en_US"
374
375# Mode for literal blocks wider than the frame. Can be
376# overflow, shrink or truncate
377#pdf_fit_mode = "shrink"
378
379# Section level that forces a break page.
380# For example: 1 means top-level sections start in a new page
381# 0 means disabled
382#pdf_break_level = 1
383
384# When a section starts in a new page, force it to be 'even', 'odd',
385# or just use 'any'
386#pdf_breakside = 'any'
387
388# Insert footnotes where they are defined instead of
389# at the end.
390#pdf_inline_footnotes = True
391
392# verbosity level. 0 1 or 2
393#pdf_verbosity = 0
394
395# If false, no index is generated.
396#pdf_use_index = True
397
398# If false, no modindex is generated.
399#pdf_use_modindex = True
400
401# If false, no coverpage is generated.
402#pdf_use_coverpage = True
403
404# Name of the cover page template to use
405pdf_cover_template = 'pdf_cover.tmpl'
406
407# Documents to append as an appendix to all manuals.
408#pdf_appendices = []
409
410# Enable experimental feature to split table cells. Use it
411# if you get "DelayedTable too big" errors
412#pdf_splittables = False
413
414# Set the default DPI for images
415#pdf_default_dpi = 72
416
417# Enable rst2pdf extension modules (default is only vectorpdf)
418# you need vectorpdf if you want to use sphinx's graphviz support
419#pdf_extensions = ['vectorpdf']
420
421# Page template name for "regular" pages
422pdf_page_template = 'cutePage'
423
424# Show Table Of Contents at the beginning?
425#pdf_use_toc = True
426
427# How many levels deep should the table of contents be?
428pdf_toc_depth = 9999
429
430# Add section number to section references
431pdf_use_numbered_links = False
432
433# Background images fitting mode
434pdf_fit_background_mode = 'scale'
435
436pdf_default_dpi = 72
diff --git a/doc/source/index.rst b/doc/source/index.rst
new file mode 100644
index 0000000..fac00c5
--- /dev/null
+++ b/doc/source/index.rst
@@ -0,0 +1,140 @@
1==========================
2Architecture Working Group
3==========================
4
5Mission
6=======
7
8 Be the recognized forum of expertise on the design and architecture of
9 OpenStack and provide guidance and resources to the Technical Committee
10 and the entire OpenStack community on architectural matters.
11
12This group is be open to all volunteers who are interested in participating
13in OpenStack-wide design discussions.
14
15Also note that this is an advisory group intended to gather information
16and produce recommendations. No new authority for enforcing those is
17to be conferred onto this group, however accepted recommendations will
18be expected to be followed for new work whenever possible.
19
20Scope
21=====
22
23* Document the existing architecture and relationship of OpenStack projects.
24* Provide information and guidance to the TC and the OpenStack community on
25 architectural matters.
26* Provide productive spaces for architects to share their designs and gain
27 support across projects to move forward with, coordinate, and implement
28 architectural decisions.
29* Start with a limited scope in order to refine the group processes and be
30 able to achieve visible results (positive or negative) within the upcoming
31 Ocata release cycle.
32
33Communication
34=============
35
36* Email: `openstack-dev mailing list`
37* IRC: #openstack-meeting-alt on Freenode
38* Meetings: `OpenStack wiki`_, `weekly meeting schedule`_ (includes day/time,
39 logs, ICS file, agenda)
40
41.. _openstack-dev mailing list: http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
42.. _OpenStack wiki: https://wiki.openstack.org/wiki/Meetings/Arch-WG
43.. _weekly meeting schedule: http://eavesdrop.openstack.org/#Architecture_Working_Group
44
45Deliverables
46============
47
48* [details tbd]
49
50How To Contribute
51=================
52
53Topics
54------
55
56The WG maintains a backlog of topics in the repo under ``backlog/``. Additions
57to the backlog should be proposed using Gerrit. Approval for addition is
58concerned primarily with the proposal fitting into the scope of the WG.
59
60* A topic background document should be proposed to the WG repo under backlog/
61* The proposal will be held for review for a minimum of one week to allow time
62 for dicussion regarding its fitness for the scope of the WG.
63* The proposal should also be added to an upcoming IRC `meeting agenda`_ to
64 allow the proposer to make a pitch and answer questions.
65* Proposals that do not receive objections after the review period will be
66 considered approved as in-scope and merged into the backlog.
67* The WG will move proposals from the backlog to the ``active/`` work area as
68 it chooses to work on them.
69
70The background document should be sufficient to describe the topic and use
71cases or other reasons it should be considered, such as how it would improve
72OpenStack as a whole or solve specific use cases.
73
74.. _meeting agenda: https://wiki.openstack.org/wiki/Meetings/Arch-WG
75
76Participation
77-------------
78
79Participation in the Architecture Working Group is voluntary and defined by
80those who attend the meetings and contribute proposals, reviews and effort into
81the group activities. There is a core review group (seeded with volunteers at
82early meetings) that has the ability to commit changes to the WG Git repo. As
83with most of OpenStack, membership of that group is merit-based with
84participation and other contributions being considered.
85
86Background
87==========
88
89OpenStack is a big system. We have debated_ what it actually is,
90and there are even t-shirts to poke fun at the fact that we don't have
91good answers.
92
93But this isn't what any of us wants. We'd like to be able to point at
94something and proudly tell people "This is what we designed and implemented."
95
96.. _debated: http://lists.openstack.org/pipermail/openstack-dev/2016-May/095452.html
97
98Problem description
99-------------------
100
101For each individual project, design is a possibility. Neutron can tell you
102they designed how their agents and drivers work. Nova can tell you that they
103designed the way conductors handle communication with API nodes and compute
104nodes. But when we start talking about how they interact with each other,
105it's clearly just a coincidental mash of de-facto standards and specs that
106don't help anyone make decisions when debugging, refactoring, or adding on
107to the system.
108
109Oslo and cross-project initiatives have brought some peace and order to the
110implementation and engineering processes, but not to the design process. New
111ideas still start largely in the project where they are needed most, and often
112conflict with similar decisions and ideas in other projects , including dlm,
113taskflow, tooz, service discovery, state machines, glance tasks, messaging
114patterns, database patterns, etc. etc. Often this creates a log jam where
115none of the projects adopt a solution that would align with others. Most
116of the time when things finally come to a head these things get done in a
117piecemeal fashion, where it's half done here, 1/3 over there, 1/4 there,
118and 3/4 over there..., which to the outside looks like **architecture chaos**,
119because that's precisely what it is.
120
121And this isn't always a technical design problem. OpenStack, for instance,
122isn't really a micro service architecture. Of course, it might look
123like on the diagram below, but we all know it really isn't.
124
125.. image:: http://docs.openstack.org/admin-guide/_images/openstack-arch-kilo-logical-v1.png
126 :width: 650px
127
128The compute node is home to agents for every single concern, and the API
129interactions between the services is too tightly woven to consider many
130of them functional without the same lockstep version of other services
131together. A game to play is ask yourself what would happen if a service
132was isolated on its own island? How functional would its API be, if at
133all? Is this something that we want? No. But there doesn't seem to be
134a place where we can go to actually design, discuss, debate, and build
135consensus around changes that would help us get to the point of gathering
136the necessary will and capability to enact these efforts.
137
138The need for attention ranges from the above project interaction level up
139to higher-level questions such as 'What other OpenStack services can any
140particular service assume to be available?'
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..b6d3a0f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
1oslosphinx>=4.7.0 # Apache-2.0
2rst2pdf
3six>=1.9.0
4sphinx>=1.2.1,!=1.3b1,<1.4 # BSD
5sphinxcontrib-httpdomain # BSD
6sphinx_rtd_theme
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..b601248
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,20 @@
1[metadata]
2name = arch_wg
3summary = OpenStack Architecture WG resources, documents and investigations
4description-file =
5 README.rst
6author = OpenStack
7classifier =
8 Environment :: OpenStack
9 Intended Audience :: Developers
10 Intended Audience :: Information Technology
11 License :: OSI Approved :: Apache Software License
12
13[files]
14packages =
15 arch_wg
16
17[build_sphinx]
18all_files = 1
19build-dir = doc/build
20source-dir = doc/source
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..ddd1771
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,27 @@
1# Licensed under the Apache License, Version 2.0 (the "License");
2# you may not use this file except in compliance with the License.
3# You may obtain a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS,
9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10# implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
14# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
15import setuptools
16
17# In python < 2.7.4, a lazy loading of package `pbr` will break
18# setuptools if some other modules registered functions in `atexit`.
19# solution from: http://bugs.python.org/issue15881#msg170215
20try:
21 import multiprocessing # noqa
22except ImportError:
23 pass
24
25setuptools.setup(
26 setup_requires=['pbr>=1.8'],
27 pbr=True)
diff --git a/test-requirements.txt b/test-requirements.txt
new file mode 100644
index 0000000..1f7de1a
--- /dev/null
+++ b/test-requirements.txt
@@ -0,0 +1,6 @@
1hacking>=0.11.0,<0.12 # Apache-2.0
2
3testrepository>=0.0.18 # Apache-2.0/BSD
4testtools>=1.4.0 # MIT
5
6os-testr>=0.8.0 # Apache-2.0
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/test_fake.py b/tests/test_fake.py
new file mode 100644
index 0000000..0266447
--- /dev/null
+++ b/tests/test_fake.py
@@ -0,0 +1,18 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13import testtools
14
15
16class TestFake(testtools.TestCase):
17 def test_fake(self):
18 pass
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..885e96d
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,22 @@
1[tox]
2envlist = docs,py27
3skipsdist = True
4
5[testenv]
6basepython = python2.7
7setenv = VIRTUAL_ENV={envdir}
8 LANG=en_US.UTF-8
9 LANGUAGE=en_US:en
10 LC_ALL=C
11deps =
12 -r{toxinidir}/requirements.txt
13 -r{toxinidir}/test-requirements.txt
14
15commands = ostestr {posargs}
16
17[testenv:venv]
18commands = {posargs}
19
20[testenv:docs]
21commands =
22 python setup.py build_sphinx