Repository: ansible/ansible

Issue:
Add public key support to proxmox module
_From @DavidVentura on September 11, 2016 23:28_

Since proxmox 4.2 it's possible to create containers with a pre-defined public key to allow ssh access as root.
##### ISSUE TYPE
- Feature Idea
##### COMPONENT NAME

proxmox
##### ANSIBLE VERSION

```
ansible 2.1.0.0

```

I can currently create containers with

<!--- Paste example playbooks or commands between quotes below -->

```
proxmox: vmid=$CT_NUMBER node='$NODE' api_user='david@pam' api_password='redacted' api_host='$API_HOST' password='$CT_PASS' hostname='$HOSTNAME' storage='redacted' ostemplate='especificos:vztmpl/debian-8.0-standard_8.4-1_amd64.tar.gz'
```

It'd be lovely to avoid having to manually attach to the new containers to add the pubkey before continuing with the process.


_Copied from original issue: ansible/ansible-modules-extras#2897_
Add public key support to proxmox module
_From @DavidVentura on September 11, 2016 23:28_

Since proxmox 4.2 it's possible to create containers with a pre-defined public key to allow ssh access as root.
##### ISSUE TYPE
- Feature Idea
##### COMPONENT NAME

proxmox
##### ANSIBLE VERSION

```
ansible 2.1.0.0

```

I can currently create containers with

<!--- Paste example playbooks or commands between quotes below -->

```
proxmox: vmid=$CT_NUMBER node='$NODE' api_user='david@pam' api_password='redacted' api_host='$API_HOST' password='$CT_PASS' hostname='$HOSTNAME' storage='redacted' ostemplate='especificos:vztmpl/debian-8.0-standard_8.4-1_amd64.tar.gz'
```

It'd be lovely to avoid having to manually attach to the new containers to add the pubkey before continuing with the process.


_Copied from original issue: ansible/ansible-modules-extras#2897_


Discussion:
_From @ansibot on September 13, 2016 2:45_

<!-- @DavidVentura: Thanks for filing this feature idea! -->

@UnderGreen ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

To clarify support for public key is a matter to send in the JSON structure a key `ssh-public-keys` and the content of the public key as value.

I patched the file promox.py this way

```
@@ -305,6 +305,7 @@ def main():
       nameserver = dict(),
       searchdomain = dict(),
       timeout = dict(type='int', default=30),
+      ssh_public_keys = dict(),
       force = dict(type='bool', default='no'),
       state = dict(default='present', choices=['present', 'absent', 'stopped', 'started', 'restarted']),
     )
@@ -355,6 +356,7 @@ def main():
                          % (module.params['ostemplate'], node, storage))

       create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout,
+                      ssh-public-keys = module.params['ssh_public_keys'],
                       password = module.params['password'],
                       hostname = module.params['hostname'],
                       ostemplate = module.params['ostemplate'],
```

So this is rather simple but I ended with an error I can't understand

```
 An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 124, in run
    res = self._execute()
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 448, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/normal.py", line 33, in run
    results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars))
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/__init__.py", line 583, in _execute_module
    (module_style, shebang, module_data) = self._configure_module(module_name=module_name, module_args=module_args, task_vars=task_vars)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/__init__.py", line 149, in _configure_module
    (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, task_vars=task_vars, module_compression=self._play_context.module_compression)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 733, in modify_module
    (module_data, module_style, shebang) = _find_snippet_imports(module_name, module_data, module_path, module_args, task_vars, module_compression)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 591, in _find_snippet_imports
    recursive_finder(module_name, module_data, py_module_names, py_module_cache, zf)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 412, in recursive_finder
    tree = ast.parse(data)
  File "/usr/lib64/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 359
SyntaxError: keyword can't be an expression

fatal: [localhost]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}
```

If I rename the hash key `ssh-public-keys` to `ssh_public_keys` the syntax error disappears (but the Proxmox API return an error because the key is unknown), so I wondered If there was a limitation in the key naming (like not supporting hyphen) either in Proxmoxer or in the proxmox module.

_From @ansibot on October 6, 2016 17:50_

@UnderGreen, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

_From @ansibot on December 7, 2016 14:7_

This repository has been locked. All new issues and pull requests should be filed in https://github.com/ansible/ansible

Please read through the <a href="http://docs.ansible.com/ansible/dev_guide/repomerge.html#move-issues-and-prs-to-new-repo">repomerge</a> page in the dev guide. The guide contains links to tools which automatically move your issue or pull request to the ansible/ansible repo.

<!-- boilerplate: repomerge -->
_From @ansibot on September 13, 2016 2:45_

<!-- @DavidVentura: Thanks for filing this feature idea! -->

@UnderGreen ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

To clarify support for public key is a matter to send in the JSON structure a key `ssh-public-keys` and the content of the public key as value.

I patched the file promox.py this way

