Пример #1
0
    def _generate_thumbnail(self):
        thumbnail = os.path.join(
            config.get_screenshot_path(),
            '%s-%s.png' % (self.vm_uuid, str(uuid.uuid4())))

        self._get_test_result()
        if stream_test_result is None:
            self._watch_stream_creation(thumbnail)
        elif stream_test_result:
            try:
                self._generate_scratch(thumbnail)
            except Exception:
                wok_log.error('screenshot_creation: Unable to create '
                              'screenshot image %s.' % thumbnail)
        else:
            self._create_black_image(thumbnail)

        if os.path.getsize(thumbnail) == 0:
            self._create_black_image(thumbnail)
        else:
            im = Image.open(thumbnail)
            try:
                # Prevent Image lib from lazy load,
                # work around pic truncate validation in thumbnail generation
                im.thumbnail(self.THUMBNAIL_SIZE)
            except Exception as e:
                wok_log.warning('Image load with warning: %s.' % e)
            im.save(thumbnail, 'PNG')

        self.info['thumbnail'] = thumbnail
Пример #2
0
def _is_dev_extended_partition(devType, devNodePath):
    if devType != 'part':
        return False

    if devNodePath.startswith('/dev/mapper'):
        try:
            dev_maj_min = _get_dev_major_min(devNodePath.split('/')[-1])
            parent_sys_path = '/sys/dev/block/' + dev_maj_min + '/slaves'
            parent_dm_name = os.listdir(parent_sys_path)[0]
            parent_maj_min = open(parent_sys_path + '/' + parent_dm_name +
                                  '/dev').readline().rstrip()
            diskPath = _get_dev_node_path(parent_maj_min)
        except Exception as e:
            wok_log.error('Error dealing with dev mapper device: ' +
                          devNodePath)
            raise OperationFailed('GGBDISK00001E', {'err': e.message})
    else:
        diskPath = devNodePath.rstrip('0123456789')

    device = PDevice(diskPath)
    try:
        extended_part = PDisk(device).getExtendedPartition()
    except NotImplementedError as e:
        wok_log.warning(
            'Error getting extended partition info for dev %s type %s: %s',
            devNodePath, devType, e.message)
        # Treate disk with unsupported partiton table as if it does not
        # contain extended partitions.
        return False
    if extended_part and extended_part.path == devNodePath:
        return True
    return False
Пример #3
0
    def _generate_thumbnail(self):
        thumbnail = os.path.join(config.get_screenshot_path(), '%s-%s.png' %
                                 (self.vm_uuid, str(uuid.uuid4())))

        self._get_test_result()
        if stream_test_result is None:
            self._watch_stream_creation(thumbnail)
        elif stream_test_result:
            try:
                self._generate_scratch(thumbnail)
            except:
                wok_log.error("screenshot_creation: Unable to create "
                              "screenshot image %s." % thumbnail)
        else:
            self._create_black_image(thumbnail)

        if os.path.getsize(thumbnail) == 0:
            self._create_black_image(thumbnail)
        else:
            im = Image.open(thumbnail)
            try:
                # Prevent Image lib from lazy load,
                # work around pic truncate validation in thumbnail generation
                im.thumbnail(self.THUMBNAIL_SIZE)
            except Exception as e:
                wok_log.warning("Image load with warning: %s." % e)
            im.save(thumbnail, "PNG")

        self.info['thumbnail'] = thumbnail
Пример #4
0
def _is_dev_extended_partition(devType, devNodePath):
    if devType != 'part':
        return False

    if devNodePath.startswith('/dev/mapper'):
        try:
            dev_maj_min = _get_dev_major_min(devNodePath.split("/")[-1])
            parent_sys_path = '/sys/dev/block/' + dev_maj_min + '/slaves'
            parent_dm_name = os.listdir(parent_sys_path)[0]
            parent_maj_min = open(
                parent_sys_path +
                '/' +
                parent_dm_name +
                '/dev').readline().rstrip()
            diskPath = _get_dev_node_path(parent_maj_min)
        except Exception as e:
            wok_log.error(
                "Error dealing with dev mapper device: " + devNodePath)
            raise OperationFailed("GGBDISK00001E", {'err': e.message})
    else:
        diskPath = devNodePath.rstrip('0123456789')

    device = PDevice(diskPath)
    try:
        extended_part = PDisk(device).getExtendedPartition()
    except NotImplementedError as e:
        wok_log.warning(
            "Error getting extended partition info for dev %s type %s: %s",
            devNodePath, devType, e.message)
        # Treate disk with unsupported partiton table as if it does not
        # contain extended partitions.
        return False
    if extended_part and extended_part.path == devNodePath:
        return True
    return False
