[PATCH 0/5] template cloning

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> The user may clone a template from an existing template with different name. Later he can customize some parts of the template to save the effort to create a full new template. For example, he can update the network of the template cloned to have a new different template. ShaoHe Feng (5): clone template: update API.md API.json: move templates_create close to template_update clone template: update controller clone template: update model and mockmodel clone template: update test case docs/API.md | 27 +++++++++- src/kimchi/API.json | 112 ++++++++++++++++++++++++++++++++++------ src/kimchi/control/templates.py | 1 + src/kimchi/mockmodel.py | 19 +++++++ src/kimchi/model/templates.py | 20 +++++++ tests/test_rest.py | 34 ++++++++++++ 6 files changed, 196 insertions(+), 17 deletions(-) -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM. **Actions (POST):** -* *No actions defined* +* clone: clone a template from an existing template with different name. + * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on. ### Collection: Storage Pools -- 1.8.4.2

On 02/11/2014 11:58 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM.
**Actions (POST):**
-* *No actions defined* +* clone: clone a template from an existing template with different name.
To clone a template the user just need to pass the template name to clone from. So I expect: POST /templates {template: /templates/my-template} This will create a new template based on /templates/my-template To change the parameters in new template user can use the edit function.
+ * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on.
### Collection: Storage Pools

