7720a8b4858f8ab865d4496190903702cdcade49
[rahunas] / src / rh-task-serviceclass.c
1 /**
2  * RahuNAS task serviceclass implementation 
3  * Author: Neutron Soutmun <neo.neutron@gmail.com>
4  * Date:   2010-07-29
5  */
6
7 #include <syslog.h>
8 #include <libgda/libgda.h>
9
10 #include "rahunasd.h"
11 #include "rh-serviceclass.h"
12 #include "rh-ipset.h"
13 #include "rh-task.h"
14
15 static struct set *rh_serviceclass_set = NULL;
16
17 static uint32_t _sc_get_slot_id(struct rahunas_serviceclass_config *sc_config)
18 {
19   uint32_t slot_id = 0;
20   time_t random_time; 
21   int  retry = 30;
22   char select_cmd[256];
23   GdaConnection *connection = NULL;
24   GdaSqlParser  *parser = NULL;
25   GList *data_list = NULL;
26
27   if (sc_config == NULL)
28     return 0;
29
30   connection = gda_connection_open_from_dsn (PROGRAM, NULL,
31                  GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
32   parser = gda_connection_create_parser (connection);
33   if (!parser) {
34     parser = gda_sql_parser_new ();
35   }
36
37   g_object_set_data_full (G_OBJECT (connection), "parser", parser, g_object_unref);
38
39   while (slot_id == 0 && (--retry > 0)) {
40     time(&random_time);
41     srandom(random_time);
42     slot_id = random() % sc_config->network_size;
43
44     if (slot_id != 0) {
45       memset (&select_cmd, '\0', sizeof (select_cmd));
46       snprintf(select_cmd, sizeof (select_cmd) - 1,
47                "SELECT * FROM dbset WHERE service_class = '%s' "
48                "AND service_class_slot_id = %u",
49                sc_config->serviceclass_name, slot_id);
50
51       DP("SQL: %s", select_cmd);
52       data_list = execute_sql_command(connection, select_cmd);
53
54       if (g_list_first (data_list) == NULL) {
55         // Available
56         free_data_list(data_list);
57         break;
58       } else { 
59         // Not available, retry
60         free_data_list(data_list);
61         slot_id = 0;
62       }
63     }
64   }
65
66   if (connection)
67     g_object_unref(G_OBJECT(connection));
68
69   return slot_id;
70 }
71
72 /* Start service task */
73 static int startservice ()
74 {
75   rh_serviceclass_set = set_adt_get(SERVICECLASS_SET_NAME);
76
77   logmsg(RH_LOG_NORMAL, "Service Class: Flushing set ...");
78   set_flush (SERVICECLASS_SET_NAME);
79   return 0;
80 }
81
82 /* Stop service task */
83 static int stopservice  ()
84 {
85   if (rh_serviceclass_set != NULL) {
86     logmsg(RH_LOG_NORMAL, "Service Class: Flushing set ...");
87     set_flush (SERVICECLASS_SET_NAME);
88     rh_free(&rh_serviceclass_set); 
89   }
90
91   return 0;
92 }
93
94 /* Initialize */
95 static void init (struct vserver *vs)
96 {
97 }
98
99 /* Cleanup */
100 static void cleanup (struct vserver *vs)
101 {
102 }
103
104 /* Start session task */
105 static int startsess (struct vserver *vs, struct task_req *req)
106 {
107   struct serviceclass *sc = NULL;
108   struct rahunas_serviceclass_config *sc_config = NULL;
109   ip_set_ip_t ip;
110   ip_set_ip_t ip1;
111   int res = 0;
112   GList *member_node = NULL;
113   struct rahunas_member *member = NULL;
114
115   if (req->serviceclass_name == NULL)
116     return 0;
117
118   member_node = member_get_node_by_id(vs, req->id);
119   if (member_node == NULL)
120     return (-1);
121
122   member = (struct rahunas_member *) member_node->data;
123
124
125   sc = serviceclass_exists(vs->main_server->serviceclass_list, -1,
126                            req->serviceclass_name);
127
128   if (sc == NULL) {
129     goto failed;
130   }
131
132   sc_config = sc->serviceclass_config;
133
134   if (req->serviceclass_slot_id == 0) {
135     req->serviceclass_slot_id = _sc_get_slot_id (sc_config);
136
137     if (req->serviceclass_slot_id == 0)
138       goto failed;
139   }
140
141   if (req->serviceclass_slot_id <= sc_config->network_size) {
142     parse_ip(idtoip(vs->v_map, req->id), &ip);
143     ip1 = ntohl (sc_config->start_addr.s_addr) + req->serviceclass_slot_id;
144
145     res = set_ipiphash_adtip_nb(rh_serviceclass_set, &ip, &ip1, IP_SET_OP_ADD_IP);
146
147     if (res != 0)
148       goto failed;
149
150     res = set_ipiphash_adtip_nb(rh_serviceclass_set, &ip1, &ip, IP_SET_OP_ADD_IP);
151
152     if (res != 0) {
153       // Revert
154       res = set_ipiphash_adtip_nb(rh_serviceclass_set, &ip, &ip1, IP_SET_OP_DEL_IP);
155       goto failed;
156     }
157
158
159     member->serviceclass_name = strdup (req->serviceclass_name);
160     member->serviceclass_description = sc_config->description;
161     member->serviceclass_slot_id = req->serviceclass_slot_id;
162
163     member->mapping_ip = strdup (ip_tostring(ip1));
164
165     logmsg (RH_LOG_NORMAL, "[%s] Service class for User: %s, IP: %s "
166                            "- Service Class: %s, Mapping: %s",
167                            vs->vserver_config->vserver_name,
168                            req->username,
169                            idtoip(vs->v_map, req->id),
170                            req->serviceclass_name,
171                            member->mapping_ip);
172   } else {
173     goto failed;
174   }
175
176   return 0;
177
178 failed:
179   if ((req->serviceclass_name != NULL) && (strlen(req->serviceclass_name) == 0))
180     goto out;
181
182   logmsg (RH_LOG_NORMAL, "[%s] Service class for User: %s, IP: %s "
183                          "- Service Class: %s, Failed!",
184                          vs->vserver_config->vserver_name,
185                          req->username,
186                          idtoip(vs->v_map, req->id),
187                          req->serviceclass_name);
188
189 out:
190   if (member->serviceclass_name != NULL &&
191         member->serviceclass_name != termstring) {
192     free (member->serviceclass_name);
193     member->serviceclass_name    = NULL;
194     member->serviceclass_slot_id = 0;
195   }
196
197   return 0;
198 }
199
200 /* Stop session task */
201 static int stopsess  (struct vserver *vs, struct task_req *req)
202 {
203   struct serviceclass *sc = NULL;
204   struct rahunas_serviceclass_config *sc_config = NULL;
205   ip_set_ip_t ip;
206   ip_set_ip_t ip1;
207   int res = 0;
208   GList *member_node = NULL;
209   struct rahunas_member *member = NULL;
210
211   member_node = member_get_node_by_id(vs, req->id);
212   if (member_node == NULL)
213     return (-1);
214
215   member = (struct rahunas_member *) member_node->data;
216
217   if (member->serviceclass_name == NULL)
218     return 0;
219
220   sc = serviceclass_exists(vs->main_server->serviceclass_list, -1,
221                            member->serviceclass_name);
222
223   if (sc == NULL) {
224     goto failed;
225   }
226
227   sc_config = sc->serviceclass_config;
228
229   if (member->serviceclass_slot_id == 0) {
230     goto failed;
231   }
232
233   if (member->serviceclass_slot_id <= sc_config->network_size) {
234     parse_ip(idtoip(vs->v_map, req->id), &ip);
235     ip1 = ntohl (sc_config->start_addr.s_addr) + member->serviceclass_slot_id;
236
237     res = set_ipiphash_adtip_nb(rh_serviceclass_set, &ip, &ip1, IP_SET_OP_DEL_IP);
238
239     if (res != 0)
240       goto failed;
241
242     res = set_ipiphash_adtip_nb(rh_serviceclass_set, &ip1, &ip, IP_SET_OP_DEL_IP);
243     if (res != 0)
244       goto failed;
245
246     logmsg (RH_LOG_NORMAL, "[%s] Service class for User: %s, IP: %s "
247                            "- Service Class: %s, Mapping: %s (Removed)",
248                            vs->vserver_config->vserver_name,
249                            member->username,
250                            idtoip(vs->v_map, req->id),
251                            member->serviceclass_name,
252                            member->mapping_ip);
253   } else {
254     goto failed;
255   }
256
257   return 0;
258
259 failed:
260   logmsg (RH_LOG_NORMAL, "[%s] Service class for User: %s, IP: %s "
261                          "- Service Class: %s, Mapping: %s (Removed Failed!)",
262                          vs->vserver_config->vserver_name,
263                          member->username,
264                          idtoip(vs->v_map, req->id),
265                          member->serviceclass_name,
266                          member->mapping_ip);
267
268   return 0;
269 }
270
271 /* Commit start session task */
272 static int commitstartsess (struct vserver *vs, struct task_req *req)
273 {
274   /* Do nothing or need to implement */
275 }
276
277 /* Commit stop session task */
278 static int commitstopsess  (struct vserver *vs, struct task_req *req)
279 {
280   /* Do nothing or need to implement */
281 }
282
283 /* Rollback start session task */
284 static int rollbackstartsess (struct vserver *vs, struct task_req *req)
285 {
286   /* Do nothing or need to implement */
287 }
288
289 /* Rollback stop session task */
290 static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
291 {
292   /* Do nothing or need to implement */
293 }
294
295 static struct task task_serviceclass = {
296   .taskname = "SERVICECLASS",
297   .taskprio = 25,
298   .init = &init,
299   .cleanup = &cleanup,
300   .startservice = &startservice,
301   .stopservice = &stopservice,
302   .startsess = &startsess,
303   .stopsess = &stopsess,
304   .commitstartsess = &commitstartsess,
305   .commitstopsess = &commitstopsess,
306   .rollbackstartsess = &rollbackstartsess,
307   .rollbackstopsess = &rollbackstopsess,
308 };
309
310 void rh_task_serviceclass_reg(struct main_server *ms) {
311   task_register(ms, &task_serviceclass);
312 }