Пример #5
0
        def parse_hdds(temperature_unit):
            # hddtemp will strangely convert a non-number (see error case
            #   below) to 32 deg F. So just always ask for C and convert later.
            out, error, rc = run_command(['hddtemp'])
            if rc:
                wok_log.error("Error retrieving HD temperatures: rc %s."
                              "output: %s" % (rc, error))
                return None

            hdds = OrderedDict()

            for hdd in out.splitlines():
                hdd_name = ''
                hdd_temp = 0.0
                try:
                    hdd_items = hdd.split(':')
                    hdd_name, hdd_temp = hdd_items[0], hdd_items[2]
                    hdd_temp = re.sub('°[C|F]', '', hdd_temp).strip()
                except Exception as e:
                    wok_log.error('Sensors hdd parse error: %s' % e.message)
                    continue
                try:
                    # Try to convert the number to a float. If it fails,
                    # don't add this disk to the list.
                    hdd_temp = float(hdd_temp)
                    if(temperature_unit == 'F'):
                        hdd_temp = 9.0/5.0 * hdd_temp + 32
                    hdds[hdd_name] = hdd_temp
                except ValueError:
                    # If no sensor data, parse float will fail. For example:
                    # "/dev/sda: IBM IPR-10 5D831200: S.M.A.R.T. not available"
                    wok_log.warning("Sensors hdd: %s" % hdd)
            hdds['unit'] = temperature_unit
            return hdds
Пример #6
0
    def get_list(self, storage_server, _target_type=None, _server_port=None):
        target_list = list()
        if not _target_type:
            target_types = STORAGE_SERVERS
        else:
            target_types = [_target_type]

        for target_type in target_types:
            if not self.caps.nfs_target_probe and target_type == 'netfs':
                targets = patch_find_nfs_target(storage_server)
            else:
                xml = self._get_storage_server_spec(
                    server=storage_server,
                    target_type=target_type,
                    server_port=_server_port,
                )
                conn = self.conn.get()
                try:
                    ret = conn.findStoragePoolSources(target_type, xml, 0)
                except libvirt.libvirtError as e:
                    wok_log.warning(
                        f'Query storage pool source fails because of '
                        f'{e.get_error_message()}'
                    )
                    continue

                targets = self._parse_target_source_result(target_type, ret)

            target_list.extend(targets)

        # Get all netfs and iscsi paths in use
        used_paths = []
        try:
            conn = self.conn.get()
            # Get all existing ISCSI and NFS pools
            pools = conn.listAllStoragePools(
                libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI |
                libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS
            )
            for pool in pools:
                pool_xml = pool.XMLDesc(0)
                root = objectify.fromstring(pool_xml)
                if root.get('type') == 'netfs' and root.source.dir is not None:
                    used_paths.append(root.source.dir.get('path'))
                elif root.get('type') == 'iscsi' and root.source.device is not None:
                    used_paths.append(root.source.device.get('path'))

        except libvirt.libvirtError as e:
            wok_log.warning(
                f'Query storage pool source fails because of {e.get_error_message()}'
            )

        # Filter target_list to not not show the used paths
        target_list = [
            elem for elem in target_list if elem.get('target') not in used_paths
        ]
        return [dict(t) for t in set(tuple(t.items()) for t in target_list)]
Пример #7
0
 def event_enospc_cb(self, conn, dom, path, dev, action, reason, args):
     if reason == "enospc":
         info = {
             "vm": dom.name(),
             "srcPath": path,
             "devAlias": dev,
         }
         add_notification("KCHEVENT0004W", info, '/plugins/kimchi')
         msg = WokMessage("KCHEVENT0004W", info, '/plugins/kimchi')
         wok_log.warning(msg.get_text())
