2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Dynowski <k.dynowski@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
22 * @author Krzysztof Dynowski (k.dynowski@samsung.com)
23 * @brief Vasum old API wrapper to slp client lib
26 #define __VASUM_WRAPPER_SOURCE__
32 #include "logger/logger.hpp"
33 #include "logger/backend-journal.hpp"
35 #include "wrapper-compat.h"
36 #include "vasum-client-impl.hpp"
38 #define MAX_EPOLL_EVENTS 16
45 std::vector<vsm_netdev> netdevs;
52 struct vsm_zone hq_root;
53 std::vector<WrappedZone> zones;
63 #define offsetof(type, memb) ((size_t)&((type *)0)->memb)
69 #define container_of(ptr, type, memb) (\
70 (type *)((char *)(ptr) - offsetof(type, memb)))
73 #define UNUSED(x) ((void)(x))
75 #define vsm_error_t vsm_error_s
76 #define vsm_attach_command_t vsm_attach_command_s
77 #define vsm_attach_options_t vsm_attach_options_s
78 #define vsm_zone_state_cb vsm_zone_state_changed_cb
80 void __attribute__ ((constructor)) wrapper_load(void);
81 void __attribute__ ((destructor)) wrapper_unload(void);
82 static void init_wrapper();
83 extern struct vasum_ops dummy_ops;
85 using namespace logger;
86 void wrapper_load(void)
88 Logger::setLogLevel(LogLevel::TRACE);
89 Logger::setLogBackend(new SystemdJournalBackend());
93 void wrapper_unload(void)
95 if (wrap.glib_stop) Client::vsm_stop_glib_loop();
99 static void callcheck()
106 if (wrap.done) return ;
107 memset(&wrap,0,sizeof(wrap));
112 static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false)
117 for (auto& zw : w->zones) {
118 if (zw.zone == zone) {
123 w->zones.push_back(WrappedZone());
124 WrappedZone& zw = w->zones.back();
125 zw.client = w->client;
127 zw.vz.name = zone->id;
129 zw.vz.user_data = NULL;
130 zw.vz.rootfs_path = zone->rootfs_path;
131 zw.vz.parent = &zw.vz;
132 LOGI("return (create) zone " << zone->id);
133 return &w->zones.back().vz;
135 LOGE("return zone NULL");
139 static int wrap_error(VsmStatus st, const Client *c)
141 if (st == VSMCLIENT_SUCCESS) LOGI("return success " << st);
142 else LOGE("return error " << st << "m=" << (c ? c->vsm_get_status_message() : "n/a"));
144 case VSMCLIENT_SUCCESS: return VSM_ERROR_NONE;
145 case VSMCLIENT_CUSTOM_ERROR: return -VSM_ERROR_GENERIC;
146 case VSMCLIENT_IO_ERROR: return -VSM_ERROR_IO;
147 case VSMCLIENT_OPERATION_FAILED: return -VSM_ERROR_NOT_PERMITTED;
148 case VSMCLIENT_INVALID_ARGUMENT: return -VSM_ERROR_INVALID;
149 case VSMCLIENT_OTHER_ERROR: return -VSM_ERROR_GENERIC;
151 return -VSM_ERROR_GENERIC;
154 static void init_context_wrap(WrappedContext *w)
156 Client::vsm_start_glib_loop();
158 w->client = new Client();
159 VsmStatus st = w->client->createSystem();
160 wrap_error(st, w->client);
162 memset(&w->hq_ctx, 0, sizeof(w->hq_ctx));
163 memset(&w->hq_root, 0, sizeof(w->hq_root));
165 vsm_context *ctx = &w->hq_ctx;
166 adt_init_list(&ctx->listeners);
168 ctx->root_zone = &w->hq_root;
169 ctx->root_zone->name = (char*)"";
170 ctx->root_zone->id=0;
171 ctx->root_zone->rootfs_path = (char*)"/";
173 ctx->root_zone->terminal = -1;
174 ctx->root_zone->state = VSM_ZONE_STATE_RUNNING;
175 ctx->root_zone->user_data = ctx->root_zone;
177 ctx->root_zone->parent = ctx->root_zone;
178 ctx->root_zone->ctx = ctx;
180 pthread_rwlock_init(&ctx->root_zone->lock, NULL);
181 adt_init_list(&ctx->root_zone->netdevs);
182 adt_init_list(&ctx->root_zone->devices);
183 adt_init_list(&ctx->root_zone->children);
185 pthread_rwlock_init(&ctx->lock, NULL);
186 adt_init_list(&ctx->listeners);
187 adt_init_list(&ctx->sc_listeners);
188 adt_init_list(&ctx->ev_listeners);
190 //struct mainloop *mainloop = mainloop_create();
191 //struct mxe_engine *engine = mxe_prepare_engine(mainloop, ctx);
192 //struct mxe_endpoint *ep = mxe_create_client(engine, SERVICEPATH);
194 ctx->foreground_zone = ctx->root_zone;
195 ctx->vsm_ops = &dummy_ops;
196 ctx->error = VSM_ERROR_NONE;
200 API vsm_context_h vsm_create_context(void)
202 LOGS(""); callcheck();
203 WrappedContext *w = new WrappedContext();
204 init_context_wrap(w);
206 vsm_context *ctx = &w->hq_ctx;
210 API int vsm_cleanup_context(vsm_context_h ctx)
212 LOGS(""); callcheck();
213 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
214 if (w->client != NULL) {
218 for (auto& zw : w->zones) {
223 return VSM_ERROR_NONE;
226 static const char *const vsm_error_strtab[] = {
230 "Operation cancelled",
232 "Connection refused",
235 "Input/Output error",
240 "Operation not permitted",
241 "Function not implemented",
242 "Operation not supported",
248 API vsm_error_e vsm_last_error(struct vsm_context *ctx)
252 return static_cast<vsm_error_e>(-1);
255 API const char *vsm_error_string(vsm_error_e error)
257 LOGS(""); callcheck();
258 if (error < 0 || error > VSM_MAX_ERROR) {
261 return vsm_error_strtab[error];
264 API int vsm_get_poll_fd(struct vsm_context *ctx)
266 LOGS(""); callcheck();
267 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
269 //FIXME Client should create Dispatcher and pass to IPCConnection
270 // now: IPCConnection has field ThreadWrapper
271 //return w->client->getEventPoll().getPollFD();
274 API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout)
276 LOGS(""); callcheck();
279 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
281 //FIXME Client should create Dispatcher and pass to IPCConnection
282 // now: IPCConnection has field ThreadWrapper
283 //TODO Use EventPoll from Dispatcher
287 API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const char *template_name, int flag)
289 LOGS("create_zone " << zone_name); callcheck();
290 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
292 //template_name = NULL; //template name not supported by libvasum-client
293 if (!w->client) return VSM_ERROR_GENERIC;
294 VsmStatus st = w->client->vsm_create_zone(zone_name, template_name);
295 if (st != VSMCLIENT_SUCCESS) {
296 LOGE("vsm_create_zone(" << zone_name << ") = " << st);
298 return wrap_error(st, w->client);
301 API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int force)
303 LOGS("zone=" << zone_name); callcheck();
304 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
306 if (!w->client) return VSM_ERROR_GENERIC;
307 VsmStatus st = w->client->vsm_destroy_zone(zone_name);
308 if (st == VSMCLIENT_SUCCESS) {
309 auto zonebyname = [zone_name](const WrappedZone& v) {return v.zone->id == zone_name;};
310 auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname);
311 w->zones.erase(zonelist);
313 return wrap_error(st, w->client);
316 API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name)
318 LOGS("zone=" << zone_name); callcheck();
319 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
320 if (!w->client) return VSM_ERROR_GENERIC;
321 VsmStatus st = w->client->vsm_start_zone(zone_name);
322 return wrap_error(st, w->client);
325 API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force)
327 LOGS("zone=" << zone_name); callcheck();
328 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
330 if (!w->client) return VSM_ERROR_GENERIC;
331 VsmStatus st = w->client->vsm_shutdown_zone(zone_name);
332 return wrap_error(st, w->client);
335 API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown)
337 LOGS("zone=" << zone_name); callcheck();
338 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
340 if (!w->client) return VSM_ERROR_GENERIC;
341 VsmStatus st = w->client->vsm_lock_zone(zone_name);
342 return wrap_error(st, w->client);
345 API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name)
347 LOGS("zone=" << zone_name); callcheck();
348 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
349 if (!w->client) return VSM_ERROR_GENERIC;
350 VsmStatus st = w->client->vsm_lock_zone(zone_name);
351 return wrap_error(st, w->client);
354 API int vsm_set_foreground(struct vsm_zone *zone)
356 LOGS(""); callcheck();
357 WrappedZone *w = container_of(zone, WrappedZone, vz);
358 if (!w->client) return VSM_ERROR_GENERIC;
359 VsmStatus st = w->client->vsm_set_active_zone(zone->name);
360 return wrap_error(st, w->client);
363 //execute command in specified zone
364 API int vsm_attach_zone(struct vsm_context *ctx,
365 const char *zone_name,
366 vsm_attach_command_t *command,
367 vsm_attach_options_t *opts,
368 pid_t *attached_process)
370 return dummy_ops.attach_zone(ctx, zone_name, command, opts,
374 //execute command in specified zone and wait
375 API int vsm_attach_zone_wait(struct vsm_context *ctx,
376 const char *zone_name,
377 vsm_attach_command_t *command,
378 vsm_attach_options_t *opts)
380 return dummy_ops.attach_zone_wait(ctx, zone_name, command, opts);
383 API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data)
385 LOGS(""); callcheck();
386 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
387 if (!w->client) return -VSM_ERROR_GENERIC;
388 callback(ctx->root_zone, user_data);
389 for (auto& z : w->zones) {
390 callback(&z.vz, user_data);
395 API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path)
397 LOGS("name=" << path); callcheck();
398 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
400 if (!w->client) return NULL;
401 //CHECK if path is same as zone_name
402 if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS)
404 return wrap_vsm_zone(w, zone, true);
407 API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid)
409 LOGS("pid=" << pid); callcheck();
410 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
413 if (!w->client) return NULL;
414 if (w->client->vsm_lookup_zone_by_pid(pid, &id) != VSMCLIENT_SUCCESS) {
415 LOGE("vsm_lookup_zone_by_pid(" << pid << ") error");
418 if (::strcmp(id, "host") == 0) {
419 return w->hq_ctx.root_zone;
421 w->client->vsm_lookup_zone_by_id(id, &zone); //zone is malloced
422 return wrap_vsm_zone(w, zone);
425 API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal)
427 LOGS("terminal=" << terminal); callcheck();
428 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
431 if (!w->client) return NULL;
432 if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS)
434 w->client->vsm_lookup_zone_by_id(id, &zone);
435 return wrap_vsm_zone(w, zone);
438 API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_cb callback, void *user_data)
440 LOGS(""); callcheck();
441 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
442 VsmSubscriptionId subscriptionId;
444 auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) ->
447 //TODO what are valid state, event
449 w->client->vsm_lookup_zone_by_id(id, &zone);
450 callback(wrap_vsm_zone(w, zone), data);
452 w->client->vsm_add_state_callback(dbus_cb, user_data, &subscriptionId);
453 return (int)subscriptionId;
456 API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle)
458 LOGS(""); callcheck();
459 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
460 VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle;
461 VsmStatus st = w->client->vsm_del_state_callback(subscriptionId);
462 return wrap_error(st, w->client);
465 API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags)
467 LOGS(""); callcheck();
468 WrappedZone *w = container_of(dom, WrappedZone, vz);
469 const char *id = dom->name;
471 w->client->vsm_lookup_zone_by_id(id, &zone);
472 VsmStatus st = w->client->vsm_grant_device(id, name, flags);
473 return wrap_error(st, w->client);
476 API int vsm_revoke_device(struct vsm_zone *dom, const char *name)
478 LOGS(""); callcheck();
479 WrappedZone *w = container_of(dom, WrappedZone, vz);
480 const char *id = dom->name;
481 VsmStatus st = w->client->vsm_revoke_device(id, name);
482 return wrap_error(st, w->client);
485 API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev)
487 LOGS(""); callcheck();
493 WrappedZone *w = container_of(zone, WrappedZone, vz);
494 const char *id = zone->name;
496 if (type == VSM_NETDEV_VETH)
497 st = w->client->vsm_create_netdev_veth(id, target, netdev);
498 else if (type == VSM_NETDEV_PHYS)
499 st = w->client->vsm_create_netdev_phys(id, netdev);
500 else if (type == VSM_NETDEV_MACVLAN) // macvlan_mode from if_link.h
501 st = w->client->vsm_create_netdev_macvlan(id, target, netdev, MACVLAN_MODE_BRIDGE);
503 LOGE("Invalid arguments");
504 //ctx->error = VSM_ERROR_INVALID;
508 if (st != VSMCLIENT_SUCCESS) {
509 LOGE("vsm_create_netdev(" << netdev << ") = " << st);
515 vnd.name = (char*)netdev; //FIXME? copy content of string
517 w->netdevs.push_back(vnd); //copy pushed to vector
518 return &w->netdevs.back(); //pointer to struct on vector
521 API int vsm_destroy_netdev(struct vsm_zone *zone, struct vsm_netdev *netdev)
523 LOGS(""); callcheck();
524 WrappedZone *w = container_of(zone, WrappedZone, vz);
526 VsmStatus st = w->client->vsm_destroy_netdev(zone->name, netdev->name);
527 if (st == VSMCLIENT_SUCCESS) {
528 auto devbyname = [netdev](const vsm_netdev& v) {return ::strcmp(v.name, netdev->name) == 0;};
529 auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
530 if (devlist != w->netdevs.end()) {
531 w->netdevs.erase(devlist);
534 return wrap_error(st, w->client);
537 API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data)
539 LOGS(""); callcheck();
540 WrappedZone *w = container_of(zone, WrappedZone, vz);
541 for (auto nd : w->netdevs) {
542 callback(&nd, user_data);
547 API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name)
549 LOGS(""); callcheck();
550 WrappedZone *w = container_of(zone, WrappedZone, vz);
552 VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd);
553 if (st == VSMCLIENT_SUCCESS) {
554 auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;};
555 auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
556 if (devlist != w->netdevs.end()) {
563 API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode)
565 LOGS(""); callcheck();
571 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
572 return VSM_ERROR_NONE;
575 API int vsm_declare_mount(struct vsm_context *ctx,
582 LOGS(""); callcheck();
589 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
590 return VSM_ERROR_NONE;
593 API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target)
595 LOGS("src=" << source << "dst=" << target); callcheck();
599 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
600 return VSM_ERROR_NONE;
603 API int vsm_add_state_changed_callback(vsm_context_h /*ctx*/, vsm_zone_state_changed_cb /*callback*/, void * /*user_data*/)
605 return VSM_ERROR_NONE;
607 API int vsm_del_state_changed_callback(vsm_context_h /*ctx*/, int /*id*/)
609 return VSM_ERROR_NONE;
611 API const char * vsm_get_zone_rootpath(vsm_zone_h /*zone*/)
615 API const char * vsm_get_zone_name(vsm_zone_h /*zone*/)
619 API int vsm_is_host_zone(vsm_zone_h /*zone*/)
621 return VSM_ERROR_NONE;
623 API vsm_zone_h vsm_join_zone(vsm_zone_h /*zone*/)
627 API int vsm_canonicalize_path(const char * /*input_path*/, char ** /*output_path*/)
629 return VSM_ERROR_NONE;