Commit 5da9c082 authored by Łukasz Nowak's avatar Łukasz Nowak

kvm: Improve boot image url handling

image-download-controller raises error state during download process, to
inform other components that download is not ready yet.

template-kvm-run.in asserts presence of all images and otherwise refuses to
start, so that it gives chance for the image to being downloaded.

Sorting images happen by proper key instead of needless links.

Fix race condition, as the hash parameter shall depend on boot image url
configuration, and not it's failure state.
parent a9e7b041
......@@ -19,7 +19,7 @@ md5sum = 087f226ba90928dcc5a722d7008c867a
[template-kvm]
filename = instance-kvm.cfg.jinja2
md5sum = baa3ee5b653731124bfc2ac2fa835787
md5sum = 2ff55931eab48f7992e8e1cb16b44b95
[template-kvm-cluster]
filename = instance-kvm-cluster.cfg.jinja2.in
......@@ -55,7 +55,7 @@ md5sum = a8cf453d20f01c707f02c4b4014580d8
[template-kvm-run]
filename = template/template-kvm-run.in
md5sum = 875261817970d0f83335824373288b9d
md5sum = 395ee373ccda3382d257fde1ff4222b0
[template-kvm-controller]
filename = template/kvm-controller-run.in
......@@ -79,11 +79,11 @@ md5sum = d57764bb7135037b4d21543b2f56ce1d
[image-download-controller]
filename = template/image-download-controller.py
md5sum = 9c67058edcc4edae0b57956c0932a9fc
md5sum = 4d48b3da5bc611fc6533335b5953c840
[image-download-config-creator]
filename = template/image-download-config-creator.py
md5sum = 54261e418ab9860efe73efd514c4d47f
md5sum = 8fbe05c4175a7f31b6bffced9ad4e91d
[whitelist-firewall-download-controller]
filename = template/whitelist-firewall-download-controller.py
......
......@@ -162,7 +162,8 @@ config-filename = ${boot-image-url-select-json-config:error-state-file}
# wrapper to execute boot-image-url-select-download on each run
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/boot-image-url-select-updater
command-line = {{ python_executable }} {{ image_download_controller }} ${boot-image-url-select-json-config:rendered} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-select-processed-config:processed-md5sum}
command-line = {{ python_executable }} {{ image_download_controller }} ${:config} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-select-processed-config:processed-md5sum}
config = ${boot-image-url-select-json-config:rendered}
md5sum-state-filename = boot-image-url-select-download-controller-md5sum-fail.json
md5sum-state-file = ${directory:boot-image-url-select-expose}/${:md5sum-state-filename}
error-state-filename = boot-image-url-select-download-controller-error.text
......@@ -258,7 +259,8 @@ config-filename = ${boot-image-url-list-json-config:error-state-file}
# wrapper to execute boot-image-url-list-download on each run
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/boot-image-url-list-updater
command-line = {{ python_executable }} {{ image_download_controller }} ${boot-image-url-list-json-config:rendered} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-list-processed-config:processed-md5sum}
command-line = {{ python_executable }} {{ image_download_controller }} ${:config} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${boot-image-url-list-processed-config:processed-md5sum}
config = ${boot-image-url-list-json-config:rendered}
md5sum-state-filename = boot-image-url-list-download-controller-md5sum-fail.json
md5sum-state-file = ${directory:boot-image-url-list-expose}/${:md5sum-state-filename}
error-state-filename = boot-image-url-list-download-controller-error.text
......@@ -355,7 +357,8 @@ config-filename = ${virtual-hard-drive-url-json-config:error-state-file}
# wrapper to execute virtual-hard-drive-url-download on each run
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/virtual-hard-drive-url-updater
command-line = {{ python_executable }} {{ image_download_controller }} ${virtual-hard-drive-url-json-config:rendered} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${virtual-hard-drive-url-processed-config:processed-md5sum}
command-line = {{ python_executable }} {{ image_download_controller }} ${:config} {{ curl_executable_location }} ${:md5sum-state-file} ${:error-state-file} ${virtual-hard-drive-url-processed-config:processed-md5sum}
config = ${virtual-hard-drive-url-json-config:rendered}
md5sum-state-filename = virtual-hard-drive-url-download-controller-md5sum-fail.json
md5sum-state-file = ${directory:virtual-hard-drive-url-expose}/${:md5sum-state-filename}
error-state-filename = virtual-hard-drive-url-download-controller-error.text
......@@ -547,13 +550,13 @@ command = [ ! -f {{ '${' + key + '}' }} ] && touch {{ '${' + key + '}' }}
{%- endmacro %}
{#- Create depending sections, as state files appear late, so it's better to have empty file which will impact the hash anyway #}
{%- if boot_image_url_list_enabled %}
{{ generate_depend_section('boot-image-url-list-depend', 'boot-image-url-list-download-wrapper:md5sum-state-file') }}
{{ generate_depend_section('boot-image-url-list-depend', 'boot-image-url-list-download-wrapper:config') }}
{%- endif %}
{%- if boot_image_url_select_enabled %}
{{ generate_depend_section('boot-image-url-select-depend', 'boot-image-url-select-download-wrapper:md5sum-state-file') }}
{{ generate_depend_section('boot-image-url-select-depend', 'boot-image-url-select-download-wrapper:config') }}
{%- endif %}
{%- if virtual_hard_drive_url_enabled %}
{{ generate_depend_section('virtual-hard-drive-url-depend', 'virtual-hard-drive-url-download-wrapper:md5sum-state-file') }}
{{ generate_depend_section('virtual-hard-drive-url-depend', 'virtual-hard-drive-url-download-wrapper:config') }}
{%- endif %}
[kvm-instance]
......
......@@ -51,7 +51,7 @@ if __name__ == "__main__":
'url': url,
'destination': md5sum,
'destination-tmp': md5sum + '_tmp',
'link': 'image_%03i' % (image_number,),
'image-number': '%03i' % (image_number,),
})
else:
print('INF: checksum %s repeated, used url %s' % (url, ))
......
......@@ -41,11 +41,13 @@ if __name__ == "__main__":
print('ERR: There are problems with configuration')
print('INF: Storing errors in %s' % (error_state_file,))
# switch to error state during image download
with open(error_state_file, 'w') as fh:
fh.write('\n'.join(['INF Download in progress']))
# clean the destination directory
file_to_keep_list = []
for image in config['image-list']:
file_to_keep_list.append(image['destination'])
file_to_keep_list.append(image['link'])
for fname in os.listdir(config['destination-directory']):
if fname not in file_to_keep_list:
print('INF: Removing obsolete %s' % (fname,))
......@@ -118,20 +120,6 @@ if __name__ == "__main__":
os.rename(destination_tmp, destination)
print('INF: %s : Stored with checksum %s' % (
image['url'], image['md5sum']))
for image in config['image-list']:
destination = os.path.join(
config['destination-directory'], image['destination'])
link = os.path.join(config['destination-directory'], image['link'])
if os.path.exists(destination):
if os.path.lexists(link):
if not os.path.islink(link):
os.remove(link)
if os.path.islink(link) and os.readlink(link) != destination:
os.remove(link)
if not os.path.lexists(link):
print('INF: %s : Symlinking %s -> %s' % (
image['url'], link, destination))
os.symlink(destination, link)
with open(md5sum_fail_file, 'w') as fh:
if new_md5sum_state_dict != {}:
json.dump(new_md5sum_state_dict, fh, indent=2)
......
......@@ -329,6 +329,22 @@ if cpu_model:
if rgx.match(cpu_model):
kvm_argument_list.extend(['-cpu', cpu_model])
def handle_image(config, name):
with open(config) as fh:
image_config = json.load(fh)
if image_config['error-amount'] == 0:
for image in sorted(image_config['image-list'], key=lambda k: k['image-number']):
destination = os.path.join(image_config['destination-directory'], image['destination'])
if os.path.exists(destination):
kvm_argument_list.extend([
'-drive',
'file=%s,media=cdrom' % (destination,)
])
else:
raise ValueError('%s not ready yet' % (name,))
else:
raise ValueError('%s not ready yet' % (name,))
# Try to connect to NBD server (and second nbd if defined).
# If not available, don't even specify it in qemu command line parameters.
# Reason: if qemu starts with unavailable NBD drive, it will just crash.
......@@ -350,33 +366,10 @@ else:
# Debian installation CDs, rendering it uninstallable
if boot_image_url_select_json_config:
# Support boot-image-url-select
with open(boot_image_url_select_json_config) as fh:
image_config = json.load(fh)
if image_config['error-amount'] == 0:
for image in sorted(image_config['image-list'], key=lambda k: k['link']):
link = os.path.join(image_config['destination-directory'], image['link'])
if os.path.exists(link) and os.path.islink(link):
kvm_argument_list.extend([
'-drive',
'file=%s,media=cdrom' % (link,)
])
else:
raise ValueError('boot-image-url-select not ready yet')
handle_image(boot_image_url_select_json_config, 'boot-image-url-select')
if boot_image_url_list_json_config:
# Support boot-image-url-list
with open(boot_image_url_list_json_config) as fh:
image_config = json.load(fh)
if image_config['error-amount'] == 0:
for image in sorted(image_config['image-list'], key=lambda k: k['link']):
link = os.path.join(image_config['destination-directory'], image['link'])
if os.path.exists(link) and os.path.islink(link):
kvm_argument_list.extend([
'-drive',
'file=%s,media=cdrom' % (link,)
])
else:
raise ValueError('boot-image-url-list not ready yet')
handle_image(boot_image_url_list_json_config, 'boot-image-url-list')
# Always add by default the default image
kvm_argument_list.extend([
'-drive', 'file=%s,media=cdrom' % default_cdrom_iso
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment