blob: 8a4ce591d2210c548f37ef1db17dc0df3db4b662 [file] [log] [blame]
Jeremy Mowery15687342015-11-29 19:08:04 -07001from core.models import Service, TenantWithContainer
2from django.db import transaction
3
4HELLO_WORLD_KIND = "helloworldservice_complete"
5
6# The class to represent the service. Most of the service logic is given for us
7# in the Service class but, we have some configuration that is specific for
8# this example.
Jeremy Moweryb971a762015-11-29 19:46:05 -07009class HelloWorldServiceComplete(Service):
Jeremy Mowery15687342015-11-29 19:08:04 -070010 KIND = HELLO_WORLD_KIND
11
12 class Meta:
13 # When the proxy field is set to True the model is represented as
Jeremy Moweryf4dea162015-12-01 09:24:27 -070014 # it's superclass in the database, but we can still change the python
Jeremy Moweryb971a762015-11-29 19:46:05 -070015 # behavior. In this case HelloWorldServiceComplete is a Service in the
Jeremy Mowery15687342015-11-29 19:08:04 -070016 # database.
17 proxy = True
18 # The name used to find this service, all directories are named this
19 app_label = "helloworldservice_complete"
20 verbose_name = "Hello World Service"
21
22# This is the class to represent the tenant. Most of the logic is given to use
23# in TenantWithContainer, however there is some configuration and logic that
24# we need to define for this example.
Jeremy Moweryb971a762015-11-29 19:46:05 -070025class HelloWorldTenantComplete(TenantWithContainer):
Jeremy Mowery15687342015-11-29 19:08:04 -070026
27 class Meta:
Jeremy Moweryb971a762015-11-29 19:46:05 -070028 # Same as a above, HelloWorldTenantComplete is represented as a
Jeremy Mowery15687342015-11-29 19:08:04 -070029 # TenantWithContainer, but we change the python behavior.
30 proxy = True
Jeremy Mowery12fd1572015-12-01 12:31:43 -070031 verbose_name = "Hello World Tenant"
Jeremy Mowery15687342015-11-29 19:08:04 -070032
33 # The kind of the service is used on forms to differentiate this service
34 # from the other services.
35 KIND = HELLO_WORLD_KIND
36
37 # Ansible requires that the sync_attributes field contain nat_ip and nat_mac
38 # these will be used to determine where to SSH to for ansible.
39 # Getters must be defined for every attribute specified here.
40 sync_attributes = ("nat_ip", "nat_mac",)
41
42 # default_attributes is used cleanly indicate what the default values for
43 # the fields are.
44 default_attributes = {'display_message': 'Hello World!'}
45
46 def __init__(self, *args, **kwargs):
Jeremy Moweryb971a762015-11-29 19:46:05 -070047 helloworld_services = HelloWorldServiceComplete.get_service_objects().all()
Jeremy Mowery15687342015-11-29 19:08:04 -070048 # When the tenant is created the default service in the form is set
Jeremy Moweryb971a762015-11-29 19:46:05 -070049 # to be the first created HelloWorldServiceComplete
Jeremy Mowery15687342015-11-29 19:08:04 -070050 if helloworld_services:
51 self._meta.get_field(
52 "provider_service").default = helloworld_services[0].id
Jeremy Moweryb971a762015-11-29 19:46:05 -070053 super(HelloWorldTenantComplete, self).__init__(*args, **kwargs)
Jeremy Mowery15687342015-11-29 19:08:04 -070054
55 def save(self, *args, **kwargs):
Jeremy Moweryb971a762015-11-29 19:46:05 -070056 super(HelloWorldTenantComplete, self).save(*args, **kwargs)
Jeremy Mowery15687342015-11-29 19:08:04 -070057 # This call needs to happen so that an instance is created for this
58 # tenant is created in the slice. One instance is created per tenant.
59 model_policy_helloworld_tenant(self.pk)
60
61 def delete(self, *args, **kwargs):
62 # Delete the instance that was created for this tenant
63 self.cleanup_container()
Jeremy Moweryb971a762015-11-29 19:46:05 -070064 super(HelloWorldTenantComplete, self).delete(*args, **kwargs)
Jeremy Mowery15687342015-11-29 19:08:04 -070065
66 # Getter for the message that will appear on the webpage
67 # By default it is "Hello World!"
68 @property
69 def display_message(self):
70 return self.get_attribute(
71 "display_message",
72 self.default_attributes['display_message'])
73
74 # Setter for the message that will appear on the webpage
75 @display_message.setter
76 def display_message(self, value):
77 self.set_attribute("display_message", value)
78
79 @property
80 def addresses(self):
81 if (not self.id) or (not self.instance):
82 return {}
83
84 addresses = {}
85 # The ports field refers to networks for the instance.
86 # This loop stores the details for the NAT network that will be
87 # necessary for ansible.
88 for ns in self.instance.ports.all():
89 if "nat" in ns.network.name.lower():
90 addresses["nat"] = (ns.ip, ns.mac)
91 return addresses
92
93 # This getter is necessary because nat_ip is a sync_attribute
94 @property
95 def nat_ip(self):
96 return self.addresses.get("nat", (None, None))[0]
97
98 # This getter is necessary because nat_mac is a sync_attribute
99 @property
100 def nat_mac(self):
101 return self.addresses.get("nat", (None, None))[1]
102
103
104def model_policy_helloworld_tenant(pk):
105 # This section of code is atomic to prevent race conditions
106 with transaction.atomic():
107 # We find all of the tenants that are waiting to update
Jeremy Moweryb971a762015-11-29 19:46:05 -0700108 tenant = HelloWorldTenantComplete.objects.select_for_update().filter(pk=pk)
Jeremy Mowery15687342015-11-29 19:08:04 -0700109 if not tenant:
110 return
111 # Since this code is atomic it is safe to always use the first tenant
112 tenant = tenant[0]
113 tenant.manage_container()