blob: 031185409d9ae835f0bb3a8d8beee5997d4a184c [file] [log] [blame]
Scott Baker4aa660e2015-06-09 12:22:29 -07001import hashlib
Scott Baker64b889b2015-05-05 17:53:12 -07002import os
3import socket
4import sys
5import base64
Scott Baker3145da12015-06-09 12:03:07 -07006import time
Scott Baker64b889b2015-05-05 17:53:12 -07007from django.db.models import F, Q
8from xos.config import Config
9from observer.syncstep import SyncStep
10from observer.ansible import run_template_ssh
11from core.models import Service
12from cord.models import VCPEService, VCPETenant, VOLTTenant
13from hpc.models import HpcService, CDNPrefix
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
Scott Bakercdf47142015-06-01 16:15:42 -070020from broadbandshield import BBS
21
Scott Baker64b889b2015-05-05 17:53:12 -070022logger = Logger(level=logging.INFO)
23
24class SyncVCPETenant(SyncStep):
25 provides=[VCPETenant]
26 observes=VCPETenant
27 requested_interval=0
28 template_name = "sync_vcpetenant.yaml"
29 service_key_name = "/opt/xos/observers/vcpe/vcpe_private_key"
30
31 def __init__(self, **args):
32 SyncStep.__init__(self, **args)
33
34 def defer_sync(self, o, reason):
Scott Baker61c8e8d2015-06-02 14:34:04 -070035 logger.info("defer object %s due to %s" % (str(o), reason))
Scott Baker59e88d52015-06-02 09:48:47 -070036 raise Exception("defer object %s due to %s" % (str(o), reason))
Scott Baker64b889b2015-05-05 17:53:12 -070037
38 def fetch_pending(self, deleted):
39 if (not deleted):
40 objs = VCPETenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
41 else:
42 objs = VCPETenant.get_deleted_tenant_objects()
43
44 return objs
45
46 def get_extra_attributes(self, o):
47 # This is a place to include extra attributes that aren't part of the
48 # object itself. In our case, it's handy to know the VLAN IDs when
49 # configuring the VCPE.
50
51 dnsdemux_ip = "none"
52 for service in HpcService.objects.all():
53 for slice in service.slices.all():
54 if "dnsdemux" in slice.name:
55 for sliver in slice.slivers.all():
Scott Baker4d5d5d72015-06-05 12:09:36 -070056 # Connect to a dnsdemux that's on the hpc_client network
57 # if one is available.
58 for ns in sliver.networkslivers.all():
59 if ns.ip and ns.network.labels and ("hpc_client" in ns.network.labels):
60 dnsdemux_ip = ns.ip
Scott Baker64b889b2015-05-05 17:53:12 -070061 if dnsdemux_ip=="none":
62 try:
63 dnsdemux_ip = socket.gethostbyname(sliver.node.name)
64 except:
65 pass
66
Scott Baker2e64a3a2015-05-06 20:06:21 -070067 cdn_prefixes = []
68 for prefix in CDNPrefix.objects.all():
69 cdn_prefixes.append(prefix.prefix)
70
Scott Bakerf674e912015-05-08 10:56:13 -070071 volts = [x for x in VOLTTenant.get_tenant_objects() if (x.vcpe is not None) and (x.vcpe.id==o.id)]
Scott Baker64b889b2015-05-05 17:53:12 -070072 vlan_ids = [x.vlan_id for x in volts]
Scott Baker74e20522015-06-10 16:16:01 -070073
74 bbs_addrs = []
75 bbs_slices = Slice.objects.filter(name="mysite_bbs")
76 if bbs_slices:
77 bbs_slice = bbs_slices[0]
78 for bbs_sliver in bbs_slice.slivers.all():
79 for ns in bbs_sliver.networkslicers.all():
80 if ns.ip and ns.network.labels and ("hpc_client" in ns.network.labels):
81 bbs_addrs.append(ns.ip)
82
83 if not bbs_addrs:
84 bbs_addrs = ["198.105.255.10",
85 "198.105.255.11",
86 "198.105.255.12",
87 "198.105.255.13"]
88
Scott Baker64b889b2015-05-05 17:53:12 -070089 return {"vlan_ids": vlan_ids,
Scott Baker2e64a3a2015-05-06 20:06:21 -070090 "dnsdemux_ip": dnsdemux_ip,
Scott Baker74e20522015-06-10 16:16:01 -070091 "cdn_prefixes": cdn_prefixes,
92 "bbs_addrs": bbs_addrs}
Scott Baker64b889b2015-05-05 17:53:12 -070093
94 def get_sliver(self, o):
95 # We need to know what slivers is associated with the object.
96 # For vCPE this is easy, as VCPETenant has a sliver field.
97
98 return o.sliver
99
100 def sync_record(self, o):
101 logger.info("sync'ing VCPETenant %s" % str(o))
102
103 sliver = self.get_sliver(o)
104 if not sliver:
105 self.defer_sync(o, "waiting on sliver")
106 return
107
108 service = o.sliver.slice.service
109 if not service:
110 # Ansible uses the service's keypair in order to SSH into the
111 # instance. It would be bad if the slice had no service.
112
113 raise Exception("Slice %s is not associated with a service" % sliver.slice.name)
114
115 if not os.path.exists(self.service_key_name):
116 raise Exception("Service key %s does not exist" % self.service_key_name)
117
118 service_key = file(self.service_key_name).read()
119
120 fields = { "sliver_name": sliver.name,
121 "hostname": sliver.node.name,
122 "instance_id": sliver.instance_id,
123 "private_key": service_key,
Scott Baker83734052015-05-12 16:13:29 -0700124 "ansible_tag": "vcpe_tenant_" + str(o.id)
Scott Baker64b889b2015-05-05 17:53:12 -0700125 }
126
127 if hasattr(o, "sync_attributes"):
128 for attribute_name in o.sync_attributes:
129 fields[attribute_name] = getattr(o, attribute_name)
130
131 fields.update(self.get_extra_attributes(o))
Scott Baker4aa660e2015-06-09 12:22:29 -0700132
133 ansible_hash = hashlib.md5(repr(sorted(fields.items()))).hexdigest()
134 quick_update = (o.last_ansible_hash == ansible_hash)
135
136 if quick_update:
137 logger.info("quick_update triggered; skipping ansible recipe")
138 else:
139 tStart = time.time()
140 run_template_ssh(self.template_name, fields)
141 logger.info("playbook execution time %d" % int(time.time()-tStart))
Scott Baker64b889b2015-05-05 17:53:12 -0700142
Scott Bakercdf47142015-06-01 16:15:42 -0700143 if o.url_filter_enable:
Scott Bakercf155f42015-06-08 19:09:53 -0700144 if (str(o.service_specific_id) != "SYNCME"):
Scott Bakerdf877da2015-06-08 18:58:39 -0700145 # XXX FIXME
146 # Also fix the spot in cord/models.py
147 logger.info("skipping sync of URL filter for SSID %s" % str(o.service_specific_id))
148 else:
Scott Baker3145da12015-06-09 12:03:07 -0700149 tStart = time.time()
Scott Bakerdf877da2015-06-08 18:58:39 -0700150 bbs = BBS(o.bbs_account, "123")
151 bbs.sync(o.url_filter_level, o.users)
Scott Baker3145da12015-06-09 12:03:07 -0700152 logger.info("bbs update tiem %d" % int(time.time()-tStart))
Scott Bakercdf47142015-06-01 16:15:42 -0700153
Scott Baker4aa660e2015-06-09 12:22:29 -0700154 o.last_ansible_hash = ansible_hash
Scott Baker64b889b2015-05-05 17:53:12 -0700155 o.save()
156
157 def delete_record(self, m):
158 pass
159