Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / Mantle.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2016 Michael Sevilla <mikesevilla3@gmail.com>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "mdstypes.h"
16 #include "MDSRank.h"
17 #include "Mantle.h"
18 #include "msg/Messenger.h"
19 #include "common/Clock.h"
20 #include "CInode.h"
21
22 #include <fstream>
23
24 #define dout_context g_ceph_context
25 #define dout_subsys ceph_subsys_mds_balancer
26 #undef dout_prefix
27 #define dout_prefix *_dout << "mds.mantle "
28 #define mantle_dout(lvl) \
29   do {\
30     auto subsys = ceph_subsys_mds;\
31     if ((dout_context)->_conf->subsys.should_gather(ceph_subsys_mds_balancer, lvl)) {\
32       subsys = ceph_subsys_mds_balancer;\
33     }\
34     dout_impl(dout_context, subsys, lvl) dout_prefix
35
36 #define mantle_dendl dendl; } while (0)
37
38
39 static int dout_wrapper(lua_State *L)
40 {
41   int level = luaL_checkinteger(L, 1);
42   lua_concat(L, lua_gettop(L)-1);
43   mantle_dout(level) << lua_tostring(L, 2) << mantle_dendl;
44   return 0;
45 }
46
47 int Mantle::balance(const std::string &script,
48                     mds_rank_t whoami,
49                     const std::vector<std::map<std::string, double>> &metrics,
50                     std::map<mds_rank_t, double> &my_targets)
51 {
52   lua_settop(L, 0); /* clear the stack */
53
54   /* load the balancer */
55   if (luaL_loadstring(L, script.c_str())) {
56     mantle_dout(0) << "WARNING: mantle could not load balancer: "
57             << lua_tostring(L, -1) << mantle_dendl;
58     return -EINVAL;
59   }
60
61   /* tell the balancer which mds is making the decision */
62   lua_pushinteger(L, (lua_Integer)whoami);
63   lua_setglobal(L, "whoami");
64
65   /* global mds metrics to hold all dictionaries */
66   lua_newtable(L);
67
68   /* push name of mds (i) and its metrics onto Lua stack */
69   for (size_t i=0; i < metrics.size(); i++) {
70     lua_newtable(L);
71
72     /* push values into this mds's table; setfield assigns key/pops val */
73     for (const auto &it : metrics[i]) {
74       lua_pushnumber(L, it.second);
75       lua_setfield(L, -2, it.first.c_str());
76     }
77
78     /* in global mds table at stack[-3], set k=stack[-1] to v=stack[-2] */
79     lua_seti(L, -2, i);
80   }
81
82   /* set the name of the global mds table */
83   lua_setglobal(L, "mds");
84
85   assert(lua_gettop(L) == 1);
86   if (lua_pcall(L, 0, 1, 0) != LUA_OK) {
87     mantle_dout(0) << "WARNING: mantle could not execute script: "
88             << lua_tostring(L, -1) << mantle_dendl;
89     return -EINVAL;
90   }
91
92   /* parse response by iterating over Lua stack */
93   if (lua_istable(L, -1) == 0) {
94     mantle_dout(0) << "WARNING: mantle script returned a malformed response" << mantle_dendl;
95     return -EINVAL;
96   }
97
98   /* fill in return value */
99   for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
100     if (!lua_isinteger(L, -2) || !lua_isnumber(L, -1)) {
101       mantle_dout(0) << "WARNING: mantle script returned a malformed response" << mantle_dendl;
102       return -EINVAL;
103     }
104     mds_rank_t rank(lua_tointeger(L, -2));
105     my_targets[rank] = lua_tonumber(L, -1);
106   }
107
108   return 0;
109 }
110
111 Mantle::Mantle (void)
112 {
113   /* build lua vm state */
114   L = luaL_newstate();
115   if (!L) {
116     mantle_dout(0) << "WARNING: mantle could not load Lua state" << mantle_dendl;
117     throw std::bad_alloc();
118   }
119
120   /* balancer policies can use basic Lua functions */
121   luaopen_base(L);
122   luaopen_coroutine(L);
123   luaopen_string(L);
124   luaopen_math(L);
125   luaopen_table(L);
126   luaopen_utf8(L);
127
128   /* setup debugging */
129   lua_register(L, "BAL_LOG", dout_wrapper);
130 }