Repository: ansible-collections/community.general

Issue:
proxmox lxc - add features (nesting, nfs, cifs...)
##### SUMMARY
Proxmox VE offers some special features for LXC containers. Please add these features to this module. These are:
- Nesting
- NFS
- CIFS
- FUSE
- Create Device Nodes

GUI Screenshot
![image](https://user-images.githubusercontent.com/38238648/90955545-9c72c180-e47e-11ea-8fee-23aa2f54665e.png)

Usage from command line:
pct create ... --features nesting=1 ...

Thank you

##### ISSUE TYPE
- Feature Idea

##### COMPONENT NAME
https://github.com/ansible-collections/community.general/blob/main/plugins/modules/cloud/misc/proxmox.py









Discussion:
Files identified in the description:
* [`plugins/modules/cloud/misc/proxmox.py`](https://github.com/ansible-collections/community.general/blob/master/plugins/modules/cloud/misc/proxmox.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @UnderGreen @joshainglis @karmab
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
I have a draft change thrown together in a forked branch. This has not been tested, but I'd like feedback on the the draft API.

https://github.com/jamesharr/community.general/tree/816-proxmox-features

Features can be turned on:
* `features: nesting=1` - turn on nesting
* `features: fuse=1` - turn on fuse
* `features: fuse=1,mknod=1,mount=nfs;cifs,nesting=1` - turn on everything

cc @Aversiste
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
So that it doesn't get missed, whoever wants to work on it, consider that `nfs` and `cifs` work only in privileged containers.
![image](https://user-images.githubusercontent.com/12948692/98820043-e4343400-2442-11eb-9477-177c425f16bf.png)

> Features can be turned on:
 
     * `features: nesting=1` - turn on nesting
 
     * `features: fuse=1` - turn on fuse
 
     * `features: fuse=1,mknod=1,mount=nfs;cifs,nesting=1` - turn on everything

@jamesharr Is there a option in another ansible module which its structure is like this? EDIT: `mounts` and `netif` in this module are `dict` type, but it seems a little weird to me for features.

I think `nesting`, `fuse`, `nfs` options would be more clear, but let's hear it out from maintainers.
Re: privileged containers.
Thanks that's worth noting in the docs


Re: passing in options this way.

This is somewhat akin to how networking is configured where the option list is passed to proxmox in raw form. With proxmox handling most of the error checking and validation. It's basically a raw value passed to proxmox


From a user experience perspective, you're right it's probably less than ideal. I'd personally like to see each as it's own option versus passing a raw option into proxmox.

The trade off is that as proxmox adds new feature options, passing in raw options means that the ansible module doesn't need to be modified, so there's no catch up game. Ansible users just add in the options they care about.

And if I'm being honest, I don't plan to maintain this ansible module myself in an ongoing capacity, I'm just adding something I'd like to have. I don't want to create more work for maintainers.
> Re: privileged containers.
> Thanks that's worth noting in the docs

Actually I was thinking if the module could check that as well, but it may be a feature idea later.
> 
> Re: passing in options this way.
> 
> This is somewhat akin to how networking is configured where the option list is passed to proxmox in raw form. With proxmox handling most of the error checking and validation. It's basically a raw value passed to proxmox
> 
> From a user experience perspective, you're right it's probably less than ideal. I'd personally like to see each as it's own option versus passing a raw option into proxmox.
> 
> The trade off is that as proxmox adds new feature options, passing in raw options means that the ansible module doesn't need to be modified, so there's no catch up game. Ansible users just add in the options they care about.
> 

You're right, but if the module just passes everything user has been said it may lead to problems which debugging it may not be easy, however it can be just passing as it is for now and checking the variables would be a feature idea too. I haven't ever used these features of containers in Proxmox, but I don't think they would change a lot.
> And if I'm being honest, I don't plan to maintain this ansible module myself in an ongoing capacity, I'm just adding something I'd like to have. I don't want to create more work for maintainers.

Overally I agree. For now passing the raw data to proxmox may be fine, but it can improve later.
> I think nesting, fuse, nfs options would be more clear, but let's hear it out from maintainers.

For me it is less confusing if all array-like variables are treated the same way.
> I have a draft change thrown together in a forked branch. This has not been tested, but I'd like feedback on the the draft API.
> 
> https://github.com/jamesharr/community.general/tree/816-proxmox-features
> 
> Features can be turned on:
> 
>     * `features: nesting=1` - turn on nesting
> 
>     * `features: fuse=1` - turn on fuse
> 
>     * `features: fuse=1,mknod=1,mount=nfs;cifs,nesting=1` - turn on everything

@jamesharr Would you want to create a PR regarding this issue?
The Implementation of this feature is buggy / not very well tested!

It forces under Ansible 2.10 the user to switch to root@pam, without 2FA, because only this User is allowed to create LCX with Features. 
Under no under circumstances your are able to use the proxmox modul to create new container!

The problem:  the invocation with an empty features variable

This forces pct to create the container with an empty feature. But creating a container with feature flag is only allowed for root@pam. This is good, because it could be a mayor security issue, if non root Users can do this. PROXMOX Team takes care to only allow this to root@pam

[pve001] => (item={'host': 'mail', 'domain': 'mail.xxx', 'external_ip': 'xx.xx.xx.xx', 'net': {'net0': 'name=eth0,ip=192.168.xx.xxx/24,ip6=slac,bridge=vmbr1,gw=xx.xx.xx.xx'}, 'description': 'PVE Mail Gateway aka PMG', 'template': 'cifsxxx:vztmpl/proxmox-mailgateway-6.3-standard_6.3-1_amd64.tar.gz', 'pool': 'infrastructure', 'cores': '2', 'ram': '4096', 'disk': '8'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "api_host": "pve001xxx",
            "api_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "api_token_id": null,
            "api_token_secret": null,
            "api_user": "root@pam",
            "cores": 2,
            "cpus": 1,
            "cpuunits": 1000,
            "description": "PVE Mail Gateway aka PMG",
            "disk": "8",
            **"features": null,**
            "force": false,
            "hookscript": null,
            "hostname": "mail",
            "ip_address": null,
            "memory": 4096,
            "mounts": null,
            "nameserver": "192.168.xx.xx",
            "netif": {
                "net0": "eth0,ip=192.168.xx.xxx/24,ip6=slac,bridge=vmbr1,gw=xx.xx.xx.xx'"
            },
            "node": "pve001",
            "onboot": true,
            "ostemplate": "cifsxx:vztmpl/proxmox-mailgateway-6.3-standard_6.3-1_amd64.tar.gz",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "pool": "infrastructure",
            "proxmox_default_behavior": "compatibility",
            "pubkey": "xxxxx",
            "searchdomain": "xxx.xxx",
            "state": "present",
            "storage": "local-zfs",
            "swap": 0,
            "timeout": 90,
            "unprivileged": true,
            "validate_certs": false,
            "vmid": null
        }

The solution: only invocate modul with feature variable, when variable is set

this recovers the modul usage as NON Root User or via Token API
@topperharly I guess that can be fixed by replacing `features=",".join(module.params['features'] or []),` by `features=",".join(module.params['features']) if module.params['features'] is not None else None,`.

Someone wants to create a PR for that?
wow... fast response.. i´m currently creating a bug issue and collection all informations. Is still necessary?
I think it's ok if you just create a PR to fix it. Please add a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#changelogs-how-to).
i´ve tested it, it works as expected ;)

also creation with non root@pam works and fails as expected. I´ve updated also the documentation

    "msg": "creation of lxc VM 104 failed with exception: 403 Forbidden: Permission check failed (changing feature flags is only allowed for root@pam) - b'{\"data\":null}'"

Resolving patch:
diff --git a/plugins/modules/cloud/misc/proxmox.py b/plugins/modules/cloud/misc/proxmox.py
--- a/plugins/modules/cloud/misc/proxmox.py
+++ b/plugins/modules/cloud/misc/proxmox.py
@@ -622,7 +622,7 @@ def main():
                             searchdomain=module.params['searchdomain'],
                             force=int(module.params['force']),
                             pubkey=module.params['pubkey'],
-                            features=",".join(module.params['features'] or []),
+                            features=",".join(module.params['features']) if module.params['features'] is not None else None,
                             unprivileged=int(module.params['unprivileged']),
                             description=module.params['description'],
                             hookscript=module.params['hookscript'])


Test patch: