Document HelloWorldService models
diff --git a/xos/helloworldservice/admin.py b/xos/helloworldservice/admin.py
index 5fa9cad..94fb699 100644
--- a/xos/helloworldservice/admin.py
+++ b/xos/helloworldservice/admin.py
@@ -1,81 +1,130 @@
 
-from core.admin import ReadOnlyAwareAdmin, ServiceAttrAsTabInline, ServicePrivilegeInline, SliceInline
+from core.admin import ReadOnlyAwareAdmin, SliceInline
 from core.middleware import get_request
 from core.models import User
 from django import forms
 from django.contrib import admin
 from helloworldservice.models import HelloWorldService, HelloWorldTenant, HELLO_WORLD_KIND
 
-
+# The class to provide an admin interface on the web for the service.
+# We do only configuration here and don't change any logic because the logic
+# is taken care of for us by ReadOnlyAwareAdmin
 class HelloWorldServiceAdmin(ReadOnlyAwareAdmin):
+    # We must set the model so that the admin knows what fields to use
     model = HelloWorldService
     verbose_name = "Hello World Service"
     verbose_name_plural = "Hello World Services"
+
+    # Setting list_display creats columns on the admin page, each value here
+    # is a column, the column is populated for every instance of the model.
     list_display = ("backend_status_icon", "name", "enabled")
+
+    # Used to indicate which values in the columns of the admin form are links.
     list_display_links = ('backend_status_icon', 'name', )
+
+    # Denotes the sections of the form, the fields in the section, and the
+    # CSS classes used to style them. We represent this as a set of tuples, each
+    # tuple as a name (or None) and a set of fields and classes.
+    # Here the first section does not have a name so we use none. That first
+    # section has several fields indicated in the 'fields' attribute, and styled
+    # by the classes indicated in the 'classes' attribute. The classes given
+    # here are important for rendering the tabs on the form. To give the tabs
+    # we must assign the classes suit-tab and suit-tab-<name> where
+    # where <name> will be used later.
     fieldsets = [(None, {'fields': ['backend_status_text', 'name', 'enabled',
                                     'versionNumber', 'description', "view_url"],
                          'classes':['suit-tab suit-tab-general']})]
+
+    # Denotes the fields that are readonly and cannot be changed.
     readonly_fields = ('backend_status_text', )
-    inlines = [SliceInline, ServiceAttrAsTabInline, ServicePrivilegeInline]
+
+    # Inlines are used to denote other models that can be edited on the same
+    # form as this one. In this case the service form also alows changes
+    # to slices.
+    inlines = [SliceInline]
 
     extracontext_registered_admins = True
 
+    # Denotes the fields that can be changed by an admin but not be all users
     user_readonly_fields = ["name", "enabled", "versionNumber", "description"]
 
+    # Associates fieldsets from this form and from the inlines.
+    # The format here are tuples, of (<name>, tab title). <name> comes from the
+    # <name> in the fielsets.
     suit_form_tabs = (('general', 'Hello World Service Details'),
-                      ('administration', 'Administration'),
-                      ('slices', 'Slices'),
-                      )
+                      ('administration', 'Tenants'),
+                      ('slices', 'Slices'),)
 
+    # Used to include a template for a tab. Here we include the
+    # helloworldserviceadmin template in the top position for the administration
+    # tab.
     suit_form_includes = (('helloworldserviceadmin.html',
                            'top',
                            'administration'),)
 
+    # Used to get the objects for this model that are associated with the
+    # requesting user.
     def queryset(self, request):
         return HelloWorldService.get_service_objects_by_user(request.user)
 
-
+# Class to repsent the form to add and edit tenants.
+# We need to define this instead of just using an admin like we did for the
+# service because tenants vary more than services and there isn't a common form.
+# This allows us to change the python behavior for the admin form to save extra
+# fields and control defaults.
 class HelloWorldTenantForm(forms.ModelForm):
+    # Defines a field for the careator of this service. It is a dropbown which
+    # is populated with all of the users.
     creator = forms.ModelChoiceField(queryset=User.objects.all())
