Merge branch 'master' of github.com:MirantisLabs/openstack-config-validator
* 'master' of github.com:MirantisLabs/openstack-config-validator: [doc] Add proposal document and update architecture model Added minimal support for running Lettuce-based inspections Added minimal RabbitMq service info collection [doc] Add configuration validator proposal document [doc] Move .dot image sources to images/src dir
This commit is contained in:
commit
71e4f7d08e
@ -4,7 +4,7 @@ from itertools import groupby
|
|||||||
from ostack_validator.common import Issue, MarkedIssue, Inspection
|
from ostack_validator.common import Issue, MarkedIssue, Inspection
|
||||||
from ostack_validator.model import OpenstackComponent
|
from ostack_validator.model import OpenstackComponent
|
||||||
from ostack_validator.discovery import OpenstackDiscovery
|
from ostack_validator.discovery import OpenstackDiscovery
|
||||||
from ostack_validator.inspections import KeystoneAuthtokenSettingsInspection, KeystoneEndpointsInspection
|
from ostack_validator.inspections import KeystoneAuthtokenSettingsInspection, KeystoneEndpointsInspection, LettuceRunnerInspection
|
||||||
|
|
||||||
def indent_prefix(indent=0):
|
def indent_prefix(indent=0):
|
||||||
s = ''
|
s = ''
|
||||||
@ -62,7 +62,7 @@ def main():
|
|||||||
|
|
||||||
openstack = discovery.discover(['172.18.65.179'], 'root', private_key=private_key)
|
openstack = discovery.discover(['172.18.65.179'], 'root', private_key=private_key)
|
||||||
|
|
||||||
all_inspections = [KeystoneAuthtokenSettingsInspection, KeystoneEndpointsInspection]
|
all_inspections = [KeystoneAuthtokenSettingsInspection, KeystoneEndpointsInspection, LettuceRunnerInspection]
|
||||||
for inspection in all_inspections:
|
for inspection in all_inspections:
|
||||||
x = inspection()
|
x = inspection()
|
||||||
x.inspect(openstack)
|
x.inspect(openstack)
|
||||||
|
@ -2,16 +2,20 @@
|
|||||||
ARCHITECTURE DATA MODEL
|
ARCHITECTURE DATA MODEL
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
--------
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Architecture data model produced by Joker could be consumed by configuration
|
We want to introduce unified data structure which contains all information
|
||||||
validator tool (Dark Knight), by architecture graph (Stencil) and others.
|
necessary to inspect, analyze, describe and visualize OpenStack architecture.
|
||||||
|
|
||||||
At some point it should be made convertible into format accepted by deployment
|
This Architecture data model could be consumed and processed by configuration
|
||||||
systems (e.g. Fuel or TripleO) which will allow to effectively 'clone' OpenStack
|
analysis and diagnostics tool (**Dark Knight**) and by architecture visualizer
|
||||||
clouds using different deployment applications.
|
(**Stencil**).
|
||||||
|
|
||||||
|
Arhictecture data model must include all information necessary to deployment
|
||||||
|
systems (e.g. **Fuel** or **TripleO**). We will implement simple conversion tools which
|
||||||
|
will allow to configure these deployment systems and effectively support
|
||||||
|
'portable' clouds.
|
||||||
|
|
||||||
This model could be reused by Rally project to compare benchmarking results for
|
This model could be reused by Rally project to compare benchmarking results for
|
||||||
different architectures.
|
different architectures.
|
||||||
@ -24,11 +28,10 @@ support contract pricing purposes.
|
|||||||
The model could be used to perform automated/guided hardening of OpenStack
|
The model could be used to perform automated/guided hardening of OpenStack
|
||||||
architecture and configuration.
|
architecture and configuration.
|
||||||
|
|
||||||
-----------
|
|
||||||
Data Format
|
Data Format
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This section proposes data model format which allows to describe any OpenStack
|
This section proposes data model format which allows to describe an OpenStack
|
||||||
installation. The model includes data regarding physical infrastructure, logical
|
installation. The model includes data regarding physical infrastructure, logical
|
||||||
topology of services and mapping between the two.
|
topology of services and mapping between the two.
|
||||||
|
|
||||||
|
68
doc/configuration_validator.rst
Normal file
68
doc/configuration_validator.rst
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
OPENSTACK DIAGNOSTICS PROPOSAL
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Project Name
|
||||||
|
------------
|
||||||
|
|
||||||
|
**Official:** OpenStack Diagnostics
|
||||||
|
**Codename:** Dark Knight
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
OpenStack cloud operators usually rely on deploymnet tools to configure all the
|
||||||
|
platform components correctly and efficiently upfront. However, after initial
|
||||||
|
deployment platform configurations and operational conditions start to change.
|
||||||
|
We propose a project that allows to analyze OpenStack architecture and diagnose
|
||||||
|
existing and potential problems using flexible set of rules.
|
||||||
|
|
||||||
|
Mission
|
||||||
|
---------
|
||||||
|
|
||||||
|
Diagnostics project mission is to **provide OpenStack cloud operators with
|
||||||
|
flexible way to inspect, analyze and diagnose architecture of the cloud and
|
||||||
|
configuration of components of the platform**.
|
||||||
|
|
||||||
|
User Stories
|
||||||
|
------------
|
||||||
|
|
||||||
|
As a **cloud operator**, I want to be able to automatically extract
|
||||||
|
configuration parameters from all OpenStack components to verify their
|
||||||
|
correctness, consistency and integrity.
|
||||||
|
As a **cloud architect**, I want to make sure that my OpenStack architecture and
|
||||||
|
configuration are compliant to 'best practices'.
|
||||||
|
As a **cloud operator**, I want automatic diagnostics tool which can tell me
|
||||||
|
what problems does my OpenStack architecture and/or configuration have or might
|
||||||
|
potentially have (e.g. at scale or if some component or node failed).
|
||||||
|
As a **cloud operator**, I want to be able to define rules used to inspect and
|
||||||
|
verify configuration of OpenStack components and store them to use for
|
||||||
|
verification of future configuration changes.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
Scope
|
||||||
|
-----
|
||||||
|
|
||||||
|
As an MVP1, we create a service that includes:
|
||||||
|
|
||||||
|
1. Rules engine with grammatic analysis capabilities
|
||||||
|
1. Extensible implementation of rules
|
||||||
|
1. REST API for running inspections
|
||||||
|
1. Storage back-end implementation for OpenStack platform architecture and
|
||||||
|
configuration data
|
||||||
|
|
||||||
|
Assumptions
|
||||||
|
-----------
|
||||||
|
|
||||||
|
We assume that we must reuse as much as possible from OpenStack Deployment
|
||||||
|
program in terms of platform configuration and architecture definitions (i.e.
|
||||||
|
TripleO Heat and configuration files templates).
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
Design
|
||||||
|
------
|
@ -408,5 +408,8 @@ class OpenstackDiscovery(object):
|
|||||||
if ' '.join(process).find('rabbit') == -1:
|
if ' '.join(process).find('rabbit') == -1:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return None
|
rabbitmq = RabbitMqComponent()
|
||||||
|
rabbitmq.version = 'unknown'
|
||||||
|
|
||||||
|
return rabbitmq
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
from ostack_validator.inspections.keystone_authtoken import KeystoneAuthtokenSettingsInspection
|
from ostack_validator.inspections.keystone_authtoken import KeystoneAuthtokenSettingsInspection
|
||||||
from ostack_validator.inspections.keystone_endpoints import KeystoneEndpointsInspection
|
from ostack_validator.inspections.keystone_endpoints import KeystoneEndpointsInspection
|
||||||
|
from ostack_validator.inspections.lettuce_runner import LettuceRunnerInspection
|
||||||
|
|
||||||
|
8
ostack_validator/inspections/lettuce/sample.feature
Normal file
8
ostack_validator/inspections/lettuce/sample.feature
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Feature: Configuration consistency
|
||||||
|
|
||||||
|
Scenario: Nova has proper Keystone host
|
||||||
|
Given I use OpenStack 2013.1
|
||||||
|
And Nova has "auth_strategy" equal to "keystone"
|
||||||
|
And Keystone addresses are @X
|
||||||
|
Then Nova should have "keystone_authtoken.auth_host" in "$X"
|
||||||
|
|
67
ostack_validator/inspections/lettuce/steps.py
Normal file
67
ostack_validator/inspections/lettuce/steps.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import string
|
||||||
|
from lettuce import *
|
||||||
|
|
||||||
|
from ostack_validator.common import Issue, Version, find
|
||||||
|
from ostack_validator.model import *
|
||||||
|
|
||||||
|
def get_variable(name):
|
||||||
|
if not hasattr(world, 'variables'):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return world.variables.get(name)
|
||||||
|
|
||||||
|
def set_variable(name, value):
|
||||||
|
if not hasattr(world, 'variables'):
|
||||||
|
world.variables = {}
|
||||||
|
|
||||||
|
world.variables[name] = value
|
||||||
|
|
||||||
|
def subst(template):
|
||||||
|
if not hasattr(world, 'variables'):
|
||||||
|
return template
|
||||||
|
|
||||||
|
tmpl = string.Template(template)
|
||||||
|
return tmpl.safe_substitute(world.variables)
|
||||||
|
|
||||||
|
def stop():
|
||||||
|
assert False, "stop"
|
||||||
|
|
||||||
|
@step(r'I use OpenStack (\w+)')
|
||||||
|
def use_openstack_version(step, version):
|
||||||
|
version = Version(version)
|
||||||
|
for component in [c for c in world.openstack.components if isinstance(c, OpenstackComponent)]:
|
||||||
|
if not Version(component.version) >= version: stop()
|
||||||
|
|
||||||
|
@step(r'Nova has "(.+)" equal to "(.*)"')
|
||||||
|
def nova_has_property(step, name, value):
|
||||||
|
name = subst(name)
|
||||||
|
value = subst(value)
|
||||||
|
|
||||||
|
for nova in [c for c in world.openstack.components if c.name.startswith('nova')]:
|
||||||
|
if not nova.config[name] == value: stop()
|
||||||
|
|
||||||
|
@step(r'Keystone addresses are @(\w+)')
|
||||||
|
def keystone_addresses(self, variable):
|
||||||
|
keystone = find(world.openstack.components, lambda c: c.name == 'keystone')
|
||||||
|
|
||||||
|
if keystone.config['bind_host'] == '0.0.0.0':
|
||||||
|
addresses = filter(lambda ip: not ip.startswith('127.'), keystone.host.network_addresses)
|
||||||
|
else:
|
||||||
|
addresses = [keystone.config['bind_host']]
|
||||||
|
|
||||||
|
set_variable(variable, addresses)
|
||||||
|
|
||||||
|
@step(r'Nova should have "(.+)" in "(.*)"')
|
||||||
|
def nova_property_assertion(self, name, values):
|
||||||
|
name = subst(name)
|
||||||
|
values = subst(values)
|
||||||
|
|
||||||
|
if not values:
|
||||||
|
return
|
||||||
|
|
||||||
|
for nova in [c for c in world.openstack.components if c.name.startswith('nova')]:
|
||||||
|
nova_value = nova.config[name]
|
||||||
|
|
||||||
|
if not (nova_value and nova_value in values):
|
||||||
|
nova.report_issue(Issue(Issue.ERROR, 'Nova should have "%s" in %s' % (name, values)))
|
||||||
|
|
20
ostack_validator/inspections/lettuce_runner.py
Normal file
20
ostack_validator/inspections/lettuce_runner.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import os.path
|
||||||
|
import lettuce
|
||||||
|
|
||||||
|
from ostack_validator.common import Inspection, Issue
|
||||||
|
|
||||||
|
class LettuceRunnerInspection(Inspection):
|
||||||
|
def inspect(self, openstack):
|
||||||
|
runner = lettuce.Runner(
|
||||||
|
base_path=os.path.join(os.path.dirname(__file__), 'lettuce')
|
||||||
|
)
|
||||||
|
|
||||||
|
lettuce.world.openstack = openstack
|
||||||
|
result = runner.run()
|
||||||
|
del lettuce.world.openstack
|
||||||
|
|
||||||
|
for feature_result in result.feature_results:
|
||||||
|
for scenario_result in [s for s in feature_result.scenario_results if not s.passed]:
|
||||||
|
for step in scenario_result.steps_undefined:
|
||||||
|
openstack.report_issue(Issue(Issue.ERROR, 'Undefined step "%s"' % step.sentence))
|
||||||
|
|
@ -270,7 +270,7 @@ class MysqlComponent(Service):
|
|||||||
name = 'mysql'
|
name = 'mysql'
|
||||||
|
|
||||||
class RabbitMqComponent(Service):
|
class RabbitMqComponent(Service):
|
||||||
pass
|
name = 'rabbitmq'
|
||||||
|
|
||||||
class FileResource(IssueReporter):
|
class FileResource(IssueReporter):
|
||||||
def __init__(self, path, contents, owner, group, permissions):
|
def __init__(self, path, contents, owner, group, permissions):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user