blob: 708fdb5a6ec857678acf21db43447843ae10f83e [file] [log] [blame]
srikanth116e6e82014-08-19 07:22:37 -07001#
2# Copyright (c) 2013 Big Switch Networks, Inc.
3#
4# Licensed under the Eclipse Public License, Version 1.0 (the
5# "License"); you may not use this file except in compliance with the
6# License. You may obtain a copy of the License at
7#
8# http://www.eclipse.org/legal/epl-v10.html
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied. See the License for the specific language governing
14# permissions and limitations under the License.
15#
16
17from sdncon.rest.config import add_config_handler
srikanthf2c888b2014-08-20 10:46:55 -070018"""
srikanth116e6e82014-08-19 07:22:37 -070019from sdncon.controller.models import Feature, GlobalConfig, Controller, \
20 ControllerInterface, ControllerDomainNameServer, \
21 FirewallRule, ControllerAlias, SnmpServerConfig, ImageDropUser
22from sdncon.controller.models import TacacsPlusConfig, TacacsPlusHost
srikanthf2c888b2014-08-20 10:46:55 -070023"""
srikanth116e6e82014-08-19 07:22:37 -070024from oswrapper import exec_os_wrapper
25import os
26import re
27import sdncon
28from django.core import serializers
29
30# FIXME: Can probably get rid of default_id when the rest of the code is
31# in place for supporting multiple controller IDs. But what about
32# unit tests where we shouldn't rely on the boot-config file existing
33def get_local_controller_id(default_id='localhost'):
34 local_controller_id = default_id
35 f = None
36 try:
37 f = open("%s/run/boot-config" % sdncon.SDN_ROOT, 'r')
38 data = f.read()
39 match = re.search("^controller-id=([0-9a-zA-Z\-]*)$", data, re.MULTILINE)
40 if match:
41 local_controller_id = match.group(1)
42 except Exception, _e:
43 # If there was any error, then just leave the controller ID as the
44 # default value.
45 pass
46 finally:
47 if f:
48 f.close()
49 return local_controller_id
50
srikanthf2c888b2014-08-20 10:46:55 -070051"""
srikanth116e6e82014-08-19 07:22:37 -070052# Add the config handlers here. Check the comments for add_config_handler in rest/config.py
53# for a description of the calling conventions for config handlers.
54
55def network_config_handler(op, old_instance, new_instance, modified_fields):
56 valid_instance = old_instance if (op == 'DELETE') else new_instance
57 if isinstance(valid_instance, Controller):
58 controller_node = valid_instance
59 controller_id = controller_node.id
60 if op == 'DELETE':
61 # no further configuration here
62 return
63 elif isinstance(valid_instance, ControllerDomainNameServer) \
64 or isinstance(valid_instance, ControllerInterface):
65 controller_id = valid_instance.controller_id
66 try:
67 controller_node = Controller.objects.get(pk=controller_id)
68 except Exception, _e:
69 # unknown controller node during delete, no need to
70 # do anything with any of these interfaces
71 return
72 else:
73 raise Exception('Unknown model change trigger network config handler')
74
75 if controller_id != get_local_controller_id():
76 return
77
78 if op == 'DELETE':
79 # don't reconfigure the interfaces during delete, since
80 # for deletes, the values of ip/netmask don't get updated
81 dns = ControllerDomainNameServer.objects.filter(
82 controller=controller_node).order_by('timestamp')
83 exec_os_wrapper('NetworkConfig', 'set',
84 [serializers.serialize("json", [controller_node]),
85 serializers.serialize("json", dns)])
86 else:
87 # op != 'DELETE'
88 #
89 # XXX what about HA?
90 # 'ifs' below isn't filtered by controller, the NetConfig
91 # target will only select interfaces assocaited with the
92 # controller-node 'localhost.
93 dns = ControllerDomainNameServer.objects.filter(
94 controller=controller_node).order_by('-priority')
95 ifs = ControllerInterface.objects.filter(controller=controller_node)
96 exec_os_wrapper('NetworkConfig', 'set',
97 [serializers.serialize("json", [controller_node]),
98 serializers.serialize("json", dns),
99 serializers.serialize("json", ifs)])
100
101def firewall_entry_handler(op, old_instance, new_instance, modified_fields=None):
102 #allow in on eth0 proto tcp from any to any port 80
103 print "XXX: firewall handler called-1"
104 command = ""
105 if op == "DELETE" and str(old_instance.interface.controller) == get_local_controller_id():
106 command += "delete "
107 instance = old_instance
108 elif (op == "INSERT" or op == "UPDATE") and str(new_instance.interface.controller) == get_local_controller_id():
109 instance = new_instance
110 else:
111 return
112
113 print instance.action
114 print instance.proto
115 print instance.port
116 print instance.src_ip
117 print instance.vrrp_ip
118 print "XXX: firewall handler called-2"
119 controller_interface = instance.interface
120 eth = 'eth' + str(controller_interface.number) #LOOK! Hardcoded to eth interface
121 proto_str = ""
122 if instance.proto != '' and instance.proto != 'vrrp':
123 proto_str = " proto " + instance.proto
124 action_str = instance.action
125 src_str = " from any"
126 if instance.src_ip != '':
127 src_str = " from " + instance.src_ip
128 dst_str = " to any"
129 if instance.vrrp_ip != '':
130 dst_str = " to " + instance.vrrp_ip
131 print "dst_str = ", dst_str
132 port_str = ""
133 if instance.port != 0:
134 port_str = " port " + str(instance.port)
135
136 command += (action_str + " in on " + eth + proto_str + src_str + dst_str + port_str)
137 print command
138
139 exec_os_wrapper('ExecuteUfwCommand', 'set', [command])
140 if instance.port == 6633 and action_str == 'reject' and op != 'DELETE':
141 exec_os_wrapper('RestartSDNPlatform', 'set', [])
142
143def ntp_config_handler(op, old_instance, new_instance, modified_fields=None):
144 if new_instance != None:
145 exec_os_wrapper("SetNtpServer", 'set', [new_instance.ntp_server])
146
147def tz_config_handler(op, old_instance, new_instance, modified_fields=None):
148 if op == "DELETE":
149 if str(old_instance.id) != get_local_controller_id():
150 return
151 exec_os_wrapper("UnsetTimezone", 'set')
152 elif op == "INSERT" or op == "UPDATE":
153 if str(new_instance.id) != get_local_controller_id():
154 return
155 if new_instance.time_zone != None and str(new_instance.time_zone) != "":
156 exec_os_wrapper("SetTimezone", 'set', [new_instance.time_zone])
157
158def logging_server_config_handler(op, old_instance, new_instance, modified_fields=None):
159 if op == "DELETE":
160 if str(old_instance.id) != get_local_controller_id():
161 return
162 exec_os_wrapper("UnsetSyslogServer", 'set',
163 [old_instance.logging_server, old_instance.logging_level])
164 elif op == "INSERT" or op == "UPDATE":
165 if str(new_instance.id) != get_local_controller_id():
166 return
167 if new_instance.logging_server != "" and new_instance.logging_enabled:
168 exec_os_wrapper("SetSyslogServer", 'set',
169 [new_instance.logging_server, new_instance.logging_level])
170 else:
171 exec_os_wrapper("UnsetSyslogServer", 'set',
172 [new_instance.logging_server, new_instance.logging_level])
173
174def vrrp_virtual_router_id_config_handle(op, old_instance, new_instance, modified_fields=None):
175 if op == "INSERT" or op == "UPDATE":
176 exec_os_wrapper("SetVrrpVirtualRouterId", 'set',
177 [new_instance.cluster_number])
178
179def netvirt_feature_config_handler(op, old_instance, new_instance, modified_fields=None):
180 if op == "INSERT" or op == "UPDATE":
181 if new_instance.netvirt_feature:
182 exec_os_wrapper("SetDefaultConfig", 'set', [new_instance.netvirt_feature])
183 else:
184 exec_os_wrapper("SetStaticFlowOnlyConfig", 'set', [new_instance.netvirt_feature])
185
186def controller_alias_config_handler(op, old_instance, new_instance, modified_fields=None):
187 if op == 'INSERT' or op == 'UPDATE':
188 if str(new_instance.controller) == get_local_controller_id():
189 exec_os_wrapper("SetHostname", 'set', [new_instance.alias])
190
191def tacacs_plus_config_handler(op, old_instance, new_instance, modified_fields=None):
192
193 if isinstance(old_instance, TacacsPlusConfig):
194 if op == 'DELETE':
195 # deleting the config singleton (presumably during shutdown?)
196 return
197
198 if isinstance(old_instance, TacacsPlusConfig):
199 config_id = old_instance.id
200 else:
201 config_id = 'tacacs'
202 try:
203 config = TacacsPlusConfig.objects.get(pk=config_id)
204 except TacacsPlusConfig.DoesNotExist:
205 # cons up a dummy config object, not necessary to save it
206 config = TacacsPlusConfig()
207
208 # get current list of hosts (op==DELETE ignored here)
209 ##hosts = TacacsPlusHost.objects.order_by('timestamp')
210 def timestampSort(h1, h2):
211 return cmp(h1.timestamp, h2.timestamp)
212 hosts = sorted(TacacsPlusHost.objects.all(), timestampSort)
213
214 # XXX roth -- config is passed as-is, not as a single-element list
215 cj = serializers.serialize("json", [config])
216 hj = serializers.serialize("json", hosts)
217 print "Calling oswrapper with:", [cj, hj]
218 exec_os_wrapper('TacacsPlusConfig', 'set', [cj, hj])
219
220def snmp_server_config_handler(op, old_instance, new_instance, modified_fields=None):
221 if op == 'DELETE':
222 exec_os_wrapper('UnsetSnmpServerConfig', 'set', [])
223 elif op == 'INSERT' or op == 'UPDATE':
224 # enable_changed is true if operation is INSERT, else compare with old instance
225 if (op == 'INSERT'):
226 enable_changed = (new_instance.server_enable is True) #since default is False
227 print 'operation= insert, enable_changed = ', enable_changed
228 else:
229 enable_changed = (new_instance.server_enable != old_instance.server_enable)
230 server_enable = new_instance.server_enable
231 community = '' if new_instance.community is None else new_instance.community
232 location = '' if new_instance.location is None else new_instance.location
233 contact = '' if new_instance.contact is None else new_instance.contact
234
235 print "Calling oswrapper with:", [server_enable, community, location, contact, enable_changed]
236 exec_os_wrapper('SetSnmpServerConfig', 'set',
237 [server_enable, community, location, contact, enable_changed])
srikanthf2c888b2014-08-20 10:46:55 -0700238"""
srikanth116e6e82014-08-19 07:22:37 -0700239def test_config_handler(op, old_instance, new_instance, modified_fields=None):
240 pass
241
242def images_user_ssh_key_config_handler(op, old_instance, new_instance, modified_fields=None):
243 if op == 'INSERT' or op == 'UPDATE':
244 sshkey = "\"" + str(new_instance.images_user_ssh_key) + "\""
245 exec_os_wrapper('SetImagesUserSSHKey', 'set', [sshkey])
246
247def init_config():
248 #
249 # Associate the config handlers with specific callout for each of the fields
250 # Keep in mind that these are the django names, NOT the rest api names,
251 #
srikanthf2c888b2014-08-20 10:46:55 -0700252 """
srikanth116e6e82014-08-19 07:22:37 -0700253 disabled_by_shell_variable = os.environ.get('SDNCON_CONFIG_HANDLERS_DISABLED', False)
254 disabled_by_file = os.path.exists("%s/sdncon_config_handlers_disabled" % sdncon.SDN_ROOT)
255 if not disabled_by_shell_variable and not disabled_by_file:
256 add_config_handler({Controller: ['ntp_server']}, ntp_config_handler)
257 add_config_handler({Controller: ['time_zone']}, tz_config_handler)
258 add_config_handler(
259 {
260 Controller: ['domain_lookups_enabled', 'domain_name', 'default_gateway'],
261 ControllerDomainNameServer: None,
262 ControllerInterface: ['ip', 'netmask', 'mode'],
263 }, network_config_handler)
264 add_config_handler({ControllerAlias: ['alias']}, controller_alias_config_handler)
265 add_config_handler({Controller: ['logging_enabled', 'logging_server', 'logging_level']}, logging_server_config_handler)
266 add_config_handler({Feature: ['netvirt_feature']}, netvirt_feature_config_handler)
267 add_config_handler({FirewallRule: None}, firewall_entry_handler)
268 add_config_handler({GlobalConfig: ['cluster_number']}, vrrp_virtual_router_id_config_handle)
269 add_config_handler({ TacacsPlusConfig: ["tacacs_plus_authn", "tacacs_plus_authz", "tacacs_plus_acct",
270 "local_authn", "local_authz",
271 "timeout", "key",],
272 TacacsPlusHost: ['ip', 'key'],
273 },
274 tacacs_plus_config_handler)
275 add_config_handler({SnmpServerConfig: ['server_enable', 'community', 'location', 'contact']}, snmp_server_config_handler)
276 add_config_handler({ImageDropUser: ['images_user_ssh_key']}, images_user_ssh_key_config_handler)
277 else:
278 add_config_handler(
279 {
280 Controller: ['domain_lookups_enabled', 'domain_name', 'default_gateway'],
281 ControllerDomainNameServer: None,
282 ControllerInterface: ['ip', 'netmask', 'mode'],
283 ControllerAlias: ['alias'],
284 FirewallRule: None,
285 Feature: None,
286 GlobalConfig: ['ha-enabled', 'cluster-number'],
287 }, test_config_handler)
srikanthf2c888b2014-08-20 10:46:55 -0700288 """