On 02/11/2014 10:32 PM, Aline Manera wrote:
On 02/11/2014 11:58 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM.
**Actions (POST):**
-* *No actions defined* +* clone: clone a template from an existing template with different name.
To clone a template the user just need to pass the template name to clone from.
So I expect: POST /templates {template: /templates/my-template}
The API can be as you did: POST /templates/my-template/clone to create a new template from my-template So in this case any parameter is needed
This will create a new template based on /templates/my-template
To change the parameters in new template user can use the edit function.
+ * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on.
### Collection: Storage Pools
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 02/12/2014 08:35 AM, Aline Manera wrote:
On 02/11/2014 10:32 PM, Aline Manera wrote:
On 02/11/2014 11:58 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM.
**Actions (POST):**
-* *No actions defined* +* clone: clone a template from an existing template with different name.
To clone a template the user just need to pass the template name to clone from.
So I expect: POST /templates {template: /templates/my-template} POST for collection is just for CREATE method. POST /templates {template: /templates/my-template} can not tell the kimchi this is a "clone" action.
The API can be as you did:
POST /templates/my-template/clone to create a new template from my-template
So in this case any parameter is needed None parameter is needed, all they are optional. In this way, user can clone and customize some parts of the template one time. Of course, user still can customize some parts of the template by "UPDATE" later.
Can we provide a reasonable default the name of the clone? How about we set the default name of the clone as follow? if the template name is "kimchi-template", then the default name is "kimchi-template-clone1". and user will clone this template twice, then the default name is "kimchi-template-clone2". With the full edit flow in place, its tempting to just add a "duplicate template" action to template. The action default everything in the new template. Do you means we let the user pre-edit the template. for if user want to clone a template with name "template1", but he just want a CPU numbers are different. He just modify the current template( "template1") , and press "clone",
Here is the history of RFC.| ||| then kimchi generate "template1-clone1" template. We will not save the "template1" what he modify. and all the attributes of new "template1-clone1" template are same with "template1" except name and CPU number. of course, the user can modify the CPU number after he does clone.
This will create a new template based on /templates/my-template
To change the parameters in new template user can use the edit function.
+ * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on.
### Collection: Storage Pools
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
-- Thanks and best regards! Sheldon Feng(???)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 02/12/2014 01:46 AM, Sheldon wrote:
On 02/12/2014 08:35 AM, Aline Manera wrote:
On 02/11/2014 10:32 PM, Aline Manera wrote:
On 02/11/2014 11:58 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM.
**Actions (POST):**
-* *No actions defined* +* clone: clone a template from an existing template with different name.
To clone a template the user just need to pass the template name to clone from.
So I expect: POST /templates {template: /templates/my-template} POST for collection is just for CREATE method. POST /templates {template: /templates/my-template} can not tell the kimchi this is a "clone" action.
The API can be as you did:
POST /templates/my-template/clone to create a new template from my-template
So in this case any parameter is needed None parameter is needed, all they are optional. In this way, user can clone and customize some parts of the template one time.
Clone will just clone the template. To customize the cloned template user will use the edit function.
Of course, user still can customize some parts of the template by "UPDATE" later.
Here is the history of RFC.| |||
Can we provide a reasonable default the name of the clone? How about we set the default name of the clone as follow? if the template name is "kimchi-template", then the default name is "kimchi-template-clone1". and user will clone this template twice, then the default name is "kimchi-template-clone2". With the full edit flow in place, its tempting to just add a "duplicate template" action to template. The action default everything in the new template.
Yeap. As Adam said the clone will just "duplicate the template" with all default in new template. And as edit flow is in place, the user an edit the cloned template accordingly.
Do you means we let the user pre-edit the template. for if user want to clone a template with name "template1", but he just want a CPU numbers are different. He just modify the current template( "template1") , and press "clone", then kimchi generate "template1-clone1" template. We will not save the "template1" what he modify. and all the attributes of new "template1-clone1" template are same with "template1" except name and CPU number. of course, the user can modify the CPU number after he does clone.
This will create a new template based on /templates/my-template
To change the parameters in new template user can use the edit function.
+ * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on.
### Collection: Storage Pools
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
-- Thanks and best regards!
Sheldon Feng(???)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 02/12/2014 08:17 PM, Aline Manera wrote:
On 02/12/2014 01:46 AM, Sheldon wrote:
On 02/12/2014 08:35 AM, Aline Manera wrote:
On 02/11/2014 10:32 PM, Aline Manera wrote:
On 02/11/2014 11:58 AM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
The user may clone a template from an existing template with different name. He can update some attributes when he clone a template. And he can also customize some parts of the template to save the effort to create a full new template later.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/docs/API.md b/docs/API.md index 580728c..bf4dd78 100644 --- a/docs/API.md +++ b/docs/API.md @@ -257,7 +257,32 @@ A interface represents available network interface on VM.
**Actions (POST):**
-* *No actions defined* +* clone: clone a template from an existing template with different name.
To clone a template the user just need to pass the template name to clone from.
So I expect: POST /templates {template: /templates/my-template} POST for collection is just for CREATE method. POST /templates {template: /templates/my-template} can not tell the kimchi this is a "clone" action.
The API can be as you did:
POST /templates/my-template/clone to create a new template from my-template
So in this case any parameter is needed None parameter is needed, all they are optional. In this way, user can clone and customize some parts of the template one time.
Clone will just clone the template. To customize the cloned template user will use the edit function. OK, change it next version.
But I do not think it is a not bad thing that we allow all parameters to be optional. Some scenarios as follow: 1. for kimchi we can still clone a template without parameters POST /templates/my-template/clone to create a new template from my-template 2 .other developer parties, maybe they just want to call kimchi API, They may just want to use kimchi UI and do not use kimchi UI, then the can call POST /templates/my-template/clone {"name": "new-name", "CPUs": 4} to create a new template from my-template and change the name and CPUs just one API call. 3. In our kimchi template page There maybe many diff templates. but all of them just display 4 information, OS, CPUs, Version, Memory. As we all know, the purpose of clone is to save the effort to create a new one and just customize some parts of the template. Usually a user want to clone a template, he will fist view the details of template. he can do the follow step. *a). he can open the details page of one template* _______________________________________________________________________ Name: my-template CDROM: F19.iso Vendor: fedora Storage Pool: default Version: 19 Network: default CPU Number: 1 Memory: 1024 Disk(GB): 10 _______________________________________________________________________ exit clone edit. *b). change one of attribute. * if he just want to edit the CPU Number to 2, The he can change it as follow: _______________________________________________________________________ Name: my-template CDROM: F19.iso Vendor: fedora Storage Pool: default Version: 19 Network: default CPU Number: /_*2*_/ Memory: 1024 Disk(GB): 10 _______________________________________________________________________ exit clone edit. *c) and click clone* VS. the "duplicate template" with default everything. The user must do as the follow steps: *a) open the one template page the check this is he want.** **b) close it.** **c) click "clone" button.** **d) open the new clone template** **e) edit the CPU Numbe** **f) save**it.** *
Of course, user still can customize some parts of the template by "UPDATE" later.
Here is the history of RFC.| |||
Can we provide a reasonable default the name of the clone? How about we set the default name of the clone as follow? if the template name is "kimchi-template", then the default name is "kimchi-template-clone1". and user will clone this template twice, then the default name is "kimchi-template-clone2". With the full edit flow in place, its tempting to just add a "duplicate template" action to template. The action default everything in the new template.
Yeap. As Adam said the clone will just "duplicate the template" with all default in new template. And as edit flow is in place, the user an edit the cloned template accordingly.
Do you means we let the user pre-edit the template. for if user want to clone a template with name "template1", but he just want a CPU numbers are different. He just modify the current template( "template1") , and press "clone", then kimchi generate "template1-clone1" template. We will not save the "template1" what he modify. and all the attributes of new "template1-clone1" template are same with "template1" except name and CPU number. of course, the user can modify the CPU number after he does clone.
This will create a new template based on /templates/my-template
To change the parameters in new template user can use the edit function.
+ * name *(optional)*: A name for the new template. + * folder *(optional)*: A virtual path which can be used to organize Templates + in a user interface. The format is an array of path components. + * icon *(optional)*: A URI to a PNG image representing this template + * os_distro *(optional)*: The operating system distribution + * os_version *(optional)*: The version of the operating system distribution + * cpus *(optional)*: The number of CPUs assigned to the VM + * memory *(optional)*: The amount of memory assigned to the VM + * cdrom *(optional)*: A volume name or URI to an ISO image + * storagepool *(optional)*: URI of the storagepool where template allocates + vm storage. + * networks *(optional)*: list of networks will be assigned to the new VM. + * disks *(optional)*: An array of requested disks with the following optional + fields (either *size* or *volume* must be specified): + * index: The device index + * size: The device size in GB + * volume: A volume name that contains the initial disk contents + * graphcis *(optional)*: A dict of graphics paramenters of this template + * type: The type of graphics. It can be VNC or spice or None. + * vnc: Graphical display using the Virtual Network + Computing protocol + * spice: Graphical display using the Simple Protocol for + Independent Computing Environments + * null: Graphics is disabled or type not supported + * listen: The network which the vnc/spice server listens on.
### Collection: Storage Pools
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
-- Thanks and best regards!
Sheldon Feng(???)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center
-- Thanks and best regards! Sheldon Feng(???)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 02/13/2014 01:27 PM, Sheldon wrote:
They may just want to use kimchi UI and do not use kimchi UI, then the can call They may just want to use REST API
-- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> commit e976b781 and d60c4b8d break the order of items in API.json templates_create should be close to template_update Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/API.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 08c77c5..10741a4 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -177,6 +177,28 @@ } } }, + "storageservers_get_list": { + "type": "object", + "properties": { + "_target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$" + } + }, + "additionalProperties": false + }, + "storagetargets_get_list": { + "type": "object", + "properties": { + "_target_type": { + "description": "List storage servers of given type", + "type": "string", + "pattern": "^netfs$" + } + }, + "additionalProperties": false + }, "templates_create": { "type": "object", "properties": { @@ -258,28 +280,6 @@ }, "additionalProperties": false }, - "storageservers_get_list": { - "type": "object", - "properties": { - "_target_type": { - "description": "List storage servers of given type", - "type": "string", - "pattern": "^netfs$" - } - }, - "additionalProperties": false - }, - "storagetargets_get_list": { - "type": "object", - "properties": { - "_target_type": { - "description": "List storage servers of given type", - "type": "string", - "pattern": "^netfs$" - } - }, - "additionalProperties": false - }, "template_update": { "type": "object", "properties": { -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Add clone action in controller also update API.json Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/API.json | 80 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/templates.py | 1 + 2 files changed, 81 insertions(+) diff --git a/src/kimchi/API.json b/src/kimchi/API.json index 10741a4..aca72a7 100644 --- a/src/kimchi/API.json +++ b/src/kimchi/API.json @@ -280,6 +280,86 @@ }, "additionalProperties": false }, + "template_clone": { + "type": "object", + "properties": { + "name": { + "description": "The name of the new template", + "type": "string", + "pattern": "^[^ ]+( +[^ ]+)*$", + "minLength": 1 + }, + "icon": { + "description": "The template icon path", + "type": "string", + "pattern": "^images/" + }, + "os_distro": { + "description": "Distribution name of the Operating System", + "type": "string", + "minLength": 1 + }, + "os_version": { + "description": "Version of the Operating System", + "type": "string", + "minLength": 1 + }, + "cpus": { + "description": "Number of CPUs for the template", + "type": "integer", + "minimum": 1 + }, + "memory": { + "description": "Memory (MB) for the template", + "type": "integer", + "minimum": 512 + }, + "cdrom": { + "description": "Path for cdrom", + "type": "string", + "pattern": "^((/)|(http)[s]?:|[t]?(ftp)[s]?:)+.*([.]iso)$" + }, + "disks": { + "description": "List of disks", + "type": "array", + "items": { + "type": "object", + "properties": { + "index": { + "description": "Index of the disk", + "type": "integer", + "minimum": 0 + }, + "size": { + "description": "Size (GB) of the disk", + "type": "number", + "minimum": 1 + } + } + }, + "minItems": 1, + "uniqueItems": true + }, + "storagepool": { + "description": "Location of the storage pool", + "type": "string", + "pattern": "^/storagepools/[^/]+/?$" + }, + "networks": { + "description": "list of which networks will be assigned to the new VM.", + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true + }, + "folder": { + "description": "Folder", + "type": "array", + "items": { "type": "string" } + }, + "graphics": { "$ref": "#/kimchitype/graphics" } + }, + "additionalProperties": false + }, "template_update": { "type": "object", "properties": { diff --git a/src/kimchi/control/templates.py b/src/kimchi/control/templates.py index ce1dda4..58dafcc 100644 --- a/src/kimchi/control/templates.py +++ b/src/kimchi/control/templates.py @@ -40,6 +40,7 @@ class Template(Resource): "memory", "cdrom", "disks", "networks", "graphics"] self.uri_fmt = "/templates/%s" + self.clone = self.generate_action_handler('clone') @property def data(self): -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> When clone template, if no name in parameters, kimchi will set a default name. Then copy the info from existing template and create a new one. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 19 +++++++++++++++++++ src/kimchi/model/templates.py | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 4e276eb..f66de3a 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -44,6 +44,7 @@ except ImportError: from kimchi import config from kimchi.asynctask import AsyncTask from kimchi.config import config as kconfig +from kimchi.control.utils import parse_request from kimchi.distroloader import DistroLoader from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import MissingParameter, NotFoundError, OperationFailed @@ -202,6 +203,24 @@ class MockModel(object): self._mock_templates[name] = t return name + def template_clone(self, name): + params = parse_request() + # set default name + if not params.get("name"): + subfixs = [v[len(name):] for v in self.templates_get_list() + if v.startswith(name)] + indexs = [int(v.lstrip("-clone")) for v in subfixs + if v.startswith("-clone") and + v.lstrip("-clone").isdigit()] + indexs.sort() + index = "1" if not indexs else str(indexs[-1] + 1) + params["name"] = name + "-clone" + index + + temp = self.template_lookup(name) + temp.update(params) + ident = self.templates_create(temp) + raise cherrypy.HTTPRedirect("/templates/%s" % ident, 303) + def template_update(self, name, params): old_t = self.template_lookup(name) new_t = copy.copy(old_t) diff --git a/src/kimchi/model/templates.py b/src/kimchi/model/templates.py index 03632a6..e8eb396 100644 --- a/src/kimchi/model/templates.py +++ b/src/kimchi/model/templates.py @@ -22,9 +22,11 @@ import copy +import cherrypy import libvirt from kimchi import xmlutils +from kimchi.control.utils import parse_request from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError from kimchi.utils import pool_name_from_uri from kimchi.vmtemplate import VMTemplate @@ -85,6 +87,24 @@ class TemplateModel(object): t = self.get_template(name, self.objstore, self.conn) return t.info + def clone(self, name): + params = parse_request() + # set default name + if not params.get("name"): + subfixs = [v[len(name):] for v in self.templates.get_list() + if v.startswith(name)] + indexs = [int(v.lstrip("-clone")) for v in subfixs + if v.startswith("-clone") and + v.lstrip("-clone").isdigit()] + indexs.sort() + index = "1" if not indexs else str(indexs[-1] + 1) + params["name"] = name + "-clone" + index + + temp = self.lookup(name) + temp.update(params) + ident = self.templates.create(temp) + raise cherrypy.HTTPRedirect("/templates/%s" % ident, 303) + def delete(self, name): with self.objstore as session: session.delete('template', name) -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
When clone template, if no name in parameters, kimchi will set a default name.
Then copy the info from existing template and create a new one.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 19 +++++++++++++++++++ src/kimchi/model/templates.py | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 4e276eb..f66de3a 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -44,6 +44,7 @@ except ImportError: from kimchi import config from kimchi.asynctask import AsyncTask from kimchi.config import config as kconfig +from kimchi.control.utils import parse_request from kimchi.distroloader import DistroLoader from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import MissingParameter, NotFoundError, OperationFailed @@ -202,6 +203,24 @@ class MockModel(object): self._mock_templates[name] = t return name
+ def template_clone(self, name): + params = parse_request() + # set default name + if not params.get("name"): + subfixs = [v[len(name):] for v in self.templates_get_list() + if v.startswith(name)] + indexs = [int(v.lstrip("-clone")) for v in subfixs + if v.startswith("-clone") and + v.lstrip("-clone").isdigit()] + indexs.sort() + index = "1" if not indexs else str(indexs[-1] + 1) + params["name"] = name + "-clone" + index + + temp = self.template_lookup(name) + temp.update(params) + ident = self.templates_create(temp) + raise cherrypy.HTTPRedirect("/templates/%s" % ident, 303) + def template_update(self, name, params): old_t = self.template_lookup(name) new_t = copy.copy(old_t) diff --git a/src/kimchi/model/templates.py b/src/kimchi/model/templates.py index 03632a6..e8eb396 100644 --- a/src/kimchi/model/templates.py +++ b/src/kimchi/model/templates.py @@ -22,9 +22,11 @@
import copy
+import cherrypy import libvirt
from kimchi import xmlutils +from kimchi.control.utils import parse_request from kimchi.exception import InvalidOperation, InvalidParameter, NotFoundError from kimchi.utils import pool_name_from_uri from kimchi.vmtemplate import VMTemplate @@ -85,6 +87,24 @@ class TemplateModel(object): t = self.get_template(name, self.objstore, self.conn) return t.info
+ def clone(self, name): + params = parse_request()
On 02/11/2014 09:58 PM, shaohef@linux.vnet.ibm.com wrote: the parse_request() should not be here. if no one oppose, I will modify the generate_action_handler as follow. and let generate_action_handler to pass the params. But I need do some test to check if this will effect other resource action. --- a/src/kimchi/control/base.py +++ b/src/kimchi/control/base.py @@ -66,6 +66,8 @@ class Resource(object): if action_args is not None: model_args.extend(parse_request()[key] for key in action_args) + else: + model_args.extend(parse_request()) fn = getattr(self.model, model_fn(self, action_name)) fn(*model_args) uri_params = tuple(self.model_args)
+ # set default name + if not params.get("name"): + subfixs = [v[len(name):] for v in self.templates.get_list() + if v.startswith(name)] + indexs = [int(v.lstrip("-clone")) for v in subfixs + if v.startswith("-clone") and + v.lstrip("-clone").isdigit()] + indexs.sort() + index = "1" if not indexs else str(indexs[-1] + 1) + params["name"] = name + "-clone" + index + + temp = self.lookup(name) + temp.update(params) + ident = self.templates.create(temp) + raise cherrypy.HTTPRedirect("/templates/%s" % ident, 303) + def delete(self, name): with self.objstore as session: session.delete('template', name)
-- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> update test_rest.py Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- tests/test_rest.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_rest.py b/tests/test_rest.py index 0ed293b..5953f18 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -818,6 +818,40 @@ class RestTests(unittest.TestCase): resp = self.request('/templates', req, 'POST') self.assertEquals(400, resp.status) + # clone a template with name parameter + old_temp = t['name'] + t['os_distro'] = 'Linux.ISO' + t['os_version'] = '1.1' + t['graphics'] = {'type': 'vnc', 'listen': '0.0.0.0'} + t['name'] = "clone-template" + req = json.dumps(t) + resp = self.request('/templates/%s/clone' % old_temp, req, 'POST') + self.assertEquals(303, resp.status) + + # Verify the clone template + res = json.loads(self.request('/templates/%s' % t['name']).read()) + verify_template(t, res) + # Delete the template + resp = self.request('/templates/%s' % t['name'], '{}', 'DELETE') + self.assertEquals(204, resp.status) + + # clone a template without name parameter + del t['name'] + req = json.dumps(t) + resp = self.request('/templates/%s/clone' % old_temp, req, 'POST') + self.assertEquals(303, resp.status) + + # Verify the clone template + res = json.loads(self.request('/templates/%s-clone1' % + old_temp).read()) + t['name'] = res['name'] + verify_template(t, res) + # Delete the template + resp = self.request('/templates/%s' % t['name'], '{}', 'DELETE') + self.assertEquals(204, resp.status) + + t['name'] = old_temp + # Update the template t['os_distro'] = 'Linux.ISO' t['os_version'] = '1.1' -- 1.8.4.2
participants (4)
-
Aline Manera
-
Ramon Medeiros
-
shaohef@linux.vnet.ibm.com
-
Sheldon