Пример #8
0
    def get_list(self, storage_server, _target_type=None, _server_port=None):
        target_list = list()
        if not _target_type:
            target_types = STORAGE_SERVERS
        else:
            target_types = [_target_type]

        for target_type in target_types:
            if not self.caps.nfs_target_probe and target_type == 'netfs':
                targets = patch_find_nfs_target(storage_server)
            else:
                xml = self._get_storage_server_spec(server=storage_server,
                                                    target_type=target_type,
                                                    server_port=_server_port)
                conn = self.conn.get()
                try:
                    ret = conn.findStoragePoolSources(target_type, xml, 0)
                except libvirt.libvirtError as e:
                    err = "Query storage pool source fails because of %s"
                    wok_log.warning(err, e.get_error_message())
                    continue

                targets = self._parse_target_source_result(target_type, ret)

            target_list.extend(targets)

        # Get all netfs and iscsi paths in use
        used_paths = []
        try:
            conn = self.conn.get()
            # Get all existing ISCSI and NFS pools
            pools = conn.listAllStoragePools(
                libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_ISCSI |
                libvirt.VIR_CONNECT_LIST_STORAGE_POOLS_NETFS)
            for pool in pools:
                pool_xml = pool.XMLDesc(0)
                root = objectify.fromstring(pool_xml)
                if root.get('type') == 'netfs' and \
                        root.source.dir is not None:
                    used_paths.append(root.source.dir.get('path'))
                elif root.get('type') == 'iscsi' and \
                        root.source.device is not None:
                    used_paths.append(root.source.device.get('path'))

        except libvirt.libvirtError as e:
            err = "Query storage pool source fails because of %s"
            wok_log.warning(err, e.get_error_message())

        # Filter target_list to not not show the used paths
        target_list = [elem for elem in target_list
                       if elem.get('target') not in used_paths]
        return [dict(t) for t in set(tuple(t.items()) for t in target_list)]
Пример #9
0
def probe_img_info(path):
    cmd = ["qemu-img", "info", "--output=json", path]
    info = dict()
    try:
        out = run_command(cmd, 10)[0]
    except TimeoutExpired:
        wok_log.warning("Cannot decide format of base img %s", path)
        return None

    info = json.loads(out)
    info['virtual-size'] = info['virtual-size'] >> 30
    info['actual-size'] = info['actual-size'] >> 30
    return info
Пример #10
0
    def _validate_pci_passthrough_env():
        # Linux kernel < 3.5 doesn't provide /sys/kernel/iommu_groups
        if os.path.isdir('/sys/kernel/iommu_groups'):
            if not glob.glob('/sys/kernel/iommu_groups/*'):
                raise InvalidOperation("KCHVMHDEV0003E")

        # Enable virt_use_sysfs on RHEL6 and older distributions
        # In recent Fedora, there is no virt_use_sysfs.
        out, err, rc = run_command(['getsebool', 'virt_use_sysfs'],
                                   silent=True)
        if rc == 0 and out.rstrip('\n') != "virt_use_sysfs --> on":
            out, err, rc = run_command(['setsebool', '-P',
                                        'virt_use_sysfs=on'])
            if rc != 0:
                wok_log.warning("Unable to turn on sebool virt_use_sysfs")
Пример #11
0
    def _validate_pci_passthrough_env():
        # Linux kernel < 3.5 doesn't provide /sys/kernel/iommu_groups
        if os.path.isdir('/sys/kernel/iommu_groups'):
            if not glob.glob('/sys/kernel/iommu_groups/*'):
                raise InvalidOperation('KCHVMHDEV0003E')

        # Enable virt_use_sysfs on RHEL6 and older distributions
        # In recent Fedora, there is no virt_use_sysfs.
        out, err, rc = run_command(
            ['getsebool', 'virt_use_sysfs'], silent=True)
        if rc == 0 and out.rstrip('\n') != 'virt_use_sysfs --> on':
            out, err, rc = run_command(
                ['setsebool', '-P', 'virt_use_sysfs=on'])
            if rc != 0:
                wok_log.warning('Unable to turn on sebool virt_use_sysfs')
