def import_template(template, vm_type, storage_pool=None): """Import external template into ON storage pool""" config = get_config() if not storage_pool: storage_pool = config.getstring('general', 'default-storage-pool') if not os.path.exists(template): raise RuntimeError("Template not found: %s" % template) if not template.endswith('tar') or template.endswith('ova'): raise RuntimeError("Expecting a file ending with .tar or .ova for a template") tmpl_name = os.path.basename(template) target_file = os.path.join(storage.get_pool_path(storage_pool), vm_type, tmpl_name) log.info("Copying template to the storage pool... %s -> %s" % (template, target_file)) unfinished_local = "%s.unfinished" % tmpl_name shutil.copyfile(template, unfinished_local) calculate_hash(unfinished_local) log.info("Unpacking template %s..." % tmpl_name) extension = 'ova' if template.endswith('ova') else 'tar' unpack_template(storage_pool, vm_type, tmpl_name.rstrip('.%s' % extension)) os.rename(unfinished_local, target_file) os.rename(unfinished_local + '.pfff', '%s.pfff' % (target_file, extension))
def _deploy_vm(vm_parameters, logger=None): from opennode.cli import actions storage_pool = actions.storage.get_default_pool() if storage_pool is None: raise Exception("Storage pool not defined") assert type( vm_parameters) is dict, 'Parameters must be a dict: %s' % vm_parameters vm_type = vm_parameters['vm_type'] template = vm_parameters['template_name'] # convert diskspace from MBs to GBs if 'disk' in vm_parameters: assert float(vm_parameters['disk']) > 1 and float(vm_parameters['disk']) < 600,\ 'Provided disk size is strange - MB vs GB issue?' if not template: if logger: logger("Cannot deploy because template is '%s'" % (template)) raise Exception("Cannot deploy because template is '%s'" % (template)) if vm_type == 'openvz': uuid = vm_parameters['uuid'] try: conn = libvirt.open('openvz:///system') deployed_uuid_list = [ivm['uuid'] for ivm in _list_vms(conn)] if uuid in deployed_uuid_list: msg = ( 'Deployment failed: a VM with UUID %s is already deployed ' '(%s)' % (uuid, deployed_uuid_list)) logging.error(msg) return logging.info('Deploying %s: %s', uuid, deployed_uuid_list) finally: conn.close() ovf_file = OvfFile( os.path.join(get_pool_path(storage_pool), vm_type, "unpacked", template + ".ovf")) vm = actions.vm.get_module(vm_type) settings = vm.get_ovf_template_settings(ovf_file) settings.update(vm_parameters) for disk in settings.get("disks", []): if disk["deploy_type"] == "file": volume_name = disk.get("source_file") or "disk" disk["source_file"] = '%s--%s.%s' % ( volume_name, settings["uuid"], disk.get('template_format', 'qcow2')) if not get_config().getboolean('general', 'disable_vm_sys_adjustment', False): errors = vm.adjust_setting_to_systems_resources(settings) if errors: if logger: logger("Got %s" % (errors, )) raise Exception("got errors %s" % (errors, )) vm.deploy(settings, storage_pool)
def get_active_template_settings(vm_name, storage_pool): """ Reads ovf settings of the specified VM """ ovf_fnm = path.join(get_pool_path(storage_pool), "openvz", "unpacked", get_template_name(vm_name) + ".ovf") if path.exists(ovf_fnm): ovf_file = OvfFile(ovf_fnm) return get_ovf_template_settings(ovf_file) else: return read_default_ovf_settings()
def get_local_templates(vm_type, storage_pool=None): """Returns a list of templates of a certain vm_type from the storage pool""" config = get_config() if not storage_pool: storage_pool = config.getstring('general', 'default-storage-pool') return [os.path.splitext(tmpl)[0] for tmpl in os.listdir("%s/%s" % (storage.get_pool_path(storage_pool), vm_type)) if tmpl.endswith('tar') or tmpl.endswith('ova')]
def get_template_info(template_name, vm_type, storage_pool=None): config = get_config() if not storage_pool: storage_pool = config.getstring("general", "default-storage-pool") ovf_file = OvfFile(os.path.join(storage.get_pool_path(storage_pool), vm_type, "unpacked", template_name + ".ovf")) vm = vm_ops.get_module(vm_type) template_settings = vm.get_ovf_template_settings(ovf_file) # XXX handle modification to system params # errors = vm.adjust_setting_to_systems_resources(template_settings) return template_settings
def _deploy_vm(vm_parameters, logger=None): from opennode.cli import actions storage_pool = actions.storage.get_default_pool() if storage_pool is None: raise Exception("Storage pool not defined") assert type(vm_parameters) is dict, 'Parameters must be a dict: %s' % vm_parameters vm_type = vm_parameters['vm_type'] template = vm_parameters['template_name'] # convert diskspace from MBs to GBs if 'disk' in vm_parameters: assert float(vm_parameters['disk']) > 1 and float(vm_parameters['disk']) < 600,\ 'Provided disk size is strange - MB vs GB issue?' if not template: if logger: logger("Cannot deploy because template is '%s'" % (template)) raise Exception("Cannot deploy because template is '%s'" % (template)) if vm_type == 'openvz': uuid = vm_parameters['uuid'] try: conn = libvirt.open('openvz:///system') deployed_uuid_list = [ivm['uuid'] for ivm in _list_vms(conn)] if uuid in deployed_uuid_list: msg = ('Deployment failed: a VM with UUID %s is already deployed ' '(%s)' % (uuid, deployed_uuid_list)) logging.error(msg) return logging.info('Deploying %s: %s', uuid, deployed_uuid_list) finally: conn.close() ovf_file = OvfFile(os.path.join(get_pool_path(storage_pool), vm_type, "unpacked", template + ".ovf")) vm = actions.vm.get_module(vm_type) settings = vm.get_ovf_template_settings(ovf_file) settings.update(vm_parameters) for disk in settings.get("disks", []): if disk["deploy_type"] == "file": volume_name = disk.get("source_file") or "disk" disk["source_file"] = '%s--%s.%s' % (volume_name, settings["uuid"], disk.get('template_format', 'qcow2')) if not get_config().getboolean('general', 'disable_vm_sys_adjustment', False): errors = vm.adjust_setting_to_systems_resources(settings) if errors: if logger: logger("Got %s" % (errors,)) raise Exception("got errors %s" % (errors,)) vm.deploy(settings, storage_pool)
def get_template_info(template_name, vm_type, storage_pool=None): config = get_config() if not storage_pool: storage_pool = config.getstring('general', 'default-storage-pool') ovf_file = OvfFile(os.path.join(storage.get_pool_path(storage_pool), vm_type, "unpacked", template_name + ".ovf")) vm = vm_ops.get_module(vm_type) template_settings = vm.get_ovf_template_settings(ovf_file) # XXX handle modification to system params #errors = vm.adjust_setting_to_systems_resources(template_settings) return template_settings
def link_template(storage_pool, tmpl_name, overwrite=True): """Setup symlinks from the OpenVZ template to the location expected by vzctl""" # added resilience. Openvz templates are distributed as tarballs, so sometimes # name and name.tar.gz are used in a mixed way config = get_config() if not tmpl_name.endswith('.tar.gz'): tmpl_name = tmpl_name + '.tar.gz' source_file = os.path.join(get_pool_path(storage_pool), 'openvz', 'unpacked', tmpl_name) dest_file = os.path.join(config.getstring('general', 'openvz-templates'), tmpl_name) if overwrite: try: os.unlink(dest_file) except OSError as exc: if exc.errno != errno.ENOENT: raise if not os.path.exists(dest_file): os.symlink(source_file, dest_file)
def unpack_template(storage_pool, vm_type, tmpl_name): """Unpacks template into the 'unpacked' folder of the storage pool. Adds symlinks as needed by the VM template vm_type.""" # we assume location of the 'unpacked' to be the same as the location of the file basedir = os.path.join(storage.get_pool_path(storage_pool), vm_type) if os.path.exists(os.path.join(basedir, "%s.tar" % tmpl_name)): tar_name = os.path.join(basedir, "%s.tar" % tmpl_name) if os.path.exists(os.path.join(basedir, "%s.ova" % tmpl_name)): tar_name = os.path.join(basedir, "%s.ova" % tmpl_name) tmpl = tarfile.open(tar_name) unpacked_dir = os.path.join(basedir, 'unpacked') tmpl.extractall(unpacked_dir) # special case for openvz vm_type if vm_type == 'openvz': from opennode.cli.actions import vm tmpl_name = [fnm for fnm in tmpl.getnames() if fnm.endswith('tar.gz') and not fnm.endswith('scripts.tar.gz')] # make sure we have only a single tarball with the image assert len(tmpl_name) == 1 vm.openvz.link_template(storage_pool, tmpl_name[0])
def unpack_template(storage_pool, vm_type, tmpl_name): """Unpacks template into the 'unpacked' folder of the storage pool. Adds symlinks as needed by the VM template vm_type.""" # we assume location of the 'unpacked' to be the same as the location of the file basedir = os.path.join(storage.get_pool_path(storage_pool), vm_type) tar_name = "" if os.path.exists(os.path.join(basedir, "%s.tar" % tmpl_name)): tar_name = os.path.join(basedir, "%s.tar" % tmpl_name) if os.path.exists(os.path.join(basedir, "%s.ova" % tmpl_name)): tar_name = os.path.join(basedir, "%s.ova" % tmpl_name) tmpl = tarfile.open(tar_name) unpacked_dir = os.path.join(basedir, 'unpacked') tmpl.extractall(unpacked_dir) # special case for openvz vm_type if vm_type == 'openvz': from opennode.cli.actions import vm tmpl_name = [fnm for fnm in tmpl.getnames() if fnm.endswith('tar.gz') and not fnm.endswith('scripts.tar.gz')] # make sure we have only a single tarball with the image assert len(tmpl_name) == 1 vm.openvz.link_template(storage_pool, tmpl_name[0])
def import_template(template, vm_type, storage_pool=None): """Import external template into ON storage pool""" config = get_config() if not storage_pool: storage_pool = config.getstring("general", "default-storage-pool") if not os.path.exists(template): raise RuntimeError("Template not found: %s" % template) if not (template.endswith("tar") or template.endswith("ova")): raise RuntimeError("Expecting a file ending with .tar or .ova for a template, %s" % template) tmpl_name = os.path.basename(template) target_file = os.path.join(storage.get_pool_path(storage_pool), vm_type, tmpl_name) log.info("Copying template to the storage pool... %s -> %s" % (template, target_file)) shutil.copyfile(template, target_file) calculate_hash(target_file) log.info("Unpacking template %s..." % target_file) extension = "ova" if template.endswith("ova") else "tar" unpack_template(storage_pool, vm_type, tmpl_name.rstrip(".%s" % extension))
def import_template(template, vm_type, storage_pool=None): """Import external template into ON storage pool""" config = get_config() if not storage_pool: storage_pool = config.getstring('general', 'default-storage-pool') if not os.path.exists(template): raise RuntimeError("Template not found: %s" % template) if not (template.endswith('tar') or template.endswith('ova')): raise RuntimeError("Expecting a file ending with .tar or .ova for a template, %s" % template) tmpl_name = os.path.basename(template) target_file = os.path.join(storage.get_pool_path(storage_pool), vm_type, tmpl_name) log.info("Copying template to the storage pool... %s -> %s" % (template, target_file)) shutil.copyfile(template, target_file) calculate_hash(target_file) log.info("Unpacking template %s..." % target_file) extension = 'ova' if template.endswith('ova') else 'tar' unpack_template(storage_pool, vm_type, tmpl_name.rstrip('.%s' % extension))
def sync_template(remote_repo, template, storage_pool, silent=False): """Synchronizes local template (cache) with the remote one (master)""" config = get_config() url = config.getstring(remote_repo, 'url') vm_type = config.getstring(remote_repo, 'type') localfile = os.path.join(storage.get_pool_path(storage_pool), vm_type, template) remotefile = urlparse.urljoin(url.rstrip('/') + '/', template) # only download if we don't already have a fresh copy if is_fresh(localfile, remotefile): return extension = "ova" if _url_exists("%s.ova" % remotefile) else "tar" unfinished_local = "%s.%s.unfinished" % (localfile, extension) unfinished_local_hash = "%s.%s.pfff.unfinished" % (localfile, extension) remote_url = "%s.%s" % (remotefile, extension) if not _url_exists(remote_url): raise TemplateException("Remote template was not found: %s" % remote_url) retries = 5 retry = 0 while not is_fresh(localfile, remotefile, unfinished=True) and retries > retry: # for resilience retry += 1 storage.prepare_storage_pool(storage_pool) download("%s.%s" % (remotefile, extension), unfinished_local, continue_=True, silent=silent) r_template_hash = "%s.%s.pfff" % (remotefile, extension) download(r_template_hash, unfinished_local_hash, continue_=True, silent=silent) os.rename(unfinished_local, '%s.%s' % (localfile, extension)) os.rename(unfinished_local_hash, '%s.%s.pfff' % (localfile, extension)) unpack_template(storage_pool, vm_type, localfile)