pep8 fixes. Check for pep8 errors on Jenkins since now.

This commit is contained in:
Mike Scherbakov 2012-05-19 13:00:25 +04:00
parent 251f5bf976
commit 90e2a4e0dc
15 changed files with 165 additions and 131 deletions

View File

@ -3,9 +3,9 @@ import os
import sys
if __name__ == "__main__":
# sys.path.insert(0, os.getcwd())
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nailgun.settings")
# sys.path.insert(0, os.getcwd())
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nailgun.settings")
from django.core.management import execute_from_command_line
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
execute_from_command_line(sys.argv)

View File

@ -14,101 +14,107 @@ _running = False
_queue = Queue.Queue()
_lock = threading.Lock()
def _restart(path):
_queue.put(True)
prefix = 'monitor (pid=%d):' % os.getpid()
print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path)
print >> sys.stderr, '%s Triggering process restart.' % prefix
os.kill(os.getpid(), signal.SIGINT)
_queue.put(True)
prefix = 'monitor (pid=%d):' % os.getpid()
print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path)
print >> sys.stderr, '%s Triggering process restart.' % prefix
os.kill(os.getpid(), signal.SIGINT)
def _modified(path):
try:
# If path doesn't denote a file and were previously
# tracking it, then it has been removed or the file type
# has changed so force a restart. If not previously
# tracking the file then we can ignore it as probably
# pseudo reference such as when file extracted from a
# collection of modules contained in a zip file.
try:
# If path doesn't denote a file and were previously
# tracking it, then it has been removed or the file type
# has changed so force a restart. If not previously
# tracking the file then we can ignore it as probably
# pseudo reference such as when file extracted from a
# collection of modules contained in a zip file.
if not os.path.isfile(path):
return path in _times
if not os.path.isfile(path):
return path in _times
# Check for when file last modified.
# Check for when file last modified.
mtime = os.stat(path).st_mtime
if path not in _times:
_times[path] = mtime
mtime = os.stat(path).st_mtime
if path not in _times:
_times[path] = mtime
# Force restart when modification time has changed, even
# if time now older, as that could indicate older file
# has been restored.
# Force restart when modification time has changed, even
# if time now older, as that could indicate older file
# has been restored.
if mtime != _times[path]:
return True
except:
# If any exception occured, likely that file has been
# been removed just before stat(), so force a restart.
if mtime != _times[path]:
return True
except:
# If any exception occured, likely that file has been
# been removed just before stat(), so force a restart.
return True
return True
return False
return False
def _monitor():
while 1:
# Check modification times on all files in sys.modules.
while 1:
# Check modification times on all files in sys.modules.
for module in sys.modules.values():
if not hasattr(module, '__file__'):
continue
path = getattr(module, '__file__')
if not path:
continue
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
path = path[:-1]
if _modified(path):
return _restart(path)
for module in sys.modules.values():
if not hasattr(module, '__file__'):
continue
path = getattr(module, '__file__')
if not path:
continue
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
path = path[:-1]
if _modified(path):
return _restart(path)
# Check modification times on files which have
# specifically been registered for monitoring.
# Check modification times on files which have
# specifically been registered for monitoring.
for path in _files:
if _modified(path):
return _restart(path)
for path in _files:
if _modified(path):
return _restart(path)
# Go to sleep for specified interval.
# Go to sleep for specified interval.
try:
return _queue.get(timeout=_interval)
except:
pass
try:
return _queue.get(timeout=_interval)
except:
pass
_thread = threading.Thread(target=_monitor)
_thread.setDaemon(True)
def _exiting():
try:
_queue.put(True)
except:
pass
_thread.join()
try:
_queue.put(True)
except:
pass
_thread.join()
atexit.register(_exiting)
def track(path):
if not path in _files:
_files.append(path)
if not path in _files:
_files.append(path)
def start(interval=1.0):
global _interval
if interval < _interval:
_interval = interval
global _running
_lock.acquire()
if not _running:
prefix = 'monitor (pid=%d):' % os.getpid()
print >> sys.stderr, '%s Starting change monitor.' % prefix
_running = True
_thread.start()
_lock.release()\
global _interval
if interval < _interval:
_interval = interval
global _running
_lock.acquire()
if not _running:
prefix = 'monitor (pid=%d):' % os.getpid()
print >> sys.stderr, '%s Starting change monitor.' % prefix
_running = True
_thread.start()
_lock.release()

View File

@ -3,6 +3,7 @@ import urllib
import httplib
from urlparse import urlparse
def query_api(url, method='GET', params={}):
if method not in ('GET', 'POST', 'PUT', 'DELETE'):
raise ValueError("Invalid method %s" % method)
@ -28,5 +29,3 @@ def query_api(url, method='GET', params={}):
pass
return (response.status, data)

