
Crístian Viana (2): Add function to convert data sizes issue #595: Return correct memory value when VM is shutoff src/kimchi/i18n.py | 2 + src/kimchi/model/vms.py | 20 ++++++- src/kimchi/utils.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 3 deletions(-) -- 2.1.0

The new function "kimchi.utils.convert_data_size" can be used to convert values from different units, e.g. converting 5 GiB to MiB, 1 GiB to B. Signed-off-by: Crístian Viana <vianac@linux.vnet.ibm.com> --- src/kimchi/i18n.py | 2 + src/kimchi/utils.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py index 2af0be6..df5422f 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -267,6 +267,8 @@ messages = { "KCHUTILS0001E": _("Invalid URI %(uri)s"), "KCHUTILS0002E": _("Timeout while running command '%(cmd)s' after %(seconds)s seconds"), "KCHUTILS0003E": _("Unable to choose a virtual machine name"), + "KCHUTILS0004E": _("Invalid data value '%(value)s'"), + "KCHUTILS0005E": _("Invalid data unit '%(unit)s'"), "KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"), "KCHVMSTOR0003E": _("The path '%(value)s' is not a valid local/remote path for the device"), diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index fc5245f..a04d3cf 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -388,3 +388,148 @@ def get_unique_file_name(all_names, name): max_num = max(max_num, int(match.group(re_group_num))) return u'%s (%d)' % (name, max_num + 1) + + +def convert_data_size(value, src_unit, dst_unit=None): + """Convert a data value from one unit to another unit + (e.g. 'MiB' -> 'GiB'). + + The data units supported by this function are made up of one prefix and one + suffix, both optional. The valid prefixes are those defined in the SI + (i.e. metric system) and those defined by the IEC, and the valid suffixes + indicate if the base unit is bit or byte. Take a look at the tables below + for the possible values: + + Prefixes: + + ================================== =================================== + PREFIX (SI) | DESCRIPTION | VALUE PREFIX (IEC) | DESCRIPTION | VALUE + ================================== =================================== + k | kilo | 1000 Ki | kibi | 1024 + ---------------------------------- ----------------------------------- + M | mega | 1000^2 Mi | mebi | 1024^2 + ---------------------------------- ----------------------------------- + G | giga | 1000^3 Gi | gibi | 1024^3 + ---------------------------------- ----------------------------------- + T | tera | 1000^4 Ti | tebi | 1024^4 + ---------------------------------- ----------------------------------- + P | peta | 1000^5 Pi | pebi | 1024^5 + ---------------------------------- ----------------------------------- + E | exa | 1000^6 Ei | exbi | 1024^6 + ---------------------------------- ----------------------------------- + Z | zetta | 1000^7 Zi | zebi | 1024^7 + ---------------------------------- ----------------------------------- + Y | yotta | 1000^8 Yi | yobi | 1024^8 + ================================== =================================== + + Suffixes: + + ==================== + SUFFIX | DESCRIPTION + ==================== + b | bit + -------------------- + B | byte + ==================== + + See http://en.wikipedia.org/wiki/Binary_prefix for more details on + those units. + + If a wrong prefix or suffix is provided, an error will be raised. + + Examples: + convert_data_size(5, 'MiB', 'KiB') -> 5120.0 + convert_data_size(5, 'MiB', 'M') -> 5.24288 + convert_data_size(5, 'MiB', 'GiB') -> 0.0048828125 + convert_data_size(5, 'MiB', 'Tb') -> 4.194304e-05 + convert_data_size(5, 'MiB') -> 5242880.0 + convert_data_size(5, 'mib') -> #ERROR# (invalid src_unit) + + Parameters: + value -- the value to be converted, in the unit specified by 'src_unit'. + this parameter can be of any type which can be cast to float + (e.g. int, float, str). + src_unit -- the unit of 'value', as described above. + if 'src_unit' is empty, the unit 'B' (byte) will be used. + dst_unit -- the unit of the return value. + if 'dst_unit' is empty, the unit 'B' (byte) will be used. + + Return: + A float number representing 'value' ('src_unit') converted to 'dst_unit'. + """ + SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] + # The IEC prefixes are the equivalent SI prefixes + 'i' + # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. + IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES) + PREFIXES_BY_BASE = {1000: SI_PREFIXES, + 1024: IEC_PREFIXES} + + SUFFIXES_WITH_MULT = {'b': 1, + 'B': 8} + DEFAULT_SUFFIX = 'B' + + DEFAULT_UNIT = 'B' + + # set the default units + if not src_unit: + src_unit = DEFAULT_UNIT + if not dst_unit: + dst_unit = DEFAULT_UNIT + + # set the default suffix + if src_unit[-1] not in SUFFIXES_WITH_MULT: + src_unit += DEFAULT_SUFFIX + if dst_unit[-1] not in SUFFIXES_WITH_MULT: + dst_unit += DEFAULT_SUFFIX + + # split prefix and suffix for better parsing + src_p = src_unit[:-1] + src_s = src_unit[-1] + dst_p = dst_unit[:-1] + dst_s = dst_unit[-1] + + # validate parameters + try: + value = float(value) + except TypeError: + raise InvalidParameter('KCHUTILS0004E', {'value': value}) + if src_p != '' and src_p not in (SI_PREFIXES + IEC_PREFIXES): + raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit}) + if src_s not in SUFFIXES_WITH_MULT: + raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit}) + if dst_p != '' and dst_p not in (SI_PREFIXES + IEC_PREFIXES): + raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit}) + if dst_s not in SUFFIXES_WITH_MULT: + raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit}) + + # convert 'value' to the most basic unit (bits)... + bits = value + + for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): + if src_s == suffix: + bits *= mult + break + + if src_p != '': + for base, prefixes in PREFIXES_BY_BASE.iteritems(): + for i, p in enumerate(prefixes): + if src_p == p: + bits *= base**(i + 1) + break + + # ...then convert the value in bits to the destination unit + ret = bits + + for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): + if dst_s == suffix: + ret /= float(mult) + break + + if dst_p != '': + for base, prefixes in PREFIXES_BY_BASE.iteritems(): + for i, p in enumerate(prefixes): + if dst_p == p: + ret /= float(base)**(i + 1) + break + + return ret -- 2.1.0

