Some hacking.py fixes and fixes in validation and cluster_ops.

All code has been cleaned to pass hacking checks;
only N301 (one import per line) has been disabled now;
VMs creation rollback has been implemented for vms creation errors.

Change-Id: I8d973dfa0c01c8d595aff5fbaf47a9f81d55f74f
This commit is contained in:
Sergey Lukjanov 2013-03-27 16:36:12 +04:00
parent 59a42394c1
commit 48ea0781ee
11 changed files with 53 additions and 31 deletions

View File

@ -17,8 +17,7 @@ import savanna.openstack.common.exception as ex
class SavannaException(ex.ApiError): class SavannaException(ex.ApiError):
""" """Base Exception for the project
Base Exception
To correctly use this class, inherit from it and define To correctly use this class, inherit from it and define
a 'message' and 'code' properties. a 'message' and 'code' properties.
@ -40,7 +39,7 @@ class ClusterNameExistedException(SavannaException):
class ImageNotFoundException(SavannaException): class ImageNotFoundException(SavannaException):
def __init__(self, value): def __init__(self, value):
self.message = "Cannot find image with name '%s'" % value self.message = "Cannot find image with id '%s'" % value
self.code = "IMAGE_NOT_FOUND" self.code = "IMAGE_NOT_FOUND"

View File

@ -64,7 +64,8 @@ CONF.register_opts(opts)
def make_app(): def make_app():
""" """App builder (wsgi)
Entry point for Savanna REST API server Entry point for Savanna REST API server
""" """
app = Flask('savanna.api') app = Flask('savanna.api')

View File

@ -22,16 +22,15 @@ LOG = logging.getLogger(__name__)
class AuthValidator: class AuthValidator:
""" """Handles token auth results and tenants."""
Auth Validation Middleware handles token auth results and tenants
"""
def __init__(self, app, conf): def __init__(self, app, conf):
self.app = app self.app = app
self.conf = conf self.conf = conf
def __call__(self, env, start_response): def __call__(self, env, start_response):
""" """Ensures that tenants in url and token are equal.
Handle incoming request by checking tenant info prom the headers and Handle incoming request by checking tenant info prom the headers and
url ({tenant_id} url attribute). url ({tenant_id} url attribute).

View File

@ -22,8 +22,7 @@
def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False): def split_path(path, minsegs=1, maxsegs=None, rest_with_last=False):
""" """Validate and split the given HTTP request path.
Validate and split the given HTTP request path.
**Examples**:: **Examples**::

View File

@ -39,8 +39,8 @@ def get_node_templates(**args):
def create_node_template(values, headers): def create_node_template(values, headers):
""" """Creates new node template from values dict.
Creates new node template from values dict
:param values: dict :param values: dict
:return: created node template resource :return: created node template resource
""" """
@ -104,14 +104,14 @@ def _cluster_creation_job(headers, cluster_id):
def terminate_cluster(headers, **args): def terminate_cluster(headers, **args):
cluster = storage.update_cluster_status('Stoping', **args) cluster = storage.update_cluster_status('Stopping', **args)
eventlet.spawn(_cluster_termination_job, headers, cluster.id) eventlet.spawn(_cluster_termination_job, headers, cluster.id)
def _cluster_termination_job(headers, cluster_id): def _cluster_termination_job(headers, cluster_id):
cluster = storage.get_cluster(id=cluster_id) cluster = storage.get_cluster(id=cluster_id)
LOG.debug("Stoping cluster '%s' creation: %s", cluster_id, LOG.debug("Stopping cluster '%s' creation: %s", cluster_id,
_cluster(cluster).dict) _cluster(cluster).dict)
if CONF.allow_cluster_ops: if CONF.allow_cluster_ops:

View File

