← Back to team overview

launchpad-reviewers team mailing list archive

[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)),