A pure Python implementation of the lxc_container ansible module
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.0 KiB

  1. # rewrite of the create_container playbook in Python; this happens because
  2. # the module for LXC container shipped with ansible is not working right now
  3. #import lxc
  4. # liliks infrastructure
  5. #container_name = "gogs"
  6. #logical_volume_name = "vm_gogs"
  7. #lvm_volume_group = "sysvg"
  8. #filesystem_size = "5G"
  9. # lilik preferred distro
  10. #distro = "debian"
  11. #release = "jessie"
  12. # our host
  13. #backing_store = "lvm"
  14. #filesystem_type = "ext4"
  15. #
  16. #
  17. #lxc_create_options = {
  18. # "release": release,
  19. # "name": container_name,
  20. # "lvname": logical_volume_name,
  21. # "vgname": lvm_volume_group,
  22. # "fstype": filesystem_type,
  23. # "fssize": filesystem_size,
  24. #}
  25. #
  26. #container = lxc.Container(container_name)
  27. #container.create(distro, args=lxc_create_options)
  28. #container.start()
  29. #---
  30. #- hosts: mcfly
  31. # remote_user: root
  32. # tasks:
  33. # - name: create a lxc container
  34. # lxc_container:
  35. # name: gogs
  36. # backing_store: lvm
  37. # container_log: true
  38. # fs_size: 5G
  39. # fs_type: ext4
  40. # lv_name: vm_gogs
  41. # state: started
  42. # template: debian
  43. # template_options: --release jessie
  44. # vg_name: sysvg
  45. # container_command: apt-get update; apt-get install python
  46. from ansible.module_utils.basic import *
  47. class LilikContainer(object):
  48. """
  49. A generic lxc container manipulation object based on python-lxc
  50. """
  51. def __init__(self, module):
  52. self.module = module
  53. self.state = module.params['state']
  54. self.name = module.params['name']
  55. self.template = module.params['template']
  56. self.backing_store = module.params['backing_store']
  57. self.lvname = module.params['lv_name']
  58. self.vgname = module.params['vg_name']
  59. self.fstype = module.params['fs_type']
  60. self.fssize = module.params['fs_size']
  61. def create_container(self):
  62. """
  63. Create a lxc.Container object as specified in the playbook, use it
  64. to create a lxc container and returns the reference
  65. """
  66. container_options = {
  67. 'bdev': self.backing_store,
  68. 'lvname': self.lvname,
  69. 'vgname': self.vgname,
  70. 'fstype': self.fstype,
  71. 'fssize': self.fssize,
  72. 'bdev' : self.backing_store,
  73. }
  74. try:
  75. import lxc
  76. except ImportError:
  77. self.module.fail_json(changed=False, msg='Error importing lxc')
  78. container = lxc.Container(name = self.name)
  79. # TODO: python2-lxc does not like bdevtype but python-lxc does
  80. return container.create(
  81. template = self.template,
  82. args = container_options,
  83. # bdevtype = self.backing_store
  84. )
  85. def main():
  86. module = AnsibleModule(
  87. argument_spec = dict(
  88. backing_store = dict(
  89. default='dir',
  90. choices=['dir', 'lvm', 'loop', 'btrsf', 'overlayfs', 'zfs',],
  91. type='str',
  92. ),
  93. container_command = dict(
  94. type='str',
  95. ),
  96. fs_size = dict(
  97. required=False,
  98. default='5G',
  99. type='str',
  100. ),
  101. fs_type = dict(
  102. required=False,
  103. default='ext4',
  104. type='str',
  105. ),
  106. lv_name = dict(
  107. type='str',
  108. ),
  109. name = dict(
  110. required=True,
  111. type='str',
  112. ),
  113. state = dict(
  114. default='started',
  115. choices=['started', 'stopped', 'restarted', 'absent', 'frozen'],
  116. type='str',
  117. ),
  118. template = dict(
  119. required=False,
  120. default='ubuntu',
  121. type='str',
  122. ),
  123. template_options = dict(required=False),
  124. vg_name = dict(
  125. required=False,
  126. default='lxc',
  127. type='str',
  128. ),
  129. )
  130. )
  131. try:
  132. import lxc
  133. except ImportError:
  134. module.fail_json(changed=False, msg='liblxc is required for this module to work')
  135. container = LilikContainer(module)
  136. result = {}
  137. result['name'] = container.name
  138. result['state'] = container.state
  139. if container.state == 'absent':
  140. # destroy the container
  141. if container.destoy():
  142. module.exit_json(changed=True)
  143. # TODO: remove redundant test
  144. # test wether the container is absent or not
  145. if container.name in lxc.list_containers():
  146. module.fail_json(changed=False)
  147. # the container has been removed
  148. else:
  149. module.exit_json(changed=True)
  150. # end TODO: remove redundant test
  151. elif container.state in ['started', 'stopped', 'restarted', 'frozen']:
  152. # the container exists, just set the state as required
  153. if container.name in lxc.list_containers():
  154. container_actions_from_state = {
  155. 'started': container.start,
  156. 'stopped': container.stop,
  157. 'restarted': container.restart,
  158. 'frozen': container.freeze,
  159. }
  160. # selected action
  161. action = container_actions.get(container.state)
  162. if action():
  163. module.exit_json(changed=True)
  164. else:
  165. module.exit_json(changed=False)
  166. # the container does not exists, create it
  167. else:
  168. try:
  169. new_container = container.create_container()
  170. module.exit_json(changed=True)
  171. except Exception as e:
  172. module.fail_json(
  173. changed=False,
  174. msg='An excption was raised while creating the container',
  175. exception_message=str(e),
  176. )
  177. if __name__ == '__main__':
  178. main()