On Mon, 2015-03-02 at 13:45 -0300, Crístian Viana wrote:
The new function "kimchi.utils.convert_data_size" can be used to convert values from different units, e.g. converting 5 GiB to MiB, 1 GiB to B.
Signed-off-by: Crístian Viana <vianac@linux.vnet.ibm.com> --- src/kimchi/i18n.py | 2 + src/kimchi/utils.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+)
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py index 2af0be6..df5422f 100644 --- a/src/kimchi/i18n.py +++ b/src/kimchi/i18n.py @@ -267,6 +267,8 @@ messages = { "KCHUTILS0001E": _("Invalid URI %(uri)s"), "KCHUTILS0002E": _("Timeout while running command '%(cmd)s' after %(seconds)s seconds"), "KCHUTILS0003E": _("Unable to choose a virtual machine name"), + "KCHUTILS0004E": _("Invalid data value '%(value)s'"), + "KCHUTILS0005E": _("Invalid data unit '%(unit)s'"),
"KCHVMSTOR0002E": _("Invalid storage type. Types supported: 'cdrom', 'disk'"), "KCHVMSTOR0003E": _("The path '%(value)s' is not a valid local/remote path for the device"), diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py index fc5245f..a04d3cf 100644 --- a/src/kimchi/utils.py +++ b/src/kimchi/utils.py @@ -388,3 +388,148 @@ def get_unique_file_name(all_names, name): max_num = max(max_num, int(match.group(re_group_num)))
return u'%s (%d)' % (name, max_num + 1) + + +def convert_data_size(value, src_unit, dst_unit=None):
s/src_unit/src_unit=None As explained below, both second and third arguments can be None and then automatically converted to use DEFAULT_UNIT. I tried "convert_data_size(4)" and got the error: TypeError: convert_data_size() takes at least 2 arguments (1 given)
+ """Convert a data value from one unit to another unit + (e.g. 'MiB' -> 'GiB'). + + The data units supported by this function are made up of one prefix and one + suffix, both optional. The valid prefixes are those defined in the SI + (i.e. metric system) and those defined by the IEC, and the valid suffixes + indicate if the base unit is bit or byte. Take a look at the tables below + for the possible values: + + Prefixes: + + ================================== =================================== + PREFIX (SI) | DESCRIPTION | VALUE PREFIX (IEC) | DESCRIPTION | VALUE + ================================== =================================== + k | kilo | 1000 Ki | kibi | 1024 + ---------------------------------- ----------------------------------- + M | mega | 1000^2 Mi | mebi | 1024^2 + ---------------------------------- ----------------------------------- + G | giga | 1000^3 Gi | gibi | 1024^3 + ---------------------------------- ----------------------------------- + T | tera | 1000^4 Ti | tebi | 1024^4 + ---------------------------------- ----------------------------------- + P | peta | 1000^5 Pi | pebi | 1024^5 + ---------------------------------- ----------------------------------- + E | exa | 1000^6 Ei | exbi | 1024^6 + ---------------------------------- ----------------------------------- + Z | zetta | 1000^7 Zi | zebi | 1024^7 + ---------------------------------- ----------------------------------- + Y | yotta | 1000^8 Yi | yobi | 1024^8 + ================================== =================================== + + Suffixes: + + ==================== + SUFFIX | DESCRIPTION + ==================== + b | bit + -------------------- + B | byte + ==================== + + See http://en.wikipedia.org/wiki/Binary_prefix for more details on + those units. + + If a wrong prefix or suffix is provided, an error will be raised. + + Examples: + convert_data_size(5, 'MiB', 'KiB') -> 5120.0 + convert_data_size(5, 'MiB', 'M') -> 5.24288 + convert_data_size(5, 'MiB', 'GiB') -> 0.0048828125 + convert_data_size(5, 'MiB', 'Tb') -> 4.194304e-05 + convert_data_size(5, 'MiB') -> 5242880.0 + convert_data_size(5, 'mib') -> #ERROR# (invalid src_unit) + + Parameters: + value -- the value to be converted, in the unit specified by 'src_unit'. + this parameter can be of any type which can be cast to float + (e.g. int, float, str). + src_unit -- the unit of 'value', as described above. + if 'src_unit' is empty, the unit 'B' (byte) will be used. + dst_unit -- the unit of the return value. + if 'dst_unit' is empty, the unit 'B' (byte) will be used. + + Return: + A float number representing 'value' ('src_unit') converted to 'dst_unit'. + """ + SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
I guess you can add a new line here, as you did between SUFFIXES_WITH_MULT and DEFAULT_SUFFIX.
+ # The IEC prefixes are the equivalent SI prefixes + 'i' + # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. + IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES)
New line here.
+ PREFIXES_BY_BASE = {1000: SI_PREFIXES, + 1024: IEC_PREFIXES} + + SUFFIXES_WITH_MULT = {'b': 1, + 'B': 8} + DEFAULT_SUFFIX = 'B' + + DEFAULT_UNIT = 'B' + + # set the default units + if not src_unit: + src_unit = DEFAULT_UNIT + if not dst_unit: + dst_unit = DEFAULT_UNIT + + # set the default suffix + if src_unit[-1] not in SUFFIXES_WITH_MULT: + src_unit += DEFAULT_SUFFIX + if dst_unit[-1] not in SUFFIXES_WITH_MULT: + dst_unit += DEFAULT_SUFFIX + + # split prefix and suffix for better parsing + src_p = src_unit[:-1] + src_s = src_unit[-1] + dst_p = dst_unit[:-1] + dst_s = dst_unit[-1] + + # validate parameters + try: + value = float(value) + except TypeError: + raise InvalidParameter('KCHUTILS0004E', {'value': value}) + if src_p != '' and src_p not in (SI_PREFIXES + IEC_PREFIXES): + raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit}) + if src_s not in SUFFIXES_WITH_MULT: + raise InvalidParameter('KCHUTILS0005E', {'unit': src_unit}) + if dst_p != '' and dst_p not in (SI_PREFIXES + IEC_PREFIXES): + raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit}) + if dst_s not in SUFFIXES_WITH_MULT: + raise InvalidParameter('KCHUTILS0005E', {'unit': dst_unit}) + + # convert 'value' to the most basic unit (bits)... + bits = value + + for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): + if src_s == suffix: + bits *= mult + break + + if src_p != '': + for base, prefixes in PREFIXES_BY_BASE.iteritems(): + for i, p in enumerate(prefixes): + if src_p == p: + bits *= base**(i + 1) + break + + # ...then convert the value in bits to the destination unit + ret = bits + + for suffix, mult in SUFFIXES_WITH_MULT.iteritems(): + if dst_s == suffix: + ret /= float(mult) + break + + if dst_p != '': + for base, prefixes in PREFIXES_BY_BASE.iteritems(): + for i, p in enumerate(prefixes): + if dst_p == p: + ret /= float(base)**(i + 1) + break + + return ret
-- Paulo Ricardo Paz Vital <pvital@gmail.com>

On 03-03-2015 05:16, Paulo Ricardo Paz Vital wrote:
s/src_unit/src_unit=None As explained below, both second and third arguments can be None and then automatically converted to use DEFAULT_UNIT.
I tried "convert_data_size(4)" and got the error: TypeError: convert_data_size() takes at least 2 arguments (1 given)
I didn't mean the first parameter to be optional. What would you expect when calling "convert_data_size(4)"? Assuming both units as bytes, the function would always return the same value which was passed to it. Both parameters *can* be None but that doesn't mean we should create a default situation where it happens, because that wouldn't be useful at all.
+ SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] I guess you can add a new line here, as you did between SUFFIXES_WITH_MULT and DEFAULT_SUFFIX.
+ # The IEC prefixes are the equivalent SI prefixes + 'i' + # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. + IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES) New line here.
+ PREFIXES_BY_BASE = {1000: SI_PREFIXES, + 1024: IEC_PREFIXES} + + SUFFIXES_WITH_MULT = {'b': 1, + 'B': 8} + DEFAULT_SUFFIX = 'B' + + DEFAULT_UNIT = 'B' + +
Well, I tried to group the variable declarations by subject: prefix-related variables, <blank space>, suffix-related variables, <blank space>, unit-related variable.