+    # Defines a text field for the display message, it is not required.
     display_message = forms.CharField(required=False)
 
     def __init__(self, *args, **kwargs):
         super(HelloWorldTenantForm, self).__init__(*args, **kwargs)
-        self.fields['kind'].widget.attrs['readonly'] = True
+        # Define the logic for obtaining the objects for the provider_service
+        # dropdown of the tenant form.
         self.fields[
             'provider_service'].queryset = HelloWorldService.get_service_objects().all()
+        # Set the initial kind to HELLO_WORLD_KIND for this tenant.
+        self.fields['kind'].initial = HELLO_WORLD_KIND
+        # If there is an instance of this model then we can set the initial
+        # form values to the existing values.
         if self.instance:
             self.fields['creator'].initial = self.instance.creator
             self.fields[
                 'display_message'].initial = self.instance.display_message
-        self.fields['kind'].initial = HELLO_WORLD_KIND
+
+        # If there is not an instnace then we need to set initial values.
         if (not self.instance) or (not self.instance.pk):
             self.fields['creator'].initial = get_request().user
             if HelloWorldService.get_service_objects().exists():
                 self.fields["provider_service"].initial = HelloWorldService.get_service_objects().all()[
                     0]
 
+    # This function describes what happens when the save button is pressed on
+    # the tenant form. In this case we set the values for the instance that were
+    # entered.
     def save(self, commit=True):
         self.instance.creator = self.cleaned_data.get("creator")
-        self.instance.display_message = self.cleaned_data.get(
-            "display_message")
+        self.instance.display_message = self.cleaned_data.get("display_message")
         return super(HelloWorldTenantForm, self).save(commit=commit)
 
     class Meta:
         model = HelloWorldTenant
 
-
+# Define the admin form for the tenant. This uses a similar structure as the
+# service but uses HelloWorldTenantForm to change the python behavior.
 class HelloWorldTenantAdmin(ReadOnlyAwareAdmin):
     verbose_name = "Hello World Tenant"
     verbose_name_plural = "Hello World Tenants"
-    list_display = ('backend_status_icon', 'id', )
-    list_display_links = ('backend_status_icon', 'id')
+    list_display = ('backend_status_icon', 'instance', 'display_message', 'id')
+    list_display_links = ('backend_status_icon', 'instance', 'display_message',
+                          'id')
     fieldsets = [(None, {'fields': ['backend_status_text', 'kind',
                                     'provider_service', 'instance', 'creator',
                                     'display_message'],
                          'classes': ['suit-tab suit-tab-general']})]
-    readonly_fields = ('backend_status_text', 'instance',)
+    readonly_fields = ('backend_status_text', 'instance', 'kind', )
     form = HelloWorldTenantForm
 
     suit_form_tabs = (('general', 'Details'),)
@@ -83,5 +132,6 @@
     def queryset(self, request):
         return HelloWorldTenant.get_tenant_objects_by_user(request.user)
 
+# Associate the admin forms with the models.
 admin.site.register(HelloWorldService, HelloWorldServiceAdmin)
 admin.site.register(HelloWorldTenant, HelloWorldTenantAdmin)
diff --git a/xos/helloworldservice/models.py b/xos/helloworldservice/models.py
index bc94e07..8c5e303 100644
--- a/xos/helloworldservice/models.py
+++ b/xos/helloworldservice/models.py
@@ -3,28 +3,48 @@
 
 HELLO_WORLD_KIND = "helloworldservice"
 
-
+# The class to represent the service. Most of the service logic is given for us
+# in the Service class but, we have some configuration that is specific for
+# this example.
 class HelloWorldService(Service):
     KIND = HELLO_WORLD_KIND
 
     class Meta:
+        # When the proxy field is set to True the model is represented as
+        # it's superclass in the database, but we can still change the pyhton
+        # behavior. In this case HelloWorldService is a Service in the database.
         proxy = True
+        # The name used to find this service, all directories are named this
         app_label = "helloworldservice"
         verbose_name = "Hello World Service"
 
