Edit LXC configuration options

    path
        path to the container parent
        default: /var/lib/lxc (system default)

        .. versionadded:: 2015.8.0

    CLI Example:

    .. code-block:: bash

        salt myminion lxc.update_lxc_conf ubuntu \\
                lxc_conf="[{'network.ipv4.ip':'10.0.3.5'}]" \\
                lxc_conf_unset="['lxc.utsname']"

def update_lxc_conf(name, lxc_conf, lxc_conf_unset, path=None):
    '''
    Edit LXC configuration options

    path
        path to the container parent
        default: /var/lib/lxc (system default)

        .. versionadded:: 2015.8.0

    CLI Example:

    .. code-block:: bash

        salt myminion lxc.update_lxc_conf ubuntu \\
                lxc_conf="[{'network.ipv4.ip':'10.0.3.5'}]" \\
                lxc_conf_unset="['lxc.utsname']"

    '''
    _ensure_exists(name, path=path)
    cpath = get_root_path(path)
    lxc_conf_p = os.path.join(cpath, name, 'config')
    if not os.path.exists(lxc_conf_p):
        raise SaltInvocationError(
            'Configuration file {0} does not exist'.format(lxc_conf_p)
        )

    changes = {'edited': [], 'added': [], 'removed': []}
    ret = {'changes': changes, 'result': True, 'comment': ''}

    # do not use salt.utils.files.fopen !
    with salt.utils.files.fopen(lxc_conf_p, 'r') as fic:
        filtered_lxc_conf = []
        for row in lxc_conf:
            if not row:
                continue
            for conf in row:
                filtered_lxc_conf.append((conf.strip(),
                                          row[conf].strip()))
        ret['comment'] = 'lxc.conf is up to date'
        lines = []
        orig_config = salt.utils.stringutils.to_unicode(fic.read())
        for line in orig_config.splitlines():
            if line.startswith('#') or not line.strip():
                lines.append([line, ''])
            else:
                line = line.split('=')
                index = line.pop(0)
                val = (index.strip(), '='.join(line).strip())
                if val not in lines:
                    lines.append(val)
        for key, item in filtered_lxc_conf:
            matched = False
            for idx, line in enumerate(lines[:]):
                if line[0] == key:
                    matched = True
                    lines[idx] = (key, item)
                    if '='.join(line[1:]).strip() != item.strip():
                        changes['edited'].append(
                            ({line[0]: line[1:]}, {key: item}))
                        break
            if not matched:
                if (key, item) not in lines:
                    lines.append((key, item))
                changes['added'].append({key: item})
        dest_lxc_conf = []
        # filter unset
        if lxc_conf_unset:
            for line in lines:
                for opt in lxc_conf_unset:
                    if (
                        not line[0].startswith(opt) and
                        line not in dest_lxc_conf
                    ):
                        dest_lxc_conf.append(line)
                    else:
                        changes['removed'].append(opt)
        else:
            dest_lxc_conf = lines
        conf = ''
        for key, val in dest_lxc_conf:
            if not val:
                conf += '{0}\n'.format(key)
            else:
                conf += '{0} = {1}\n'.format(key.strip(), val.strip())
        conf_changed = conf != orig_config
        chrono = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
        if conf_changed:
            # DO NOT USE salt.utils.files.fopen here, i got (kiorky)
            # problems with lxc configs which were wiped !
            with salt.utils.files.fopen('{0}.{1}'.format(lxc_conf_p, chrono), 'w') as wfic:
                wfic.write(salt.utils.stringutils.to_str(conf))
            with salt.utils.files.fopen(lxc_conf_p, 'w') as wfic:
                wfic.write(salt.utils.stringutils.to_str(conf))
            ret['comment'] = 'Updated'
            ret['result'] = True

    if not any(changes[x] for x in changes):
        # Ensure an empty changes dict if nothing was modified
        ret['changes'] = {}
    return ret