On Tue, 2015-03-03 at 10:21 -0300, Crístian Viana wrote:
On 03-03-2015 05:16, Paulo Ricardo Paz Vital wrote:
s/src_unit/src_unit=None As explained below, both second and third arguments can be None and then automatically converted to use DEFAULT_UNIT.
I tried "convert_data_size(4)" and got the error: TypeError: convert_data_size() takes at least 2 arguments (1 given)
I didn't mean the first parameter to be optional. What would you expect when calling "convert_data_size(4)"? Assuming both units as bytes, the function would always return the same value which was passed to it. Both parameters *can* be None but that doesn't mean we should create a default situation where it happens, because that wouldn't be useful at all.
OK, so I think you should do some modifications on code to be coherent with what you intend to do. First, you should re-write the documentation part where you explain the parameters, by removing the line "if 'src_unit' is empty, the unit 'B' (byte) will be used.", because it will never happen. Second, it's not necessary the following block, again, because it will never happen. Removing this block, you will guarantee that 'src_unit' and 'dst_unit' will be always different and you will not create a default situatio. + if not src_unit: + src_unit = DEFAULT_UNIT
+ SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] I guess you can add a new line here, as you did between SUFFIXES_WITH_MULT and DEFAULT_SUFFIX.
+ # The IEC prefixes are the equivalent SI prefixes + 'i' + # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. + IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES) New line here.
+ PREFIXES_BY_BASE = {1000: SI_PREFIXES, + 1024: IEC_PREFIXES} + + SUFFIXES_WITH_MULT = {'b': 1, + 'B': 8} + DEFAULT_SUFFIX = 'B' + + DEFAULT_UNIT = 'B' + +
Well, I tried to group the variable declarations by subject: prefix-related variables, <blank space>, suffix-related variables, <blank space>, unit-related variable.
Got it! However, I'm "old school" and learned that if you add a comment, you, as a best practice, should add a blank line between the previous line and the comment line :-P

