blob: 5f9c1db9b7fe8a6f9317604c9bc57995af90eedc [file] [log] [blame]
Scott Baker46831592016-06-20 17:32:04 -07001import os
2import base64
3from collections import defaultdict
Scott Baker71c20eb2017-03-14 21:35:18 -07004from synchronizers.new_base.syncstep import SyncStep, DeferredException
5from synchronizers.new_base.modelaccessor import *
Scott Baker46831592016-06-20 17:32:04 -07006from xos.logger import observer_logger as logger
Scott Baker46831592016-06-20 17:32:04 -07007import json
8
9class SyncVRouterTenant(SyncStep):
10 provides=[VRouterTenant]
11 observes = VRouterTenant
12 requested_interval=30
13 playbook='sync_host.yaml'
14
15 def get_fabric_onos_service(self):
Scott Baker71c20eb2017-03-14 21:35:18 -070016 fs = FabricService.objects.first()
Scott Baker7462a142017-07-19 16:34:29 -070017 for link in fs.subscribed_links.all():
18 if link.provider_service_instance:
19 # cast from ServiceInstance to ONOSApp
20 apps = ONOSApp.objects.filter(id=link.provider_service_instance.id)
21 if apps:
22 # cast from Service to ONOSService
23 onos = ONOSService.objects.get(id=apps[0].owner.id)
24 return onos
25 return None
Scott Baker46831592016-06-20 17:32:04 -070026
27 def get_node_tag(self, node, tagname):
Scott Baker8daf78d2017-03-15 11:39:44 -070028 tags = Tag.objects.filter(content_type=model_accessor.get_content_type_id(node),
29 object_id=node.id,
30 name=tagname)
Scott Baker71c20eb2017-03-14 21:35:18 -070031 if tags:
32 return tags[0].value
33 else:
Scott Baker46831592016-06-20 17:32:04 -070034 return None
35
Scott Baker71c20eb2017-03-14 21:35:18 -070036 def fetch_pending(self, deleted):
Scott Baker8474a742017-06-15 10:34:07 -070037 # If fetch_pending is being called for delete, then just execute the standard delete logic.
38 if deleted:
39 return super(SyncVRouterTenant, self).fetch_pending(deleted)
40
Scott Baker71c20eb2017-03-14 21:35:18 -070041 fs = FabricService.objects.first()
42 if (not fs) or (not fs.autoconfig):
43 return None
44
45 # TODO: Why is this a nonstandard synchronizer query?
Scott Baker8474a742017-06-15 10:34:07 -070046 objs = VRouterTenant.objects.all()
Scott Baker46831592016-06-20 17:32:04 -070047
Scott Bakeref17d0c2017-02-20 08:45:45 -080048 objs = list(objs)
49
Andy Baviera3c73732016-06-27 15:24:59 -040050 # Check that each is a valid vCPE tenant or instance
51 for vroutertenant in objs:
Scott Baker7462a142017-07-19 16:34:29 -070052 # TODO: hardcoded service dependency
53 vsg = self.get_vsg_subscriber(vroutertenant)
54 if vsg:
55 if not vsg.instance:
Andy Baviera3c73732016-06-27 15:24:59 -040056 objs.remove(vroutertenant)
57 else:
58 # Maybe the VRouterTenant is for an instance
Scott Baker71c20eb2017-03-14 21:35:18 -070059 # TODO: tenant_for_instance_id needs to be a real database field
Andy Baviera3c73732016-06-27 15:24:59 -040060 instance_id = vroutertenant.get_attribute("tenant_for_instance_id")
61 if not instance_id:
62 objs.remove(vroutertenant)
63 else:
64 instance = Instance.objects.filter(id=instance_id)[0]
65 if not instance.instance_name:
66 objs.remove(vroutertenant)
67
Scott Baker46831592016-06-20 17:32:04 -070068 return objs
69
Scott Baker7462a142017-07-19 16:34:29 -070070 def get_vsg_subscriber(self, vroutertenant):
71 links = vroutertenant.provided_links.all()
72 for link in links:
73 if not link.subscriber_service_instance:
74 continue
75 # cast from ServiceInstance to VSGTEnant
76 vsgs = VSGTenant.objects.filter(id=link.subscriber_service_instance.id)
77 if vsgs:
78 return vsgs[0]
79 return None
80
Scott Baker46831592016-06-20 17:32:04 -070081 def map_sync_inputs(self, vroutertenant):
82
83 fos = self.get_fabric_onos_service()
84
Scott Baker7462a142017-07-19 16:34:29 -070085 if not fos:
86 raise Exception("No fabric onos service")
87
Scott Baker46831592016-06-20 17:32:04 -070088 name = None
89 instance = None
90 # VRouterTenant setup is kind of hacky right now, we'll
91 # need to revisit. The idea is:
92 # * Look up the instance corresponding to the address
93 # * Look up the node running the instance
94 # * Get the "location" tag, push to the fabric
Scott Baker7462a142017-07-19 16:34:29 -070095
96 # TODO: hardcoded service dependency
97 vsg = self.get_vsg_subscriber(vroutertenant)
98 if vsg:
Scott Baker71c20eb2017-03-14 21:35:18 -070099 instance = vsg.instance
Scott Baker7462a142017-07-19 16:34:29 -0700100 name = str(vsg)
Scott Baker46831592016-06-20 17:32:04 -0700101 else:
Scott Baker46831592016-06-20 17:32:04 -0700102 instance_id = vroutertenant.get_attribute("tenant_for_instance_id")
Andy Baviera3c73732016-06-27 15:24:59 -0400103 instance = Instance.objects.filter(id=instance_id)[0]
104 name = str(instance)
Scott Baker46831592016-06-20 17:32:04 -0700105
106 node = instance.node
107 location = self.get_node_tag(node, "location")
108
Scott Baker71c20eb2017-03-14 21:35:18 -0700109 if not location:
110 raise DeferredException("No location tag for node %s tenant %s -- skipping" % (str(node), str(vroutertenant)))
111
Andy Bavier82d89832016-06-28 15:31:06 -0400112 # Create JSON
113 data = {
114 "%s/-1" % vroutertenant.public_mac : {
115 "basic" : {
116 "ips" : [ vroutertenant.public_ip ],
117 "location" : location
118 }
119 }
120 }
121 # Stupid Ansible... leading space so it doesn't think it's a dict
122 rest_body = " " + json.dumps(data)
Andy Bavier92e3e002016-06-28 14:30:39 -0400123
Scott Baker46831592016-06-20 17:32:04 -0700124 # Is it a POST or DELETE?
125
Scott Baker46831592016-06-20 17:32:04 -0700126 fields = {
127 'rest_hostname': fos.rest_hostname,
128 'rest_port': fos.rest_port,
Scott Baker46831592016-06-20 17:32:04 -0700129 'rest_endpoint': "onos/v1/network/configuration/hosts",
Andy Bavier82d89832016-06-28 15:31:06 -0400130 'rest_body': rest_body,
Scott Baker46831592016-06-20 17:32:04 -0700131 'ansible_tag': '%s'%name, # name of ansible playbook
132 }
133 return fields
134
135 def map_sync_outputs(self, controller_image, res):
136 pass