-
+# This is the class to represent the tenant. Most of the logic is given to use
+# in TenantWithContainer, however there is some configuration and logic that
+# we need to define for this example.
 class HelloWorldTenant(TenantWithContainer):
 
     class Meta:
+        # Same as a above, HelloWorldTenant is represented as a
+        # TenantWithContainer, but we change the python behavior.
         proxy = True
 
+    # The kind of the service is used on forms to differentiate this service
+    # from the other services.
     KIND = HELLO_WORLD_KIND
+
+    # Ansible requires that the sync_attributes field contain nat_ip and nat_mac
+    # these will be used to determine where to SSH to for ansible.
+    # Getters must be defined for every attribute specified here.
     sync_attributes = ("nat_ip", "nat_mac",)
 
+    # default_attributes is used cleanly indicate what the default values for
+    # the fields are.
     default_attributes = {'display_message': 'Hello World!'}
 
     def __init__(self, *args, **kwargs):
         helloworld_services = HelloWorldService.get_service_objects().all()
+        # When the tenant is created the default service in the form is set
+        # to be the first created HelloWorldService
         if helloworld_services:
             self._meta.get_field(
                 "provider_service").default = helloworld_services[0].id
@@ -32,18 +52,24 @@
 
     def save(self, *args, **kwargs):
         super(HelloWorldTenant, self).save(*args, **kwargs)
+        # This call needs to happen so that an instance is created for this
+        # tenant is created in the slice. One instance is created per tenant.
         model_policy_helloworld_tenant(self.pk)
 
     def delete(self, *args, **kwargs):
+        # Delete the instance that was created for this tenant
         self.cleanup_container()
         super(HelloWorldTenant, self).delete(*args, **kwargs)
 
+    # Getter for the message that will appear on the webpage
+    # By default it is "Hello World!"
     @property
     def display_message(self):
         return self.get_attribute(
             "display_message",
             self.default_attributes['display_message'])
 
+    # Setter for the message that will appear on the webpage
     @display_message.setter
     def display_message(self, value):
         self.set_attribute("display_message", value)
@@ -54,23 +80,31 @@
             return {}
 
         addresses = {}
+        # The ports field refers to networks for the instnace.
+        # This loop stores the details for the NAT network that will be
+        # necessary for ansible..
         for ns in self.instance.ports.all():
             if "nat" in ns.network.name.lower():
                 addresses["nat"] = (ns.ip, ns.mac)
         return addresses
 
+    # This getter is necessary because nat_ip is a sync_attribute
     @property
     def nat_ip(self):
         return self.addresses.get("nat", (None, None))[0]
 
+    # This getter is necessary because nat_mac is a sync_attribute
     @property
     def nat_mac(self):
         return self.addresses.get("nat", (None, None))[1]
 
 def model_policy_helloworld_tenant(pk):
+    # This section of code is atomic to prevent race conditions
     with transaction.atomic():
+        # We find all of the tenants that are waiting to update
         tenant = HelloWorldTenant.objects.select_for_update().filter(pk=pk)
         if not tenant:
             return
+        # Since this code is atomic it is safe to always use the first tenant
         tenant = tenant[0]
         tenant.manage_container()
diff --git a/xos/helloworldservice/templates/helloworldserviceadmin.html b/xos/helloworldservice/templates/helloworldserviceadmin.html
index eb8ec35..03f36b8 100644
--- a/xos/helloworldservice/templates/helloworldserviceadmin.html
+++ b/xos/helloworldservice/templates/helloworldserviceadmin.html
@@ -1,5 +1,10 @@
+<!-- Template used to for the button leading to the helloworldteant form. -->
 <div class = "left-nav">
-<ul>
-<li><a href="/admin/helloworldservice/helloworldtenant/">Hello World Tenants</a></li>
-</ul>
+  <ul>
+    <li>
+      <a href="/admin/helloworldservice/helloworldtenant/">
+        Hello World Tenants
+      </a>
+    </li>
+  </ul>
 </div>