On 03/03/2015 11:00, Paulo Ricardo Paz Vital wrote:
On Tue, 2015-03-03 at 10:21 -0300, Crístian Viana wrote:
s/src_unit/src_unit=None As explained below, both second and third arguments can be None and then automatically converted to use DEFAULT_UNIT.
I tried "convert_data_size(4)" and got the error: TypeError: convert_data_size() takes at least 2 arguments (1 given) I didn't mean the first parameter to be optional. What would you expect when calling "convert_data_size(4)"? Assuming both units as bytes, the function would always return the same value which was passed to it. Both
On 03-03-2015 05:16, Paulo Ricardo Paz Vital wrote: parameters *can* be None but that doesn't mean we should create a default situation where it happens, because that wouldn't be useful at all.
OK, so I think you should do some modifications on code to be coherent with what you intend to do.
First, you should re-write the documentation part where you explain the parameters, by removing the line "if 'src_unit' is empty, the unit 'B' (byte) will be used.", because it will never happen.
Second, it's not necessary the following block, again, because it will never happen. Removing this block, you will guarantee that 'src_unit' and 'dst_unit' will be always different and you will not create a default situatio.
+ if not src_unit: + src_unit = DEFAULT_UNIT
I don't think we should use None as a default parameter and then covert it to a real parameter. It should use the real parameter in function. def convert_data_size(value, src_unit, dst_unit='B'): And make the first and second parameters required. So we always need to pass the value and its unit to do the conversion. And the default destination unit is 'B'.
+ SI_PREFIXES = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] I guess you can add a new line here, as you did between SUFFIXES_WITH_MULT and DEFAULT_SUFFIX.
+ # The IEC prefixes are the equivalent SI prefixes + 'i' + # but, exceptionally, 'k' becomes 'Ki' instead of 'ki'. + IEC_PREFIXES = map(lambda p: 'Ki' if p == 'k' else p + 'i', SI_PREFIXES) New line here.
+ PREFIXES_BY_BASE = {1000: SI_PREFIXES, + 1024: IEC_PREFIXES} + + SUFFIXES_WITH_MULT = {'b': 1, + 'B': 8} + DEFAULT_SUFFIX = 'B' + + DEFAULT_UNIT = 'B' + + Well, I tried to group the variable declarations by subject: prefix-related variables, <blank space>, suffix-related variables, <blank space>, unit-related variable. Got it! However, I'm "old school" and learned that if you add a comment, you, as a best practice, should add a blank line between the previous line and the comment line :-P
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

