[PATCH 0/7] Make Template defaults configurable

Aline Manera (7): Remove useless variable in osinfo.py Merge common_spec wiht defaults value in osinfo.py Make Template defaults configurable Add libvirt-daemon-config-network package as Kimchi dependency Verify all networks set as Template defaults prior to server start up Create option to auto create ISO pool or not on server start up Verify storage pool set as Template default prior to server starts up contrib/DEBIAN/control.in | 1 + contrib/kimchi.spec.fedora.in | 3 ++ contrib/kimchi.spec.suse.in | 3 ++ docs/README.md | 14 +++--- src/Makefile.am | 2 +- src/kimchi.conf.in | 3 ++ src/kimchi/config.py.in | 1 + src/kimchi/model/model.py | 44 +---------------- src/kimchi/model/networks.py | 61 ++++++++++------------- src/kimchi/model/storagepools.py | 66 +++++++++++++++++++++++++ src/kimchi/model/templates.py | 2 - src/kimchi/osinfo.py | 101 ++++++++++++++++++++++++++++++--------- src/kimchid.in | 3 ++ src/template.conf | 47 ++++++++++++++++++ 14 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 src/template.conf -- 2.1.0

modern_spec is not used anywhere so remove it. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/osinfo.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/kimchi/osinfo.py b/src/kimchi/osinfo.py index ede2541..d1ae424 100644 --- a/src/kimchi/osinfo.py +++ b/src/kimchi/osinfo.py @@ -38,9 +38,6 @@ common_spec = {'cpus': 1, 'memory': 1024, 'disks': [{'index': 0, 'size': 10, 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} -modern_spec = dict(common_spec, disk_bus='virtio', nic_model='virtio') - - template_specs = {'x86': {'old': dict(common_spec, disk_bus='ide', nic_model='e1000', sound_model='ich6'), 'modern': dict(common_spec, disk_bus='virtio', -- 2.1.0

common_spec value is used for all entries in template_specs dict. As lookup() returns as result a merge of defaults and template_specs values, there is no need to maintain 2 different dicts (defaults and common_spec). So merge them into one dict (defaults) to make the code simpler. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/osinfo.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/kimchi/osinfo.py b/src/kimchi/osinfo.py index d1ae424..05c685e 100644 --- a/src/kimchi/osinfo.py +++ b/src/kimchi/osinfo.py @@ -33,37 +33,32 @@ SUPPORTED_ARCHS = {'x86': ('i386', 'i686', 'x86_64'), 'ppc64le': ('ppc64le')} -common_spec = {'cpus': 1, 'memory': 1024, 'disks': [{'index': 0, 'size': 10, - 'format': 'qcow2'}], - 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} - - -template_specs = {'x86': {'old': dict(common_spec, disk_bus='ide', +template_specs = {'x86': {'old': dict(disk_bus='ide', nic_model='e1000', sound_model='ich6'), - 'modern': dict(common_spec, disk_bus='virtio', + 'modern': dict(disk_bus='virtio', nic_model='virtio', sound_model='ich6')}, - 'power': {'old': dict(common_spec, disk_bus='scsi', + 'power': {'old': dict(disk_bus='scsi', nic_model='spapr-vlan', cdrom_bus='scsi', kbd_type="kbd", kbd_bus='usb', mouse_bus='usb', tablet_bus='usb', memory=1280), - 'modern': dict(common_spec, disk_bus='virtio', + 'modern': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', kbd_type="kbd", mouse_bus='usb', tablet_bus='usb', memory=1280)}, - 'ppc64le': {'old': dict(common_spec, disk_bus='virtio', + 'ppc64le': {'old': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', kbd_type="keyboard", mouse_bus='usb', tablet_bus='usb', memory=1280), - 'modern': dict(common_spec, disk_bus='virtio', + 'modern': dict(disk_bus='virtio', nic_model='virtio', cdrom_bus='scsi', kbd_bus='usb', @@ -93,7 +88,11 @@ icon_available_distros = [icon[5:-4] for icon in glob.glob1('%s/images/' defaults = {'networks': ['default'], 'storagepool': '/storagepools/default', 'domain': 'kvm', 'arch': os.uname()[4], - 'graphics': {'type': 'vnc', 'listen': '127.0.0.1'}} + 'graphics': {'type': 'vnc', 'listen': '127.0.0.1'}, + 'cpus': 1, + 'memory': 1024, + 'disks': [{'index': 0, 'size': 10, 'format': 'qcow2'}], + 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} def _get_arch(): @@ -106,9 +105,10 @@ def get_template_default(template_type, field): host_arch = _get_arch() # Assuming 'power' = 'ppc64le' because lookup() does the same, # claiming libvirt compatibility. - if host_arch in ('power', 'ppc64le'): - return template_specs['power'][template_type][field] - return template_specs[host_arch][template_type][field] + host_arch = 'power' if host_arch == 'ppc64le' else host_arch + tmpl_defaults = copy.deepcopy(defaults) + tmpl_defaults.update(template_specs[host_arch][template_type]) + return tmpl_defaults[field] def lookup(distro, version): -- 2.1.0

Reviewed-by: Crístian Deives <cristiandeives@gmail.com> On 23-04-2015 16:51, Aline Manera wrote:
common_spec value is used for all entries in template_specs dict. As lookup() returns as result a merge of defaults and template_specs values, there is no need to maintain 2 different dicts (defaults and common_spec). So merge them into one dict (defaults) to make the code simpler.
Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com>

Create a template configuration file (template.conf) to handle all the template default values. Also parse it to set the right values on osinfo.py As template.conf file uses nested sections, it is required to install an additional package python-configobj to parse it. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- contrib/DEBIAN/control.in | 1 + contrib/kimchi.spec.fedora.in | 2 ++ contrib/kimchi.spec.suse.in | 2 ++ docs/README.md | 8 ++--- src/Makefile.am | 2 +- src/kimchi/model/templates.py | 2 -- src/kimchi/osinfo.py | 78 +++++++++++++++++++++++++++++++++++++------ src/template.conf | 47 ++++++++++++++++++++++++++ 8 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 src/template.conf diff --git a/contrib/DEBIAN/control.in b/contrib/DEBIAN/control.in index 069e14b..0747d0f 100644 --- a/contrib/DEBIAN/control.in +++ b/contrib/DEBIAN/control.in @@ -6,6 +6,7 @@ Architecture: all Depends: python-cherrypy3 (>= 3.2.0), python-cheetah, python-imaging, + python-configobj, websockify, novnc, python-jsonschema (>= 1.3.0), diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index 750dada..874ab96 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -14,6 +14,7 @@ Requires: libvirt-python Requires: python-cherrypy >= 3.2.0 Requires: python-cheetah Requires: python-websockify +Requires: python-configobj Requires: novnc Requires: m2crypto Requires: python-imaging @@ -159,6 +160,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/ %{_datadir}/kimchi %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/template.conf %{_sysconfdir}/kimchi/nginx.conf.in %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index 7e4172d..9734852 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -14,6 +14,7 @@ Requires: libvirt-python Requires: python-CherryPy >= 3.2.0 Requires: python-Cheetah Requires: python-websockify +Requires: python-configobj Requires: novnc Requires: python-imaging Requires: python-M2Crypto @@ -98,6 +99,7 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/kimchi/ui/ %{_datadir}/kimchi %{_sysconfdir}/kimchi/kimchi.conf +%{_sysconfdir}/kimchi/template.conf %{_sysconfdir}/kimchi/distros.d/debian.json %{_sysconfdir}/kimchi/distros.d/fedora.json %{_sysconfdir}/kimchi/distros.d/opensuse.json diff --git a/docs/README.md b/docs/README.md index 5407264..3f02529 100644 --- a/docs/README.md +++ b/docs/README.md @@ -55,7 +55,7 @@ Install Dependencies python-ipaddr python-ldap python-lxml nfs-utils \ iscsi-initiator-utils libxslt pyparted nginx \ python-libguestfs libguestfs-tools python-websockify \ - novnc spice-html5 + novnc spice-html5 python-configobj # If using RHEL, install the following additional packages: $ sudo yum install python-unittest2 python-ordereddict @@ -81,7 +81,7 @@ channel at RHN Classic or Red Hat Satellite. $ sudo apt-get install gcc make autoconf automake gettext git \ python-cherrypy3 python-cheetah python-libvirt \ - libvirt-bin python-imaging \ + libvirt-bin python-imaging python-configobj \ python-pam python-m2crypto python-jsonschema \ qemu-kvm libtool python-psutil python-ethtool \ sosreport python-ipaddr python-ldap \ @@ -104,8 +104,8 @@ channel at RHN Classic or Red Hat Satellite. python-pam python-M2Crypto python-jsonschema \ rpm-build kvm python-psutil python-ethtool \ python-ipaddr python-ldap python-lxml nfs-client \ - open-iscsi libxslt-tools python-xml \ - python-parted nginx python-libguestfs \ + open-iscsi libxslt-tools python-xml python-parted \ + nginx python-libguestfs python-configobj \ guestfs-tools python-websockify novnc Packages version requirement: diff --git a/src/Makefile.am b/src/Makefile.am index dfeb24e..a91d920 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,7 +28,7 @@ EXTRA_DIST = kimchid.in \ bin_SCRIPTS = kimchid confdir = $(sysconfdir)/kimchi -dist_conf_DATA = kimchi.conf nginx.conf.in +dist_conf_DATA = kimchi.conf nginx.conf.in template.conf BUILT_SOURCES = kimchi.conf diff --git a/src/kimchi/model/templates.py b/src/kimchi/model/templates.py index 8a1820d..ef83706 100644 --- a/src/kimchi/model/templates.py +++ b/src/kimchi/model/templates.py @@ -68,8 +68,6 @@ class TemplatesModel(object): # exception if a topology is invalid. CPUInfoModel(conn=self.conn).\ check_topology(params['cpus'], topology) - else: - params['cpu_info'] = dict() conn = self.conn.get() pool_uri = params.get(u'storagepool', '') diff --git a/src/kimchi/osinfo.py b/src/kimchi/osinfo.py index 05c685e..67d85be 100644 --- a/src/kimchi/osinfo.py +++ b/src/kimchi/osinfo.py @@ -21,10 +21,10 @@ import copy import glob import os - +from collections import defaultdict +from configobj import ConfigObj from distutils.version import LooseVersion - from kimchi.config import paths @@ -85,14 +85,72 @@ icon_available_distros = [icon[5:-4] for icon in glob.glob1('%s/images/' % paths.ui_dir, 'icon-*.png')] -defaults = {'networks': ['default'], - 'storagepool': '/storagepools/default', - 'domain': 'kvm', 'arch': os.uname()[4], - 'graphics': {'type': 'vnc', 'listen': '127.0.0.1'}, - 'cpus': 1, - 'memory': 1024, - 'disks': [{'index': 0, 'size': 10, 'format': 'qcow2'}], - 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} +def _get_tmpl_defaults(): + """ + ConfigObj returns a dict like below when no changes were made in the + template configuration file (template.conf) + + {'main': {}, 'storage': {'disk.0': {}}, 'processor': {}, 'graphics': {}} + + The default values should be like below: + + {'main': {'networks': ['default'], 'memory': '1024'}, + 'storage': {'pool': 'default', + 'disk.0': {'format': 'qcow2', 'size': '10'}}, + 'processor': {'cpus': '1'}, + 'graphics': {'type': 'spice', 'listen': '127.0.0.1'}} + """ + # Create dict with default values + tmpl_defaults = defaultdict(dict) + tmpl_defaults['main']['networks'] = ['default'] + tmpl_defaults['main']['memory'] = 1024 + tmpl_defaults['storage']['pool'] = 'default' + tmpl_defaults['storage']['disk.0'] = {'size': 10, 'format': 'qcow2'} + tmpl_defaults['processor']['cpus'] = 1 + tmpl_defaults['graphics'] = {'type': 'vnc', 'listen': '127.0.0.1'} + + default_config = ConfigObj(tmpl_defaults) + + # Load template configuration file + config_file = os.path.join(paths.conf_dir, 'template.conf') + config = ConfigObj(config_file) + + # Merge default configuration with file configuration + default_config.merge(config) + + # Create a dict with default values according to data structure + # expected by VMTemplate + defaults = {'domain': 'kvm', 'arch': os.uname()[4], + 'cdrom_bus': 'ide', 'cdrom_index': 2, 'mouse_bus': 'ps2'} + + # Parse main section to get networks and memory values + main_section = default_config.pop('main') + defaults.update(main_section) + + # Parse storage section to get storage pool and disks values + storage_section = default_config.pop('storage') + defaults['storagepool'] = '/storagepools/' + storage_section.pop('pool') + defaults['disks'] = [] + for disk in storage_section.keys(): + data = storage_section[disk] + data['index'] = int(disk.split('.')[1]) + defaults['disks'].append(data) + + # Parse processor section to get cpus and cpu_topology values + processor_section = default_config.pop('processor') + defaults['cpus'] = processor_section.pop('cpus') + defaults['cpu_info'] = {} + if len(processor_section.keys()) > 0: + defaults['cpu_info']['topology'] = processor_section + + # Update defaults values with graphics values + defaults['graphics'] = default_config.pop('graphics') + + return defaults + + +# Set defaults values according to template.conf file +defaults = _get_tmpl_defaults() def _get_arch(): diff --git a/src/template.conf b/src/template.conf new file mode 100644 index 0000000..f3615e6 --- /dev/null +++ b/src/template.conf @@ -0,0 +1,47 @@ +# +# Configuration file for Kimchi Templates +# + +[main] +# Memory in MB +#memory = 1024 + +# List of networks separated by comma +# Represents the virtual network interfaces to be assigned to guest +#networks = default, + +[storage] +# Storage pool used to handle the guest disk +#pool = default + +# Specify multiple [[disk.X]] sub-sections to add multiples disks to guest +# All the disk files will be created in the same storage pool as set above +[[disk.0]] +# Disk size in GB +#size = 10 + +# Disk format +#format = qcow2 + +[graphics] +# Graphics type +# Valid options: vnc | spice +#type = vnc + +# The network which the vnc/spice server listens on +#listen = 127.0.0.1 + +[processor] +# Number of vcpus +# When specifying CPU topology, make sure cpus value is equal to the product +# of sockets, cores, and threads. +#cpus = 1 + +# Number of sockets (not set by default) +#sockets = + +# Number of cores per socket (not set by default) +#cores = + +# Number of threads per core (not set by default) +#threads = -- 2.1.0

The libvirt-daemon-config-network package for Fedora/RHEL and openSUSE installs /etc/libvirt/qemu/network/default.xml which creates the default network. So having this package as dependency eliminates the Kimchi needs to create on start up. This package is not required for Ubuntu, as it is already included in the libvirt-bin package. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- contrib/kimchi.spec.fedora.in | 1 + contrib/kimchi.spec.suse.in | 1 + docs/README.md | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/contrib/kimchi.spec.fedora.in b/contrib/kimchi.spec.fedora.in index 874ab96..9c7e2fd 100644 --- a/contrib/kimchi.spec.fedora.in +++ b/contrib/kimchi.spec.fedora.in @@ -11,6 +11,7 @@ Requires: qemu-kvm Requires: gettext-devel Requires: libvirt Requires: libvirt-python +Requires: libvirt-daemon-config-network Requires: python-cherrypy >= 3.2.0 Requires: python-cheetah Requires: python-websockify diff --git a/contrib/kimchi.spec.suse.in b/contrib/kimchi.spec.suse.in index 9734852..bd25097 100644 --- a/contrib/kimchi.spec.suse.in +++ b/contrib/kimchi.spec.suse.in @@ -11,6 +11,7 @@ Requires: kvm Requires: gettext-tools Requires: libvirt Requires: libvirt-python +Requires: libvirt-daemon-config-network Requires: python-CherryPy >= 3.2.0 Requires: python-Cheetah Requires: python-websockify diff --git a/docs/README.md b/docs/README.md index 3f02529..034a591 100644 --- a/docs/README.md +++ b/docs/README.md @@ -49,7 +49,7 @@ Install Dependencies $ sudo yum install gcc make autoconf automake gettext-devel git \ python-cherrypy python-cheetah libvirt-python \ - libvirt python-imaging \ + libvirt libvirt-daemon-config-network python-imaging \ PyPAM m2crypto python-jsonschema rpm-build \ qemu-kvm python-psutil python-ethtool sos \ python-ipaddr python-ldap python-lxml nfs-utils \ @@ -100,8 +100,8 @@ channel at RHN Classic or Red Hat Satellite. $ sudo zypper install gcc make autoconf automake gettext-tools git \ python-CherryPy python-Cheetah libvirt-python \ - libvirt python-imaging \ - python-pam python-M2Crypto python-jsonschema \ + libvirt libvirt-daemon-config-network python-pam \ + python-imaging python-M2Crypto python-jsonschema \ rpm-build kvm python-psutil python-ethtool \ python-ipaddr python-ldap python-lxml nfs-client \ open-iscsi libxslt-tools python-xml python-parted \ -- 2.1.0

Reviewed-by: Crístian Deives <cristiandeives@gmail.com> On 23-04-2015 16:51, Aline Manera wrote:
The libvirt-daemon-config-network package for Fedora/RHEL and openSUSE installs /etc/libvirt/qemu/network/default.xml which creates the default network. So having this package as dependency eliminates the Kimchi needs to create on start up.
This package is not required for Ubuntu, as it is already included in the libvirt-bin package.
Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com>

Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/model/networks.py | 61 +++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/src/kimchi/model/networks.py b/src/kimchi/model/networks.py index 92aed92..9550584 100644 --- a/src/kimchi/model/networks.py +++ b/src/kimchi/model/networks.py @@ -29,6 +29,7 @@ from kimchi import netinfo from kimchi import network as knetwork from kimchi.exception import InvalidOperation, InvalidParameter from kimchi.exception import MissingParameter, NotFoundError, OperationFailed +from kimchi.osinfo import defaults as tmpl_defaults from kimchi.rollbackcontext import RollbackContext from kimchi.utils import kimchi_log, run_command from kimchi.xmlutils.network import create_vlan_tagged_bridge_xml @@ -43,42 +44,32 @@ class NetworksModel(object): def __init__(self, **kargs): self.conn = kargs['conn'] if self.conn.isQemuURI(): - self._default_network_check() - - def _default_network_check(self): - def create_default_network(): - try: - subnet = self._get_available_address(knetwork.DefaultNetsPool) - params = {"name": "default", "connection": "nat", - "subnet": subnet} - self.create(params) - return conn.networkLookupByName("default") - except Exception as e: - kimchi_log.error("Fatal: Cannot create default network " - "because of %s, exit kimchid", e.message) - sys.exit(1) + self._check_default_networks() + def _check_default_networks(self): + networks = list(set(tmpl_defaults['networks'])) conn = self.conn.get() - try: - net = conn.networkLookupByName("default") - except libvirt.libvirtError: - net = create_default_network() - if net.isActive() == 0: + error_msg = "Please, check the configuration in \ + /etc/kimchi/template.conf to ensure it lists only valid \ + networks." + + for net in networks: try: - net.create() - except libvirt.libvirtError as e: - # FIXME we can not distinguish this error from other internal - # error by error code. - if ("network is already in use by interface" - in e.message.lower()): - # libvirt do not support update IP element, so delete the - # the network and create new one. - net.undefine() - create_default_network() - else: - kimchi_log.error("Fatal: Cannot activate default network " - "because of %s, exit kimchid", e.message) + net = conn.networkLookupByName(net) + except libvirt.libvirtError, e: + msg = "Fatal: Unable to find network %s. " + error_msg + kimchi_log.error(msg % net) + kimchi_log.error("Details: %s", e.message) + sys.exit(1) + + if net.isActive() == 0: + try: + net.create() + except libvirt.libvirtError as e: + msg = "Fatal: Unable to activate network %s. " + error_msg + kimchi_log.error(msg % net) + kimchi_log.error("Details: %s", e.message) sys.exit(1) def create(self, params): @@ -274,10 +265,10 @@ class NetworkModel(object): 'persistent': True if network.isPersistent() else False} def _is_network_in_use(self, name): - # The network "default" is used for Kimchi proposal and should not be - # deactivate or deleted. Otherwise, we will allow user create + # All the networks listed as default in template.conf file should not + # be deactivate or deleted. Otherwise, we will allow user create # inconsistent templates from scratch - if name == 'default': + if name in tmpl_defaults['networks']: return True vms = self._get_vms_attach_to_a_network(name) -- 2.1.0

Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi.conf.in | 3 +++ src/kimchi/config.py.in | 1 + src/kimchid.in | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/kimchi.conf.in b/src/kimchi.conf.in index 9f62ac0..cd141f5 100644 --- a/src/kimchi.conf.in +++ b/src/kimchi.conf.in @@ -33,6 +33,9 @@ # Max request body size in KB, default value is 4GB #max_body_size = 4 * 1024 * 1024 +# Automatically create ISO pool on server start up +#create_iso_pool = true + [logging] # Log directory #log_dir = @localstatedir@/log/kimchi diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in index f2e1cac..610c380 100644 --- a/src/kimchi/config.py.in +++ b/src/kimchi/config.py.in @@ -295,6 +295,7 @@ def _get_config(): config.set("server", "ssl_key", "") config.set("server", "environment", "production") config.set("server", "federation", "off") + config.set("server", "create_iso_pool", "true") config.set('server', 'max_body_size', '4*1024*1024') config.add_section("authentication") config.set("authentication", "method", "pam") diff --git a/src/kimchid.in b/src/kimchid.in index 57dc3c8..4ea7a42 100644 --- a/src/kimchid.in +++ b/src/kimchid.in @@ -47,6 +47,7 @@ def main(options): cherrypy_port = config.config.get("server", "cherrypy_port") runningEnv = config.config.get("server", "environment") federation = config.config.get("server", "federation") + isopool = config.config.get("server", "create_iso_pool") logDir = config.config.get("logging", "log_dir") logLevel = config.config.get("logging", "log_level") @@ -73,6 +74,8 @@ def main(options): help="Register and discover Kimchi peers in the same " "network using openSLP. Check README-federation for" " more details.") + parser.add_option('--create_iso_pool', default=isopool, + help="Automatically create ISO pool on server start up.") parser.add_option('--test', action='store_true', help="Run server in mock model") (options, args) = parser.parse_args() -- 2.1.0

The verification was being done in model/model.py but as it is only related to storage pools, it was added to model/storagepools.py This patch also adds a new option 'create_iso_pool' to kimchid, so the user can choose to create or not the ISO pool during server starts up. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/kimchi/model/model.py | 44 +-------------------------- src/kimchi/model/storagepools.py | 66 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/kimchi/model/model.py b/src/kimchi/model/model.py index 566be66..40ebc98 100644 --- a/src/kimchi/model/model.py +++ b/src/kimchi/model/model.py @@ -1,7 +1,7 @@ # # Project Kimchi # -# Copyright IBM, Corp. 2014 +# Copyright IBM, Corp. 2014-2015 # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -18,14 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import inspect -import logging import os -import sys - -import cherrypy -import libvirt -import lxml.etree as ET -from lxml.builder import E from kimchi.basemodel import BaseModel from kimchi.model.libvirtconnection import LibvirtConnection @@ -33,10 +26,6 @@ from kimchi.objectstore import ObjectStore from kimchi.utils import import_module, listPathModules -DEFAULT_POOLS = {'default': {'path': '/var/lib/libvirt/images'}, - 'ISO': {'path': '/var/lib/kimchi/isos'}} - - class Model(BaseModel): def __init__(self, libvirt_uri=None, objstore_loc=None): @@ -44,10 +33,6 @@ class Model(BaseModel): self.conn = LibvirtConnection(libvirt_uri) kargs = {'objstore': self.objstore, 'conn': self.conn} - if self.conn.isQemuURI(): - for pool_name, pool_arg in DEFAULT_POOLS.iteritems(): - self._default_pool_check(pool_name, pool_arg) - this = os.path.basename(__file__) this_mod = os.path.splitext(this)[0] @@ -64,30 +49,3 @@ class Model(BaseModel): models.append(instance(**kargs)) return super(Model, self).__init__(models) - - def _default_pool_check(self, pool_name, pool_arg): - conn = self.conn.get() - pool = E.pool(E.name(pool_name), type='dir') - pool.append(E.target(E.path(pool_arg['path']))) - xml = ET.tostring(pool) - try: - pool = conn.storagePoolLookupByName(pool_name) - except libvirt.libvirtError: - try: - pool = conn.storagePoolDefineXML(xml, 0) - # Add build step to make sure target directory created - pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW) - pool.setAutostart(1) - except libvirt.libvirtError, e: - cherrypy.log.error("Fatal: Cannot create default pool because " - "of %s, exit kimchid" % e.message, - severity=logging.ERROR) - sys.exit(1) - - if pool.isActive() == 0: - try: - pool.create(0) - except libvirt.libvirtError, e: - err = "Fatal: Default pool cannot be activated, exit kimchid" - cherrypy.log.error(err, severity=logging.ERROR) - sys.exit(1) diff --git a/src/kimchi/model/storagepools.py b/src/kimchi/model/storagepools.py index b85f3b4..88645a9 100644 --- a/src/kimchi/model/storagepools.py +++ b/src/kimchi/model/storagepools.py @@ -18,18 +18,28 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import libvirt +import lxml.etree as ET +import sys +from lxml.builder import E + +from kimchi.config import config from kimchi.scan import Scanner from kimchi.exception import InvalidOperation, MissingParameter from kimchi.exception import NotFoundError, OperationFailed from kimchi.model.config import CapabilitiesModel from kimchi.model.host import DeviceModel from kimchi.model.libvirtstoragepool import StoragePoolDef +from kimchi.osinfo import defaults as tmpl_defaults from kimchi.utils import add_task, kimchi_log, pool_name_from_uri, run_command from kimchi.xmlutils.utils import xpath_get_text +DEFAULT_POOLS = {'default': {'path': '/var/lib/libvirt/images'}, + 'ISO': {'path': '/var/lib/kimchi/isos'}} + ISO_POOL_NAME = u'kimchi_isos' + POOL_STATE_MAP = {0: 'inactive', 1: 'initializing', 2: 'active', @@ -57,6 +67,62 @@ class StoragePoolsModel(object): self.caps = CapabilitiesModel(**kargs) self.device = DeviceModel(**kargs) + if self.conn.isQemuURI(): + self._check_default_pools() + + def _check_default_pools(self): + default_pool = tmpl_defaults['storagepool'] + default_pool = default_pool.split('/')[2] + + if default_pool != 'default': + del DEFAULT_POOLS['default'] + DEFAULT_POOLS[default_pool] = {} + + if config.get("server", "create_iso_pool") != "true": + del DEFAULT_POOLS['ISO'] + + error_msg = "Please, check the configuration in \ + /etc/kimchi/template.conf to ensure it has a valid \ + storage pool." + + conn = self.conn.get() + for pool_name in DEFAULT_POOLS: + try: + pool = conn.storagePoolLookupByName(pool_name) + except libvirt.libvirtError, e: + pool_path = DEFAULT_POOLS[pool_name].get('path') + if pool_path is None: + msg = "Fatal: Unable to find storage pool %s. " + error_msg + kimchi_log.error(msg % pool_name) + kimchi_log.error("Details: %s", e.message) + sys.exit(1) + + # Try to create the pool + pool = E.pool(E.name(pool_name), type='dir') + pool.append(E.target(E.path(pool_path))) + xml = ET.tostring(pool) + try: + pool = conn.storagePoolDefineXML(xml, 0) + # Add build step to make sure target directory created + pool.build(libvirt.VIR_STORAGE_POOL_BUILD_NEW) + pool.setAutostart(1) + except libvirt.libvirtError, e: + msg = "Fatal: Unable to create storage pool %s. " + msg += error_msg + kimchi_log.error(msg % pool_name) + kimchi_log.error("Details: %s", e.message) + sys.exit(1) + + if pool.isActive() == 0: + try: + pool.create(0) + except libvirt.libvirtError, e: + msg = "Fatal: Unable to craete storage pool %s. " + msg += error_msg + kimchi_log.error(msg % pool_name) + kimchi_log.error("Details: %s", e.message) + sys.exit(1) + def get_list(self): try: conn = self.conn.get() -- 2.1.0

I tested this patchset on VMs running Fedora, RHEL and Ubuntu, and only on RHEL and Ubuntu the tests haven't finished. As soon as they start, I get the following error message: libvirt: error : internal error: Network is already in use by interface ens3 Fatal: Unable to activate network <libvirt.virNetwork object at 0x2146290>. Please, check the configuration in /etc/kimchi/template.conf to ensure it lists only valid networks. Details: internal error: Network is already in use by interface ens3 As you can see from the error message, there are many unexpected blank spaces inside the error string. And I'm afraid the path "/etc/kimchi/template.conf" may not always be correct depending on how the user is running / has installed Kimchi. For example, I'm running Kimchi from the source code, the error message tells me to check /etc/kimchi/template.conf but that file doesn't exist here. On 23-04-2015 16:51, Aline Manera wrote:
Aline Manera (7): Remove useless variable in osinfo.py Merge common_spec wiht defaults value in osinfo.py Make Template defaults configurable Add libvirt-daemon-config-network package as Kimchi dependency Verify all networks set as Template defaults prior to server start up Create option to auto create ISO pool or not on server start up Verify storage pool set as Template default prior to server starts up
contrib/DEBIAN/control.in | 1 + contrib/kimchi.spec.fedora.in | 3 ++ contrib/kimchi.spec.suse.in | 3 ++ docs/README.md | 14 +++--- src/Makefile.am | 2 +- src/kimchi.conf.in | 3 ++ src/kimchi/config.py.in | 1 + src/kimchi/model/model.py | 44 +---------------- src/kimchi/model/networks.py | 61 ++++++++++------------- src/kimchi/model/storagepools.py | 66 +++++++++++++++++++++++++ src/kimchi/model/templates.py | 2 - src/kimchi/osinfo.py | 101 ++++++++++++++++++++++++++++++--------- src/kimchid.in | 3 ++ src/template.conf | 47 ++++++++++++++++++ 14 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 src/template.conf

On 30/04/2015 10:36, Crístian Deives wrote:
I tested this patchset on VMs running Fedora, RHEL and Ubuntu, and only on RHEL and Ubuntu the tests haven't finished. As soon as they start, I get the following error message:
libvirt: error : internal error: Network is already in use by interface ens3 Fatal: Unable to activate network <libvirt.virNetwork object at 0x2146290>. Please, check the configuration in /etc/kimchi/template.conf to ensure it lists only valid networks. Details: internal error: Network is already in use by interface ens3
It is because you are probably running on nested virtualization and as Kimchi depends on libvirt-daemon-config-network it creates the default network pointing to the address range in use by the host. If we want to automatically get another address range while using nested virtualization I recommend open an issue againsta libvirt to get it fixed on libvirt-daemon-config-network package.
As you can see from the error message, there are many unexpected blank spaces inside the error string. And I'm afraid the path "/etc/kimchi/template.conf" may not always be correct depending on how the user is running / has installed Kimchi. For example, I'm running Kimchi from the source code, the error message tells me to check /etc/kimchi/template.conf but that file doesn't exist here.
I will fix it and send V2.
On 23-04-2015 16:51, Aline Manera wrote:
Aline Manera (7): Remove useless variable in osinfo.py Merge common_spec wiht defaults value in osinfo.py Make Template defaults configurable Add libvirt-daemon-config-network package as Kimchi dependency Verify all networks set as Template defaults prior to server start up Create option to auto create ISO pool or not on server start up Verify storage pool set as Template default prior to server starts up
contrib/DEBIAN/control.in | 1 + contrib/kimchi.spec.fedora.in | 3 ++ contrib/kimchi.spec.suse.in | 3 ++ docs/README.md | 14 +++--- src/Makefile.am | 2 +- src/kimchi.conf.in | 3 ++ src/kimchi/config.py.in | 1 + src/kimchi/model/model.py | 44 +---------------- src/kimchi/model/networks.py | 61 ++++++++++------------- src/kimchi/model/storagepools.py | 66 +++++++++++++++++++++++++ src/kimchi/model/templates.py | 2 - src/kimchi/osinfo.py | 101 ++++++++++++++++++++++++++++++--------- src/kimchid.in | 3 ++ src/template.conf | 47 ++++++++++++++++++ 14 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 src/template.conf

Thanks for the review, Cristian! I will apply patches 1, 2, 4 and 6 by now and send a V2 containing the changes you suggested for the other patches. On 23/04/2015 16:51, Aline Manera wrote:
Aline Manera (7): Remove useless variable in osinfo.py Merge common_spec wiht defaults value in osinfo.py Make Template defaults configurable Add libvirt-daemon-config-network package as Kimchi dependency Verify all networks set as Template defaults prior to server start up Create option to auto create ISO pool or not on server start up Verify storage pool set as Template default prior to server starts up
contrib/DEBIAN/control.in | 1 + contrib/kimchi.spec.fedora.in | 3 ++ contrib/kimchi.spec.suse.in | 3 ++ docs/README.md | 14 +++--- src/Makefile.am | 2 +- src/kimchi.conf.in | 3 ++ src/kimchi/config.py.in | 1 + src/kimchi/model/model.py | 44 +---------------- src/kimchi/model/networks.py | 61 ++++++++++------------- src/kimchi/model/storagepools.py | 66 +++++++++++++++++++++++++ src/kimchi/model/templates.py | 2 - src/kimchi/osinfo.py | 101 ++++++++++++++++++++++++++++++--------- src/kimchid.in | 3 ++ src/template.conf | 47 ++++++++++++++++++ 14 files changed, 240 insertions(+), 111 deletions(-) create mode 100644 src/template.conf
participants (2)
-
Aline Manera
-
Crístian Deives