| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 1 | import hashlib |
| 2 | import os |
| 3 | import socket |
| 4 | import sys |
| 5 | import base64 |
| 6 | import time |
| 7 | from django.db.models import F, Q |
| 8 | from xos.config import Config |
| 9 | from observer.syncstep import SyncStep |
| 10 | from observer.ansible import run_template_ssh |
| 11 | from observers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible |
| 12 | from core.models import Service, Slice |
| 13 | from services.onos.models import ONOSService, ONOSApp |
| 14 | from util.logger import Logger, logging |
| 15 | |
| 16 | # hpclibrary will be in steps/.. |
| 17 | parentdir = os.path.join(os.path.dirname(__file__),"..") |
| 18 | sys.path.insert(0,parentdir) |
| 19 | |
| 20 | logger = Logger(level=logging.INFO) |
| 21 | |
| 22 | class 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 Baker | 42b020f | 2015-10-20 11:07:27 -0700 | [diff] [blame] | 66 | 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 Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 76 | def write_configs(self, o): |
| 77 | o.config_fns = [] |
| Scott Baker | a758d82 | 2015-12-03 21:14:39 -0800 | [diff] [blame] | 78 | o.rest_configs = [] |
| Scott Baker | 42b020f | 2015-10-20 11:07:27 -0700 | [diff] [blame] | 79 | o.files_dir = self.get_files_dir(o) |
| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 80 | |
| 81 | if not os.path.exists(o.files_dir): |
| 82 | os.makedirs(o.files_dir) |
| 83 | |
| Scott Baker | 57da61c | 2015-12-07 22:21:33 -0800 | [diff] [blame] | 84 | # 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 Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 92 | o.config_fns.append(fn) |
| Scott Baker | 57da61c | 2015-12-07 22:21:33 -0800 | [diff] [blame] | 93 | 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 Baker | a758d82 | 2015-12-03 21:14:39 -0800 | [diff] [blame] | 97 | # 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 Baker | 57da61c | 2015-12-07 22:21:33 -0800 | [diff] [blame] | 102 | file(os.path.join(o.files_dir, fn),"w").write(" " +value) |
| Scott Baker | a758d82 | 2015-12-03 21:14:39 -0800 | [diff] [blame] | 103 | o.rest_configs.append( {"endpoint": endpoint, "fn": fn} ) |
| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 104 | |
| 105 | def prepare_record(self, o): |
| 106 | self.write_configs(o) |
| 107 | |
| 108 | def get_extra_attributes(self, o): |
| Scott Baker | 1420b0c | 2015-12-14 21:16:46 -0800 | [diff] [blame] | 109 | instance = self.get_instance(o) |
| 110 | |
| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 111 | fields={} |
| Scott Baker | 42b020f | 2015-10-20 11:07:27 -0700 | [diff] [blame] | 112 | fields["files_dir"] = o.files_dir |
| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 113 | fields["appname"] = o.name |
| Scott Baker | 1420b0c | 2015-12-14 21:16:46 -0800 | [diff] [blame] | 114 | fields["nat_ip"] = instance.get_ssh_ip() |
| Scott Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 115 | fields["config_fns"] = o.config_fns |
| Scott Baker | a758d82 | 2015-12-03 21:14:39 -0800 | [diff] [blame] | 116 | fields["rest_configs"] = o.rest_configs |
| Scott Baker | 1420b0c | 2015-12-14 21:16:46 -0800 | [diff] [blame] | 117 | 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 Baker | 065e15c | 2015-10-19 21:20:24 -0700 | [diff] [blame] | 126 | 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 |