Пример #12
0
def _is_dev_extended_partition(devType, devNodePath):
    if devType != "part":
        return False
    diskPath = devNodePath.rstrip("0123456789")
    device = PDevice(diskPath)
    try:
        extended_part = PDisk(device).getExtendedPartition()
    except NotImplementedError as e:
        wok_log.warning("Error getting extended partition info for dev %s type %s: %s", devNodePath, devType, e.message)
        # Treate disk with unsupported partiton table as if it does not
        # contain extended partitions.
        return False
    if extended_part and extended_part.path == devNodePath:
        return True
    return False
Пример #13
0
def _is_dev_extended_partition(devType, devNodePath):
    if devType != 'part':
        return False
    diskPath = devNodePath.rstrip('0123456789')
    device = PDevice(diskPath)
    try:
        extended_part = PDisk(device).getExtendedPartition()
    except NotImplementedError as e:
        wok_log.warning(
            "Error getting extended partition info for dev %s type %s: %s",
            devNodePath, devType, e.message)
        # Treate disk with unsupported partiton table as if it does not
        # contain extended partitions.
        return False
    if extended_part and extended_part.path == devNodePath:
        return True
    return False
Пример #14
0
        def parse_hdds(temperature_unit):
            # hddtemp will strangely convert a non-number (see error case
            #   below) to 32 deg F. So just always ask for C and convert later.
            out, error, rc = run_command(['hddtemp'])
            if rc:
                wok_log.error("Error retrieving HD temperatures: rc %s."
                              "output: %s" % (rc, error))
                return None

            hdds = OrderedDict()

            for hdd in out.splitlines():
                # This error message occurs when the HDD does not
                # have S.M.A.R.T (Self-Monitoring, Analysis, and
                # Reporting Technology) available. Skip the hdd line
                # in this case.
                if 'S.M.A.R.T. not available' in hdd:
                    continue

                hdd_name = ''
                hdd_temp = 0.0
                try:
                    hdd_items = hdd.split(':')
                    hdd_name, hdd_temp = hdd_items[0], hdd_items[2]
                    hdd_temp = re.sub('°[C|F]', '', hdd_temp).strip()
                except Exception as e:
                    wok_log.error('Sensors hdd parse error: %s' % e.message)
                    continue
                try:
                    # Try to convert the number to a float. If it fails,
                    # don't add this disk to the list.
                    hdd_temp = float(hdd_temp)
                    if(temperature_unit == 'F'):
                        hdd_temp = 9.0/5.0 * hdd_temp + 32
                    hdds[hdd_name] = hdd_temp
                except ValueError:
                    # If no sensor data, parse float will fail.
                    wok_log.warning("Sensors hdd: %s" % hdd)
            hdds['unit'] = temperature_unit
            return hdds
Пример #15
0
        def parse_hdds(temperature_unit):
            # hddtemp will strangely convert a non-number (see error case
            #   below) to 32 deg F. So just always ask for C and convert later.
            out, error, rc = run_command(['hddtemp'])
            if rc:
                wok_log.error("Error retrieving HD temperatures: rc %s."
                              "output: %s" % (rc, error))
                return None

            hdds = OrderedDict()

            for hdd in out.splitlines():
                # This error message occurs when the HDD does not
                # have S.M.A.R.T (Self-Monitoring, Analysis, and
                # Reporting Technology) available. Skip the hdd line
                # in this case.
                if 'S.M.A.R.T. not available' in hdd:
                    continue

                hdd_name = ''
                hdd_temp = 0.0
                try:
                    hdd_items = hdd.split(':')
                    hdd_name, hdd_temp = hdd_items[0], hdd_items[2]
                    hdd_temp = re.sub('°[C|F]', '', hdd_temp).strip()
                except Exception as e:
                    wok_log.error('Sensors hdd parse error: %s' % e.message)
                    continue
                try:
                    # Try to convert the number to a float. If it fails,
                    # don't add this disk to the list.
                    hdd_temp = float(hdd_temp)
                    if(temperature_unit == 'F'):
                        hdd_temp = 9.0/5.0 * hdd_temp + 32
                    hdds[hdd_name] = hdd_temp
                except ValueError:
                    # If no sensor data, parse float will fail.
                    wok_log.warning("Sensors hdd: %s" % hdd)
            hdds['unit'] = temperature_unit
            return hdds
