[Kimchi-devel] [PATCH 5/5] Add/remove users and groups to VMs

Daniel H Barboza danielhb at linux.vnet.ibm.com
Mon Apr 14 18:31:33 UTC 2014


Reviewed-by: Daniel Barboza <danielhb at linux.vnet.ibm.com>

On 04/11/2014 05:58 PM, Aline Manera wrote:
> From: Aline Manera <alinefm at br.ibm.com>
>
> To update (add/remove) the users and groups of a virtual machine, you
> should use the REST command:
>
> /vms/<vm_name> PUT "{ 'users': [ 'user1', 'user2' ],
>                        'groups': [ 'group1', 'group2' ] }"
>
> Users and groups associated with a virtual machine must be valid when
> they are
> added to the VM. Such verification is not done when they are removed
> from the
> system. This means that virtual machines may contain outdated
> information about
> users and groups.
>
> Signed-off-by: Crístian Viana <vianac at linux.vnet.ibm.com>
> Signed-off-by: Aline Manera <alinefm at br.ibm.com>
> ---
>   docs/API.md               |    2 ++
>   po/en_US.po               |   24 +++++++++++++++++--
>   po/kimchi.pot             |   24 +++++++++++++++++--
>   po/pt_BR.po               |   57 +++++++++++++++++++++++++++++++--------------
>   po/zh_CN.po               |   56 ++++++++++++++++++++++++++++++--------------
>   src/kimchi/control/vms.py |    2 +-
>   src/kimchi/i18n.py        |    4 +++-
>   src/kimchi/mockmodel.py   |    3 +--
>   src/kimchi/model/vms.py   |   55 +++++++++++++++++++++++++++++++++++++------
>   tests/test_model.py       |   40 +++++++++++++++++++++++++++++++
>   10 files changed, 217 insertions(+), 50 deletions(-)
>
> diff --git a/docs/API.md b/docs/API.md
> index b726b9c..2c57665 100644
> --- a/docs/API.md
> +++ b/docs/API.md
> @@ -101,6 +101,8 @@ the following general conventions:
>   * **DELETE**: Remove the Virtual Machine
>   * **PUT**: update the parameters of existed VM
>       * name: New name for this VM (only applied for shutoff VM)
> +    * users: New list of system users.
> +    * groups: New list of system groups.
>   * **POST**: *See Virtual Machine Actions*
>   
>   **Actions (POST):**
> diff --git a/po/en_US.po b/po/en_US.po
> index 0b05f1e..f7b6e38 100644
> --- a/po/en_US.po
> +++ b/po/en_US.po
> @@ -6,7 +6,7 @@ msgid ""
>   msgstr ""
>   "Project-Id-Version: kimchi 0.1\n"
>   "Report-Msgid-Bugs-To: \n"
> -"POT-Creation-Date: 2014-04-09 17:11-0300\n"
> +"POT-Creation-Date: 2014-04-10 14:32-0300\n"
>   "PO-Revision-Date: 2013-07-11 17:32-0400\n"
>   "Last-Translator: Crístian Viana <vianac at linux.vnet.ibm.com>\n"
>   "Language-Team: English\n"
> @@ -914,7 +914,7 @@ msgid "Unable to create virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
>   #, python-format
> -msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> +msgid "Unable to update virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
>   #, python-format
> @@ -957,6 +957,26 @@ msgstr ""
>   msgid "Unable to delete virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
> +msgid "User names list must be an array"
> +msgstr ""
> +
> +msgid "User name must be a string"
> +msgstr ""
> +
> +msgid "Group names list must be an array"
> +msgstr ""
> +
> +msgid "Group name must be a string"
> +msgstr ""
> +
> +#, python-format
> +msgid "User %(user)s does not exist"
> +msgstr ""
> +
> +#, python-format
> +msgid "Group %(group)s does not exist"
> +msgstr ""
> +
>   #, python-format
>   msgid "Interface %(iface)s does not exist in virtual machine %(name)s"
>   msgstr ""
> diff --git a/po/kimchi.pot b/po/kimchi.pot
> index 92d5401..1da141b 100755
> --- a/po/kimchi.pot
> +++ b/po/kimchi.pot
> @@ -8,7 +8,7 @@ msgid ""
>   msgstr ""
>   "Project-Id-Version: PACKAGE VERSION\n"
>   "Report-Msgid-Bugs-To: \n"
> -"POT-Creation-Date: 2014-04-09 17:11-0300\n"
> +"POT-Creation-Date: 2014-04-10 14:32-0300\n"
>   "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
>   "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
>   "Language-Team: LANGUAGE <LL at li.org>\n"
> @@ -902,7 +902,7 @@ msgid "Unable to create virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
>   #, python-format
> -msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> +msgid "Unable to update virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
>   #, python-format
> @@ -945,6 +945,26 @@ msgstr ""
>   msgid "Unable to delete virtual machine %(name)s. Details: %(err)s"
>   msgstr ""
>   
> +msgid "User names list must be an array"
> +msgstr ""
> +
> +msgid "User name must be a string"
> +msgstr ""
> +
> +msgid "Group names list must be an array"
> +msgstr ""
> +
> +msgid "Group name must be a string"
> +msgstr ""
> +
> +#, python-format
> +msgid "User %(user)s does not exist"
> +msgstr ""
> +
> +#, python-format
> +msgid "Group %(group)s does not exist"
> +msgstr ""
> +
>   #, python-format
>   msgid "Interface %(iface)s does not exist in virtual machine %(name)s"
>   msgstr ""
> diff --git a/po/pt_BR.po b/po/pt_BR.po
> index cbb2b31..098ca8e 100644
> --- a/po/pt_BR.po
> +++ b/po/pt_BR.po
> @@ -20,7 +20,7 @@ msgid ""
>   msgstr ""
>   "Project-Id-Version: kimchi 1.0\n"
>   "Report-Msgid-Bugs-To: \n"
> -"POT-Creation-Date: 2014-04-09 17:11-0300\n"
> +"POT-Creation-Date: 2014-04-10 14:32-0300\n"
>   "PO-Revision-Date: 2013-06-27 10:48+0000\n"
>   "Last-Translator: Crístian Viana <vianac at linux.vnet.ibm.com>\n"
>   "Language-Team: Aline Manera <alinefm at br.ibm.com>\n"
> @@ -407,13 +407,10 @@ msgstr ""
>   msgid "Create a network"
>   msgstr "Criar uma rede"
>   
> -#, fuzzy
>   msgid ""
>   "This network is not persistent. Instead of stop, this action will "
>   "permanently delete it. Would you like to continue?"
>   msgstr ""
> -"O storage pool não é persistente. Ao invés de desativar, essa ação vai "
> -"removê-lo permanentemente. Deseja continuar?"
>   
>   msgid ""
>   "This will permanently delete the storage pool. Would you like to continue?"
> @@ -840,13 +837,13 @@ msgstr "Essa API suporta apenas JSON"
>   msgid "Datastore is not initiated in the model object."
>   msgstr "Datastore não é inicializado no objeto modelo."
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to start task due error: %(err)s"
> -msgstr "Não foi possível iniciar a máquina virtual %(name)s. Detalhes: %(err)s"
> +msgstr ""
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]"
> -msgstr "O usuário '%(userid)s' falhou na autenticação. [Error code: %(code)s]"
> +msgstr ""
>   
>   msgid "You are not authorized to access Kimchi"
>   msgstr "Você não está autorizado para acessar o Kimchi"
> @@ -965,8 +962,8 @@ msgid "Unable to create virtual machine %(name)s. Details: %(err)s"
>   msgstr "Não é possível criar a máquina virtual %(name)s. Detalhes: %(err)s"
>   
>   #, python-format
> -msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> -msgstr "Não é possível renomear a máquina virtual %(name)s. Detalhes: %(err)s"
> +msgid "Unable to update virtual machine %(name)s. Details: %(err)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s"
> @@ -1008,6 +1005,26 @@ msgstr "Não é possível parar a máquina virtual %(name)s. Detalhes: %(err)s"
>   msgid "Unable to delete virtual machine %(name)s. Details: %(err)s"
>   msgstr "Não é possível apagar a máquina virtual %(name)s. Detalhes: %(err)s"
>   
> +msgid "User names list must be an array"
> +msgstr ""
> +
> +msgid "User name must be a string"
> +msgstr ""
> +
> +msgid "Group names list must be an array"
> +msgstr ""
> +
> +msgid "Group name must be a string"
> +msgstr ""
> +
> +#, python-format
> +msgid "User %(user)s does not exist"
> +msgstr ""
> +
> +#, python-format
> +msgid "Group %(group)s does not exist"
> +msgstr ""
> +
>   #, python-format
>   msgid "Interface %(iface)s does not exist in virtual machine %(name)s"
>   msgstr "Interface %(iface)s não existe na máquina virtual %(name)s"
> @@ -1107,13 +1124,13 @@ msgstr ""
>   msgid "The volume: %(volume)s in not in storage pool %(pool)s"
>   msgstr "O volume de storage: %(volume)s não existe no storage pool %(pool)s"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to create template due error: %(err)s"
> -msgstr "Não é possível criar o storage pool %(name)s.Detalhes: %(err)s"
> +msgstr ""
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to delete template due error: %(err)s"
> -msgstr "Incapaz de deletar a rede ativa %(name)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Storage pool %(name)s already exists"
> @@ -1277,9 +1294,9 @@ msgstr ""
>   "Um grupo de volume chamado '%(name)s' já existe. Por favor, escolher outro "
>   "nome para criar o pool lógico."
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to update database with deep scan information due error: %(err)s"
> -msgstr "Incapaz de carregar as informações do repositório. Detalhes: %(err)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Storage volume %(name)s already exists"
> @@ -1356,10 +1373,10 @@ msgstr "Formato do volume não suportado"
>   msgid "Storage volume requires a volume name"
>   msgstr "Volume requer um nome"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid ""
>   "Unable to update database with storage volume information due error: %(err)s"
> -msgstr "Incapaz de deletar o volume %(name)s. Detalhes: %(err)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Interface %(name)s does not exist"
> @@ -1686,3 +1703,7 @@ msgstr "Não é possível adicionar o repositório. Detalhes: %(err)s"
>   #, python-format
>   msgid "Unable to remove repository. Details: '%(err)s'"
>   msgstr "Incapaz de remover o repositório. Detalhes: %(err)s"
> +
> +#~ msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> +#~ msgstr ""
> +#~ "Não é possível renomear a máquina virtual %(name)s. Detalhes: %(err)s"
> diff --git a/po/zh_CN.po b/po/zh_CN.po
> index 3b3754c..a1a72b9 100644
> --- a/po/zh_CN.po
> +++ b/po/zh_CN.po
> @@ -20,7 +20,7 @@ msgid ""
>   msgstr ""
>   "Project-Id-Version: kimchi 0.1\n"
>   "Report-Msgid-Bugs-To: \n"
> -"POT-Creation-Date: 2014-04-09 17:11-0300\n"
> +"POT-Creation-Date: 2014-04-10 14:32-0300\n"
>   "PO-Revision-Date: 2013-06-27 10:48+0000\n"
>   "Last-Translator: ShaoHe Feng <shaohef at linux.vnet.ibm.com>\n"
>   "Language-Team: ShaoHe Feng <shaohef at linux.vnet.ibm.com>\n"
> @@ -389,11 +389,10 @@ msgstr "此操作将中断依赖此网络的虚拟机的网络连接。"
>   msgid "Create a network"
>   msgstr "创建一个网络"
>   
> -#, fuzzy
>   msgid ""
>   "This network is not persistent. Instead of stop, this action will "
>   "permanently delete it. Would you like to continue?"
> -msgstr "对于非持久存储池,这个操作将会永久删除存储池而不是停用。是否继续?"
> +msgstr ""
>   
>   msgid ""
>   "This will permanently delete the storage pool. Would you like to continue?"
> @@ -812,13 +811,13 @@ msgstr "这个API仅支持JSON"
>   msgid "Datastore is not initiated in the model object."
>   msgstr "尚未为model对象初始化数据存储。"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to start task due error: %(err)s"
> -msgstr "不能启动虚拟机 %(name)s. 详情:%(err)s"
> +msgstr ""
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Authentication failed for user '%(username)s'. [Error code: %(code)s]"
> -msgstr "用户 '%(userid)s' 验证失败。[错误代码: %(code)s]"
> +msgstr ""
>   
>   msgid "You are not authorized to access Kimchi"
>   msgstr "您没有被授权访问Kimchi"
> @@ -926,8 +925,8 @@ msgid "Unable to create virtual machine %(name)s. Details: %(err)s"
>   msgstr "不能创建虚拟机%(name)s。详情:%(err)s"
>   
>   #, python-format
> -msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> -msgstr "不能重命名虚拟机%(name)s。详情:%(err)s"
> +msgid "Unable to update virtual machine %(name)s. Details: %(err)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Unable to retrieve virtual machine %(name)s. Details: %(err)s"
> @@ -969,6 +968,26 @@ msgstr "不能停止虚拟机 %(name)s. 详情:%(err)s"
>   msgid "Unable to delete virtual machine %(name)s. Details: %(err)s"
>   msgstr "不能删除虚拟机 %(name)s. 详情:%(err)s"
>   
> +msgid "User names list must be an array"
> +msgstr ""
> +
> +msgid "User name must be a string"
> +msgstr ""
> +
> +msgid "Group names list must be an array"
> +msgstr ""
> +
> +msgid "Group name must be a string"
> +msgstr ""
> +
> +#, python-format
> +msgid "User %(user)s does not exist"
> +msgstr ""
> +
> +#, python-format
> +msgid "Group %(group)s does not exist"
> +msgstr ""
> +
>   #, python-format
>   msgid "Interface %(iface)s does not exist in virtual machine %(name)s"
>   msgstr "虚拟机 %(name)s 中没有接口 %(iface)s"
> @@ -1061,13 +1080,13 @@ msgstr "当模板的存储池是iscsi或scsi时,必须为模板指定一个卷
>   msgid "The volume: %(volume)s in not in storage pool %(pool)s"
>   msgstr "存储池%(pool)s中没有存储卷%(volume)s"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to create template due error: %(err)s"
> -msgstr "不能创建存储池 %(name)s。详情: %(err)s"
> +msgstr ""
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to delete template due error: %(err)s"
> -msgstr "不能删除激活的网络%(name)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Storage pool %(name)s already exists"
> @@ -1210,9 +1229,9 @@ msgid ""
>   "to create the logical pool."
>   msgstr "卷组'%(name)s'已经存在,请选择其它的名字来创建逻辑存储池。"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid "Unable to update database with deep scan information due error: %(err)s"
> -msgstr "不能获取软件仓库的信息。详情:'%(err)s'"
> +msgstr ""
>   
>   #, python-format
>   msgid "Storage volume %(name)s already exists"
> @@ -1282,10 +1301,10 @@ msgstr "存储卷格式不支持"
>   msgid "Storage volume requires a volume name"
>   msgstr "存储卷需要名字"
>   
> -#, fuzzy, python-format
> +#, python-format
>   msgid ""
>   "Unable to update database with storage volume information due error: %(err)s"
> -msgstr "不能删除存储卷%(name)s。详情:%(err)s"
> +msgstr ""
>   
>   #, python-format
>   msgid "Interface %(name)s does not exist"
> @@ -1581,3 +1600,6 @@ msgstr "不能增加软件仓库。详情:'%(err)s'"
>   #, python-format
>   msgid "Unable to remove repository. Details: '%(err)s'"
>   msgstr "不能移除软件仓库。详情:'%(err)s'"
> +
> +#~ msgid "Unable to rename virtual machine %(name)s. Details: %(err)s"
> +#~ msgstr "不能重命名虚拟机%(name)s。详情:%(err)s"
> diff --git a/src/kimchi/control/vms.py b/src/kimchi/control/vms.py
> index 63c1e24..a44764b 100644
> --- a/src/kimchi/control/vms.py
> +++ b/src/kimchi/control/vms.py
> @@ -32,7 +32,7 @@ class VMs(Collection):
>   class VM(Resource):
>       def __init__(self, model, ident):
>           super(VM, self).__init__(model, ident)
> -        self.update_params = ["name"]
> +        self.update_params = ["name", "users", "groups"]
>           self.screenshot = VMScreenShot(model, ident)
>           self.uri_fmt = '/vms/%s'
>           for ident, node in sub_nodes.items():
> diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
> index 20f9716..ef46505 100644
> --- a/src/kimchi/i18n.py
> +++ b/src/kimchi/i18n.py
> @@ -68,7 +68,7 @@ messages = {
>       "KCHVM0005E": _("Remote ISO image is not supported by this server."),
>       "KCHVM0006E": _("Screenshot not supported for virtual machine %(name)s"),
>       "KCHVM0007E": _("Unable to create virtual machine %(name)s. Details: %(err)s"),
> -    "KCHVM0008E": _("Unable to rename virtual machine %(name)s. Details: %(err)s"),
> +    "KCHVM0008E": _("Unable to update virtual machine %(name)s. Details: %(err)s"),
>       "KCHVM0009E": _("Unable to retrieve virtual machine %(name)s. Details: %(err)s"),
>       "KCHVM0010E": _("Unable to connect to powered off machine %(name)s."),
>       "KCHVM0011E": _("Virtual machine name must be a string"),
> @@ -84,6 +84,8 @@ messages = {
>       "KCHVM0023E": _("User name must be a string"),
>       "KCHVM0024E": _("Group names list must be an array"),
>       "KCHVM0025E": _("Group name must be a string"),
> +    "KCHVM0026E": _("User %(user)s does not exist"),
> +    "KCHVM0027E": _("Group %(group)s does not exist"),
>   
>       "KCHVMIF0001E": _("Interface %(iface)s does not exist in virtual machine %(name)s"),
>       "KCHVMIF0002E": _("Network %(network)s specified for virtual machine %(name)s does not exist"),
> diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
> index 87ca21c..4fb28c6 100644
> --- a/src/kimchi/mockmodel.py
> +++ b/src/kimchi/mockmodel.py
> @@ -49,7 +49,6 @@ from kimchi.exception import MissingParameter, NotFoundError, OperationFailed
>   from kimchi.model.storagepools import ISO_POOL_NAME
>   from kimchi.model.storageservers import STORAGE_SERVERS
>   from kimchi.model.utils import get_vm_name
> -from kimchi.model.vms import VM_STATIC_UPDATE_PARAMS
>   from kimchi.objectstore import ObjectStore
>   from kimchi.screenshot import VMScreenshot
>   from kimchi.utils import pool_name_from_uri
> @@ -98,7 +97,7 @@ class MockModel(object):
>                   self._mock_vms[dom.name] = dom
>   
>           for key, val in params.items():
> -            if key in VM_STATIC_UPDATE_PARAMS and key in dom.info:
> +            if key in dom.info:
>                   dom.info[key] = val
>   
>       def _live_vm_update(self, dom, params):
> diff --git a/src/kimchi/model/vms.py b/src/kimchi/model/vms.py
> index ba091e5..f567390 100644
> --- a/src/kimchi/model/vms.py
> +++ b/src/kimchi/model/vms.py
> @@ -17,6 +17,7 @@
>   # 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 lxml.etree as ET
>   import os
>   import time
>   import uuid
> @@ -24,9 +25,11 @@ from xml.etree import ElementTree
>   
>   import libvirt
>   from cherrypy.process.plugins import BackgroundTask
> +from lxml.builder import E
>   
>   from kimchi import vnc
>   from kimchi import xmlutils
> +from kimchi.auth import Group, User
>   from kimchi.config import READONLY_POOL_TYPE
>   from kimchi.exception import InvalidOperation, InvalidParameter
>   from kimchi.exception import NotFoundError, OperationFailed
> @@ -240,25 +243,63 @@ class VMModel(object):
>           self._live_vm_update(dom, params)
>           return dom.name().decode('utf-8')
>   
> +    def _get_metadata_node(self, users, groups):
> +        access = E.access()
> +        for user in users:
> +            access.append(E.user(user))
> +
> +        for group in groups:
> +            access.append(E.group(group))
> +
> +        return E.metadata(E.kimchi(access))
> +
>       def _static_vm_update(self, dom, params):
>           state = DOM_STATE_MAP[dom.info()[0]]
>   
>           old_xml = new_xml = dom.XMLDesc(0)
>   
> +        metadata_xpath = "/domain/metadata/kimchi/access/%s"
> +        users = xpath_get_text(old_xml, metadata_xpath % "user")
> +        groups = xpath_get_text(old_xml, metadata_xpath % "group")
> +
>           for key, val in params.items():
> -            if key in VM_STATIC_UPDATE_PARAMS:
> -                xpath = VM_STATIC_UPDATE_PARAMS[key]
> -                new_xml = xmlutils.xml_item_update(new_xml, xpath, val)
> +            if key == 'users':
> +                for user in val:
> +                    if not User(user).exists():
> +                        raise OperationFailed("KCHVM0026E", {'user': user})
> +                users = val
> +            elif key == 'groups':
> +                for group in val:
> +                    if not Group(group).exists():
> +                        raise OperationFailed("KCHVM0027E", {'group': group})
> +                groups = val
> +            else:
> +                if key in VM_STATIC_UPDATE_PARAMS:
> +                    xpath = VM_STATIC_UPDATE_PARAMS[key]
> +                    new_xml = xmlutils.xml_item_update(new_xml, xpath, val)
>   
> +        conn = self.conn.get()
>           try:
>               if 'name' in params:
>                   if state == 'running':
>                       msg_args = {'name': dom.name(), 'new_name': params['name']}
>                       raise InvalidParameter("KCHVM0003E", msg_args)
> -                else:
> -                    dom.undefine()
> -            conn = self.conn.get()
> -            dom = conn.defineXML(new_xml)
> +
> +                # Undefine old vm and create a new one with updated values
> +                dom.undefine()
> +                conn = self.conn.get()
> +                dom = conn.defineXML(new_xml)
> +
> +            # Update metadata element
> +            root = ET.fromstring(new_xml)
> +            current_metadata = root.find('metadata')
> +            new_metadata = self._get_metadata_node(users, groups)
> +            if current_metadata is not None:
> +                root.replace(current_metadata, new_metadata)
> +            else:
> +                root.append(new_metadata)
> +            dom = conn.defineXML(ET.tostring(root))
> +
>           except libvirt.libvirtError as e:
>               dom = conn.defineXML(old_xml)
>               raise OperationFailed("KCHVM0008E", {'name': dom.name(),
> diff --git a/tests/test_model.py b/tests/test_model.py
> index 00c02d3..357d969 100644
> --- a/tests/test_model.py
> +++ b/tests/test_model.py
> @@ -18,9 +18,11 @@
>   # 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 grp
>   import os
>   import platform
>   import psutil
> +import pwd
>   import shutil
>   import tempfile
>   import threading
> @@ -608,6 +610,44 @@ class ModelTests(unittest.TestCase):
>               rollback.prependDefer(self._rollback_wrapper, inst.vm_delete,
>                                     u'пeω-∨м')
>   
> +            # change only VM users - groups are not changed (default is empty)
> +            users = ['root']
> +            inst.vm_update(u'пeω-∨м', {'users': users})
> +            self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['groups'])
> +
> +            # change only VM groups - users are not changed (default is empty)
> +            groups = ['root']
> +            inst.vm_update(u'пeω-∨м', {'groups': groups})
> +            self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups'])
> +
> +            # change VM users and groups by adding a new element to each one
> +            users.append(pwd.getpwuid(os.getuid()).pw_name)
> +            groups.append(grp.getgrgid(os.getgid()).gr_name)
> +            inst.vm_update(u'пeω-∨м', {'users': users, 'groups': groups})
> +            self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups'])
> +
> +            # change VM users (wrong value) and groups
> +            # when an error occurs, everything fails and nothing is changed
> +            self.assertRaises(OperationFailed, inst.vm_update, u'пeω-∨м',
> +                              {'users': ['userdoesnotexist'], 'groups': []})
> +            self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups'])
> +
> +            # change VM users and groups (wrong value)
> +            # when an error occurs, everything fails and nothing is changed
> +            self.assertRaises(OperationFailed, inst.vm_update, u'пeω-∨м',
> +                              {'users': [], 'groups': ['groupdoesnotexist']})
> +            self.assertEquals(users, inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals(groups, inst.vm_lookup(u'пeω-∨м')['groups'])
> +
> +            # change VM users and groups by removing all elements
> +            inst.vm_update(u'пeω-∨м', {'users': [], 'groups': []})
> +            self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['users'])
> +            self.assertEquals([], inst.vm_lookup(u'пeω-∨м')['groups'])
> +
>       @unittest.skipUnless(utils.running_as_root(), 'Must be run as root')
>       def test_network(self):
>           inst = model.Model('qemu:///system', self.tmp_store)




More information about the Kimchi-devel mailing list