View File

@ -3,19 +3,23 @@ from django import forms
from django.forms.fields import Field, CharField, ChoiceField
from nailgun.models import Environment, Node, Role
class EnvironmentForm(forms.ModelForm):
class Meta:
model = Environment
def validate_node_metadata(value):
if value is not None:
if isinstance(value, dict):
for field in ('block_device', 'interfaces', 'cpu', 'memory'):
if not field in value:
raise ValidationError('Node metadata \'%s\' field is required' % field)
raise ValidationError("Node metadata '%s' \
field is required" % field)
else:
raise ValidationError('Node metadata must be a dictionary')
class NodeForm(forms.Form):
metadata = Field(required=False, validators=[validate_node_metadata])
status = ChoiceField(required=False, choices=Node.NODE_STATUSES)

View File

@ -38,7 +38,7 @@ class ConfigHandler(BaseHandler):
allowed_methods = ('POST',)
""" Creates JSON files for chef-solo. This should be moved to the queue. """
""" Creates JSON files for chef-solo. This should be moved to the queue """
def create(self, request, environment_id):
env_id = environment_id
nodes = Node.objects.filter(environment__id=env_id)
@ -63,7 +63,8 @@ class ConfigHandler(BaseHandler):
["role[" + x.name + "]" for x in n.roles.all()]
solo_json['all_roles'] = nodes_per_role
filepath = os.path.join(settings.CHEF_CONF_FOLDER, n.name + '.json')
filepath = os.path.join(settings.CHEF_CONF_FOLDER,
n.name + '.json')
f = open(filepath, 'w')
f.write(json.dumps(solo_json))
f.close()
@ -78,7 +79,8 @@ class NodeHandler(BaseHandler):
def read(self, request, environment_id, node_name=None):
try:
if node_name:
return Node.objects.get(name=node_name, environment__id=environment_id)
return Node.objects.get(name=node_name,
environment__id=environment_id)
else:
return Node.objects.filter(environment__id=environment_id)
except ObjectDoesNotExist:
@ -87,9 +89,11 @@ class NodeHandler(BaseHandler):
@validate_json(NodeForm)
def update(self, request, environment_id, node_name):
try:
node = Node.objects.get(name=node_name, environment__id=environment_id)
node = Node.objects.get(name=node_name,
environment__id=environment_id)
for key, value in request.form.cleaned_data.items():
if key in request.form.data: # check if parameter is really passed by client
# check if parameter is really passed by client
if key in request.form.data:
setattr(node, key, value)
node.save()
return node
@ -106,16 +110,20 @@ class RoleHandler(BaseHandler):
def read(self, request, environment_id, node_name, role_name=None):
try:
if role_name:
return Role.objects.get(nodes__environment__id=environment_id, nodes__name=node_name, name=role_name)
return Role.objects.get(nodes__environment__id=environment_id,
nodes__name=node_name, name=role_name)
else:
return Role.objects.filter(nodes__environment__id=environment_id, nodes__name=node_name)
return Role.objects.filter(
nodes__environment__id=environment_id,
nodes__name=node_name)
except ObjectDoesNotExist:
return rc.NOT_FOUND
def create(self, request, environment_id, node_name, role_name):
try:
print environment_id, node_name, role_name
node = Node.objects.get(environment__id=environment_id, name=node_name)
node = Node.objects.get(environment__id=environment_id,
name=node_name)
role = Role.objects.get(name=role_name)
if role in node.roles.all():
@ -128,7 +136,8 @@ class RoleHandler(BaseHandler):
def delete(self, request, environment_id, node_name, role_name):
try:
node = Node.objects.get(environment__id=environment_id, name=node_name)
node = Node.objects.get(environment__id=environment_id,
name=node_name)
role = Role.objects.get(name=role_name)
node.roles.remove(role)
return rc.DELETED

View File

