[PATCH 0/7] VM supports interfaces

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' \ http://localhost:800/vms/test-vm-8/ifaces/ [ { "mac":"52:54:00:00:00:08", "model":"virtio", "type":"network", "network":"default", "name":"52:54:00:00:00:08" } ] $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' \ http://localhost:800/vms/test-vm-8/ifaces/52:54:00:00:00:08 { "mac":"52:54:00:00:00:08", "model":"virtio", "type":"network", "network":"default", "name":"52:54:00:00:00:08" } ShaoHe Feng (7): Add a control.vm module add a method to load vms sub collection automatically VM supports interfaces: update API VM supports interfaces: update model VM supports interfaces: update controller VM supports interfaces: update mockmodel VM supports interfaces: update testcase Makefile.am | 1 + configure.ac | 1 + contrib/kimchi.spec.fedora.in | 1 + contrib/kimchi.spec.suse.in | 1 + docs/API.md | 47 ++++++++++++++++++++++++++++ src/kimchi/control/Makefile.am | 2 ++ src/kimchi/control/vm/Makefile.am | 32 +++++++++++++++++++ src/kimchi/control/vm/__init__.py | 66 +++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vm/ifaces.py | 48 ++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++ src/kimchi/mockmodel.py | 31 ++++++++++++++++++ src/kimchi/model.py | 31 ++++++++++++++++++ tests/test_model.py | 19 +++++++++++ tests/test_rest.py | 31 ++++++++++++++++++ 14 files changed, 320 insertions(+) create mode 100644 src/kimchi/control/vm/Makefile.am create mode 100644 src/kimchi/control/vm/__init__.py create mode 100644 src/kimchi/control/vm/ifaces.py -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> All vm devices should be in this module Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- Makefile.am | 1 + configure.ac | 1 + contrib/kimchi.spec.fedora.in | 1 + contrib/kimchi.spec.suse.in | 1 + src/kimchi/control/Makefile.am | 2 ++ src/kimchi/control/vm/Makefile.am | 32 ++++++++++++++++++++++++++++++++ src/kimchi/control/vm/__init__.py | 22 ++++++++++++++++++++++ 7 files changed, 60 insertions(+) create mode 100644 src/kimchi/control/vm/Makefile.am create mode 100644 src/kimchi/control/vm/__init__.py diff --git a/Makefile.am b/Makefile.am index 04ad696..c9a880c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ PEP8_WHITELIST = \ src/kimchi/cachebust.py \ src/kimchi/config.py.in \ src/kimchi/control/*.py \ + src/kimchi/control/vm/*.py \ src/kimchi/disks.py \ src/kimchi/distroloader.py \ src/kimchi/exception.py \ diff --git a/configure.ac b/configure.ac index e4ccb83..5148f12 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,7 @@ AC_CONFIG_FILES([ src/distros.d/Makefile src/kimchi/Makefile src/kimchi/control/Makefile + src/kimchi/control/vm/Makefile plugins/Makefile plugins/sample/Makefile plugins/sample/ui/Makefile diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index cc8c298..4fa94d4 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -113,6 +113,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* +%{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/API.json %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index d1aec7b..9f16dfb 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -60,6 +60,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* +%{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/API.json %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md diff --git a/src/kimchi/control/Makefile.am b/src/kimchi/control/Makefile.am index 925c593..42f62c3 100644 --- a/src/kimchi/control/Makefile.am +++ b/src/kimchi/control/Makefile.am @@ -20,6 +20,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +SUBDIRS = vm + control_PYTHON = *.py controldir = $(pythondir)/kimchi/control diff --git a/src/kimchi/control/vm/Makefile.am b/src/kimchi/control/vm/Makefile.am new file mode 100644 index 0000000..17340af --- /dev/null +++ b/src/kimchi/control/vm/Makefile.am @@ -0,0 +1,32 @@ +# +# Kimchi +# +# Copyright IBM Corp, 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# Royce Lv <lvroyce@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +vm_PYTHON = \ + __init__.py + + +vmdir = $(pythondir)/kimchi/control/vm + +install-data-local: + $(MKDIR_P) $(DESTDIR)$(vmdir) diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py new file mode 100644 index 0000000..f22e568 --- /dev/null +++ b/src/kimchi/control/vm/__init__.py @@ -0,0 +1,22 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# Royce Lv <lvroyce@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -- 1.8.4.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
All vm devices should be in this module
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com> --- Makefile.am | 1 + configure.ac | 1 + contrib/kimchi.spec.fedora.in | 1 + contrib/kimchi.spec.suse.in | 1 + src/kimchi/control/Makefile.am | 2 ++ src/kimchi/control/vm/Makefile.am | 32 ++++++++++++++++++++++++++++++++ src/kimchi/control/vm/__init__.py | 22 ++++++++++++++++++++++ 7 files changed, 60 insertions(+) create mode 100644 src/kimchi/control/vm/Makefile.am create mode 100644 src/kimchi/control/vm/__init__.py
diff --git a/Makefile.am b/Makefile.am index 04ad696..c9a880c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ PEP8_WHITELIST = \ src/kimchi/cachebust.py \ src/kimchi/config.py.in \ src/kimchi/control/*.py \ + src/kimchi/control/vm/*.py \ src/kimchi/disks.py \ src/kimchi/distroloader.py \ src/kimchi/exception.py \ diff --git a/configure.ac b/configure.ac index e4ccb83..5148f12 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,7 @@ AC_CONFIG_FILES([ src/distros.d/Makefile src/kimchi/Makefile src/kimchi/control/Makefile + src/kimchi/control/vm/Makefile plugins/Makefile plugins/sample/Makefile plugins/sample/ui/Makefile diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index cc8c298..4fa94d4 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -113,6 +113,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* +%{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/API.json %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index d1aec7b..9f16dfb 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -60,6 +60,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/kimchid %{python_sitelib}/kimchi/*.py* %{python_sitelib}/kimchi/control/*.py* +%{python_sitelib}/kimchi/control/vm/*.py* %{python_sitelib}/kimchi/API.json %{_datadir}/kimchi/doc/API.md %{_datadir}/kimchi/doc/README.md diff --git a/src/kimchi/control/Makefile.am b/src/kimchi/control/Makefile.am index 925c593..42f62c3 100644 --- a/src/kimchi/control/Makefile.am +++ b/src/kimchi/control/Makefile.am @@ -20,6 +20,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+SUBDIRS = vm + control_PYTHON = *.py
controldir = $(pythondir)/kimchi/control diff --git a/src/kimchi/control/vm/Makefile.am b/src/kimchi/control/vm/Makefile.am new file mode 100644 index 0000000..17340af --- /dev/null +++ b/src/kimchi/control/vm/Makefile.am @@ -0,0 +1,32 @@ +# +# Kimchi +# +# Copyright IBM Corp, 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# Royce Lv <lvroyce@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +vm_PYTHON = \ + __init__.py + + +vmdir = $(pythondir)/kimchi/control/vm + +install-data-local: + $(MKDIR_P) $(DESTDIR)$(vmdir) diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py new file mode 100644 index 0000000..f22e568 --- /dev/null +++ b/src/kimchi/control/vm/__init__.py @@ -0,0 +1,22 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# Royce Lv <lvroyce@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> When define a new vms sub collection, we do not need to touch vms module any more. such as: add a ifaces, we can define it as follow in vm/ifaces.py: from kimchi.control.vm import SubCollection @SubCollection('ifaces') class VmIfaces(Collection): def __init__(self, model, vm): super(VmIfaces, self).__init__(model) Then access URL: /vms/vm-name/ifaces/mac VM resource can dispatch ifaces automatically Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py index f22e568..f3f6e48 100644 --- a/src/kimchi/control/vm/__init__.py +++ b/src/kimchi/control/vm/__init__.py @@ -20,3 +20,47 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import imp + + +class SubCollection(object): + def __init__(self, name): + self.name = name + + def __call__(self, fun): + fun._sub_collection_name = {"name": self.name} + return fun + + +def _listPathModules(path): + modules = set() + for f in os.listdir(path): + base, ext = os.path.splitext(f) + if ext in ('.py', '.pyc', '.pyo'): + modules.add(base) + return sorted(modules) + + +def _load_sub_collections(path): + for mod_name in _listPathModules(path): + if mod_name.startswith("_"): + continue + + mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) + module = imp.load_module(mod_name, mod_fobj, + mod_absp, mod_desc) + sub_collections = {} + + for collection in [getattr(module, x) for x in dir(module)]: + if not hasattr(collection, "_sub_collection_name"): + continue + + name = collection._sub_collection_name["name"] + sub_collections.update({name: collection}) + + return sub_collections + + +VmDevices = _load_sub_collections(os.path.dirname(__file__)) -- 1.8.4.2

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
When define a new vms sub collection, we do not need to touch vms module any more.
such as: add a ifaces, we can define it as follow in vm/ifaces.py:
from kimchi.control.vm import SubCollection
@SubCollection('ifaces') class VmIfaces(Collection): def __init__(self, model, vm): super(VmIfaces, self).__init__(model)
Then access URL: /vms/vm-name/ifaces/mac VM resource can dispatch ifaces automatically
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py index f22e568..f3f6e48 100644 --- a/src/kimchi/control/vm/__init__.py +++ b/src/kimchi/control/vm/__init__.py @@ -20,3 +20,47 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import imp + + +class SubCollection(object): + def __init__(self, name): + self.name = name + + def __call__(self, fun): + fun._sub_collection_name = {"name": self.name} + return fun + + +def _listPathModules(path): + modules = set() + for f in os.listdir(path): + base, ext = os.path.splitext(f) + if ext in ('.py', '.pyc', '.pyo'): + modules.add(base) + return sorted(modules) + + +def _load_sub_collections(path): + for mod_name in _listPathModules(path): + if mod_name.startswith("_"): + continue + + mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) + module = imp.load_module(mod_name, mod_fobj, + mod_absp, mod_desc) + sub_collections = {} + + for collection in [getattr(module, x) for x in dir(module)]: + if not hasattr(collection, "_sub_collection_name"): + continue + + name = collection._sub_collection_name["name"] + sub_collections.update({name: collection}) + + return sub_collections + + +VmDevices = _load_sub_collections(os.path.dirname(__file__)) I think it should be done as a general facility. You could write a
On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote: metaclass for resource and load its sub collection in "__new__"

On 01/20/2014 01:56 PM, Mark Wu wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
When define a new vms sub collection, we do not need to touch vms module any more.
such as: add a ifaces, we can define it as follow in vm/ifaces.py:
from kimchi.control.vm import SubCollection
@SubCollection('ifaces') class VmIfaces(Collection): def __init__(self, model, vm): super(VmIfaces, self).__init__(model)
Then access URL: /vms/vm-name/ifaces/mac VM resource can dispatch ifaces automatically
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py index f22e568..f3f6e48 100644 --- a/src/kimchi/control/vm/__init__.py +++ b/src/kimchi/control/vm/__init__.py @@ -20,3 +20,47 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import imp + + +class SubCollection(object): + def __init__(self, name): + self.name = name + + def __call__(self, fun): + fun._sub_collection_name = {"name": self.name} + return fun + + +def _listPathModules(path): + modules = set() + for f in os.listdir(path): + base, ext = os.path.splitext(f) + if ext in ('.py', '.pyc', '.pyo'): + modules.add(base) + return sorted(modules) + + +def _load_sub_collections(path): + for mod_name in _listPathModules(path): + if mod_name.startswith("_"): + continue + + mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) + module = imp.load_module(mod_name, mod_fobj, + mod_absp, mod_desc) + sub_collections = {} + + for collection in [getattr(module, x) for x in dir(module)]: + if not hasattr(collection, "_sub_collection_name"): + continue + + name = collection._sub_collection_name["name"] + sub_collections.update({name: collection}) + + return sub_collections + + +VmDevices = _load_sub_collections(os.path.dirname(__file__)) I think it should be done as a general facility. You could write a
On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote: metaclass for resource and load its sub collection in "__new__"
ACK -- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 01/20/2014 03:56 AM, Mark Wu wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
When define a new vms sub collection, we do not need to touch vms module any more.
such as: add a ifaces, we can define it as follow in vm/ifaces.py:
from kimchi.control.vm import SubCollection
@SubCollection('ifaces') class VmIfaces(Collection): def __init__(self, model, vm): super(VmIfaces, self).__init__(model)
Then access URL: /vms/vm-name/ifaces/mac VM resource can dispatch ifaces automatically
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/__init__.py | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/src/kimchi/control/vm/__init__.py b/src/kimchi/control/vm/__init__.py index f22e568..f3f6e48 100644 --- a/src/kimchi/control/vm/__init__.py +++ b/src/kimchi/control/vm/__init__.py @@ -20,3 +20,47 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import imp + + +class SubCollection(object): + def __init__(self, name): + self.name = name + + def __call__(self, fun): + fun._sub_collection_name = {"name": self.name} + return fun + + +def _listPathModules(path): + modules = set() + for f in os.listdir(path): + base, ext = os.path.splitext(f) + if ext in ('.py', '.pyc', '.pyo'): + modules.add(base) + return sorted(modules) + + +def _load_sub_collections(path): + for mod_name in _listPathModules(path): + if mod_name.startswith("_"): + continue + + mod_fobj, mod_absp, mod_desc = imp.find_module(mod_name, [path]) + module = imp.load_module(mod_name, mod_fobj, + mod_absp, mod_desc) + sub_collections = {} + + for collection in [getattr(module, x) for x in dir(module)]: + if not hasattr(collection, "_sub_collection_name"): + continue + + name = collection._sub_collection_name["name"] + sub_collections.update({name: collection}) + + return sub_collections + + +VmDevices = _load_sub_collections(os.path.dirname(__file__)) I think it should be done as a general facility. You could write a
On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote: metaclass for resource and load its sub collection in "__new__"
+1. That way all application can use it.
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Now kimchi supports network get/create/delete/activate/deactivate REST API. We need to support the attach/detach/ a Network to a VM. https://github.com/kimchi-project/kimchi/wiki/customize-VM#organization-of-s... And get the info of Network attached to a VM. more libvirt network interfaces info: http://libvirt.org/formatdomain.html#elementsNICS Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/docs/API.md b/docs/API.md index 6e240eb..db2837e 100644 --- a/docs/API.md +++ b/docs/API.md @@ -149,6 +149,53 @@ Represents a snapshot of the Virtual Machine's primary monitor. * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on. +### Sub-Collection: Virtual Machine Network Interfaces + +**URI:** /vms/*:name*/ifaces + +Represents all network interfaces attached to a Virtual Machine. + +**Methods:** + +* **GET**: Retrieve a summarized list of all network interfaces attached to a Virtual Machine. + +* **POST**: attach a network interface to VM + * type: The type of VM network interface that libvirt supports. + Now kimchi just supports 'network' type. + * network *(optional)*: the name of resource network, it is required when the + interface type is network. + * model *(optional)*: model of emulated network interface card. It can be one of these models: + ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. + When model is missing, libvirt will set 'rtl8139' as default value. + +### Sub-Resource: Virtual Machine Network Interface + +**URI:** /vms/*:name*/ifaces/*:name* + +A interface represents available network interface on VM. + +**Methods:** + +* **GET**: Retrieve the full description of the VM network interface + * name: The identifier of the network interface. + * type: The type of VM network interface that libvirt supports. + It will be one of these types: 'network', 'bridge', 'user','ethernet', + 'direct', 'hostdev', 'mcast', 'server' and 'client'. + * network *(optional)*: the name of resource network, only be available when the + interface type is network. + * bridge *(optional)*: the name of resource bridge, only be available when the + interface type is bridge. + * mac: Media Access Control Address of the VM interface. + * model: model of emulated network interface card. It will be one of these models: + ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. + +* **DELETE**: detach the network interface from VM + +**Actions (POST):** + +*No actions defined* + + ### Resource: Template **URI:** /templates/*:name* -- 1.8.4.2

