Rename directories
diff --git a/xos/configurations/devel/Dockerfile.devel b/xos/configurations/devel/Dockerfile.devel
index a253f3f..60c0143 100644
--- a/xos/configurations/devel/Dockerfile.devel
+++ b/xos/configurations/devel/Dockerfile.devel
@@ -4,7 +4,7 @@
ADD xos/configurations/common/flat_net_name /root/setup/
ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
-ADD xos/configurations/common/id_rsa /opt/xos/observers/helloworldservice/helloworldservice_private_key
+ADD xos/configurations/common/id_rsa /opt/xos/observers/helloworldservice_complete/helloworldservice_private_key
ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
ADD xos/configurations/common/node_key /root/setup/node_key
ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
diff --git a/xos/helloworldservice/__init__.py b/xos/helloworldservice/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/xos/helloworldservice/__init__.py
+++ /dev/null
diff --git a/xos/helloworldservice/admin.py b/xos/helloworldservice/admin.py
deleted file mode 100644
index 4db2f57..0000000
--- a/xos/helloworldservice/admin.py
+++ /dev/null
@@ -1,141 +0,0 @@
-
-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 creates 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 are used to denote other models that can be edited on the same
- # form as this one. In this case the service form also allows 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 fieldsets.
- suit_form_tabs = (('general', 'Hello World Service Details'),
- ('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 represent 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 creator of this service. It is a dropdown 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)
- # Set the kind field to readonly
- 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
-
- # If there is not an instance 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")
- 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 = ('id', 'backend_status_icon', 'instance', 'display_message')
- 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',)
- form = HelloWorldTenantForm
-
- suit_form_tabs = (('general', 'Details'),)
-
- 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
deleted file mode 100644
index 499c8b4..0000000
--- a/xos/helloworldservice/models.py
+++ /dev/null
@@ -1,112 +0,0 @@
-from core.models import Service, TenantWithContainer
-from django.db import transaction
-
-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
- super(HelloWorldTenant, self).__init__(*args, **kwargs)
-
- 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)
-
- @property
- def addresses(self):
- if (not self.id) or (not self.instance):
- return {}
-
- addresses = {}
- # The ports field refers to networks for the instance.
- # 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
deleted file mode 100644
index 0c60f1a..0000000
--- a/xos/helloworldservice/templates/helloworldserviceadmin.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- Template used to for the button leading to the HelloWorldTenant form. -->
-<div class = "left-nav">
- <ul>
- <li>
- <a href="/admin/helloworldservice/helloworldtenant/">
- Hello World Tenants
- </a>
- </li>
- </ul>
-</div>
diff --git a/xos/observers/helloworldservice/helloworldservice-observer.py b/xos/observers/helloworldservice/helloworldservice-observer.py
deleted file mode 100755
index 75dcc46..0000000
--- a/xos/observers/helloworldservice/helloworldservice-observer.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-
-# This imports and runs ../../xos-observer.py
-# Runs the standard XOS observer
-
-import importlib
-import os
-import sys
-observer_path = os.path.join(os.path.dirname(
- os.path.realpath(__file__)), "../..")
-sys.path.append(observer_path)
-mod = importlib.import_module("xos-observer")
-mod.main()
diff --git a/xos/observers/helloworldservice/helloworldservice_config b/xos/observers/helloworldservice/helloworldservice_config
deleted file mode 100644
index ab0024d..0000000
--- a/xos/observers/helloworldservice/helloworldservice_config
+++ /dev/null
@@ -1,50 +0,0 @@
-# Required by XOS
-[plc]
-name=plc
-deployment=plc
-
-# Required by XOS
-[db]
-name=xos
-user=postgres
-password=password
-host=localhost
-port=5432
-
-# Required by XOS
-[api]
-host=localhost
-port=8000
-ssl_key=None
-ssl_cert=None
-ca_ssl_cert=None
-ratelimit_enabled=0
-omf_enabled=0
-mail_support_address=support@localhost
-nova_enabled=True
-logfile=/var/log/xos.log
-
-# Sets options for the observer
-[observer]
-# Optional name
-name=helloworldservice
-# This is the location to the dependency graph you generate
-dependency_graph=/opt/xos/observers/helloworldservice/model-deps
-# The location of your SyncSteps
-steps_dir=/opt/xos/observers/helloworldservice/steps
-# A temporary directory that will be used by ansible
-sys_dir=/opt/xos/observers/helloworldservice/sys
-# Location of the file to save logging messages to the backend log is often used
-logfile=/var/log/xos_backend.log
-# If this option is true, then nothing will change, we simply pretend to run
-pretend=False
-# If this is False then XOS will use an exponential backoff with the observer
-# fails, since we will be waiting for an instnace, we don't want this.
-backoff_disabled=True
-# We want to output from ansible to be logged
-save_ansible_output=True
-# This determines how we SSH to a client, if this is set to True then we try
-# to ssh using the instance name as a proxy, if this is disabled we ssh using
-# the NAT IP of the instance. On CloudLab the first option will fail so we must
-# set this to False
-proxy_ssh=False
diff --git a/xos/observers/helloworldservice/model-deps b/xos/observers/helloworldservice/model-deps
deleted file mode 100644
index 0967ef4..0000000
--- a/xos/observers/helloworldservice/model-deps
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/xos/observers/helloworldservice/run.sh b/xos/observers/helloworldservice/run.sh
deleted file mode 100755
index 0fc5670..0000000
--- a/xos/observers/helloworldservice/run.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-# Runs the XOS observer using helloworldservice_config
-export XOS_DIR=/opt/xos
-python helloworldservice-observer.py -C $XOS_DIR/observers/helloworldservice/helloworldservice_config
diff --git a/xos/observers/helloworldservice/steps/sync_helloworldtenant.py b/xos/observers/helloworldservice/steps/sync_helloworldtenant.py
deleted file mode 100644
index c959999..0000000
--- a/xos/observers/helloworldservice/steps/sync_helloworldtenant.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import os
-import sys
-from django.db.models import Q, F
-from helloworldservice.models import HelloWorldService, HelloWorldTenant
-from observers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
-
-parentdir = os.path.join(os.path.dirname(__file__), "..")
-sys.path.insert(0, parentdir)
-
-# Class to define how we sync a tenant. Using SyncInstanceUsingAnsible we
-# indicate where the find the YAML for ansible, where to find the SSH key,
-# and the logic for determining what tenant needs updating, what additional
-# attributes are needed, and how to delete an instance.
-class SyncHelloWorldServiceTenant(SyncInstanceUsingAnsible):
- # Indicates the position in the data model, this will run when XOS needs to
- # enact a HelloWorldTenant
- provides = [HelloWorldTenant]
- # The actual model being enacted, usually the same as provides.
- observes = HelloWorldTenant
- # Number of milliseconds between interruptions of the observer
- requested_interval = 0
- # The ansible template to run
- template_name = "sync_helloworldtenant.yaml"
- # The location of the SSH private key to use when ansible connects to
- # instances.
- service_key_name = "/opt/xos/observers/helloworldservice/helloworldservice_private_key"
-
- def __init__(self, *args, **kwargs):
- super(SyncHelloWorldServiceTenant, self).__init__(*args, **kwargs)
-
- # Defines the logic for determining what HelloWorldTenants need to be
- # enacted.
- def fetch_pending(self, deleted):
- # If the update is not a deletion, then we get all of the instnaces that
- # have been updated or have not been enacted.
- if (not deleted):
- objs = HelloWorldTenant.get_tenant_objects().filter(
- Q(enacted__lt=F('updated')) | Q(enacted=None), Q(lazy_blocked=False))
- else:
- # If this is a deletion we get all of the deleted tenants..
- objs = HelloWorldTenant.get_deleted_tenant_objects()
-
- return objs
-
- # Gets the attributes that are used by the Ansible template but are not
- # part of the set of default attributes.
- def get_extra_attributes(self, o):
- return {"display_message": o.display_message}
diff --git a/xos/observers/helloworldservice/steps/sync_helloworldtenant.yaml b/xos/observers/helloworldservice/steps/sync_helloworldtenant.yaml
deleted file mode 100644
index 719c75f..0000000
--- a/xos/observers/helloworldservice/steps/sync_helloworldtenant.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
----
-- hosts: {{ instance_name }}
- gather_facts: False
- connection: ssh
- user: ubuntu
- sudo: yes
- tasks:
- - name: install apache
- apt: name=apache2 state=present update_cache=yes
-
- - name: write message
- shell: echo "{{ display_message }}" > /var/www/html/index.html
-
- - name: stop apache
- service: name=apache2 state=stopped
-
- - name: start apache
- service: name=apache2 state=started
diff --git a/xos/observers/helloworldservice/stop.sh b/xos/observers/helloworldservice/stop.sh
deleted file mode 100755
index 76e68d9..0000000
--- a/xos/observers/helloworldservice/stop.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-# Kill the observer
-pkill -9 -f helloworldservice-observer.py
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index d7ec5e7..252ee08 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -154,7 +154,7 @@
'core',
'hpc',
'cord',
- 'helloworldservice',
+ 'helloworldservice_complete',
'services.onos',
'ceilometer',
'requestrouter',