Пример #16
0
 def event_enospc_cb(self, conn, dom, path, dev, action, reason, args):
     if reason == 'enospc':
         info = {'vm': dom.name(), 'srcPath': path, 'devAlias': dev}
         add_notification('KCHEVENT0004W', info, '/plugins/kimchi')
         msg = WokMessage('KCHEVENT0004W', info, '/plugins/kimchi')
         wok_log.warning(msg.get_text())
Пример #17
0
 def kernel_support_vfio():
     out, err, rc = run_command(['modprobe', 'vfio-pci'])
     if rc != 0:
         wok_log.warning("Unable to load Kernal module vfio-pci.")
         return False
     return True
Пример #18
0
def _get_tmpl_defaults():
    """
    ConfigObj returns a dict like below when no changes were made in the
    template configuration file (template.conf)

    {'main': {}, 'memory': {}, 'storage': {'disk.0': {}}, 'processor': {},
     'graphics': {}}

    The default values should be like below:

    {'main': {'networks': ['default']},
     'memory': {'current': 1024, 'maxmemory': 1024},
     'storage': { 'disk.0': {'format': 'qcow2', 'size': '10',
                             'pool': '/plugins/kimchi/storagepools/default'}},
     'processor': {'vcpus': '1',  'maxvcpus': 1},
     'graphics': {'type': 'spice', 'listen': '127.0.0.1'}}

    The default values on s390x architecture:

    {'memory': {'current': 1024, 'maxmemory': 1024},
     'storage': { 'disk.0': {'format': 'qcow2', 'size': '10',
                             'pool': '/plugins/kimchi/storagepools/default'}},
     'processor': {'vcpus': '1',  'maxvcpus': 1},
     'graphics': {'type': 'spice', 'listen': '127.0.0.1'}}
    """
    # Create dict with default values
    tmpl_defaults = defaultdict(dict)

    host_arch = _get_arch()
    tmpl_defaults['main']['networks'] = ['default']
    if host_arch in ['s390x', 's390']:
        tmpl_defaults['main']['networks'] = []

    tmpl_defaults['memory'] = {
        'current': _get_default_template_mem(),
        'maxmemory': _get_default_template_mem(),
    }
    tmpl_defaults['storage']['disk.0'] = {
        'size': 10,
        'format': 'qcow2',
        'pool': 'default',
    }
    is_on_s390x = True if _get_arch() == 's390x' else False

    if is_on_s390x:
        tmpl_defaults['storage']['disk.0']['path'] = '/var/lib/libvirt/images/'
        del tmpl_defaults['storage']['disk.0']['pool']

    tmpl_defaults['processor']['vcpus'] = 1
    tmpl_defaults['processor']['maxvcpus'] = 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(kimchiPaths.sysconf_dir, 'template.conf')
    config = ConfigObj(config_file)

    # File configuration takes preference.
    # In s390x, file configuration can have storage pool or path.
    # Default configuration for s390x is storage path.
    # In case file conf has storage pool then storage pool takes preference.
    # When conf file has explicitly storage pool: "defaults" should
    # have storage pool and default configured path should be removed,
    # as either storage can be path or pool, cannot be both.
    # When conf file does not explicity storage pool or have explicitly
    # storage path: "default" should have storage path only and cannot
    # have default pool.
    #
    # Check file conf has storage configured.
    if is_on_s390x and config.get('storage').get('disk.0'):
        # remove storage from default_config as file configuration takes
        # preference.
        default_config.pop('storage')

        # Get storage configuration present in conf file
        config_pool = config.get('storage').get('disk.0').get('pool')
        config_path = config.get('storage').get('disk.0').get('path')

        # If storage configured in conf file then it should have either
        # pool or path.
        if not config_pool and not config_path:
            raise InvalidParameter('KCHTMPL0040E')

        # On s390x if config file has both path and pool uncommented
        # then path should take preference.
        if config_pool and config_path:
            wok_log.warning('Both default pool and path are specified in' +
                            ' template.conf. Hence default pool is being' +
                            ' ignored and only default path will be used')
            config.get('storage').get('disk.0').pop('pool')

    # 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
    defaults.update(default_config.pop('main'))
    defaults['memory'] = default_config.pop('memory')

    defaults['memory']['current'] = int(defaults['memory']['current'])
    defaults['memory']['maxmemory'] = int(defaults['memory']['maxmemory'])

    # for s390x architecture, set default console as virtio
    if is_on_s390x:
        defaults['console'] = 'virtio'

    # Parse storage section to get disks values
    storage_section = default_config.pop('storage')
    defaults['disks'] = []

    for index, disk in enumerate(storage_section.keys()):
        data = storage_section[disk]
        data['index'] = int(disk.split('.')[1])
        # Right now 'Path' is only supported on s390x
        if storage_section[disk].get('path') and is_on_s390x:
            data['path'] = storage_section[disk].pop('path')
            if 'size' not in storage_section[disk]:
                data['size'] = tmpl_defaults['storage']['disk.0']['size']
            else:
                data['size'] = storage_section[disk].pop('size')

            if 'format' not in storage_section[disk]:
                data['format'] = tmpl_defaults['storage']['disk.0']['format']
            else:
                data['format'] = storage_section[disk].pop('format')
        else:
            data['pool'] = {
                'name':
                '/plugins/kimchi/storagepools/' +
                storage_section[disk].pop('pool')
            }

        defaults['disks'].append(data)

    # Parse processor section to get vcpus and cpu_topology values
    processor_section = default_config.pop('processor')
    defaults['cpu_info'] = {
        'vcpus': processor_section.pop('vcpus'),
        'maxvcpus': processor_section.pop('maxvcpus'),
    }
    if len(processor_section.keys()) > 0:
        defaults['cpu_info']['topology'] = processor_section

    # Update defaults values with graphics values
    defaults['graphics'] = default_config.pop('graphics')

    # Setting default memory device slots
    defaults['mem_dev_slots'] = MEM_DEV_SLOTS.get(os.uname()[4], 256)

    return defaults