```
@@ -305,6 +305,7 @@ def main():
       nameserver = dict(),
       searchdomain = dict(),
       timeout = dict(type='int', default=30),
+      ssh_public_keys = dict(),
       force = dict(type='bool', default='no'),
       state = dict(default='present', choices=['present', 'absent', 'stopped', 'started', 'restarted']),
     )
@@ -355,6 +356,7 @@ def main():
                          % (module.params['ostemplate'], node, storage))

       create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout,
+                      ssh-public-keys = module.params['ssh_public_keys'],
                       password = module.params['password'],
                       hostname = module.params['hostname'],
                       ostemplate = module.params['ostemplate'],
```

So this is rather simple but I ended with an error I can't understand

```
 An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 124, in run
    res = self._execute()
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 448, in _execute
    result = self._handler.run(task_vars=variables)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/normal.py", line 33, in run
    results = merge_hash(results, self._execute_module(tmp=tmp, task_vars=task_vars))
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/__init__.py", line 583, in _execute_module
    (module_style, shebang, module_data) = self._configure_module(module_name=module_name, module_args=module_args, task_vars=task_vars)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/plugins/action/__init__.py", line 149, in _configure_module
    (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, task_vars=task_vars, module_compression=self._play_context.module_compression)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 733, in modify_module
    (module_data, module_style, shebang) = _find_snippet_imports(module_name, module_data, module_path, module_args, task_vars, module_compression)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 591, in _find_snippet_imports
    recursive_finder(module_name, module_data, py_module_names, py_module_cache, zf)
  File "/home/baptistemm/Code/ansible-venv/lib/python2.7/site-packages/ansible/executor/module_common.py", line 412, in recursive_finder
    tree = ast.parse(data)
  File "/usr/lib64/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 359
SyntaxError: keyword can't be an expression

fatal: [localhost]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}
```

If I rename the hash key `ssh-public-keys` to `ssh_public_keys` the syntax error disappears (but the Proxmox API return an error because the key is unknown), so I wondered If there was a limitation in the key naming (like not supporting hyphen) either in Proxmoxer or in the proxmox module.

_From @ansibot on October 6, 2016 17:50_

@UnderGreen, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

_From @ansibot on December 7, 2016 14:7_

This repository has been locked. All new issues and pull requests should be filed in https://github.com/ansible/ansible

Please read through the <a href="http://docs.ansible.com/ansible/dev_guide/repomerge.html#move-issues-and-prs-to-new-repo">repomerge</a> page in the dev guide. The guide contains links to tools which automatically move your issue or pull request to the ansible/ansible repo.

<!-- boilerplate: repomerge -->

Resolving patch:
diff --git a/lib/ansible/modules/cloud/misc/proxmox.py b/lib/ansible/modules/cloud/misc/proxmox.py
--- a/lib/ansible/modules/cloud/misc/proxmox.py
+++ b/lib/ansible/modules/cloud/misc/proxmox.py
@@ -175,6 +175,13 @@
      - Indicate desired state of the instance
     choices: ['present', 'started', 'absent', 'stopped', 'restarted']
     default: present
+  pubkey:
+    description:
+      - Public key to add to /root/.ssh/authorized_keys. This was added on Proxmox 4.2, it is ignored for earlier versions
+    version_added: "2.3"
+    default: null
+    required: false
+
 notes:
   - Requires proxmoxer and requests modules on host. This modules can be installed with pip.
 requirements: [ "proxmoxer", "python >= 2.7", "requests" ]
@@ -329,6 +336,7 @@ def node_check(proxmox, node):
 def create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, swap, timeout, **kwargs):
   proxmox_node = proxmox.nodes(node)
   kwargs = dict((k,v) for k, v in kwargs.items() if v is not None)
+
   if VZ_TYPE =='lxc':
       kwargs['cpulimit']=cpus
       kwargs['rootfs']=disk
@@ -338,9 +346,14 @@ def create_instance(module, proxmox, vmid, node, disk, storage, cpus, memory, sw
       if 'mounts' in kwargs:
         kwargs.update(kwargs['mounts'])
         del kwargs['mounts']
+      if 'pubkey' in kwargs:
+        if float(proxmox.version.get()['version']) >= 4.2:
+          kwargs['ssh-public-keys'] = kwargs['pubkey']
+        del kwargs['pubkey']
   else:
       kwargs['cpus']=cpus
       kwargs['disk']=disk
+
   taskid = getattr(proxmox_node, VZ_TYPE).create(vmid=vmid, storage=storage, memory=memory, swap=swap, **kwargs)
 
   while timeout:
@@ -428,6 +441,7 @@ def main():
           timeout = dict(type='int', default=30),
           force = dict(type='bool', default='no'),
           state = dict(default='present', choices=['present', 'absent', 'stopped', 'started', 'restarted']),
+          pubkey = dict(type='str', default=None)
           )
   )
 
@@ -502,7 +516,9 @@ def main():
                       cpuunits = module.params['cpuunits'],
                       nameserver = module.params['nameserver'],
                       searchdomain = module.params['searchdomain'],
-                      force = int(module.params['force']))
+                      force = int(module.params['force']),
+                      pubkey = module.params['pubkey']
+                 )
 
       module.exit_json(changed=True, msg="deployed VM %s from template %s"  % (vmid, module.params['ostemplate']))
     except Exception as e:


Test patch: