blob: 94875f48ee6933b5ae4fdbc9c6b88dfdc3e9b7c8 [file] [log] [blame]
Sapan Bhatia2ac88642016-01-15 10:43:19 -05001import os
2import requests
3import socket
4import sys
5import base64
6from django.db.models import F, Q
7from xos.config import Config
8from synchronizers.base.syncstep import SyncStep
9from synchronizers.base.ansible import run_template_ssh
10from core.models import Service
11from services.cord.models import VCPEService, VCPETenant, VBNGTenant, VBNGService
12from services.hpc.models import HpcService, CDNPrefix
Scott Baker3a01eb22016-01-15 07:57:33 -080013from xos.logger import Logger, logging
Sapan Bhatia2ac88642016-01-15 10:43:19 -050014
15# VBNG_API = "http://10.0.3.136:8181/onos/virtualbng/privateip/"
16
17# hpclibrary will be in steps/..
18parentdir = os.path.join(os.path.dirname(__file__),"..")
19sys.path.insert(0,parentdir)
20
21logger = Logger(level=logging.INFO)
22
23class SyncVBNGTenant(SyncStep):
24 provides=[VCPETenant]
25 observes=VCPETenant
26 requested_interval=0
27
28 def __init__(self, **args):
29 SyncStep.__init__(self, **args)
30
31 def fetch_pending(self, deleted):
32 if (not deleted):
33 objs = VBNGTenant.get_tenant_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
34 else:
35 objs = VBNGTenant.get_deleted_tenant_objects()
36
37 return objs
38
39 def defer_sync(self, o, reason):
40 logger.info("defer object %s due to %s" % (str(o), reason))
41 raise Exception("defer object %s due to %s" % (str(o), reason))
42
43 def get_vbng_service(self, o):
44 if not o.provider_service:
45 raise Exception("vBNG tenant %s has no provider_service" % str(o.id))
46 services = VBNGService.get_service_objects().filter(id = o.provider_service.id)
47 if not services:
48 raise Exception("vBNG tenant %s is associated with the wrong kind of provider_service" % str(o.id))
49 return services[0]
50
51 def get_vbng_url(self, o):
52 service = self.get_vbng_service(o)
53
54 # if the service object specifies a vbng_url, then use it
55 if service.vbng_url:
56 return service.vbng_url
57
58 # otherwise, see if the service has tenancy in ONOS
59 for tenant in service.subscribed_tenants.all():
60 if tenant.provider_service and tenant.provider_service.kind == "onos":
61 onos_service = tenant.provider_service
62 if not onos_service.slices.exists():
63 raise Exception("vBNG service is linked to an ONOSApp, but the App's Service has no slices")
64 onos_slice = onos_service.slices.all()[0]
65 if not onos_slice.instances.exists():
66 raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice has no instances")
67 instance = onos_slice.instances.all()[0]
68
69 #onos_app = ONOSApp.objects.filter(id = tenant.id)
70 #instance = onos_app.instance
71 #if not instance:
72 # raise Exception("ONOSApp has no instance")
73
74 if not instance.instance_name:
75 raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance is not instantiated")
76 ip = instance.get_network_ip("nat")
77 if not ip:
78 raise Exception("vBNG service is linked to an ONOSApp, but the App's Service's Slice's first instance does not have an ip")
79
80 logger.info("Using ip %s from ONOS Instance %s" % (ip, instance))
81
82 return "http://%s:8181/onos/virtualbng/" % ip
83
84 raise Exception("vBNG service does not have vbng_url set, and is not linked to an ONOSApp")
85
86 def get_private_interface(self, o):
87 vcpes = VCPETenant.get_tenant_objects().all()
88 vcpes = [x for x in vcpes if (x.vbng is not None) and (x.vbng.id == o.id)]
89 if not vcpes:
90 raise Exception("No vCPE tenant is associated with vBNG %s" % str(o.id))
91 if len(vcpes)>1:
92 raise Exception("More than one vCPE tenant is associated with vBNG %s" % str(o.id))
93
94 vcpe = vcpes[0]
95 instance = vcpe.instance
96
97 if not instance:
98 raise Exception("No instance associated with vBNG %s" % str(o.id))
99
100 if not vcpe.wan_ip:
101 self.defer_sync(o, "does not have a WAN IP yet")
102
103 if not vcpe.wan_container_mac:
104 # this should never happen; container MAC is computed from WAN IP
105 self.defer_sync(o, "does not have a WAN container MAC yet")
106
107 return (vcpe.wan_ip, vcpe.wan_container_mac, vcpe.instance.node.name)
108
109 def sync_record(self, o):
110 logger.info("sync'ing VBNGTenant %s" % str(o))
111
112 if not o.routeable_subnet:
113 (private_ip, private_mac, private_hostname) = self.get_private_interface(o)
114 logger.info("contacting vBNG service to request mapping for private ip %s mac %s host %s" % (private_ip, private_mac, private_hostname) )
115
116 url = self.get_vbng_url(o) + "privateip/%s/%s/%s" % (private_ip, private_mac, private_hostname)
117 logger.info( "vbng url: %s" % url )
118 r = requests.post(url )
119 if (r.status_code != 200):
120 raise Exception("Received error from bng service (%d)" % r.status_code)
121 logger.info("received public IP %s from private IP %s" % (r.text, private_ip))
122
123 if r.text == "0":
124 raise Exception("VBNG service failed to return a routeable_subnet (probably ran out)")
125
126 o.routeable_subnet = r.text
127 o.mapped_ip = private_ip
128 o.mapped_mac = private_mac
129 o.mapped_hostname = private_hostname
130
131 o.save()
132
133 def delete_record(self, o):
134 logger.info("deleting VBNGTenant %s" % str(o))
135
136 if o.mapped_ip:
137 private_ip = o.mapped_ip
138 logger.info("contacting vBNG service to delete private ip %s" % private_ip)
139 r = requests.delete(self.get_vbng_url(o) + "privateip/%s" % private_ip, )
140 if (r.status_code != 200):
141 raise Exception("Received error from bng service (%d)" % r.status_code)
142