On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
Now kimchi supports network get/create/delete/activate/deactivate REST API.
We need to support the attach/detach/ a Network to a VM. https://github.com/kimchi-project/kimchi/wiki/customize-VM#organization-of-s... And get the info of Network attached to a VM.
more libvirt network interfaces info: http://libvirt.org/formatdomain.html#elementsNICS
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- docs/API.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/docs/API.md b/docs/API.md index 6e240eb..db2837e 100644 --- a/docs/API.md +++ b/docs/API.md @@ -149,6 +149,53 @@ Represents a snapshot of the Virtual Machine's primary monitor. * null: Graphics is disabled or type not supported * listen: The network which the vnc/spice server listens on.
+### Sub-Collection: Virtual Machine Network Interfaces + +**URI:** /vms/*:name*/ifaces + +Represents all network interfaces attached to a Virtual Machine. + +**Methods:** + +* **GET**: Retrieve a summarized list of all network interfaces attached to a Virtual Machine. + +* **POST**: attach a network interface to VM + * type: The type of VM network interface that libvirt supports. + Now kimchi just supports 'network' type. + * network *(optional)*: the name of resource network, it is required when the + interface type is network. + * model *(optional)*: model of emulated network interface card. It can be one of these models: + ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. + When model is missing, libvirt will set 'rtl8139' as default value. + +### Sub-Resource: Virtual Machine Network Interface + +**URI:** /vms/*:name*/ifaces/*:name*
**URI:** /vms/*:name*/ifaces/*:mac*
+ +A interface represents available network interface on VM. + +**Methods:** + +* **GET**: Retrieve the full description of the VM network interface + * name: The identifier of the network interface. + * type: The type of VM network interface that libvirt supports. + It will be one of these types: 'network', 'bridge', 'user','ethernet', + 'direct', 'hostdev', 'mcast', 'server' and 'client'. + * network *(optional)*: the name of resource network, only be available when the + interface type is network. + * bridge *(optional)*: the name of resource bridge, only be available when the + interface type is bridge. + * mac: Media Access Control Address of the VM interface. + * model: model of emulated network interface card. It will be one of these models: + ne2k_pci, i82551, i82557b, i82559er, rtl8139, e1000, pcnet and virtio. +
As we will use the "mac" to identify the iface we can remove "name" parameter
+* **DELETE**: detach the network interface from VM + +**Actions (POST):** + +*No actions defined* + + ### Resource: Template
**URI:** /templates/*:name*

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Support vm ifaces collection GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/ Support vm iface resource GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/mac Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/model.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 2c6d3a1..350244b 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -45,6 +45,7 @@ import uuid from cherrypy.process.plugins import BackgroundTask from cherrypy.process.plugins import SimplePlugin from collections import defaultdict +from lxml import objectify from xml.etree import ElementTree @@ -967,6 +968,36 @@ class Model(object): iface.destroy() iface.undefine() + def vmifaces_get_list(self, vm): + dom = self._get_vm(vm) + xml = dom.XMLDesc(0) + root = objectify.fromstring(xml) + macs = [iface.mac.get('address') + for iface in root.devices.findall("interface")] + return macs + + def vmiface_lookup(self, vm, name): + info = {} + dom = self._get_vm(vm) + xml = dom.XMLDesc(0) + root = objectify.fromstring(xml) + + iface = [iface for iface in root.devices.findall("interface") + if iface.mac.get('address') == name] + if not iface: + raise NotFoundError('iface: "%s"' % name) + iface = iface[0] + + info['type'] = iface.attrib['type'] + info['name'] = info['mac'] = iface.mac.get('address') + info['model'] = iface.model.get('type') + if info['type'] == 'network': + info['network'] = iface.source.get('network') + if info['type'] == 'bridge': + info['bridge'] = iface.source.get('bridge') + + return info + def add_task(self, target_uri, fn, opaque=None): id = self.next_taskid self.next_taskid = self.next_taskid + 1 -- 1.8.4.2

On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
Support vm ifaces collection GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/
Support vm iface resource GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/mac
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/model.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/src/kimchi/model.py b/src/kimchi/model.py index 2c6d3a1..350244b 100644 --- a/src/kimchi/model.py +++ b/src/kimchi/model.py @@ -45,6 +45,7 @@ import uuid from cherrypy.process.plugins import BackgroundTask from cherrypy.process.plugins import SimplePlugin from collections import defaultdict +from lxml import objectify from xml.etree import ElementTree
@@ -967,6 +968,36 @@ class Model(object): iface.destroy() iface.undefine()
+ def vmifaces_get_list(self, vm): + dom = self._get_vm(vm) + xml = dom.XMLDesc(0) + root = objectify.fromstring(xml) + macs = [iface.mac.get('address') + for iface in root.devices.findall("interface")] + return macs + + def vmiface_lookup(self, vm, name):
use 'mac' instead of 'name'
+ info = {} + dom = self._get_vm(vm) + xml = dom.XMLDesc(0) + root = objectify.fromstring(xml) + + iface = [iface for iface in root.devices.findall("interface") + if iface.mac.get('address') == name] + if not iface: + raise NotFoundError('iface: "%s"' % name) + iface = iface[0] + + info['type'] = iface.attrib['type'] + info['name'] = info['mac'] = iface.mac.get('address')
As I commented on previous patch 'name' isn't needed as we will use 'mac' as iface identifier
+ info['model'] = iface.model.get('type') + if info['type'] == 'network': + info['network'] = iface.source.get('network') + if info['type'] == 'bridge': + info['bridge'] = iface.source.get('bridge') + + return info + def add_task(self, target_uri, fn, opaque=None): id = self.next_taskid self.next_taskid = self.next_taskid + 1

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> add VmIfaces collection and VmIface resource Update VM resource. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 48 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/kimchi/control/vm/ifaces.py diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py new file mode 100644 index 0000000..c121d83 --- /dev/null +++ b/src/kimchi/control/vm/ifaces.py @@ -0,0 +1,48 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from kimchi.control.base import Collection, Resource +from kimchi.control.vm import SubCollection + + +@SubCollection('ifaces') +class VmIfaces(Collection): + def __init__(self, model, vm): + super(VmIfaces, self).__init__(model) + self.resource = VmIface + self.vm = vm + self.resource_args = [self.vm, ] + self.model_args = [self.vm, ] + + +class VmIface(Resource): + def __init__(self, model, vm, ident): + super(VmIface, self).__init__(model, ident) + self.vm = vm + self.ident = ident + self.info = {} + self.model_args = [self.vm, self.ident] + self.uri_fmt = '/vms/%s/iface/%s' + + @property + def data(self): + return self.info diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..312802e 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -24,6 +24,7 @@ from kimchi.control.base import Collection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.vm import VmDevices class VMs(Collection): @@ -57,6 +58,14 @@ class VM(Resource): 'port': self.info['graphics']['port']} } + def _cp_dispatch(self, vpath): + if vpath: + sub_collection = vpath.pop(0) + device = VmDevices.get(sub_collection, None) + if device: + # incoming text, from URL, is not unicode, need decode + return device(self.model, self.ident.decode("utf-8")) + class VMScreenShot(Resource): def __init__(self, model, ident): -- 1.8.4.2

On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
add VmIfaces collection and VmIface resource
Update VM resource.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 48 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/kimchi/control/vm/ifaces.py
diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py new file mode 100644 index 0000000..c121d83 --- /dev/null +++ b/src/kimchi/control/vm/ifaces.py @@ -0,0 +1,48 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from kimchi.control.base import Collection, Resource +from kimchi.control.vm import SubCollection + + +@SubCollection('ifaces') +class VmIfaces(Collection): + def __init__(self, model, vm): + super(VmIfaces, self).__init__(model) + self.resource = VmIface + self.vm = vm + self.resource_args = [self.vm, ] + self.model_args = [self.vm, ] + + +class VmIface(Resource): + def __init__(self, model, vm, ident): + super(VmIface, self).__init__(model, ident) + self.vm = vm + self.ident = ident + self.info = {} + self.model_args = [self.vm, self.ident] + self.uri_fmt = '/vms/%s/iface/%s' + + @property + def data(self): + return self.info diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..312802e 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -24,6 +24,7 @@
from kimchi.control.base import Collection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.vm import VmDevices
class VMs(Collection): @@ -57,6 +58,14 @@ class VM(Resource): 'port': self.info['graphics']['port']} }
+ def _cp_dispatch(self, vpath): + if vpath: + sub_collection = vpath.pop(0) + device = VmDevices.get(sub_collection, None) + if device: + # incoming text, from URL, is not unicode, need decode + return device(self.model, self.ident.decode("utf-8")) + You don't need to use a customized dispatch handler because it can be done by the default cherryp dispatch handler if you add the 'subcollection' to your resource as an attribute.
class VMScreenShot(Resource): def __init__(self, model, ident):

On 01/20/2014 01:36 PM, Mark Wu wrote:
On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
add VmIfaces collection and VmIface resource
Update VM resource.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 48 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/kimchi/control/vm/ifaces.py
diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py new file mode 100644 index 0000000..c121d83 --- /dev/null +++ b/src/kimchi/control/vm/ifaces.py @@ -0,0 +1,48 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from kimchi.control.base import Collection, Resource +from kimchi.control.vm import SubCollection + + +@SubCollection('ifaces') +class VmIfaces(Collection): + def __init__(self, model, vm): + super(VmIfaces, self).__init__(model) + self.resource = VmIface + self.vm = vm + self.resource_args = [self.vm, ] + self.model_args = [self.vm, ] + + +class VmIface(Resource): + def __init__(self, model, vm, ident): + super(VmIface, self).__init__(model, ident) + self.vm = vm + self.ident = ident + self.info = {} + self.model_args = [self.vm, self.ident] + self.uri_fmt = '/vms/%s/iface/%s' + + @property + def data(self): + return self.info diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..312802e 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -24,6 +24,7 @@
from kimchi.control.base import Collection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.vm import VmDevices
class VMs(Collection): @@ -57,6 +58,14 @@ class VM(Resource): 'port': self.info['graphics']['port']} }
+ def _cp_dispatch(self, vpath): + if vpath: + sub_collection = vpath.pop(0) + device = VmDevices.get(sub_collection, None) + if device: + # incoming text, from URL, is not unicode, need decode + return device(self.model, self.ident.decode("utf-8")) + You don't need to use a customized dispatch handler because it can be done by the default cherryp dispatch handler if you add the 'subcollection' to your resource as an attribute. ACK. it can be same with Root sub collection/resource.
class VMScreenShot(Resource): def __init__(self, model, ident):
-- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 01/20/2014 03:36 AM, Mark Wu wrote:
On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
add VmIfaces collection and VmIface resource
Update VM resource.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 48 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/kimchi/control/vm/ifaces.py
diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py new file mode 100644 index 0000000..c121d83 --- /dev/null +++ b/src/kimchi/control/vm/ifaces.py @@ -0,0 +1,48 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from kimchi.control.base import Collection, Resource +from kimchi.control.vm import SubCollection + + +@SubCollection('ifaces') +class VmIfaces(Collection): + def __init__(self, model, vm): + super(VmIfaces, self).__init__(model) + self.resource = VmIface + self.vm = vm + self.resource_args = [self.vm, ] + self.model_args = [self.vm, ] + + +class VmIface(Resource): + def __init__(self, model, vm, ident): + super(VmIface, self).__init__(model, ident) + self.vm = vm + self.ident = ident + self.info = {} + self.model_args = [self.vm, self.ident] + self.uri_fmt = '/vms/%s/iface/%s' + + @property + def data(self): + return self.info diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..312802e 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -24,6 +24,7 @@
from kimchi.control.base import Collection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.vm import VmDevices
class VMs(Collection): @@ -57,6 +58,14 @@ class VM(Resource): 'port': self.info['graphics']['port']} }
+ def _cp_dispatch(self, vpath): + if vpath: + sub_collection = vpath.pop(0) + device = VmDevices.get(sub_collection, None) + if device: + # incoming text, from URL, is not unicode, need decode + return device(self.model, self.ident.decode("utf-8")) + You don't need to use a customized dispatch handler because it can be done by the default cherryp dispatch handler if you add the 'subcollection' to your resource as an attribute.
+1
class VMScreenShot(Resource): def __init__(self, model, ident):
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
add VmIfaces collection and VmIface resource
Update VM resource.
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/control/vm/ifaces.py | 48 +++++++++++++++++++++++++++++++++++++++++ src/kimchi/control/vms.py | 9 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/kimchi/control/vm/ifaces.py
diff --git a/src/kimchi/control/vm/ifaces.py b/src/kimchi/control/vm/ifaces.py new file mode 100644 index 0000000..c121d83 --- /dev/null +++ b/src/kimchi/control/vm/ifaces.py @@ -0,0 +1,48 @@ +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013 +# +# Authors: +# ShaoHe Feng <shaohef@linux.vnet.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +from kimchi.control.base import Collection, Resource +from kimchi.control.vm import SubCollection + + +@SubCollection('ifaces') +class VmIfaces(Collection): + def __init__(self, model, vm): + super(VmIfaces, self).__init__(model) + self.resource = VmIface + self.vm = vm + self.resource_args = [self.vm, ] + self.model_args = [self.vm, ] + +
Just a nit: in other resources we used "VM" at the begging instead of "Vm" So if we follow the same it should be VMIfaces and VMIface
+class VmIface(Resource): + def __init__(self, model, vm, ident): + super(VmIface, self).__init__(model, ident) + self.vm = vm + self.ident = ident + self.info = {} + self.model_args = [self.vm, self.ident] + self.uri_fmt = '/vms/%s/iface/%s' + + @property + def data(self): + return self.info diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py index 7843be7..312802e 100644 --- a/src/kimchi/control/vms.py +++ b/src/kimchi/control/vms.py @@ -24,6 +24,7 @@
from kimchi.control.base import Collection, Resource from kimchi.control.utils import internal_redirect +from kimchi.control.vm import VmDevices
class VMs(Collection): @@ -57,6 +58,14 @@ class VM(Resource): 'port': self.info['graphics']['port']} }
+ def _cp_dispatch(self, vpath): + if vpath: + sub_collection = vpath.pop(0) + device = VmDevices.get(sub_collection, None) + if device: + # incoming text, from URL, is not unicode, need decode + return device(self.model, self.ident.decode("utf-8")) +
class VMScreenShot(Resource): def __init__(self, model, ident):

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> Support vm ifaces collection GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/ Support vm iface resource GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/mac Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 4ef3fa6..4027526 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -488,6 +488,17 @@ class MockModel(object): def networks_get_list(self): return sorted(self._mock_networks.keys()) + def vmifaces_get_list(self, vm): + dom = self._get_vm(vm) + macs = dom.ifaces.keys() + return macs + + def vmiface_lookup(self, vm, name): + dom = self._get_vm(vm) + info = dom.ifaces[name].info + info['name'] = info['mac'] + return info + def tasks_get_list(self): with self.objstore as session: return session.get_list('task') @@ -626,12 +637,32 @@ class MockVMTemplate(VMTemplate): return disk_paths +class MockVMIface(object): + counter = 0 + + def __init__(self, network=None): + self.info = {'type': 'network', + 'model': 'virtio', + 'network': network if network else "net%s" % self.counter, + 'mac': self.get_mac() + } + + @classmethod + def get_mac(cls): + mac = ":".join(["52", "54"] + ["%02x" % (cls.counter/(256**i) % 256) + for i in range(3, -1, -1)]) + cls.counter = cls.counter + 1 + return mac + + class MockVM(object): def __init__(self, uuid, name, template_info): self.uuid = uuid self.name = name self.disk_paths = [] self.networks = template_info['networks'] + ifaces = [MockVMIface(net) for net in self.networks] + self.ifaces = dict([(iface.info['mac'], iface) for iface in ifaces]) self.info = {'state': 'shutoff', 'stats': "{'cpu_utilization': 20, 'net_throughput' : 35, \ 'net_throughput_peak': 100, 'io_throughput': 45, \ -- 1.8.4.2

On 01/16/2014 11:56 PM, shaohef@linux.vnet.ibm.com wrote: > From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> > > Support vm ifaces collection GET method > $ curl -u user -H 'Accept: application/json' -H 'Content-type: > application/json' http://localhost:800/vms/vm-name/ifaces/ > > Support vm iface resource GET method > $ curl -u user -H 'Accept: application/json' -H 'Content-type: > application/json' http://localhost:800/vms/vm-name/ifaces/mac > > Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> > --- > src/kimchi/mockmodel.py | 31 +++++++++++++++++++++++++++++++ > 1 file changed, 31 insertions(+) > > diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py > index 4ef3fa6..4027526 100644 > --- a/src/kimchi/mockmodel.py > +++ b/src/kimchi/mockmodel.py > @@ -488,6 +488,17 @@ class MockModel(object): > def networks_get_list(self): > return sorted(self._mock_networks.keys()) > > + def vmifaces_get_list(self, vm): > + dom = self._get_vm(vm) > + macs = dom.ifaces.keys() > + return macs > + > + def vmiface_lookup(self, vm, name): > + dom = self._get_vm(vm) > + info = dom.ifaces[name].info > + info['name'] = info['mac'] > + return info > + > def tasks_get_list(self): > with self.objstore as session: > return session.get_list('task') > @@ -626,12 +637,32 @@ class MockVMTemplate(VMTemplate): > return disk_paths > > > +class MockVMIface(object): > + counter = 0 > + > + def __init__(self, network=None): add: + self.__class__.count += 1 > + self.info = {'type': 'network', > + 'model': 'virtio', > + 'network': network if network else "net%s" % self.counter, > + 'mac': self.get_mac() > + } > + > + @classmethod > + def get_mac(cls): > + mac = ":".join(["52", "54"] + ["%02x" % (cls.counter/(256**i) % 256) > + for i in range(3, -1, -1)]) > + cls.counter = cls.counter + 1 remove: + cls.counter = cls.counter + 1 > + return mac > + > + > class MockVM(object): > def __init__(self, uuid, name, template_info): > self.uuid = uuid > self.name = name > self.disk_paths = [] > self.networks = template_info['networks'] > + ifaces = [MockVMIface(net) for net in self.networks] > + self.ifaces = dict([(iface.info['mac'], iface) for iface in ifaces]) > self.info = {'state': 'shutoff', > 'stats': "{'cpu_utilization': 20, 'net_throughput' : 35, \ > 'net_throughput_peak': 100, 'io_throughput': 45, \ -- Thanks and best regards! Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com> IBM Linux Technology Center

On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
Support vm ifaces collection GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/
Support vm iface resource GET method $ curl -u user -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:800/vms/vm-name/ifaces/mac
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/mockmodel.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py index 4ef3fa6..4027526 100644 --- a/src/kimchi/mockmodel.py +++ b/src/kimchi/mockmodel.py @@ -488,6 +488,17 @@ class MockModel(object): def networks_get_list(self): return sorted(self._mock_networks.keys())
+ def vmifaces_get_list(self, vm): + dom = self._get_vm(vm) + macs = dom.ifaces.keys() + return macs + + def vmiface_lookup(self, vm, name): + dom = self._get_vm(vm) + info = dom.ifaces[name].info + info['name'] = info['mac'] + return info + def tasks_get_list(self): with self.objstore as session: return session.get_list('task') @@ -626,12 +637,32 @@ class MockVMTemplate(VMTemplate): return disk_paths
+class MockVMIface(object): + counter = 0 + + def __init__(self, network=None): + self.info = {'type': 'network', + 'model': 'virtio', + 'network': network if network else "net%s" % self.counter, + 'mac': self.get_mac() + } + + @classmethod + def get_mac(cls):
+ mac = ":".join(["52", "54"] + ["%02x" % (cls.counter/(256**i) % 256) + for i in range(3, -1, -1)])
Maybe you can use the following code to generate the mac.
import virtinst.util print virtinst.util.randomMAC() 00:16:3e:fd:b4:3a
+ cls.counter = cls.counter + 1 + return mac + + class MockVM(object): def __init__(self, uuid, name, template_info): self.uuid = uuid self.name = name self.disk_paths = [] self.networks = template_info['networks'] + ifaces = [MockVMIface(net) for net in self.networks] + self.ifaces = dict([(iface.info['mac'], iface) for iface in ifaces]) self.info = {'state': 'shutoff', 'stats': "{'cpu_utilization': 20, 'net_throughput' : 35, \ 'net_throughput_peak': 100, 'io_throughput': 45, \

From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> update test_rest and test_model Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- tests/test_model.py | 19 +++++++++++++++++++ tests/test_rest.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/tests/test_model.py b/tests/test_model.py index a38e3c6..65c31d2 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -121,6 +121,25 @@ class ModelTests(unittest.TestCase): inst.template_delete('test') @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') + def test_vm_ifaces(self): + inst = kimchi.model.Model(objstore_loc=self.tmp_store) + with RollbackContext() as rollback: + params = {'name': 'test', 'disks': []} + inst.templates_create(params) + rollback.prependDefer(inst.template_delete, 'test') + params = {'name': 'kimchi-ifaces', 'template': '/templates/test'} + inst.vms_create(params) + rollback.prependDefer(inst.vm_delete, 'kimchi-ifaces') + + ifaces = inst.vmifaces_get_list('kimchi-ifaces') + self.assertEquals(1, len(ifaces)) + + iface = inst.vmiface_lookup('kimchi-ifaces', ifaces[0]) + self.assertEquals(17, len(iface['mac'])) + self.assertEquals("default", iface['network']) + self.assertIn("model", iface) + + @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_storage_provisioning(self): inst = kimchi.model.Model(objstore_loc=self.tmp_store) diff --git a/tests/test_rest.py b/tests/test_rest.py index a8e5842..b7ce364 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -340,6 +340,37 @@ class RestTests(unittest.TestCase): resp = self.request('/templates/test', '{}', 'DELETE') self.assertEquals(204, resp.status) + def test_vm_iface(self): + + with RollbackContext() as rollback: + # Create a template as a base for our VMs + req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso'}) + resp = self.request('/templates', req, 'POST') + self.assertEquals(201, resp.status) + # Delete the template + rollback.prependDefer(self.request, + '/templates/test', '{}', 'DELETE') + + # Create a VM with default args + req = json.dumps({'name': 'test-vm', + 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + # Delete the VM + rollback.prependDefer(self.request, + '/vms/test-vm', '{}', 'DELETE') + + ifaces = json.loads(self.request('/vms/test-vm/ifaces').read()) + self.assertEquals(1, len(ifaces)) + + for iface in ifaces: + res = json.loads(self.request('/vms/test-vm/ifaces/%s' % + iface['name']).read()) + self.assertEquals('default', res['network']) + self.assertEquals(17, len(res['mac'])) + self.assertEquals('virtio', res['model']) + + def test_vm_customise_storage(self): # Create a Template req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso', -- 1.8.4.2

Reviewed-by: Aline Manera <alinefm@linux.vnet.ibm.com> On 01/16/2014 01:56 PM, shaohef@linux.vnet.ibm.com wrote:
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
update test_rest and test_model
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- tests/test_model.py | 19 +++++++++++++++++++ tests/test_rest.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+)
diff --git a/tests/test_model.py b/tests/test_model.py index a38e3c6..65c31d2 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -121,6 +121,25 @@ class ModelTests(unittest.TestCase): inst.template_delete('test')
@unittest.skipUnless(utils.running_as_root(), 'Must be run as root') + def test_vm_ifaces(self): + inst = kimchi.model.Model(objstore_loc=self.tmp_store) + with RollbackContext() as rollback: + params = {'name': 'test', 'disks': []} + inst.templates_create(params) + rollback.prependDefer(inst.template_delete, 'test') + params = {'name': 'kimchi-ifaces', 'template': '/templates/test'} + inst.vms_create(params) + rollback.prependDefer(inst.vm_delete, 'kimchi-ifaces') + + ifaces = inst.vmifaces_get_list('kimchi-ifaces') + self.assertEquals(1, len(ifaces)) + + iface = inst.vmiface_lookup('kimchi-ifaces', ifaces[0]) + self.assertEquals(17, len(iface['mac'])) + self.assertEquals("default", iface['network']) + self.assertIn("model", iface) + + @unittest.skipUnless(utils.running_as_root(), 'Must be run as root') def test_vm_storage_provisioning(self): inst = kimchi.model.Model(objstore_loc=self.tmp_store)
diff --git a/tests/test_rest.py b/tests/test_rest.py index a8e5842..b7ce364 100644 --- a/tests/test_rest.py +++ b/tests/test_rest.py @@ -340,6 +340,37 @@ class RestTests(unittest.TestCase): resp = self.request('/templates/test', '{}', 'DELETE') self.assertEquals(204, resp.status)
+ def test_vm_iface(self): + + with RollbackContext() as rollback: + # Create a template as a base for our VMs + req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso'}) + resp = self.request('/templates', req, 'POST') + self.assertEquals(201, resp.status) + # Delete the template + rollback.prependDefer(self.request, + '/templates/test', '{}', 'DELETE') + + # Create a VM with default args + req = json.dumps({'name': 'test-vm', + 'template': '/templates/test'}) + resp = self.request('/vms', req, 'POST') + self.assertEquals(201, resp.status) + # Delete the VM + rollback.prependDefer(self.request, + '/vms/test-vm', '{}', 'DELETE') + + ifaces = json.loads(self.request('/vms/test-vm/ifaces').read()) + self.assertEquals(1, len(ifaces)) + + for iface in ifaces: + res = json.loads(self.request('/vms/test-vm/ifaces/%s' % + iface['name']).read()) + self.assertEquals('default', res['network']) + self.assertEquals(17, len(res['mac'])) + self.assertEquals('virtio', res['model']) + + def test_vm_customise_storage(self): # Create a Template req = json.dumps({'name': 'test', 'cdrom': '/nonexistent.iso',
participants (4)
-
Aline Manera
-
Mark Wu
-
shaohef@linux.vnet.ibm.com
-
Sheldon