kameleon-builder 2.0.0.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. data/.editorconfig +23 -0
  2. data/.env +51 -0
  3. data/.gitignore +22 -0
  4. data/AUTHORS +19 -0
  5. data/CHANGELOG +36 -0
  6. data/COPYING +340 -0
  7. data/Gemfile +4 -0
  8. data/README.md +53 -0
  9. data/Rakefile +24 -0
  10. data/Vagrantfile +68 -0
  11. data/bin/kameleon +16 -0
  12. data/contrib/kameleon_bashrc.sh +138 -0
  13. data/contrib/scripts/VirtualBox_deploy.sh +12 -0
  14. data/contrib/scripts/chroot_env +9 -0
  15. data/contrib/scripts/create_passwd.py +17 -0
  16. data/contrib/scripts/umount-chroot.sh +290 -0
  17. data/contrib/steps/bootstrap/debian/bootstrap_if_needed.yaml +47 -0
  18. data/contrib/steps/bootstrap/debian/bootstrap_static.yaml +38 -0
  19. data/contrib/steps/setup/add_timestamp.yaml +6 -0
  20. data/contrib/steps/setup/autologin.yaml +16 -0
  21. data/contrib/steps/setup/copy_ssh_auth_file.yaml +10 -0
  22. data/contrib/steps/setup/debian/add_network_interface.yaml +7 -0
  23. data/contrib/steps/setup/debian/cluster_tools_install.yaml +16 -0
  24. data/contrib/steps/setup/debian/network_config_static.yaml +17 -0
  25. data/contrib/steps/setup/generate_user_ssh_key.yaml +15 -0
  26. data/contrib/steps/setup/install_my_ssh_key.yaml +26 -0
  27. data/contrib/steps/setup/make_swap_file.yaml +9 -0
  28. data/contrib/steps/setup/root_ssh_config.yaml +18 -0
  29. data/contrib/steps/setup/set_user_password.yaml +7 -0
  30. data/contrib/steps/setup/system_optimization.yaml +8 -0
  31. data/docs/.gitignore +1 -0
  32. data/docs/Makefile +177 -0
  33. data/docs/make.bat +242 -0
  34. data/docs/source/_static/.gitignore +0 -0
  35. data/docs/source/aliases.rst +29 -0
  36. data/docs/source/checkpoint.rst +28 -0
  37. data/docs/source/cli.rst +3 -0
  38. data/docs/source/commands.rst +62 -0
  39. data/docs/source/conf.py +254 -0
  40. data/docs/source/context.rst +42 -0
  41. data/docs/source/faq.rst +3 -0
  42. data/docs/source/getting_started.rst +3 -0
  43. data/docs/source/index.rst +38 -0
  44. data/docs/source/installation.rst +3 -0
  45. data/docs/source/recipe.rst +256 -0
  46. data/docs/source/why.rst +3 -0
  47. data/docs/source/workspace.rst +11 -0
  48. data/kameleon-builder.gemspec +37 -0
  49. data/lib/kameleon.rb +75 -0
  50. data/lib/kameleon/cli.rb +176 -0
  51. data/lib/kameleon/context.rb +83 -0
  52. data/lib/kameleon/engine.rb +357 -0
  53. data/lib/kameleon/environment.rb +38 -0
  54. data/lib/kameleon/error.rb +51 -0
  55. data/lib/kameleon/logger.rb +53 -0
  56. data/lib/kameleon/recipe.rb +474 -0
  57. data/lib/kameleon/shell.rb +290 -0
  58. data/lib/kameleon/step.rb +213 -0
  59. data/lib/kameleon/utils.rb +45 -0
  60. data/lib/kameleon/version.rb +3 -0
  61. data/templates/COPYRIGHT +21 -0
  62. data/templates/aliases/defaults.yaml +83 -0
  63. data/templates/checkpoints/docker.yaml +14 -0
  64. data/templates/checkpoints/qcow2.yaml +44 -0
  65. data/templates/debian-wheezy-chroot.yaml +98 -0
  66. data/templates/debian-wheezy-docker.yaml +97 -0
  67. data/templates/fedora-docker.yaml +96 -0
  68. data/templates/steps/bootstrap/debian/debootstrap.yaml +13 -0
  69. data/templates/steps/bootstrap/fedora/docker_bootstrap.yaml +25 -0
  70. data/templates/steps/bootstrap/fedora/yum_bootstrap.yaml +22 -0
  71. data/templates/steps/bootstrap/prepare_appliance_with_nbd.yaml +93 -0
  72. data/templates/steps/bootstrap/prepare_docker.yaml +38 -0
  73. data/templates/steps/bootstrap/start_chroot.yaml +53 -0
  74. data/templates/steps/bootstrap/start_docker.yaml +12 -0
  75. data/templates/steps/export/build_appliance_from_docker.yaml +105 -0
  76. data/templates/steps/export/clean_appliance.yaml +3 -0
  77. data/templates/steps/export/save_appliance_from_nbd.yaml +54 -0
  78. data/templates/steps/setup/create_user.yaml +12 -0
  79. data/templates/steps/setup/debian/kernel_install.yaml +20 -0
  80. data/templates/steps/setup/debian/keyboard_config.yaml +10 -0
  81. data/templates/steps/setup/debian/network_config.yaml +30 -0
  82. data/templates/steps/setup/debian/software_install.yaml +15 -0
  83. data/templates/steps/setup/debian/system_config.yaml +12 -0
  84. data/templates/steps/setup/fedora/kernel_install.yaml +27 -0
  85. data/templates/steps/setup/fedora/software_install.yaml +10 -0
  86. data/tests/helper.rb +22 -0
  87. data/tests/recipes/dummy_recipe.yaml +48 -0
  88. data/tests/recipes/steps/bootstrap/dummy_distro/dummy_bootstrap_static.yaml +4 -0
  89. data/tests/recipes/steps/export/dummy_save_appliance.yaml +9 -0
  90. data/tests/recipes/steps/setup/default/dummy_root_passwd.yaml +8 -0
  91. data/tests/recipes/steps/setup/dummy_distro/dummy_software_install.yaml +7 -0
  92. data/tests/test_context.rb +16 -0
  93. data/tests/test_recipe.rb +15 -0
  94. data/tests/test_version.rb +9 -0
  95. metadata +300 -0
