[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] get memory in openvz driver



OpenVZ has several parameters for memory management. All of them can be configured independetly.

Patch allow to get configuration of memory from container config and then calculate total usage of memory.

It is open question how to manage memory?
Index: src/openvz_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_conf.c,v
retrieving revision 1.33
diff -u -p -r1.33 openvz_conf.c
--- src/openvz_conf.c	5 Aug 2008 10:53:05 -0000	1.33
+++ src/openvz_conf.c	13 Aug 2008 08:32:57 -0000
@@ -138,6 +138,35 @@ strtoI(const char *str)
     return val;
 }
 
+/* openvz memory parameters have pattern
+"456633:2345565" - barrier & limit
+function split to 2 separate value
+*/
+int
+splitValues(const char *value, unsigned long *barrier, unsigned long *limit)
+{
+    if (value == NULL)
+        return -1;
+
+    if (sscanf(value, "%lu:%lu" , barrier, limit) != 2)
+        return -1;
+
+    return 0;
+}
+
+/* function return memory page size
+*/
+static long
+get_pagesize(void)
+{
+    long pagesize;
+    if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) {
+        /*Unable to get page size*/
+         pagesize = 4096; //set default
+    }
+    return pagesize;
+}
+
 /* function checks MAC address is empty
    return 0 - empty
           1 - not
@@ -814,4 +843,310 @@ int openvzAssignUUIDs(void)
     return 0;
 }
 
+const char *ubc_names[] = {
+    "KMEMSIZE",
+    "LOCKEDPAGES",
+    "PRIVVMPAGES",
+    "SHMPAGES",
+    "NUMPROC",
+    "PHYSPAGES",
+    "VMGUARPAGES",
+    "OOMGUARPAGES",
+    "NUMTCPSOCK",
+    "NUMFLOCK",
+    "NUMPTY",
+    "NUMSIGINFO",
+    "TCPSNDBUF",
+    "TCPRCVBUF",
+    "OTHERSOCKBUF",
+    "DGRAMRCVBUF",
+    "NUMOTHERSOCK",
+    "NUMFILE",
+    "DCACHESIZE",
+    "NUMIPTENT",
+    "AVNUMPROC",
+    NULL
+};
+
+/* function return list of parameters based on
+* parameter names
+* return  pointer to openvz_param or NULL
+*/
+static struct openvz_param*
+openvzGetEmptyParams(const char *list_names[]) {
+    int i = 0, count;
+    struct openvz_param *params;
+
+    /*get count*/
+    while(list_names[i] != NULL)
+        i++;
+
+    if (i == 0)
+        return NULL;
+
+    count = i + 1;
+
+    if (VIR_ALLOC_N(params, count) < 0) /*could not allocate memory*/
+        return NULL;
+
+    i = 0;
+    while(list_names[i] != NULL) {
+        params[i].name = strdup(list_names[i]);
+        if (params[i].name == NULL) /*could not allocate memory*/
+            break;
+
+        params[i].value = NULL;
+        i++;
+    }
+
+    params[i].name = NULL;
+    params[i].value = NULL;
+
+    return params;
+}
+
+static void
+openvzFreeParams(struct openvz_param * params) {
+    int i = 0;
+
+    if (params == NULL)
+        return;
+
+    while(params[i].name != NULL) {
+        VIR_FREE(params[i].name);
+
+        if (params[i].value != NULL) {
+             VIR_FREE(params[i].value);
+        }
+        i++;
+    }
+
+    VIR_FREE(params);
+}
+
+void
+openvzFreeUbParam(struct openvz_ub_param *ub)
+{
+    if (ub == NULL)
+        return;
+#define FREE_P(x) if (ub->x != NULL) VIR_FREE(ub->x);
+
+    FREE_P(kmemsize)
+    FREE_P(lockedpages)
+    FREE_P(privvmpages)
+    FREE_P(shmpages)
+    FREE_P(numproc)
+    FREE_P(physpages)
+    FREE_P(vmguarpages)
+    FREE_P(oomguarpages)
+    FREE_P(numtcpsock)
+    FREE_P(numflock)
+    FREE_P(numpty)
+    FREE_P(numsiginfo)
+    FREE_P(tcpsndbuf)
+    FREE_P(tcprcvbuf)
+    FREE_P(othersockbuf)
+    FREE_P(dgramrcvbuf)
+    FREE_P(numothersock)
+    FREE_P(numfile)
+    FREE_P(dcachesize)
+    FREE_P(numiptent)
+    FREE_P(avnumproc)
+
+#undef FREE_P
+    VIR_FREE(ub);
+}
+
+/*
+* Read several parameters from container config
+* return: -1 - error
+*          0 - OK
+* TODO: rewrite function to don't read config several times
+*/
+static int
+openvzReadMultiConfigParams(int vpsid, struct openvz_param *params)
+{
+    int i = 0;
+    char value[1024];
+    int ret = 0;
+
+    while(params[i].name != NULL) {
+       ret = openvzReadConfigParam(vpsid, params[i].name, value, 1024);
+       if (ret < 0)
+           return -1;
+       if (ret > 0)
+           params[i].value = strdup(value);
+       /*do nothing if parameter don't found*/
+
+       i++;
+    }
+
+    return 0;
+}
+
+/* search parameter in list and return it value
+* return pointer to value or NULL
+*/
+static char *
+openvzGetParamValue(struct openvz_param *params, const char *name)
+{
+    int j;
+    for (j = 0; params[j].name != NULL; j++) {
+        if (STREQ(params[j].name, name)) {
+            return params[j].value;
+        }
+    }
+    return NULL;
+}
+
+static int
+openvzConvertParams2UbParams(struct openvz_param *params, 
+                             struct openvz_ub_param *ub)
+{
+    char *value;
+    if (ub == NULL || params == NULL)
+        return -1;
+
+#define PARAM2UB(param_name, ub_param_name) \
+            if ((value = openvzGetParamValue(params, param_name)) != NULL) { \
+                 if (VIR_ALLOC(ub->ub_param_name) < 0) \
+                     goto error; \
+                 if (splitValues(value, &ub->ub_param_name->barrier, \
+                                        &ub->ub_param_name->limit) <0) \
+                     VIR_FREE(ub->ub_param_name); \
+            }
+
+    PARAM2UB("KMEMSIZE", kmemsize)
+    PARAM2UB("LOCKEDPAGES",lockedpages)
+    PARAM2UB("PRIVVMPAGES",privvmpages)
+    PARAM2UB("SHMPAGES",shmpages)
+    PARAM2UB("NUMPROC",numproc)
+    PARAM2UB("PHYSPAGES",physpages)
+    PARAM2UB("VMGUARPAGES",vmguarpages)
+    PARAM2UB("OOMGUARPAGES",oomguarpages)
+    PARAM2UB("NUMTCPSOCK",numtcpsock)
+    PARAM2UB("NUMFLOCK",numflock)
+    PARAM2UB("NUMPTY",numpty)
+    PARAM2UB("NUMSIGINFO",numsiginfo)
+    PARAM2UB("TCPSNDBUF",tcpsndbuf)
+    PARAM2UB("TCPRCVBUF",tcprcvbuf)
+    PARAM2UB("OTHERSOCKBUF",othersockbuf)
+    PARAM2UB("DGRAMRCVBUF",dgramrcvbuf)
+    PARAM2UB("NUMOTHERSOCK",numothersock)
+    PARAM2UB("NUMFILE",numfile)
+    PARAM2UB("DCACHESIZE",dcachesize)
+    PARAM2UB("NUMIPTENT",numiptent)
+    PARAM2UB("AVNUMPROC",avnumproc)
+
+#undef PARAM2UB
+
+    return 0;
+
+error:
+    return -1;
+}
+
+
+/* read user bean counter parameters from config
+* return pointer to openvz_ub_param or NULL
+*/
+struct openvz_ub_param *
+openvzReadUbParams(virConnectPtr conn, int vpsid)
+{
+    struct openvz_ub_param *ub = NULL;
+    struct openvz_param *params;
+    params = openvzGetEmptyParams(ubc_names);
+    if (params == NULL) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+              _("Could not get empty list of parameters"));
+        return NULL;
+    }
+
+    if (openvzReadMultiConfigParams(vpsid, params) < 0) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+              _("Could not read list of parameters"));
+        goto error;
+    }
+
+    if (VIR_ALLOC(ub) < 0) {
+        openvzError(conn, VIR_ERR_NO_MEMORY,
+              _("Could not allocate openvz_ub_param"));
+        goto error;
+    }
+
+    if (openvzConvertParams2UbParams(params, ub) < 0) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+              _("Could not convert to UBC"));
+        goto error;
+    }
+
+    openvzFreeParams(params);
+    return ub;
+error:
+    if (ub != NULL)
+        openvzFreeUbParam(ub);
+    openvzFreeParams(params);
+    return NULL;
+}
+
+/* calculate guaranteed memory for container
+*/
+int
+openvzUb2Memory(struct openvz_ub_param *ub, unsigned long *memory)
+{
+    unsigned long lowmem, mem, allmem;
+
+    if (ub->oomguarpages == NULL ||
+        ub->kmemsize == NULL ||
+        ub->tcpsndbuf == NULL ||
+        ub->tcprcvbuf == NULL ||
+        ub->othersockbuf == NULL ||
+        ub->dgramrcvbuf == NULL ||
+        ub->lockedpages == NULL)
+        return -1;
+
+    lowmem = ub->kmemsize->limit +
+             ub->tcpsndbuf->limit +
+             ub->tcprcvbuf->limit +
+             ub->othersockbuf->limit +
+             ub->dgramrcvbuf->limit +
+             ub->lockedpages->limit * get_pagesize();
+
+    mem = ub->oomguarpages->barrier * get_pagesize();
+    allmem = mem + lowmem; //in bytes
+    *memory = allmem / 1024; //in kb
+
+    return 0;
+}
+
+/* calculate maximum awailable memory for container
+*/
+int
+openvzUb2MaxMemory(struct openvz_ub_param *ub, unsigned long *memory)
+{
+    unsigned long lowmem, mem, allmem;
+
+    if (ub->privvmpages == NULL ||
+        ub->kmemsize == NULL ||
+        ub->tcpsndbuf == NULL ||
+        ub->tcprcvbuf == NULL ||
+        ub->othersockbuf == NULL ||
+        ub->dgramrcvbuf == NULL ||
+        ub->lockedpages == NULL)
+        return -1;
+
+    lowmem = ub->kmemsize->limit +
+             ub->tcpsndbuf->limit +
+             ub->tcprcvbuf->limit +
+             ub->othersockbuf->limit +
+             ub->dgramrcvbuf->limit +
+             ub->lockedpages->limit * get_pagesize();
+
+    mem = ub->privvmpages->barrier * get_pagesize();
+    allmem = mem + lowmem; //in bytes
+    *memory = allmem / 1024; //in kb
+
+    return 0;
+}
+
 #endif