@ -1,11 +1,15 @@
from django.conf.urls import patterns, include, url
from piston.resource import Resource
from handlers import EnvironmentHandler, NodeHandler, RoleHandler, ConfigHandler
from handlers import EnvironmentHandler, NodeHandler
from handlers import RoleHandler, ConfigHandler
class JsonResource(Resource):
def determine_emitter(self, request, *args, **kwargs):
return 'json'
environment_handler = JsonResource(EnvironmentHandler)
node_handler = JsonResource(NodeHandler)
role_handler = JsonResource(RoleHandler)
@ -14,9 +18,13 @@ config_handler = JsonResource(ConfigHandler)
urlpatterns = patterns('',
url(r'^environments/?$', environment_handler),
url(r'^environments/(?P<environment_id>\d+)/?$', environment_handler),
url(r'^environments/(?P<environment_id>\d+)/chef-config/?$', config_handler),
url(r'^environments/(?P<environment_id>\d+)/chef-config/?$',
config_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/?$', node_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/?$', node_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/roles/?$', role_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/(?P<node_name>[\w\.\-]+)/roles/(?P<role_name>\w+)/?$', role_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/'
r'(?P<node_name>[\w\.\-]+)/?$', node_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/'
r'(?P<node_name>[\w\.\-]+)/roles/?$', role_handler),
url(r'^environments/(?P<environment_id>\d+)/nodes/'
r'(?P<node_name>[\w\.\-]+)/roles/(?P<role_name>\w+)/?$', role_handler),
)

View File

@ -2,6 +2,7 @@ import json
from piston.utils import FormValidationError, HttpStatusCode, rc
from piston.decorator import decorator
def validate_json(v_form):
@decorator
def wrap(f, self, request, *a, **kwa):

View File

@ -1,5 +1,6 @@
import traceback
class ExceptionLoggingMiddleware(object):
def process_exception(self, request, exception):
print traceback.format_exc()

View File

@ -20,7 +20,7 @@ class Node(models.Model):
)
environment = models.ForeignKey(Environment, related_name='nodes')
name = models.CharField(max_length=100, primary_key=True)
status = models.CharField(max_length=30, choices=NODE_STATUSES, default='online')
status = models.CharField(max_length=30, choices=NODE_STATUSES,
default='online')
metadata = JSONField()
roles = models.ManyToManyField(Role, related_name='nodes')

View File

@ -15,12 +15,12 @@ MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': os.path.join(PROJECT_ROOT, 'nailgun.sqlite'), # Or path to database file if using sqlite3.
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(PROJECT_ROOT, 'nailgun.sqlite'),
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
'HOST': '',
'PORT': '',
}
}
@ -98,7 +98,8 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware',
)
if DEBUG: MIDDLEWARE_CLASSES += ('nailgun.middleware.ExceptionLoggingMiddleware',)
if DEBUG:
MIDDLEWARE_CLASSES += ('nailgun.middleware.ExceptionLoggingMiddleware',)
ROOT_URLCONF = 'nailgun.urls'

View File

@ -1,9 +1,9 @@
from celery.task import task
@task
def add(x, y):
for i in xrange(1, 10):
time.sleep(1)
add.update_state(state="PROGRESS", meta={"current": i, "total": 10})
return x + y
for i in xrange(1, 10):
time.sleep(1)
add.update_state(state="PROGRESS", meta={"current": i, "total": 10})
return x + y

View File

@ -1,12 +1,15 @@
import os
from django import template
from django.contrib.staticfiles.finders import FileSystemFinder
TEMPLATE_EXTENSION = '.html'
register = template.Library()
finder = FileSystemFinder()
@register.simple_tag
def jst(template_name):
template_filename = os.path.join('jst', template_name + TEMPLATE_EXTENSION)

View File

@ -134,7 +134,6 @@ class TestHandlers(TestCase):
name=self.node_name)
self.assertEquals(nodes_from_db[0].roles.all()[0].name, "myrole")
# Tests for RoleHandler
def test_can_get_list_of_roles_for_node(self):
resp = self.client.get(self.node_url + '/roles')
@ -151,8 +150,10 @@ class TestHandlers(TestCase):
roles_from_db = Role.objects.all()
nodes_from_db = Node.objects.filter(environment_id=1,
name=self.node_name)
self.assertEquals(nodes_from_db[0].roles.all()[0].name, self.role.name)
self.assertEquals(nodes_from_db[0].roles.all()[1].name, self.another_role.name)
self.assertEquals(nodes_from_db[0].roles.all()[0].name,
self.role.name)
self.assertEquals(nodes_from_db[0].roles.all()[1].name,
self.another_role.name)
#def test_jsons_created_for_chef_solo(self):
#resp = self.client.post('/api/environments/1/chef-config/')

View File

@ -45,6 +45,6 @@ class TestRolesNodesAssociation(TestCase):
node1.roles.add(role2)
self.assertEquals(len(node1.roles.all()), 2)
self.assertEquals(Node.objects.filter(roles__name__startswith="myr")[0].name,
self.assertEquals(Node.objects.filter(
roles__name__startswith="myr")[0].name,
"test.example.com")

View File

@ -1,5 +1,6 @@
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'index.html', {})