(→Usage) |
|||
| Line 1: | Line 1: | ||
= What is IMG = | = What is IMG = | ||
| - | IMG (Image Me Give) is a small python client/server application suite, its sole job is to get a | + | IMG (Image Me Give) is a small python client/server application suite, its sole job is to get a kickstart file from a user, via a web interface, command line or BOSS process. Then it runs Moblin-Image-Creator, either in a host or in a VM. IMG also has the capability to run as a BOSS participant and thus be a part of a build process. |
[[File:IMG.png]] | [[File:IMG.png]] | ||
| Line 9: | Line 9: | ||
:Fire and forget about it, check back later with the cli client for results | :Fire and forget about it, check back later with the cli client for results | ||
* Queue view with django, | * Queue view with django, | ||
| - | :Show a nice html view of currently running or standby MIC jobs in the | + | :Show a nice html view of currently running or standby MIC jobs in the queue |
| - | * Submit | + | * Submit a ks via a web interface |
:Upload via a form | :Upload via a form | ||
* No security | * No security | ||
:No https or file filter restrictions :) | :No https or file filter restrictions :) | ||
| + | * Two ways of communication | ||
| + | : BOSS and pure AMQP messages | ||
== Example workflow == | == Example workflow == | ||
| Line 19: | Line 21: | ||
The application consists of two parts, django frontend and the actual image creation application. Both of them are connected via AMQP, RabbitMQ is used as the server. | The application consists of two parts, django frontend and the actual image creation application. Both of them are connected via AMQP, RabbitMQ is used as the server. | ||
| - | So an example workflow: | + | So an example workflow, in AMQP: |
| - | # User posts an image creation request with email address and sample kickstart file (or | + | # User posts an image creation request with email address and sample kickstart file (or a package overlay), using a form or the command line client. |
# Django application receives the request and imports the information on a model object and saves it. | # Django application receives the request and imports the information on a model object and saves it. | ||
# When the object is saved, a message is sent via a broker to the image creation app, containing the details for the creation. | # When the object is saved, a message is sent via a broker to the image creation app, containing the details for the creation. | ||
## Image creation commences | ## Image creation commences | ||
| - | ## Virtual machine disk image containing mic2 | + | ## Virtual machine disk image containing mic2 is engaged (as a kvm overlay image), with ssh access. |
| - | ### When a | + | ### When a package overlay is received, a kickstart file is constructed from a ready-made template and passed to kickstart part |
### When a kickstart file is received, it is passed directly to worker | ### When a kickstart file is received, it is passed directly to worker | ||
## Worker starts up and connects to the virtual machine using ssh and passes the required arguments to mic2. | ## Worker starts up and connects to the virtual machine using ssh and passes the required arguments to mic2. | ||
| Line 32: | Line 34: | ||
## When mic2 has finished, the virtual machine is shut down by the worker. | ## When mic2 has finished, the virtual machine is shut down by the worker. | ||
## When image is created, the virtual machine disk image is deleted | ## When image is created, the virtual machine disk image is deleted | ||
| - | |||
| - | |||
| - | + | And an example workflow, in BOSS: | |
| - | + | TO BE DONE | |
| - | + | ||
| + | = Worker = | ||
| - | + | The worker code is responsible of running mic2 either locally or on a virtual machine. The initialisation code takes care of creating the necessary command stubs for mic2 use for either implementations. It also handles the KVM creation command stubs. | |
| - | + | The method "build" is where the actual business happens. It runs in two ways, as described earlier. | |
| - | + | In KVM mode, it first creates an overlay image from the base image (not distributed) and then starts it using the overlay image as the hard disk. Virtio is used as a speed optimisation method for KVM. When a specific amount of time has passed, it will copy the kickstart and mic2 config file to the guest VM. Then it runs mic2 in the VM with parameters specified in the init method. After mic2 has run, the image is copied from the guest using scp. | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | It | + | In local mode, only mic2 is run on the host machine. It will create the image based on the options in the init method along with the kickstart file. |
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | + | = BOSS participant = | |
| + | See [http://meego.gitorious.org/meego-infrastructure-tools/imger/blobs/master/src/img_boss/boss_build_image.py boss_build_image.py] for the source code. | ||
| - | + | The general design of the client is pretty much the same as the AMQP server, since they both get activated and then call the worker code to create the image, with or without KVM. The worker code is described in the section above. | |
| - | + | More information about BOSS [Infrastructure/BOSS]. | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
= BOSS Client = | = BOSS Client = | ||
| Line 140: | Line 80: | ||
-r RELEASE --release Image release, goes directly to mic2 | -r RELEASE --release Image release, goes directly to mic2 | ||
-a ARCH --arch Architecture to use | -a ARCH --arch Architecture to use | ||
| + | |||
| + | = Server = | ||
| + | |||
| + | See [http://meego.gitorious.org/meego-infrastructure-tools/imger/blobs/master/src/img_amqp/build_image.py build_image.py] for example server. | ||
| + | |||
| + | This section documents the server component of IMG. | ||
| + | |||
| + | == Functionality == | ||
| + | |||
| + | === Consumer functions === | ||
| + | |||
| + | *kickstarter_callback: | ||
| + | :Receives messages as described [#Kickstarter here], decodes JSON data to variables and creates a kickstart file with the received list of packages and then submits them to the mic-image-creator [#MoblinImageCreator here]. | ||
| + | *mic2_callback: | ||
| + | :Receives messages as described [#MoblinImageCreator here], decodes JSON data to variables and runs moblin-image-creator (NB! this has to exist in /usr/bin/moblin-image-creator, will be changeable in the future) against the supplied configuration file and image type. | ||
| + | :The images are saved to to a configured location, needs to be changed in the python subprocess call in order to get downloadable images (eg. to a webserver media path). | ||
| + | :If the image creation fails (is caught with "CalledProcessError" exception in the code, this happens with nonzero exit status), a message is sent to "error_queue" queue, with the following JSON encoded dictionary: | ||
| + | |||
| + | 'error': Contains the error message of the exception received from the python subprocess call. | ||
| + | 'id': identification string of the original message sent to "image_queue" queue | ||
| + | 'url': Contains the URL from which one can download the log | ||
| + | |||
| + | |||
| + | :If the image creation succeeds, a message is queued to "link_queue" queue, with the following JSON encoded dictionary: | ||
| + | |||
| + | 'url': Contains the URL from which one can download the image | ||
| + | |||
| + | 'id': identification string of the original message sent to "image_queue" queue | ||
| + | |||
| + | == Exchanges == | ||
| + | |||
| + | * image_exchange, The exchange for image creationg related queues | ||
| + | * django_result_exchange, Exchange for results, picked up by django | ||
| + | |||
| + | == Queues == | ||
| + | |||
| + | Queues for exchange "image_exchange": | ||
| + | |||
| + | * image_queue | ||
| + | :Stores messages related to Moblin Image Creator runtime. | ||
| + | * kickstarter_queue | ||
| + | :Stores messages related to kickstarter runtime. | ||
| + | |||
| + | Queues for exchange "django_result_exchange": | ||
| + | |||
| + | * status_queue | ||
| + | :Contains messages in the following format (JSON encoded dictionary): | ||
| + | ** 'status': status of the image build, compulsory | ||
| + | ** 'id': the identification string of the original message sent to kickstarter_queue, compulsory | ||
| + | ** 'url': Contains the URL from which one can download the image | ||
| + | ** 'log': specifies the log file to read from | ||
| + | ** 'error': any error messages faced | ||
| + | |||
| + | |||
| + | = Client = | ||
| + | |||
| + | For demonstration see [http://meego.gitorious.org/meego-infrastructure-tools/imger/blobs/master/src/img_amqp/img_client.py img_client.py] for example client. | ||
| + | |||
| + | |||
| + | == Usage == | ||
| + | |||
| + | img_client.py -p|--poll <id> -n|--name <name> -t|--type <imagetype> -e|--email <author@email> -r|--release -a|--arch s|--submit -k <kickstart_file.ks>" | ||
| + | |||
| + | where: | ||
| + | : -p|--poll <message_id>, poll the AMQP server for messages relating to the id, see -a|--async | ||
| + | : -t|--type <imagetype>, image type, can be of: livecd, liveusb, loop, raw, nand, mrstnand, vdi or vmdk | ||
| + | : -n|--name Image name | ||
| + | : -a|--arch Image architecture | ||
| + | : -r|--release Image release number | ||
| + | : -c|--config Configuration file to use | ||
| + | |||
| + | == Documentation == | ||
| + | |||
| + | This client version uses AMQP as the message bus to communicate with the server. The format for the messages is described in the next part of this document. | ||
| + | |||
| + | ==== Messages ==== | ||
| + | |||
| + | The general message format is JSON encoded dictionary. | ||
| + | |||
| + | ===== Moblin Image Creator ===== | ||
| + | |||
| + | To initialize the actual image building, send a JSON formatted message as follows: | ||
| + | |||
| + | {'email':email, 'id':id, 'imagetype':imagetype, 'ksfile':ksfile, 'name': name, 'arch':arch, 'release':release} | ||
| + | |||
| + | where: | ||
| + | * email, email address of the submitter | ||
| + | * id, identification string of the original message (passed on from kickstarter process) | ||
| + | * imagetype, image type of values: livecd, liveusb, loop, raw, nand, mrstnand, vdi or vmdk | ||
| + | * ksfile, the actual kickstar file to upload (in text) | ||
| + | * name, the name for the image | ||
| + | * arch, architecture to use for the image building | ||
| + | * release, release numbering, $VERTICAL-$ARCH-$VARIANT like in mic2 | ||
| + | |||
= Django client = | = Django client = | ||
| Line 149: | Line 183: | ||
* Get the overlay text from the form field | * Get the overlay text from the form field | ||
* use python strings split() method to split the overlay text in to a list, with a comma delimiter | * use python strings split() method to split the overlay text in to a list, with a comma delimiter | ||
| - | + | ** construct a kickstart file using this list and append the packages to the kickstart files package list | |
| - | **append the | + | |
| - | + | ||
* queue | * queue | ||
:This view is responsible of two things. Firstly it checks wether there are any messages in the "status_queue" message queue, if there are, then it updates the !ImageJob model object (identified by the identification string from the message) to include the ready image URL. | :This view is responsible of two things. Firstly it checks wether there are any messages in the "status_queue" message queue, if there are, then it updates the !ImageJob model object (identified by the identification string from the message) to include the ready image URL. | ||
| Line 191: | Line 223: | ||
=== Forms === | === Forms === | ||
| - | ==== | + | ==== UploadFileForm ==== |
Contains the following fields | Contains the following fields | ||
* email, email field | * email, email field | ||
* overlay, text input field | * overlay, text input field | ||
| + | * name, text input field | ||
* platform, select field for the platform, parsed from the default template | * platform, select field for the platform, parsed from the default template | ||
| + | * release, a text input field for release | ||
| + | * arch, architecture selection field | ||
* imagetype, select field for the image type, with values: livecd, liveusb, loop, raw, nand, mrstnand, vdi, vmdk | * imagetype, select field for the image type, with values: livecd, liveusb, loop, raw, nand, mrstnand, vdi, vmdk | ||
* ksfile, the raw kickstart file | * ksfile, the raw kickstart file | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| Line 229: | Line 259: | ||
Currently, IMGer can run the MIC2 jobs inside a KVM virtual machine, the only prerequisites are that image is located in /usr/share/img/base.img (configurable in the future) path and that the virtual machine has MIC2 installed and configured. | Currently, IMGer can run the MIC2 jobs inside a KVM virtual machine, the only prerequisites are that image is located in /usr/share/img/base.img (configurable in the future) path and that the virtual machine has MIC2 installed and configured. | ||
| - | One must also confirm that the image SSH-keys in the source distribution are configured in the virtual machine and both keys exist in /usr/share/img (configurable in the future) | + | Suse studio is one way to create the images, just make sure that you have a rpm repository which contains mic2, python-xml and qemu-static-arm to make mic2 run properly on the image. |
| + | |||
| + | One must also confirm that the image SSH-keys in the source distribution are configured in the virtual machine and both keys exist in /usr/share/img (configurable in the future). During the runtime of IMGer, it is possible that ssh-keys inside the image may change, this is already handled by IMGer by ignoring the host key checking. | ||
= BOSS Workitem definition = | = BOSS Workitem definition = | ||
| Line 241: | Line 273: | ||
"type":type, from values: livecd, liveusb, loop, raw, nand, mrstnand, vdi or vmdk | "type":type, from values: livecd, liveusb, loop, raw, nand, mrstnand, vdi or vmdk | ||
"name":name, a simple string for the image name | "name":name, a simple string for the image name | ||
| - | + | "arch":architecture, for image | |
| + | "release":release | ||
== Output == | == Output == | ||
| Line 251: | Line 284: | ||
Image: A direct URL to the finished image | Image: A direct URL to the finished image | ||
Log: A direct URL to the log file of the mic2 output | Log: A direct URL to the log file of the mic2 output | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
Contents |
IMG (Image Me Give) is a small python client/server application suite, its sole job is to get a kickstart file from a user, via a web interface, command line or BOSS process. Then it runs Moblin-Image-Creator, either in a host or in a VM. IMG also has the capability to run as a BOSS participant and thus be a part of a build process.
The application consists of two parts, django frontend and the actual image creation application. Both of them are connected via AMQP, RabbitMQ is used as the server.
So an example workflow, in AMQP:
And an example workflow, in BOSS:
TO BE DONE
The worker code is responsible of running mic2 either locally or on a virtual machine. The initialisation code takes care of creating the necessary command stubs for mic2 use for either implementations. It also handles the KVM creation command stubs.
The method "build" is where the actual business happens. It runs in two ways, as described earlier.
In KVM mode, it first creates an overlay image from the base image (not distributed) and then starts it using the overlay image as the hard disk. Virtio is used as a speed optimisation method for KVM. When a specific amount of time has passed, it will copy the kickstart and mic2 config file to the guest VM. Then it runs mic2 in the VM with parameters specified in the init method. After mic2 has run, the image is copied from the guest using scp.
In local mode, only mic2 is run on the host machine. It will create the image based on the options in the init method along with the kickstart file.
See boss_build_image.py for the source code.
The general design of the client is pretty much the same as the AMQP server, since they both get activated and then call the worker code to create the image, with or without KVM. The worker code is described in the section above.
More information about BOSS [Infrastructure/BOSS].
See boss_img_client.py for example BOSS client.
Usage: boss_client.py -n|--name <name> -t|--type <imagetype> -e|--email <author@email> -r|--release <release> -a|--arch <arch >-s|--submit -k <kickstart_file.ks>
boss_client.py Sends a message (poll for result later) to the BOSS, using <kickstart.ks> as the kickstart file.
Options:
-h, --help show this help message and exit
-s, --submit Submit to BOSS, takes no options
-k KICKSTART, --kickstart=KICKSTART
Kickstart file
-t TYPE, --type=TYPE Image type
-n NAME, --name=NAME Image name
-e EMAIL, --email=EMAIL
Author email
-r RELEASE --release Image release, goes directly to mic2
-a ARCH --arch Architecture to use
See build_image.py for example server.
This section documents the server component of IMG.
'error': Contains the error message of the exception received from the python subprocess call. 'id': identification string of the original message sent to "image_queue" queue 'url': Contains the URL from which one can download the log
'url': Contains the URL from which one can download the image
'id': identification string of the original message sent to "image_queue" queue
Queues for exchange "image_exchange":
Queues for exchange "django_result_exchange":
For demonstration see img_client.py for example client.
img_client.py -p|--poll <id> -n|--name <name> -t|--type <imagetype> -e|--email <author@email> -r|--release -a|--arch s|--submit -k <kickstart_file.ks>"
where:
This client version uses AMQP as the message bus to communicate with the server. The format for the messages is described in the next part of this document.
The general message format is JSON encoded dictionary.
To initialize the actual image building, send a JSON formatted message as follows:
{'email':email, 'id':id, 'imagetype':imagetype, 'ksfile':ksfile, 'name': name, 'arch':arch, 'release':release}
where:
url(r'submit/$', 'meego_img.app.views.submit', name='img-app-submit'), url(r'queue/$', 'meego_img.app.views.queue', name='img-app-queue'), url(r'job/(?P<msgid>\S+)$', 'meego_img.app.views.job', name='img-app-job'), url(r'images/(?P<msgid>\S+)$', 'meego_img.app.views.download',name='img-app-download'),
IMG currently has only one model, !ImageJob, here is the Django code for it:
# Create your models here.
class ImageJob(models.Model):
email = models.CharField(max_length=40)
filename = models.CharField(max_length=40)
logfile = models.CharField(max_length=50)
task_id = models.CharField(max_length=30)
imagefile = models.CharField(max_length=50)
created = models.DateTimeField(auto_now_add=True)
error = models.CharField(max_length=500)
type = models.CharField(max_length=10)
status = models.CharField(max_length=30)
def delete(self, *args, **kwargs):
if self.logfile:
if os.path.exists(self.logfile):
os.remove(self.logfile)
os.remove(self.logfile.replace("-log", ""))
print "Removed %s"%self.logfile
super(ImageJob, self).delete(*args, **kwargs)
As can be seen in the delete method, this model cleans up all image creation related files, like the kickstarter file and log file.
Contains the following fields
The configuration file is to be installed in /etc/imger/img.conf and a sample file is here.
base_url: A base URL that has a direct access to the base_dir via HTTP, example http://127.0.0.1 base_dir: A directory to put the finished images, example /var/www/images num_workers: Number of workers to start, OBSOLETE, USE INITSCRIPT OR MANUALLY RUN MANY PARTICIPANTS post_creation: Path to a script to run after the image is created use_kvm: Wether to use a virtual machine, values are "yes" or "no"
mic_opts: Example, mic_opts = --save-kernel, --use_comps, so comma separated options
amqp_host: Host that runs BOSS amqp_user: Username to tap into the BOSS virtual host amqp_pwd: Password amqp_vhost: The actual virtual host to connect to
Currently, IMGer can run the MIC2 jobs inside a KVM virtual machine, the only prerequisites are that image is located in /usr/share/img/base.img (configurable in the future) path and that the virtual machine has MIC2 installed and configured.
Suse studio is one way to create the images, just make sure that you have a rpm repository which contains mic2, python-xml and qemu-static-arm to make mic2 run properly on the image.
One must also confirm that the image SSH-keys in the source distribution are configured in the virtual machine and both keys exist in /usr/share/img (configurable in the future). During the runtime of IMGer, it is possible that ssh-keys inside the image may change, this is already handled by IMGer by ignoring the host key checking.
The following defines the input dictionary for the participant:
"kickstart" : a kickstart file, in raw, not a path "email": email address, not parsed so can be a dummy address "id": a simple UUID, eg. from pythons uuid library "type":type, from values: livecd, liveusb, loop, raw, nand, mrstnand, vdi or vmdk "name":name, a simple string for the image name "arch":architecture, for image "release":release
The work item can contain the following dictionary entries:
Status: Status, is either "DONE" or "ERROR" in the final workitem, depending on success/failure URL: URL to a image/log/kickstart file location on the worker Error: An error string with details of the error, if any Image: A direct URL to the finished image Log: A direct URL to the log file of the mic2 output