launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #14838
[Merge] lp:~rvb/maas/commissioning-status into lp:maas
Raphaël Badin has proposed merging lp:~rvb/maas/commissioning-status into lp:maas.
Commit message:
Remove status from nodecommissioningresult. Add new integer field on nodecommissioningresult;
The new field will be used to store the return code of the script used to produce the output stored in nodecommissioningresult.data.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~rvb/maas/commissioning-status/+merge/140645
This is a 'cleanup' that fixes a miscommunication between Jeroen and myself about how the commissioning scripts should report their output. The field I added (named 'status') on nodecommissioningresult is replaced by an integer field (named 'script_result') which stores the return value of the script used to produce the output stored in nodecommissioningresult.data.
I've updated the 'signal' API method accordingly.
--
https://code.launchpad.net/~rvb/maas/commissioning-status/+merge/140645
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/maas/commissioning-status into lp:maas.
=== modified file 'src/maasserver/testing/factory.py'
--- src/maasserver/testing/factory.py 2012-11-26 08:52:01 +0000
+++ src/maasserver/testing/factory.py 2012-12-19 12:37:21 +0000
@@ -230,14 +230,18 @@
interface.save()
return interface
- def make_node_commission_result(self, node=None, name=None, data=None):
+ def make_node_commission_result(self, node=None, name=None,
+ script_result=None, data=None):
if node is None:
node = self.make_node()
if name is None:
name = "ncrname-" + self.getRandomString(92)
if data is None:
data = "ncrdata-" + self.getRandomString(1000)
- ncr = NodeCommissionResult(node=node, name=name, data=data)
+ if script_result is None:
+ script_result = random.randint(0, 10)
+ ncr = NodeCommissionResult(
+ node=node, name=name, script_result=script_result, data=data)
ncr.save()
return ncr
=== modified file 'src/maasserver/tests/test_node.py'
--- src/maasserver/tests/test_node.py 2012-12-18 12:31:47 +0000
+++ src/maasserver/tests/test_node.py 2012-12-19 12:37:21 +0000
@@ -50,7 +50,6 @@
)
from maastesting.testcase import TestCase as DjangoLessTestCase
from metadataserver import commissioning
-from metadataserver.enum import COMMISSIONING_STATUS
from metadataserver.models import (
NodeCommissionResult,
NodeUserData,
@@ -495,7 +494,7 @@
node = factory.make_node(status=NODE_STATUS.DECLARED)
NodeCommissionResult.objects.store_data(
node, factory.getRandomString(),
- factory.getRandomEnum(COMMISSIONING_STATUS),
+ random.randint(0, 10),
factory.getRandomString())
node.start_commissioning(factory.make_admin())
self.assertItemsEqual([], node.nodecommissionresult_set.all())
@@ -504,8 +503,9 @@
node = factory.make_node()
filename = factory.getRandomString()
text = factory.getRandomString()
- status = factory.getRandomEnum(COMMISSIONING_STATUS)
- NodeCommissionResult.objects.store_data(node, filename, status, text)
+ script_result = random.randint(0, 10)
+ NodeCommissionResult.objects.store_data(
+ node, filename, script_result, text)
other_node = factory.make_node(status=NODE_STATUS.DECLARED)
other_node.start_commissioning(factory.make_admin())
self.assertEqual(
=== modified file 'src/metadataserver/api.py'
--- src/metadataserver/api.py 2012-12-13 11:40:36 +0000
+++ src/metadataserver/api.py 2012-12-19 12:37:21 +0000
@@ -190,14 +190,14 @@
def _store_commissioning_results(self, node, request):
"""Store commissioning result files for `node`."""
- status = get_mandatory_param(request.POST, 'status')
+ script_result = request.POST.get('script_result', None)
for name, uploaded_file in request.FILES.items():
raw_content = uploaded_file.read()
if name == "00-maas-01-lshw.out":
node.set_hardware_details(raw_content)
contents = raw_content.decode('utf-8')
NodeCommissionResult.objects.store_data(
- node, name, status, contents)
+ node, name, script_result, contents)
@operation(idempotent=False)
def signal(self, request, version=None, mac=None):
@@ -213,13 +213,14 @@
:param status: A commissioning status code. This can be "OK" (to
signal that commissioning has completed successfully), or "FAILED"
(to signal failure), or "WORKING" (for progress reports).
+ :param script_result: If this call uploads files, this parameter must
+ be provided and will be stored as the return value for the script
+ which produced these files.
:param error: An optional error string. If given, this will be stored
(overwriting any previous error string), and displayed in the MAAS
UI. If not given, any previous error string will be cleared.
"""
node = get_queried_node(request, for_mac=mac)
- status = request.POST.get('status', None)
-
status = get_mandatory_param(request.POST, 'status')
if node.status not in self.signalable_states:
raise NodeStateViolation(
=== added file 'src/metadataserver/migrations/0009_delete_status.py'
--- src/metadataserver/migrations/0009_delete_status.py 1970-01-01 00:00:00 +0000
+++ src/metadataserver/migrations/0009_delete_status.py 2012-12-19 12:37:21 +0000
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+import datetime
+
+from django.db import models
+from south.db import db
+from south.v2 import SchemaMigration
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Deleting field 'NodeCommissionResult.status'
+ db.delete_column(u'metadataserver_nodecommissionresult', 'status')
+
+
+ def backwards(self, orm):
+ # Adding field 'NodeCommissionResult.status'
+ db.add_column(u'metadataserver_nodecommissionresult', 'status',
+ self.gf('django.db.models.fields.CharField')(default=u'OK', max_length=100),
+ keep_default=False)
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ u'maasserver.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'after_commissioning_action': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'architecture': ('django.db.models.fields.CharField', [], {'default': "u'i386/generic'", 'max_length': '31'}),
+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'hardware_details': ('maasserver.fields.XMLField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-73e09bf8-49d0-11e2-8c9f-3c970e0e56dc'", 'unique': 'True', 'max_length': '41'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'null': 'True'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'maasserver.nodegroup': {
+ 'Meta': {'object_name': 'NodeGroup'},
+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'unique': 'True'}),
+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
+ },
+ u'maasserver.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'metadataserver.commissioningscript': {
+ 'Meta': {'object_name': 'CommissioningScript'},
+ 'content': ('metadataserver.fields.BinaryField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ u'metadataserver.nodecommissionresult': {
+ 'Meta': {'unique_together': "((u'node', u'name'),)", 'object_name': 'NodeCommissionResult'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'data': ('django.db.models.fields.CharField', [], {'max_length': '1048576'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'metadataserver.nodekey': {
+ 'Meta': {'object_name': 'NodeKey'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'unique': 'True'}),
+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'unique': 'True'})
+ },
+ u'metadataserver.nodeuserdata': {
+ 'Meta': {'object_name': 'NodeUserData'},
+ 'data': ('metadataserver.fields.BinaryField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'unique': 'True'})
+ },
+ 'piston.consumer': {
+ 'Meta': {'object_name': 'Consumer'},
+ 'description': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': "orm['auth.User']"})
+ },
+ 'piston.token': {
+ 'Meta': {'object_name': 'Token'},
+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Consumer']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1355917041L'}),
+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+ }
+ }
+
+ complete_apps = ['metadataserver']
\ No newline at end of file
=== added file 'src/metadataserver/migrations/0010_add_script_result.py'
--- src/metadataserver/migrations/0010_add_script_result.py 1970-01-01 00:00:00 +0000
+++ src/metadataserver/migrations/0010_add_script_result.py 2012-12-19 12:37:21 +0000
@@ -0,0 +1,162 @@
+# -*- coding: utf-8 -*-
+import datetime
+
+from django.db import models
+from south.db import db
+from south.v2 import SchemaMigration
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'NodeCommissionResult.script_result'
+ db.add_column(u'metadataserver_nodecommissionresult', 'script_result',
+ self.gf('django.db.models.fields.IntegerField')(default=0),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'NodeCommissionResult.script_result'
+ db.delete_column(u'metadataserver_nodecommissionresult', 'script_result')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ u'maasserver.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'after_commissioning_action': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'architecture': ('django.db.models.fields.CharField', [], {'default': "u'i386/generic'", 'max_length': '31'}),
+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '10', 'null': 'True', 'blank': 'True'}),
+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'hardware_details': ('maasserver.fields.XMLField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-5065b92a-49d4-11e2-8786-3c970e0e56dc'", 'unique': 'True', 'max_length': '41'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'null': 'True'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'maasserver.nodegroup': {
+ 'Meta': {'object_name': 'NodeGroup'},
+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'unique': 'True'}),
+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
+ },
+ u'maasserver.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'metadataserver.commissioningscript': {
+ 'Meta': {'object_name': 'CommissioningScript'},
+ 'content': ('metadataserver.fields.BinaryField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
+ },
+ u'metadataserver.nodecommissionresult': {
+ 'Meta': {'unique_together': "((u'node', u'name'),)", 'object_name': 'NodeCommissionResult'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
+ 'data': ('django.db.models.fields.CharField', [], {'max_length': '1048576'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
+ 'script_result': ('django.db.models.fields.IntegerField', [], {}),
+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
+ },
+ u'metadataserver.nodekey': {
+ 'Meta': {'object_name': 'NodeKey'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'unique': 'True'}),
+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Token']", 'unique': 'True'})
+ },
+ u'metadataserver.nodeuserdata': {
+ 'Meta': {'object_name': 'NodeUserData'},
+ 'data': ('metadataserver.fields.BinaryField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'unique': 'True'})
+ },
+ 'piston.consumer': {
+ 'Meta': {'object_name': 'Consumer'},
+ 'description': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': "orm['auth.User']"})
+ },
+ 'piston.token': {
+ 'Meta': {'object_name': 'Token'},
+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['piston.Consumer']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1355918694L'}),
+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
+ }
+ }
+
+ complete_apps = ['metadataserver']
\ No newline at end of file
=== modified file 'src/metadataserver/models/nodecommissionresult.py'
--- src/metadataserver/models/nodecommissionresult.py 2012-12-12 11:25:17 +0000
+++ src/metadataserver/models/nodecommissionresult.py 2012-12-19 12:37:21 +0000
@@ -18,16 +18,13 @@
from django.db.models import (
CharField,
ForeignKey,
+ IntegerField,
Manager,
)
from django.shortcuts import get_object_or_404
from maasserver.models.cleansave import CleanSave
from maasserver.models.timestampedmodel import TimestampedModel
from metadataserver import DefaultMeta
-from metadataserver.enum import (
- COMMISSIONING_STATUS,
- COMMISSIONING_STATUS_CHOICES,
- )
class NodeCommissionResultManager(Manager):
@@ -37,11 +34,11 @@
"""Remove all existing results for a node."""
self.filter(node=node).delete()
- def store_data(self, node, name, status, data):
+ def store_data(self, node, name, script_result, data):
"""Store data about a node."""
existing, created = self.get_or_create(
node=node, name=name,
- defaults=dict(status=status, data=data))
+ defaults=dict(script_result=script_result, data=data))
if not created:
existing.data = data
existing.save()
@@ -74,9 +71,6 @@
node = ForeignKey(
'maasserver.Node', null=False, editable=False, unique=False)
- status = CharField(
- max_length=100, unique=False, editable=False,
- choices=COMMISSIONING_STATUS_CHOICES,
- default=COMMISSIONING_STATUS.DEFAULT_STATUS)
+ script_result = IntegerField(editable=False)
name = CharField(max_length=255, unique=False, editable=False)
data = CharField(max_length=1024 * 1024, editable=True)
=== modified file 'src/metadataserver/tests/test_api.py'
--- src/metadataserver/tests/test_api.py 2012-12-13 11:40:36 +0000
+++ src/metadataserver/tests/test_api.py 2012-12-19 12:37:21 +0000
@@ -17,6 +17,7 @@
from io import BytesIO
import json
import os.path
+import random
import tarfile
from django.conf import settings
@@ -48,7 +49,6 @@
MetaDataHandler,
UnknownMetadataVersion,
)
-from metadataserver.enum import COMMISSIONING_STATUS
from metadataserver.models import (
NodeCommissionResult,
NodeKey,
@@ -403,17 +403,17 @@
self.assertEqual(
NODE_STATUS.COMMISSIONING, reload_object(node).status)
- def test_signaling_stores_status(self):
+ def test_signaling_stores_script_result(self):
node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
client = self.make_node_client(node=node)
- new_status = factory.getRandomEnum(COMMISSIONING_STATUS)
+ script_result = random.randint(0, 10)
filename = factory.getRandomString()
response = self.call_signal(
- client, status=new_status,
+ client, script_result=script_result,
files={filename: factory.getRandomString().encode('ascii')})
self.assertEqual(httplib.OK, response.status_code, response.content)
result = NodeCommissionResult.objects.get(node=node)
- self.assertEqual(new_status, result.status)
+ self.assertEqual(script_result, result.script_result)
def test_signaling_WORKING_keeps_owner(self):
user = factory.make_user()
@@ -497,8 +497,10 @@
for status in statuses}
for status, node in nodes.items():
client = self.make_node_client(node=node)
+ script_result = random.randint(0, 10)
self.call_signal(
client, status=status,
+ script_result=script_result,
files={filename: factory.getRandomString().encode('ascii')})
self.assertEqual(
{status: filename for status in statuses},
@@ -510,7 +512,9 @@
node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
client = self.make_node_client(node=node)
text = factory.getRandomString().encode('ascii')
- response = self.call_signal(client, files={'file.txt': text})
+ script_result = random.randint(0, 10)
+ response = self.call_signal(
+ client, script_result=script_result, files={'file.txt': text})
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
text, NodeCommissionResult.objects.get_data(node, 'file.txt'))
@@ -519,8 +523,10 @@
unicode_text = '<\u2621>'
node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
client = self.make_node_client(node=node)
+ script_result = random.randint(0, 10)
response = self.call_signal(
- client, files={'file.txt': unicode_text.encode('utf-8')})
+ client, script_result=script_result,
+ files={'file.txt': unicode_text.encode('utf-8')})
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
unicode_text,
@@ -533,7 +539,9 @@
for counter in range(3)}
node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
client = self.make_node_client(node=node)
- response = self.call_signal(client, files=contents)
+ script_result = random.randint(0, 10)
+ response = self.call_signal(
+ client, script_result=script_result, files=contents)
self.assertEqual(httplib.OK, response.status_code)
self.assertEqual(
contents,
@@ -550,8 +558,10 @@
contents = factory.getRandomString(size_limit, spaces=True)
node = factory.make_node(status=NODE_STATUS.COMMISSIONING)
client = self.make_node_client(node=node)
+ script_result = random.randint(0, 10)
response = self.call_signal(
- client, files={'output.txt': contents.encode('utf-8')})
+ client, script_result=script_result,
+ files={'output.txt': contents.encode('utf-8')})
self.assertEqual(httplib.OK, response.status_code)
stored_data = NodeCommissionResult.objects.get_data(
node, 'output.txt')
@@ -561,8 +571,10 @@
node = factory.make_node(status=NODE_STATUS.COMMISSIONING, memory=512)
client = self.make_node_client(node=node)
xmlbytes = "<t\xe9st/>".encode("utf-8")
+ script_result = random.randint(0, 10)
response = self.call_signal(
- client, files={'00-maas-01-lshw.out': xmlbytes})
+ client, script_result=script_result,
+ files={'00-maas-01-lshw.out': xmlbytes})
self.assertEqual(httplib.OK, response.status_code)
node = reload_object(node)
self.assertEqual(xmlbytes, node.hardware_details)
=== modified file 'src/metadataserver/tests/test_nodecommissionresult.py'
--- src/metadataserver/tests/test_nodecommissionresult.py 2012-12-12 11:25:17 +0000
+++ src/metadataserver/tests/test_nodecommissionresult.py 2012-12-19 12:37:21 +0000
@@ -12,12 +12,13 @@
__metaclass__ = type
__all__ = []
+from random import randint
+
from django.core.exceptions import ValidationError
from django.http import Http404
from maasserver.testing.factory import factory
from maasserver.utils.orm import get_one
from maastesting.djangotestcase import DjangoTestCase
-from metadataserver.enum import COMMISSIONING_STATUS
from metadataserver.models import NodeCommissionResult
@@ -81,9 +82,9 @@
node = factory.make_node()
name = factory.getRandomString(255)
data = factory.getRandomString(1024 * 1024)
- status = factory.getRandomEnum(COMMISSIONING_STATUS)
+ script_result = randint(0, 10)
NodeCommissionResult.objects.store_data(
- node, name=name, status=status, data=data)
+ node, name=name, script_result=script_result, data=data)
self.assertAttributes(
get_one(NodeCommissionResult.objects.filter(node=node)),
@@ -92,11 +93,11 @@
def test_store_data_updates_existing(self):
node = factory.make_node()
name = factory.getRandomString(255)
- status = factory.getRandomEnum(COMMISSIONING_STATUS)
+ script_result = randint(0, 10)
factory.make_node_commission_result(node=node, name=name)
data = factory.getRandomString(1024 * 1024)
NodeCommissionResult.objects.store_data(
- node, name=name, status=status, data=data)
+ node, name=name, script_result=script_result, data=data)
self.assertAttributes(
get_one(NodeCommissionResult.objects.filter(node=node)),