On 10/03/2014 01:46 PM, Christy Perez wrote:
On 10/03/2014 10:31 AM, Aline Manera wrote:
> On 09/02/2014 07:56 PM, Christy Perez wrote:
>> Aline,
>>
>> A question for you (inline)...
>>
>> On 08/25/2014 02:08 PM, Christy Perez wrote:
>>> On 08/21/2014 01:22 PM, Aline Manera wrote:
>>>> On 08/18/2014 08:04 PM, Christy Perez wrote:
>>>>> In order to allow a guest to use SMT/hyperthreading, we should
>>>>> enable passing in of the sockets, cores, and threads values when
>>>>> creating a template.
>>>>>
>>>>> All three values must be specified, as per the topology descr at
>>>>>
http://libvirt.org/formatdomain.html#elementsCPU
>>>>>
>>>>> Signed-off-by: Christy Perez <christy(a)linux.vnet.ibm.com>
>>>>> ---
>>>>> docs/API.md | 7 +++++++
>>>>> src/kimchi/API.json | 28
++++++++++++++++++++++++++--
>>>>> src/kimchi/control/templates.py | 11 ++++++++---
>>>>> src/kimchi/osinfo.py | 2 +-
>>>>> src/kimchi/vmtemplate.py | 22 ++++++++++++++++++++++
>>>>> 5 files changed, 64 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/docs/API.md b/docs/API.md
>>>>> index d75c55f..cb4d541 100644
>>>>> --- a/docs/API.md
>>>>> +++ b/docs/API.md
>>>>> @@ -200,6 +200,13 @@ Represents a snapshot of the Virtual
Machine's
>>>>> primary monitor.
>>>>> Independent Computing Environments
>>>>> * null: Graphics is disabled or type not supported
>>>>> * listen: The network which the vnc/spice server listens
>>>>> on.
>>>>> + * cpu_info *(optional)*: CPU-specific information.
>>>>> + * topology: Specify sockets, threads, and cores to run the
>>>>> virtual CPU
>>>>> + threads on.
>>>>> + All three are required in order to specify cpu
topology.
>>>>> + * sockets - The number of sockets to use.
>>>>> + * cores - The number of cores per socket.
>>>>> + * threads - The number of threads per core.
>>>>>
>>>>> ### Sub-Collection: Virtual Machine Network Interfaces
>>>>>
>>>>> diff --git a/src/kimchi/API.json b/src/kimchi/API.json
>>>>> index c3fc5e3..d510634 100644
>>>>> --- a/src/kimchi/API.json
>>>>> +++ b/src/kimchi/API.json
>>>>> @@ -26,6 +26,28 @@
>>>>> ]
>>>>> }
>>>>> }
>>>>> + },
>>>>> + "cpu_info": {
>>>>> + "description": "Configure CPU specifics
for a VM.",
>>>>> + "type": "object",
>>>>> + "properties": {
>>>>> + "topology": {
>>>>> + "description": "Configure the
guest CPU
>>>>> topology.",
>>>>> + "type": "object",
>>>>> + "properties": {
>>>>> + "sockets": {
>>>>> + "type": "number"
>>>>> + },
>>>>> + "cores": {
>>>>> + "type": "number"
>>>>> + },
>>>>> + "threads": {
>>>>> + "type": "number"
>>>>> + }
>>>>> + },
>>>>> + "required": [ "sockets",
"cores", "threads" ]
>>>> Usually we set the required = true for each parameter.
>>>>
>>>> "sockets": {
>>>> "type": "number",
>>>> "required": true
>>>> },
>>>>
>>> I've changed it to that.
>>>>> + }
>>>>> + }
>>>>> }
>>>>> },
>>>>> "properties": {
>>>>> @@ -438,7 +460,8 @@
>>>>> "type": "array",
>>>>> "items": { "type":
"string" }
>>>>> },
>>>>> - "graphics": { "$ref":
"#/kimchitype/graphics" }
>>>>> + "graphics": { "$ref":
"#/kimchitype/graphics" },
>>>>> + "cpu_info": { "$ref":
"#/kimchitype/cpu_info" }
>>>>> },
>>>>> "additionalProperties": false,
>>>>> "error": "KCHAPI0001E"
>>>>> @@ -608,7 +631,8 @@
>>>>> "type": "array",
>>>>> "items": { "type":
"string" }
>>>>> },
>>>>> - "graphics": { "$ref":
"#/kimchitype/graphics" }
>>>>> + "graphics": { "$ref":
"#/kimchitype/graphics" },
>>>>> + "cpu_info": { "$ref":
"#/kimchitype/cpu_info" }
>>>>> },
>>>>> "additionalProperties": false,
>>>>> "error": "KCHAPI0001E"
>>>>> diff --git a/src/kimchi/control/templates.py
>>>>> b/src/kimchi/control/templates.py
>>>>> index e17fa54..5ef35ce 100644
>>>>> --- a/src/kimchi/control/templates.py
>>>>> +++ b/src/kimchi/control/templates.py
>>>>> @@ -38,13 +38,14 @@ def __init__(self, model, ident):
>>>>> self.update_params = ["name",
"folder", "icon",
>>>>> "os_distro",
>>>>> "storagepool",
"os_version", "cpus",
>>>>> "memory",
"cdrom", "disks",
>>>>> "networks",
>>>>> - "graphics"]
>>>>> + "graphics",
"cpu_info"]
>>>>> self.uri_fmt = "/templates/%s"
>>>>> self.clone =
self.generate_action_handler('clone')
>>>>>
>>>>> @property
>>>>> def data(self):
>>>>> - return {'name': self.ident,
>>>>> + return_data = {
>>>>> + 'name': self.ident,
>>>>> 'icon': self.info['icon'],
>>>>> 'invalid': self.info['invalid'],
>>>>> 'os_distro':
self.info['os_distro'],
>>>>> @@ -56,4 +57,8 @@ def data(self):
>>>>> 'storagepool':
self.info['storagepool'],
>>>>> 'networks':
self.info['networks'],
>>>>> 'folder': self.info.get('folder',
[]),
>>>>> - 'graphics': self.info['graphics']}
>>>>> + 'graphics': self.info['graphics']
>>>>> + }
>>>>> + if (self.info.get('cpu_info')):
>>>>> + return_data['cpu_info'] =
self.info['cpu_info']
>>>> We should always return the same data set while accessing a template
>>>> That way "cpu_info" must always have a value.
>> How would you suggest we handle this then? If it's not set, we can't
>> return 0's or 1's.
>>
>> All 0's won't work:
>>
>> # virsh edit domainname
>> error: XML error: Invalid CPU topology
>> Failed. Try again? [y,n,f,?]:
>>
>> All 1's as a default but a change in the vcpus would lead to an error:
>>
>> # virsh edit domainname
>> error: Maximum CPUs greater than topology limit
>> Failed. Try again? [y,n,f,?]:
> Do we need to have both <vcpu> and cpu topology?
> Does the cpu topology not override the <vcpu>?
>
> <vcpu>%(cpus)s</vcpu>
> + %(cpu_info)s
>
>
I just tried deleting it from the XML of a guest I had with a topology
element of 1 socket, 1 core, and 2 threads. It looks like if you don't
put vcpus, it defaults back to just '1', so, yes. We need both.
Ok. Thanks for confirm and test it.
Is just returning and empty string for this value okay? I actually
sent
a v2 to the ml at the same time you replied to this, but I had a typo in
the address so it didn't make it to the list. I'll hold off on v2 for
this discussion.
>>>>> + return return_data
>>>>> diff --git a/src/kimchi/osinfo.py b/src/kimchi/osinfo.py
>>>>> index 1ad353c..8492bb7 100644
>>>>> --- a/src/kimchi/osinfo.py
>>>>> +++ b/src/kimchi/osinfo.py
>>>>> @@ -32,7 +32,7 @@
>>>>> 'power': ('ppc',
'ppc64')}
>>>>>
>>>>>
>>>>> -common_spec = {'cpus': 1, 'cpu_cores': 1,
'cpu_threads': 1, 'memory':
>>>>> 1024,
>>>>> +common_spec = {'cpus': 1, 'cpu_sockets':
'1', 'cpu_cores': 1,
>>>>> 'cpu_threads': 1, 'memory': 1024,
>>>> Why are you using a different structure here?
>>>> I'd expect to have
>>>> {..., 'cpu_info': {cores: .., threads:..., sockets:...}}
>>> The structure was like that already. I just put in the new value for
>>> sockets. I didn't look too deeply into how the rest of the code uses the
>>> osifno spec information, but I left it as-is so as not to break any
>>> current functionality.
>>>
>>>> And even with this cpu info (with cores, threads, sockets) we will
>>>> continue to have the "cpus" data?
>>> Yes. With all 1's as the default, the cpus can be left as-is.
>>>
>>> I'm adding a check in the vmtemplates code to make sure that this value
>>> is always a product of the three values.
>>>
>>> When we add in some intelligence, we can set the vcpu to be a multiple.
>>>
>>>>> 'disks': [{'index': 0,
'size': 10}], 'cdrom_bus':
>>>>> 'ide',
>>>>> 'cdrom_index': 2, 'mouse_bus':
'ps2'}
>>>>>
>>>>> diff --git a/src/kimchi/vmtemplate.py b/src/kimchi/vmtemplate.py
>>>>> index 761bac5..c64e61d 100644
>>>>> --- a/src/kimchi/vmtemplate.py
>>>>> +++ b/src/kimchi/vmtemplate.py
>>>>> @@ -359,6 +359,22 @@ def _get_input_output_xml(self):
>>>>> input_output += sound % self.info
>>>>> return input_output
>>>>>
>>>>> + def _get_cpu_xml(self):
>>>>> +
>>>>> + cpu_info = self.info.get('cpu_info')
>>>>> + if cpu_info is not None:
>>>>> + cpu_topo = cpu_info.get('topology')
>>>>> + if cpu_topo is not None:
>>>>> + return """
>>>>> + <cpu>
>>>>> + <topology sockets='%(sockets)s'
>>>>> + cores='%(cores)s'
>>>>> + threads='%(threads)s'/>
>>>>> + </cpu>
>>>> We are in a movement to use "lxml.builder.E" to build the xml
>>>> instead of
>>>> string.
>>>> Could you do it in that way too?
>>> Sure! I was wondering about that. I just stuck with how it was being
>>> done everywhere else, but I like that method.
>>>>> + """ % cpu_topo
>>>>> +
>>>>> + return ""
>>>>> +
>>>>> def to_vm_xml(self, vm_name, vm_uuid, **kwargs):
>>>>> params = dict(self.info)
>>>>> params['name'] = vm_name
>>>>> @@ -371,6 +387,11 @@ def to_vm_xml(self, vm_name, vm_uuid,
**kwargs):
>>>>> graphics = kwargs.get('graphics')
>>>>> params['graphics'] =
self._get_graphics_xml(graphics)
>>>>> + if params.get('cpu_info') is not None:
>>>>> + params['cpu_info'] = self._get_cpu_xml()
>>>>> + else:
>>>>> + params['cpu_info'] = ''
>>>>> +
>>>> As this "cpu_info" is set in the "common_spec" for
any ISO file, this
>>>> information will always exist. Otherwise we have a bug
>>>> So you can assume that info will be there for use.
>>> ACK. Thanks.
>>>
>>>>> # Current implementation just allows to create disk in
one
>>>>> single
>>>>> # storage pool, so we cannot mix the types (scsi volumes
vs
>>>>> img file)
>>>>> storage_type = self._get_storage_type()
>>>>> @@ -401,6 +422,7 @@ def to_vm_xml(self, vm_name, vm_uuid, **kwargs):
>>>>> <uuid>%(uuid)s</uuid>
>>>>> <memory
unit='MiB'>%(memory)s</memory>
>>>>> <vcpu>%(cpus)s</vcpu>
>>>>> + %(cpu_info)s
>>>>> <os>
>>>>> <type arch='%(arch)s'>hvm</type>
>>>>> <boot dev='hd'/>
>> Regards,
>>
>> - Christy