[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