Index: src/openvz_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_conf.h,v
retrieving revision 1.11
diff -u -p -r1.11 openvz_conf.h
--- src/openvz_conf.h	5 Aug 2008 10:53:05 -0000	1.11
+++ src/openvz_conf.h	13 Aug 2008 08:32:57 -0000
@@ -88,6 +88,42 @@ struct openvz_vm {
     struct openvz_vm *next;
 };
 
+struct openvz_param {
+    char *name;
+    char *value;
+};
+
+struct openvz_ub_limit {
+    unsigned long barrier, limit;
+};
+
+/*describe OpenVZ user bean conters
+* struct is copied with modification from vzctl
+*/
+struct openvz_ub_param {
+    struct openvz_ub_limit * kmemsize;
+    struct openvz_ub_limit * lockedpages;
+    struct openvz_ub_limit * privvmpages;
+    struct openvz_ub_limit * shmpages;
+    struct openvz_ub_limit * numproc;
+    struct openvz_ub_limit * physpages;
+    struct openvz_ub_limit * vmguarpages;
+    struct openvz_ub_limit * oomguarpages;
+    struct openvz_ub_limit * numtcpsock;
+    struct openvz_ub_limit * numflock;
+    struct openvz_ub_limit * numpty;
+    struct openvz_ub_limit * numsiginfo;
+    struct openvz_ub_limit * tcpsndbuf;
+    struct openvz_ub_limit * tcprcvbuf;
+    struct openvz_ub_limit * othersockbuf;
+    struct openvz_ub_limit * dgramrcvbuf;
+    struct openvz_ub_limit * numothersock;
+    struct openvz_ub_limit * numfile;
+    struct openvz_ub_limit * dcachesize;
+    struct openvz_ub_limit * numiptent;
+    struct openvz_ub_limit * avnumproc;
+};
+
 static inline int
 openvzIsActiveVM(struct openvz_vm *vm)
 {
@@ -120,5 +156,11 @@ int strtoI(const char *str);
 int openvzCheckEmptyMac(const unsigned char *mac);
 char *openvzMacToString(const unsigned char *mac);
 int openvzSetDefinedUUID(int vpsid, unsigned char *uuid);
+int splitValues(const char *value,
+                unsigned long *barrier, unsigned long *limit);
+struct openvz_ub_param * openvzReadUbParams(virConnectPtr conn, int vpsid);
+int openvzUb2Memory(struct openvz_ub_param *ub, unsigned long *memory);
+int openvzUb2MaxMemory(struct openvz_ub_param *ub, unsigned long *memory);
+void openvzFreeUbParam(struct openvz_ub_param *ub);
 
 #endif /* OPENVZ_CONF_H */
Index: src/openvz_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.c,v
retrieving revision 1.37
diff -u -p -r1.37 openvz_driver.c
--- src/openvz_driver.c	5 Aug 2008 10:53:05 -0000	1.37
+++ src/openvz_driver.c	13 Aug 2008 08:32:57 -0000
@@ -94,6 +94,8 @@ static int openvzDomainUndefine(virDomai
 static void cmdExecFree(char *cmdExec[]);
 
 static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
+static int openvzGetMemory(virConnectPtr conn, int vpsid, unsigned long *memory);
+static int openvzGetMaxMemory(virConnectPtr conn, int vpsid, unsigned long *memory);
 
 struct openvz_driver ovz_driver;
 
@@ -262,6 +264,10 @@ static int openvzDomainGetInfo(virDomain
         }
     }
 
+    openvzGetMemory(dom->conn, strtoI(dom->name), &(info->memory)) ;
+    openvzGetMaxMemory(dom->conn, strtoI(dom->name), &(info->maxMem)) ;
+
+
     /* TODO These need to be calculated differently for OpenVZ */
     //info->cpuTime =
     //info->maxMem = vm->def->maxmem;
@@ -704,6 +710,48 @@ static virDrvOpenStatus openvzOpen(virCo
    return VIR_DRV_OPEN_SUCCESS;
 };
 
+static int openvzGetMemory(virConnectPtr conn, int vpsid, unsigned long *memory) {
+    struct openvz_ub_param *ub;
+    ub = openvzReadUbParams(conn, vpsid);
+
+    if(ub == NULL) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+               _("Could not read UBC parameters for VPS %d"), vpsid);
+        return -1;
+    }
+
+    if (openvzUb2Memory(ub, memory) < 0) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+               _("Unable to calculate memory for VPS %d: not enough UBC parameters"), vpsid);
+        return -1;
+    }
+
+    openvzFreeUbParam(ub);
+    return 0;
+}
+
+static int openvzGetMaxMemory(virConnectPtr conn, int vpsid, unsigned long *memory) {
+    struct openvz_ub_param *ub;
+    ub = openvzReadUbParams(conn, vpsid);
+
+    if(ub == NULL) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+               _("Could not read UBC parameters for VPS %d"), vpsid);
+        return -1;
+    }
+
+    if (openvzUb2MaxMemory(ub, memory) < 0) {
+        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+               _("Unable to calculate memory for VPS %d: not enough UBC parameters"), vpsid);
+        return -1;
+    }
+
+    openvzFreeUbParam(ub);
+    return 0;
+}
+
+
+
 static int openvzClose(virConnectPtr conn) {
 
     struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
Index: src/openvz_driver.h
===================================================================
RCS file: /data/cvs/libvirt/src/openvz_driver.h,v
retrieving revision 1.5
diff -u -p -r1.5 openvz_driver.h
--- src/openvz_driver.h	10 Apr 2008 16:54:54 -0000	1.5
+++ src/openvz_driver.h	13 Aug 2008 08:32:57 -0000
@@ -49,6 +49,7 @@ int openvzRegister(void);
                                         fprintf(stderr, "\nERROR: ");\
                                 fprintf(stderr, "\n\t");\
                                 fprintf(stderr, msg);\
-                                fprintf(stderr, "\n"); }
+                                fprintf(stderr, "\n");\
+                                fflush(stderr); }
 
 #endif

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]