Пример #19
0
 def log_error(e):
     wok_log = logging.getLogger('Model')
     wok_log.warning('Exception in generating debug file: %s', e)
Пример #20
0
 def event_enospc_cb(self, conn, dom, path, dev, action, reason, args):
     if reason == 'enospc':
         info = {'vm': dom.name(), 'srcPath': path, 'devAlias': dev}
         add_notification('KCHEVENT0004W', info, '/plugins/kimchi')
         msg = WokMessage('KCHEVENT0004W', info, '/plugins/kimchi')
         wok_log.warning(msg.get_text())
Пример #21
0
 def log_error(e):
     wok_log = logging.getLogger('Model')
     wok_log.warning('Exception in generating debug file: %s', e)
Пример #22
0
 def kernel_support_vfio():
     out, err, rc = run_command(['modprobe', 'vfio-pci'])
     if rc != 0:
         wok_log.warning('Unable to load Kernal module vfio-pci.')
         return False
     return True
Пример #23
0
 def log_error(e):
     wok_log = logging.getLogger("Model")
     wok_log.warning("Exception in generating debug file: %s", e)
Пример #24
0
def _get_tmpl_defaults():
    """
    ConfigObj returns a dict like below when no changes were made in the
    template configuration file (template.conf)

    {'main': {}, 'memory': {}, 'storage': {'disk.0': {}}, 'processor': {},
     'graphics': {}}

    The default values should be like below:

    {'main': {'networks': ['default']},
     'memory': {'current': 1024, 'maxmemory': 1024},
     'storage': { 'disk.0': {'format': 'qcow2', 'size': '10',
                             'pool': '/plugins/kimchi/storagepools/default'}},
     'processor': {'vcpus': '1',  'maxvcpus': 1},
     'graphics': {'type': 'spice', 'listen': '127.0.0.1'}}

    The default values on s390x architecture:

    {'memory': {'current': 1024, 'maxmemory': 1024},
     'storage': { 'disk.0': {'format': 'qcow2', 'size': '10',
                             'pool': '/plugins/kimchi/storagepools/default'}},
     'processor': {'vcpus': '1',  'maxvcpus': 1},
     'graphics': {'type': 'spice', 'listen': '127.0.0.1'}}
    """
    # Create dict with default values
    tmpl_defaults = defaultdict(dict)

    host_arch = _get_arch()
    tmpl_defaults['main']['networks'] = ['default']
    if host_arch in ['s390x', 's390']:
        tmpl_defaults['main']['networks'] = []

    tmpl_defaults['memory'] = {'current': _get_default_template_mem(),
                               'maxmemory': _get_default_template_mem()}
    tmpl_defaults['storage']['disk.0'] = {'size': 10, 'format': 'qcow2',
                                          'pool': 'default'}
    is_on_s390x = True if _get_arch() == 's390x' else False

    if is_on_s390x:
        tmpl_defaults['storage']['disk.0']['path'] = '/var/lib/libvirt/images/'
        del tmpl_defaults['storage']['disk.0']['pool']

    tmpl_defaults['processor']['vcpus'] = 1
    tmpl_defaults['processor']['maxvcpus'] = 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(kimchiPaths.sysconf_dir, 'template.conf')
    config = ConfigObj(config_file)

    # File configuration takes preference.
    # In s390x, file configuration can have storage pool or path.
    # Default configuration for s390x is storage path.
    # In case file conf has storage pool then storage pool takes preference.
    # When conf file has explicitly storage pool: "defaults" should
    # have storage pool and default configured path should be removed,
    # as either storage can be path or pool, cannot be both.
    # When conf file does not explicity storage pool or have explicitly
    # storage path: "default" should have storage path only and cannot
    # have default pool.
    #
    # Check file conf has storage configured.
    if is_on_s390x and config.get('storage').get('disk.0'):
        # remove storage from default_config as file configuration takes
        # preference.
        default_config.pop('storage')

        # Get storage configuration present in conf file
        config_pool = config.get('storage').get('disk.0').get('pool')
        config_path = config.get('storage').get('disk.0').get('path')

        # If storage configured in conf file then it should have either
        # pool or path.
        if not config_pool and not config_path:
            raise InvalidParameter('KCHTMPL0040E')

        # On s390x if config file has both path and pool uncommented
        # then path should take preference.
        if config_pool and config_path:
            wok_log.warning("Both default pool and path are specified in" +
                            " template.conf. Hence default pool is being" +
                            " ignored and only default path will be used")
            config.get('storage').get('disk.0').pop('pool')

    # 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
    defaults.update(default_config.pop('main'))
    defaults['memory'] = default_config.pop('memory')

    defaults['memory']['current'] = int(defaults['memory']['current'])
    defaults['memory']['maxmemory'] = int(defaults['memory']['maxmemory'])

    # for s390x architecture, set default console as virtio
    if is_on_s390x:
        defaults['console'] = 'virtio'

    # Parse storage section to get disks values
    storage_section = default_config.pop('storage')
    defaults['disks'] = []

    for index, disk in enumerate(storage_section.keys()):
        data = storage_section[disk]
        data['index'] = int(disk.split('.')[1])
        # Right now 'Path' is only supported on s390x
        if storage_section[disk].get('path') and is_on_s390x:
            data['path'] = storage_section[disk].pop('path')
            if 'size' not in storage_section[disk]:
                data['size'] = tmpl_defaults['storage']['disk.0']['size']
            else:
                data['size'] = storage_section[disk].pop('size')

            if 'format' not in storage_section[disk]:
                data['format'] = tmpl_defaults['storage']['disk.0']['format']
            else:
                data['format'] = storage_section[disk].pop('format')
        else:
            data['pool'] = {"name": '/plugins/kimchi/storagepools/' +
                                    storage_section[disk].pop('pool')}

        defaults['disks'].append(data)

    # Parse processor section to get vcpus and cpu_topology values
    processor_section = default_config.pop('processor')
    defaults['cpu_info'] = {'vcpus': processor_section.pop('vcpus'),
                            'maxvcpus': processor_section.pop('maxvcpus')}
    if len(processor_section.keys()) > 0:
        defaults['cpu_info']['topology'] = processor_section

    # Update defaults values with graphics values
    defaults['graphics'] = default_config.pop('graphics')

    # Setting default memory device slots
    defaults['mem_dev_slots'] = MEM_DEV_SLOTS.get(os.uname()[4], 256)

    return defaults