Newer libvirt versions report 0 when reading the current memory of a shutoff VM by calling the method "domain.info()". So when the VM is shutoff, the REST command "GET /vms/<vm>" is returning an invalid memory value. Read the memory value from the VM's XML descriptor when it is shutoff, and keep returning the value from "domain.info()" otherwise. Fix issue #595 (Memory is set to 0 (null) when editing guest). Signed-off-by: Crístian Viana <vianac@linux.vnet.ibm.com> --- src/kimchi/model/vms.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py index 379c850..3a10158 100644 --- a/src/kimchi/model/vms.py +++ b/src/kimchi/model/vms.py @@ -41,8 +41,8 @@ from kimchi.model.utils import get_metadata_node from kimchi.model.utils import set_metadata_node from kimchi.rollbackcontext import RollbackContext from kimchi.screenshot import VMScreenshot -from kimchi.utils import add_task, get_next_clone_name, import_class -from kimchi.utils import kimchi_log, run_setfacl_set_attr +from kimchi.utils import add_task, convert_data_size, get_next_clone_name +from kimchi.utils import import_class, kimchi_log, run_setfacl_set_attr from kimchi.utils import template_name_from_uri from kimchi.xmlutils.utils import xpath_get_text, xml_item_update from kimchi.xmlutils.utils import dictize @@ -70,6 +70,8 @@ XPATH_DOMAIN_NAME = '/domain/name' XPATH_DOMAIN_MAC = "/domain/devices/interface[@type='network']/mac/@address" XPATH_DOMAIN_MAC_BY_ADDRESS = "./devices/interface[@type='network']/"\ "mac[@address='%s']" +XPATH_DOMAIN_MEMORY = '/domain/memory' +XPATH_DOMAIN_MEMORY_UNIT = '/domain/memory/@unit' XPATH_DOMAIN_UUID = '/domain/uuid' @@ -793,11 +795,23 @@ class VMModel(object): res['io_throughput_peak'] = vm_stats.get('max_disk_io', 100) users, groups = self._get_access_info(dom) + if state == 'shutoff': + xml = dom.XMLDesc(0) + val = xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0] + unit_list = xpath_get_text(xml, XPATH_DOMAIN_MEMORY_UNIT) + if len(unit_list) > 0: + unit = unit_list[0] + else: + unit = 'KiB' + memory = convert_data_size(val, unit, 'MiB') + else: + memory = info[2] >> 10 + return {'name': name, 'state': state, 'stats': res, 'uuid': dom.UUIDString(), - 'memory': info[2] >> 10, + 'memory': memory, 'cpus': info[3], 'screenshot': screenshot, 'icon': icon, -- 2.1.0