@ -23,6 +23,7 @@ import paramiko
from savanna.openstack.common import log as logging from savanna.openstack.common import log as logging
from savanna.storage.db import DB from savanna.storage.db import DB
from savanna.storage.models import Node, ServiceUrl from savanna.storage.models import Node, ServiceUrl
from savanna.storage.storage import update_cluster_status
from savanna.utils.openstack.nova import novaclient from savanna.utils.openstack.nova import novaclient
@ -121,6 +122,7 @@ def launch_cluster(headers, cluster):
for _ in xrange(0, nc.count): for _ in xrange(0, nc.count):
node = dict() node = dict()
node['id'] = None
if ntype == 'JT+NN': if ntype == 'JT+NN':
node['name'] = '%s-master' % cluster.name node['name'] = '%s-master' % cluster.name
else: else:
@ -133,10 +135,14 @@ def launch_cluster(headers, cluster):
node['is_up'] = False node['is_up'] = False
clmap['nodes'].append(node) clmap['nodes'].append(node)
for node in clmap['nodes']: try:
LOG.debug("Starting node for cluster '%s', node: %s, iamge: %s", for node in clmap['nodes']:
cluster.name, node, clmap['image']) LOG.debug("Starting node for cluster '%s', node: %s, image: %s",
_launch_node(nova, node, clmap['image']) cluster.name, node, clmap['image'])
_launch_node(nova, node, clmap['image'])
except Exception, e:
_rollback_cluster_creation(cluster, clmap, nova, e)
return
all_set = False all_set = False
@ -170,10 +176,28 @@ def launch_cluster(headers, cluster):
def _launch_node(nova, node, image): def _launch_node(nova, node, image):
srv = nova.servers.create(node['name'], image, node['flavor']) srv = nova.servers.create(node['name'], image, node['flavor'])
#srv = _find_by_name(nova_client.servers.list(), node['name'])
node['id'] = srv.id node['id'] = srv.id
def _rollback_cluster_creation(cluster, clmap, nova, error):
update_cluster_status("Error", id=cluster.id)
LOG.warn("Can't launch all vms for cluster '%s': %s", cluster.id, error)
for node in clmap['nodes']:
if node['id']:
_stop_node_silently(nova, cluster, node['id'])
LOG.info("All vms of cluster '%s' has been stopped", cluster.id)
def _stop_node_silently(nova, cluster, vm_id):
LOG.debug("Stopping vm '%s' of cluster '%s'", vm_id, cluster.id)
try:
nova.servers.delete(vm_id)
except Exception, e:
LOG.error("Can't silently remove node '%s': %s", vm_id, e)
def _check_if_up(nova, node): def _check_if_up(nova, node):
if node['is_up']: if node['is_up']:
# all set # all set

View File

@ -31,8 +31,8 @@ def get_node_templates(**args):
def create_node_template(name, node_type_id, tenant_id, flavor_id, configs): def create_node_template(name, node_type_id, tenant_id, flavor_id, configs):
""" """Creates new node templates.
Creates new node templates
:param name: template name :param name: template name
:param node_type_id: node type :param node_type_id: node type
:param tenant_id: tenant :param tenant_id: tenant
@ -86,8 +86,8 @@ def get_clusters(**args):
def create_cluster(name, base_image_id, tenant_id, templates): def create_cluster(name, base_image_id, tenant_id, templates):
""" """Creates new cluster.
Creates new cluster
:param name: cluster name :param name: cluster name
:param base_image_id: base image :param base_image_id: base image
:param tenant_id: tenant :param tenant_id: tenant
@ -124,8 +124,8 @@ def update_cluster_status(new_status, **args):
## Node Process ops: ## Node Process ops:
def create_node_process(name, properties): def create_node_process(name, properties):
""" """Creates new node process and node process properties.
Creates new node process and node process properties
:param name: process name :param name: process name
:param properties: array of triples (name, required, default) :param properties: array of triples (name, required, default)
:return: created node process :return: created node process
@ -152,8 +152,8 @@ def get_node_types(**args):
def create_node_type(name, processes): def create_node_type(name, processes):
""" """Creates new node type using specified list of processes
Creates new node type using specified list of processes
:param name: :param name:
:param processes: :param processes:
:return: :return:

View File

@ -238,7 +238,7 @@ class TestServiceLayer(unittest.TestCase):
api.terminate_cluster({"X-Tenant-Id": "tenant-01"}, id="cluster-id") api.terminate_cluster({"X-Tenant-Id": "tenant-01"}, id="cluster-id")
update_status.assert_called_once_with('Stoping', id="cluster-id") update_status.assert_called_once_with('Stopping', id="cluster-id")
spawn.assert_called_once_with(api._cluster_termination_job, spawn.assert_called_once_with(api._cluster_termination_job,
{"X-Tenant-Id": "tenant-01"}, {"X-Tenant-Id": "tenant-01"},
"cluster-id") "cluster-id")

View File

@ -46,6 +46,6 @@ def get_flavors(headers):
def get_images(headers): def get_images(headers):
images = [image.name for image images = [image.id for image
in novaclient(headers).images.list()] in novaclient(headers).images.list()]
return images return images

View File

@ -122,7 +122,7 @@ def _guess_groups(opt, mod_obj):
# is it in the DEFAULT group? # is it in the DEFAULT group?
if (opt.dest in cfg.CONF and if (opt.dest in cfg.CONF and
not isinstance(cfg.CONF[opt.dest], cfg.CONF.GroupAttr)): not isinstance(cfg.CONF[opt.dest], cfg.CONF.GroupAttr)):
groups.append('DEFAULT') groups.append('DEFAULT')
# what other groups is it in? # what other groups is it in?

View File

@ -15,7 +15,7 @@ echo "=============================="
# python tools/hacking.py --doctest # python tools/hacking.py --doctest
# Until all these issues get fixed, ignore. # Until all these issues get fixed, ignore.
PEP8='python tools/hacking.py --ignore=E12,E711,E721,E712,N301,N303,N403,N404' PEP8='python tools/hacking.py --ignore=N301'
EXCLUDE='--exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*' EXCLUDE='--exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*'
EXCLUDE+=',*egg,build,*hacking.py' EXCLUDE+=',*egg,build,*hacking.py'