blob: 0feb2e5e5ee097c0ae1e4c3fa6c612c8e706a20e [file] [log] [blame]
Scott Baker065e15c2015-10-19 21:20:24 -07001import hashlib
2import os
3import socket
4import sys
5import base64
6import time
7from django.db.models import F, Q
8from xos.config import Config
9from observer.syncstep import SyncStep
10from observer.ansible import run_template_ssh
11from observers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
12from core.models import Service, Slice
13from services.onos.models import ONOSService, ONOSApp
14from util.logger import Logger, logging
15
16# hpclibrary will be in steps/..
17parentdir = os.path.join(os.path.dirname(__file__),"..")
18sys.path.insert(0,parentdir)
19
20logger = Logger(level=logging.INFO)
21
22class SyncONOSApp(SyncInstanceUsingAnsible):
23 provides=[ONOSApp]
24 observes=ONOSApp
25 requested_interval=0
26 template_name = "sync_onosapp.yaml"
27 service_key_name = "/opt/xos/observers/onos/onos_key"
28
29 def __init__(self, *args, **kwargs):
30 super(SyncONOSApp, self).__init__(*args, **kwargs)
31
32 def fetch_pending(self, deleted):
33 if (not deleted):
34 objs = ONOSApp.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
35 else:
36 objs = ONOSApp.get_deleted_tenant_objects()
37
38 return objs
39
40 def get_instance(self, o):
41 # We assume the ONOS service owns a slice, so pick one of the instances
42 # inside that slice to sync to.
43
44 serv = self.get_onos_service(o)
45
46 if serv.use_external_host:
47 return serv.use_external_host
48
49 if serv.slices.exists():
50 slice = serv.slices.all()[0]
51 if slice.instances.exists():
52 return slice.instances.all()[0]
53
54 return None
55
56 def get_onos_service(self, o):
57 if not o.provider_service:
58 return None
59
60 onoses = ONOSService.get_service_objects().filter(id=o.provider_service.id)
61 if not onoses:
62 return None
63
64 return onoses[0]
65
Scott Baker42b020f2015-10-20 11:07:27 -070066 def get_files_dir(self, o):
67 if not hasattr(Config(), "observer_steps_dir"):
68 # make steps_dir mandatory; there's no valid reason for it to not
69 # be defined.
70 raise Exception("observer_steps_dir is not defined in config file")
71
72 step_dir = Config().observer_steps_dir
73
74 return os.path.join(step_dir, "..", "files", str(self.get_onos_service(o).id), o.name)
75
Scott Baker065e15c2015-10-19 21:20:24 -070076 def write_configs(self, o):
77 o.config_fns = []
Scott Bakera758d822015-12-03 21:14:39 -080078 o.rest_configs = []
Scott Baker42b020f2015-10-20 11:07:27 -070079 o.files_dir = self.get_files_dir(o)
Scott Baker065e15c2015-10-19 21:20:24 -070080
81 if not os.path.exists(o.files_dir):
82 os.makedirs(o.files_dir)
83
Scott Baker57da61c2015-12-07 22:21:33 -080084 # Combine the service attributes with the tenant attributes. Tenant
85 # attribute can override service attributes.
86 attrs = o.provider_service.serviceattribute_dict
87 attrs.update(o.tenantattribute_dict)
88
89 for (name, value) in attrs.items():
90 if name.startswith("config_"):
91 fn = name[7:] # .replace("_json",".json")
Scott Baker065e15c2015-10-19 21:20:24 -070092 o.config_fns.append(fn)
Scott Baker57da61c2015-12-07 22:21:33 -080093 file(os.path.join(o.files_dir, fn),"w").write(value)
94 if name.startswith("rest_"):
95 fn = name[5:].replace("/","_")
96 endpoint = name[5:]
Scott Bakera758d822015-12-03 21:14:39 -080097 # Ansible goes out of it's way to make our life difficult. If
98 # 'lookup' sees a file that it thinks contains json, then it'll
99 # insist on parsing and return a json object. We just want
100 # a string, so prepend a space and then strip the space off
101 # later.
Scott Baker57da61c2015-12-07 22:21:33 -0800102 file(os.path.join(o.files_dir, fn),"w").write(" " +value)
Scott Bakera758d822015-12-03 21:14:39 -0800103 o.rest_configs.append( {"endpoint": endpoint, "fn": fn} )
Scott Baker065e15c2015-10-19 21:20:24 -0700104
105 def prepare_record(self, o):
106 self.write_configs(o)
107
108 def get_extra_attributes(self, o):
Scott Baker1420b0c2015-12-14 21:16:46 -0800109 instance = self.get_instance(o)
110
Scott Baker065e15c2015-10-19 21:20:24 -0700111 fields={}
Scott Baker42b020f2015-10-20 11:07:27 -0700112 fields["files_dir"] = o.files_dir
Scott Baker065e15c2015-10-19 21:20:24 -0700113 fields["appname"] = o.name
Scott Baker1420b0c2015-12-14 21:16:46 -0800114 fields["nat_ip"] = instance.get_ssh_ip()
Scott Baker065e15c2015-10-19 21:20:24 -0700115 fields["config_fns"] = o.config_fns
Scott Bakera758d822015-12-03 21:14:39 -0800116 fields["rest_configs"] = o.rest_configs
Scott Baker1420b0c2015-12-14 21:16:46 -0800117 if o.dependencies:
118 fields["dependencies"] = [x.strip() for x in o.dependencies.split(",")]
119 else:
120 fields["dependencies"] = []
121
122 if (instance.isolation=="container"):
123 fields["ONOS_container"] = "%s-%s" % (instance.slice.name, str(instance.id))
124 else:
125 fields["ONOS_container"] = "ONOS"
Scott Baker065e15c2015-10-19 21:20:24 -0700126 return fields
127
128 def sync_fields(self, o, fields):
129 # the super causes the playbook to be run
130 super(SyncONOSApp, self).sync_fields(o, fields)
131
132 def run_playbook(self, o, fields):
133 super(SyncONOSApp, self).run_playbook(o, fields)
134
135 def delete_record(self, m):
136 pass