Reviewed-by: Paulo Vital <pvital@gmail.com> Tested-by: Paulo Vital <pvital@gmail.com> On Mon, 2015-03-02 at 13:45 -0300, Crístian Viana wrote:
Newer libvirt versions report 0 when reading the current memory of a shutoff VM by calling the method "domain.info()". So when the VM is shutoff, the REST command "GET /vms/<vm>" is returning an invalid memory value.
Read the memory value from the VM's XML descriptor when it is shutoff, and keep returning the value from "domain.info()" otherwise.
Fix issue #595 (Memory is set to 0 (null) when editing guest).
Signed-off-by: Crístian Viana <vianac@linux.vnet.ibm.com> --- src/kimchi/model/vms.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py index 379c850..3a10158 100644 --- a/src/kimchi/model/vms.py +++ b/src/kimchi/model/vms.py @@ -41,8 +41,8 @@ from kimchi.model.utils import get_metadata_node from kimchi.model.utils import set_metadata_node from kimchi.rollbackcontext import RollbackContext from kimchi.screenshot import VMScreenshot -from kimchi.utils import add_task, get_next_clone_name, import_class -from kimchi.utils import kimchi_log, run_setfacl_set_attr +from kimchi.utils import add_task, convert_data_size, get_next_clone_name +from kimchi.utils import import_class, kimchi_log, run_setfacl_set_attr from kimchi.utils import template_name_from_uri from kimchi.xmlutils.utils import xpath_get_text, xml_item_update from kimchi.xmlutils.utils import dictize @@ -70,6 +70,8 @@ XPATH_DOMAIN_NAME = '/domain/name' XPATH_DOMAIN_MAC = "/domain/devices/interface[@type='network']/mac/@address" XPATH_DOMAIN_MAC_BY_ADDRESS = "./devices/interface[@type='network']/"\ "mac[@address='%s']" +XPATH_DOMAIN_MEMORY = '/domain/memory' +XPATH_DOMAIN_MEMORY_UNIT = '/domain/memory/@unit' XPATH_DOMAIN_UUID = '/domain/uuid'
@@ -793,11 +795,23 @@ class VMModel(object): res['io_throughput_peak'] = vm_stats.get('max_disk_io', 100) users, groups = self._get_access_info(dom)
+ if state == 'shutoff': + xml = dom.XMLDesc(0) + val = xpath_get_text(xml, XPATH_DOMAIN_MEMORY)[0] + unit_list = xpath_get_text(xml, XPATH_DOMAIN_MEMORY_UNIT) + if len(unit_list) > 0: + unit = unit_list[0] + else: + unit = 'KiB' + memory = convert_data_size(val, unit, 'MiB') + else: + memory = info[2] >> 10 + return {'name': name, 'state': state, 'stats': res, 'uuid': dom.UUIDString(), - 'memory': info[2] >> 10, + 'memory': memory, 'cpus': info[3], 'screenshot': screenshot, 'icon': icon,
participants (3)
-
Aline Manera
-
Crístian Viana
-
Paulo Ricardo Paz Vital