@@ -0,0 +1,42 @@
1
+ -------
2
+ Context
3
+ -------
4
+
5
+ To understand how Kameleon work you have to get the *context* notion. A context
6
+ is an execution environnement with his variables (like $PATH, $TERM,...), his
7
+ tools (debootstrap, yum, ...) and all his specifics (filesystem, local/remote,
8
+ ...). When you build an appliance you deal with 3 contexts:
9
+
10
+ - The *local* context which is the Kameleon execution environnement
11
+ - The *out* context where you will bootstrap the appliance
12
+ - The *in* context which is inside the newly created appliance
13
+
14
+ These context are setup using the two globals variables: ``out_context``
15
+ and ``in_context``. They both takes 3 arguments:
16
+
17
+ cmd
18
+ The command to initialize the context
19
+ workdir (optional)
20
+ The working directory to tell to Kameleon where to execute the command
21
+ exec_prefix (optional)
22
+ The command to execute before every Kameleon command in this context
23
+
24
+ For example, you are building an appliance on your laptop and you run Kameleon
25
+ in a bash shell with this configuration:
26
+
27
+ .. code-block:: yaml
28
+
29
+ out_context:
30
+ cmd: bash
31
+ workdir: $$kameleon_cwd
32
+
33
+ in_context:
34
+ cmd: chroot $$rootfs bash
35
+ workdir: /
36
+
37
+
38
+ Your *local* context is this shell where you launch Kameleon on your laptop,
39
+ the *out* is a child bash of this context, and the *in* is inside the new
40
+ environnement accessed by the chroot. As you can see the local and the out
41
+ context are often very similar but sometimes it could be useful for the out
42
+ context to be elsewhere (in a VM for example).
@@ -0,0 +1,3 @@
1
+ ---
2
+ FAQ
3
+ ---
@@ -0,0 +1,3 @@
1
+ ---------------
2
+ Getting Started
3
+ ---------------
@@ -0,0 +1,38 @@
1
+ .. Kameleon documentation master file, created by
2
+ sphinx-quickstart on Thu Feb 13 19:01:14 2014.
3
+ You can adapt this file completely to your liking, but it should at least
4
+ contain the root `toctree` directive.
5
+
6
+ Welcome to Kameleon's documentation!
7
+ ====================================
8
+
9
+ Kameleon should be seen as a simple but powerful tool to generate customized
10
+ appliances. With Kameleon, you make your recipe that describes how to create
11
+ step by step your own distribution. At start Kameleon is used to create custom
12
+ kvm, LXC, VirtualBox, iso images, ..., but as it is designed to be very generic
13
+ you can probably do a lot more than that.
14
+
15
+
16
+ .. toctree::
17
+ :maxdepth: 2
18
+
19
+ why.rst
20
+ installation.rst
21
+ getting_started.rst
22
+ cli.rst
23
+ recipe.rst
24
+ context.rst
25
+ commands.rst
26
+ workspace.rst
27
+ checkpoint.rst
28
+ aliases.rst
29
+ faq.rst
30
+
31
+
32
+ Indices and tables
33
+ ==================
34
+
35
+ * :ref:`genindex`
36
+ * :ref:`modindex`
37
+ * :ref:`search`
38
+
@@ -0,0 +1,3 @@
1
+ ------------
2
+ Installation
3
+ ------------
@@ -0,0 +1,256 @@
1
+ ------
2
+ Recipe
3
+ ------
4
+
5
+ Kameleon compute YAML files, named *recipes*, that describes how you will
6
+ build your appliance. These files are stored in the root of your `Workspace`_.
7
+ A recipe is a hierarchical structure of `Sections`_, `Steps`_, `Microsteps`_ and
8
+ `Commands`_. Here is an overview of this structure:
9
+
10
+ .. code-block:: yaml
11
+
12
+ recipe
13
+ └── section
14
+ └── step
15
+ └── microstep
16
+ └──command
17
+
18
+ The recipe also contains set of `Global variables`_ declaration and some
19
+ imports like `Aliases`_ and `Checkpoint`_.
20
+
21
+ This is an example of a recipe:
22
+
23
+ .. code-block:: yaml
24
+
25
+ ---
26
+ # Loads some helpful aliases
27
+ aliases: defaults.yaml
28
+ # Enables qcow2 checkpoint
29
+ checkpoint: qcow2.yaml
30
+ #== Global variables use by Kameleon engine and the steps
31
+ global:
32
+ ## User varibales : used by the recipe
33
+ cachedir: /var/cache/kameleon
34
+ rootfs: $$kameleon_cwd/rootfs
35
+ user_name: kameleon
36
+ arch: amd64
37
+
38
+ nbd_device: /dev/nbd10
39
+ container: "$${kameleon_recipe_name}_temp.qcow2"
40
+
41
+ distrib: debian
42
+ release: wheezy
43
+
44
+ ## System variables. Required by kameleon engine
45
+ # Include specific steps
46
+ include_steps: [$$distrib/$$release, $$distrib]
47
+
48
+ # Shell session from where we launch exec_out commands. There is often a
49
+ # local bash session, but it can be a remote shell on other machines or on
50
+ # any shell. (eg. bash, chroot, fakechroot, ssh, tmux, lxc...)
51
+ out_context:
52
+ cmd: bash
53
+ workdir: $$kameleon_cwd
54
+
55
+ # Shell session that allows us to connect to the building machine in order to
56
+ # configure it and setup additional programs
57
+ default_env: "USER=root HOME=/root LC_ALL=POSIX"
58
+ in_context:
59
+ cmd: $$default_env chroot $$rootfs bash
60
+ workdir: /
61
+
62
+ #== Bootstrap the new system and create the 'in_context'
63
+ bootstrap:
64
+ - debootstrap:
65
+ - release: $$release
66
+ - arch: $$arch
67
+ - repository: http://ftp.fr.debian.org/debian/
68
+ - rootfs_archive: $$cachedir/$$distrib/$$release/$$arch/debootstrap.tar.gz
69
+ - prepare_appliance_with_nbd:
70
+ - mountdir: $$rootfs
71
+ - image_size: 2G
72
+ - filesystem_type: ext4
73
+ - rootfs_archive: $$cachedir/$$distrib/$$release/$$arch/debootstrap.tar.gz
74
+ - start_chroot:
75
+ - rootfs: $$rootfs
76
+
77
+
78
+ #== Install and configuration steps
79
+ # WARNING: this part should be independante from the build context (whenever
80
+ # possible...)
81
+ setup:
82
+ # Install
83
+ - software_install:
84
+ - packages: >
85
+ debian-keyring ntp zip unzip rsync sudo less vim bash-completion
86
+ - kernel_install:
87
+ - arch: $$arch
88
+ # Configuration
89
+ - system_config:
90
+ - locales: fr_FR en_US
91
+ - lang: fr_FR.UTF-8
92
+ - timezone: Europe/Paris
93
+ - keyboard_config:
94
+ - layout: "fr,us"
95
+ - network_config:
96
+ - hostname: kameleon-$$distrib
97
+ - create_user:
98
+ - name: $$user_name
99
+ - group: admin
100
+ - password: $$user_name
101
+
102
+ #== Export the generated appliance in the format of your choice
103
+ export:
104
+ - save_appliance_from_nbd:
105
+ - filename: "$${kameleon_recipe_name}"
106
+ - save_as_qcow2
107
+ # - save_as_tgz
108
+ # - save_as_raw
109
+ # - save_as_vmdk
110
+ # - save_as_vdi
111
+
112
+ Section
113
+ -------
114
+
115
+ Each section is a list of `Steps`_. Currently, there is 3 sections:
116
+
117
+ bootstrap
118
+ This section contains the bootstrap of the new system and create the *in*
119
+ context (see `Contexts`_).
120
+
121
+ setup
122
+ This one is dedicated to the install and configuration steps.
123
+
124
+ export
125
+ Export the generated appliance in the format of your choice.
126
+
127
+
128
+ Step
129
+ ----
130
+
131
+ Each *step* contains a list of microsteps that contains a list of Commands_
132
+ written in one YAML file. To be found by Kameleon this file must be named by
133
+ with the step name plus the YAML extension ``.yaml``. For example the
134
+ ``software_install.yaml`` step file looks like this:
135
+
136
+ .. code-block:: yaml
137
+
138
+ # Software Install
139
+ - add_contribs_source:
140
+ - exec_in: perl -pi -e "s/main$/main contrib non-free/" /etc/apt/sources.list
141
+ - update_repositories:
142
+ - exec_in: apt-get -y --force-yes update
143
+ - upgrade_system:
144
+ - exec_in: apt-get -y --force-yes dist-upgrade
145
+ - clean:
146
+ - on_export_init:
147
+ - exec_in: apt-get -y --force-yes autoclean
148
+ - exec_in: apt-get -y --force-yes clean
149
+ - exec_in: apt-get -y --force-yes autoremove
150
+ # default packages
151
+ - packages: "ntp sudo"
152
+ - extra_packages:
153
+ - exec_in: apt-get -y --force-yes install $$packages
154
+
155
+
156
+ A step will be called like a function in the recipe. You should provide a set
157
+ of local variables if needed by the step or to override default variables (see
158
+ Variables_). Optionally, you can select only some microsteps to execute. Here
159
+ is an example of step call:
160
+
161
+ .. code-block:: yaml
162
+
163
+ - software_install:
164
+ - update_repositories
165
+ - add_contribs_source
166
+ - clean
167
+ - extra_packages
168
+ - packages: "debian-keyring ntp zip unzip rsync sudo"
169
+
170
+ Steps path
171
+ ~~~~~~~~~~
172
+
173
+ The steps are YAML formated files stored in the ``recipe/steps`` directory of
174
+ the Workspace_. To enable a better recipe reuse and ease of write the steps
175
+ are stored by default in specific folders depending on the sections.
176
+
177
+ Kameleon is looking for the steps files using the ``include_steps`` list value,
178
+ if it is set in the recipe (NOT mandatory). These includes are often the
179
+ distribution steps. For example if you are building an ubuntu based
180
+ distribution you can use:
181
+
182
+ .. code-block:: yaml
183
+
184
+ include_steps:
185
+ - ubuntu
186
+ - debian/wheezy
187
+ - debian
188
+
189
+ It also search uppermost within the current section folder. For the previous
190
+ example, in the bootstrap section, the search paths are scanned in this
191
+ order:
192
+
193
+ .. code-block:: yaml
194
+
195
+ steps/bootstrap/ubuntu
196
+ steps/ubuntu
197
+ steps/bootstrap/debian/wheezy
198
+ steps/debian/wheezy
199
+ steps/bootstrap/debian
200
+ steps/debian
201
+ steps/bootstrap/
202
+ steps/
203
+
204
+
205
+ Variables
206
+ ---------
207
+
208
+ Kameleon is using preprocessed variables. You can define it with the YAML
209
+ key/value syntax ``my_var: my_value``.To access these variables you have to use
210
+ the two dollars (``$$``) prefix. Like in a Shell you can also use
211
+ ``$${var_name}`` to include your variables in string like this
212
+ ``my-$${variable_name}-templated``. It's also possible to use nested variables
213
+ like:
214
+
215
+ .. code-block:: yaml
216
+
217
+ my_var: foo
218
+ my_nested_var: $${my_var}-bar
219
+
220
+ Be careful, in YAML you cannot mix dictionary and list on the same level.
221
+ That's why, in the global dictionary, you can define your variables like in the
222
+ example above but, in the recipe or the steps, you must prefix your variable
223
+ with a ``-`` like this ``- my_var: foo``.
224
+
225
+
226
+ Global variables
227
+ ~~~~~~~~~~~~~~~~~
228
+
229
+ Global variables are defined in the ``global`` dictionary of the recipe.
230
+ Kameleon use some global variable to enable the appliance build. See Context_
231
+ and `Steps path`_ for more details
232
+
233
+
234
+ Step local variables
235
+ ~~~~~~~~~~~~~~~~~~~~
236
+
237
+ In the recipe, you can provide some variables when you call a step. This
238
+ variable override the global and the default variables.
239
+
240
+
241
+ Step default variables
242
+ ~~~~~~~~~~~~~~~~~~~~~~
243
+
244
+ In the step file, you can define some default variables for your microsteps. Be
245
+ careful, to avoid some mistakes, these variables can be override by the step
246
+ local variables but not by the global ones. If this is the behavior you
247
+ expected just add a step local variable that take the global variable value
248
+ like this:
249
+
250
+ .. code-block:: yaml
251
+
252
+ global:
253
+ foo: bar
254
+ setup:
255
+ - my_step:
256
+ - foo: $$foo
@@ -0,0 +1,3 @@
1
+ --------------
2
+ Why Kameleon ?
3
+ --------------
@@ -0,0 +1,11 @@
1
+ ---------
2
+ Workspace
3
+ ---------
4
+
5
+ The workspaces are the folders containing your Kameleon recipes and builds. When
6
+ you use ``kameleon new`` a workspace is created if it does not exists. A
7
+ workspace may contains several recipes.
8
+
9
+ *Be careful*: All the *steps are shared between recipes within a workspace*. So
10
+ if you do NOT want to share steps between different recipes you MUST use
11
+ different workspace.
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kameleon/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "kameleon-builder"
8
+ s.version = Kameleon::VERSION
9
+ s.authors = ["Salem Harrache",
10
+ "Michael Mercier",
11
+ "Cristan Ruiz",
12
+ "Bruno Bzeznik"]
13
+ s.email = ["salem.harrache@inria.fr",
14
+ "michael.mercier@inria.fr",
15
+ "cristian.ruiz@imag.fr",
16
+ "bruno.bzeznik@imag.fr"]
17
+ s.description = %q{The mindful appliance builder}
18
+ s.summary = %q{Kameleon is a tool to build virtual machines from scratch}
19
+ s.homepage = "http://kameleon.readthedocs.org/"
20
+ s.license = "GPL-2"
21
+
22
+ s.files = `git ls-files`.split($/)
23
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
+ s.test_files = s.files.grep(%r{^(tests|s|features)/})
25
+ s.require_paths = ["lib"]
26
+
27
+ s.add_dependency 'childprocess', '~> 0.3'
28
+ s.add_dependency 'thor', '~> 0.15'
29
+ s.add_dependency 'table_print', '~> 1.5'
30
+ s.add_dependency 'log4r-color', '~> 1.2'
31
+
32
+ s.add_development_dependency 'pry', '~> 0.9'
33
+ s.add_development_dependency 'pry-debugger', '~> 0.2'
34
+ s.add_development_dependency 'rake', '~> 10.1'
35
+ s.add_development_dependency 'minitest', '~> 4.7'
36
+ s.add_development_dependency 'coveralls', '~> 0.7'
37
+ end
data/lib/kameleon.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'securerandom'
2
+ require 'yaml'
3
+ require 'fileutils'
4
+ require 'optparse'
5
+ require 'erb'
6
+ require 'ostruct'
7
+ require 'tempfile'
8
+ require 'pp'
9
+ require 'thor'
10
+ require 'childprocess'
11
+ require 'log4r-color'
12
+ require 'log4r-color/configurator'
13
+ require 'pathname'
14
+ require 'table_print'
15
+
16
+ module Kameleon
17
+ # to force yaml to dump ASCII-8Bit strings as strings
18
+ YAML::ENGINE.yamler='syck'
19
+
20
+ # add a PROGRESS and NOTICE level
21
+ Log4r::Configurator.custom_levels(:DEBUG, :INFO, :NOTICE,
22
+ :PROGRESS, :WARN, :ERROR,
23
+ :FATAL)
24
+
25
+ class << self
26
+ attr_writer :logger, :env, :source_root, :templates_path, :templates_names,
27
+ :templates_files
28
+
29
+ # The source root is the path to the root directory of the kameleon gem.
30
+ def source_root
31
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
32
+ end
33
+
34
+ def templates_path
35
+ @templates_path ||= Pathname.new(File.join(source_root, 'templates'))
36
+ end
37
+
38
+ def templates_files
39
+ if @templates.nil?
40
+ files = Dir.foreach(templates_path).map do |f|
41
+ Pathname.new(File.join(templates_path, f)) if f.include?(".yaml")
42
+ end
43
+ @templates = files.compact
44
+ end
45
+ @templates
46
+ end
47
+
48
+ def templates_names
49
+ if @templates_names.nil?
50
+ names = templates_files.map do |f|
51
+ f.basename(f.extname).to_s
52
+ end
53
+ @templates_names = names
54
+ end
55
+ @templates_names
56
+ end
57
+
58
+ def logger
59
+ @logger ||= Log4r::Logger.new("kameleon::[global]")
60
+ end
61
+
62
+ def env
63
+ @env ||= Environment.new
64
+ end
65
+
66
+ end
67
+ end
68
+
69
+ # Load the things which must be loaded before anything else
70
+ require 'kameleon/utils'
71
+ require 'kameleon/error'
72
+ require 'kameleon/cli'
73
+ require 'kameleon/environment'
74
+ require 'kameleon/version'
75
+ require 'kameleon/logger'