def domain_xml_to_test(domain_id, ssl=True): id = domain_id # INFO TO DEVELOPER, QUE DE UN ERROR SI EL ID NO EXISTE dict_domain = get_domain(domain_id) xml = dict_domain['xml'] x = DomainXML(xml) if ssl is True: x.reset_viewer_passwd() else: x.spice_remove_passwd_nossl() x.remove_selinux_options() x.remove_boot_order_from_disks() xml = x.return_xml() log.debug('#####################################################3') log.debug('#####################################################3') log.debug('#####################################################3') log.debug('#####################################################3') log.debug(xml) log.debug('#####################################################3') log.debug('#####################################################3') log.debug('#####################################################3') log.debug('#####################################################3') x.dict_from_xml() update_domain_dict_hardware(id, x.vm_dict, xml=xml) # update_domain_viewer_started_values(id,passwd=x.viewer_passwd) return xml
def deleting_disks_from_domain(self, id_domain, force=False): # ALBERTO FALTA ACABAR dict_domain = get_domain(id_domain) if dict_domain['kind'] != 'desktop' and force is False: log.info('{} is a template, disks will be deleted') if len(dict_domain['hardware']['disks']) > 0: index_disk = 0 for d in dict_domain['hardware']['disks']: disk_path = d['file'] pool_id = dict_domain['hypervisors_pools'][0] if pool_id not in self.manager.pools.keys(): log.error( 'hypervisor pool {} nor running in manager, can\'t delete disks in domain {}'.format(pool_id, id_domain)) return False next_hyp = self.manager.pools[pool_id].get_next() log.debug('hypervisor where delete disk {}: {}'.format(disk_path, next_hyp)) cmds = create_cmds_delete_disk(disk_path) action = dict() action['id_domain'] = id_domain action['type'] = 'delete_disk' action['disk_path'] = disk_path action['domain'] = id_domain action['ssh_commands'] = cmds action['index_disk'] = index_disk try: update_domain_status(status='DeletingDomainDisk', id_domain=id_domain, hyp_id=False, detail='Deleting disk {} in domain {}, queued in hypervisor thread {}'.format( disk_path, id_domain, next_hyp )) self.manager.q.workers[next_hyp].put(action) except Exception as e: update_domain_status(status='Stopped', id_domain=id_domain, hyp_id=False, detail='Creating template operation failed when insert action in queue for disk operations') log.error( 'Creating disk operation failed when insert action in queue for disk operations in host {}. Exception: {}'.format( next_hyp, e)) return False index_disk += 1 else: log.debug('no disk to delete in domain {}'.format(id_domain)) return True
def recreate_xml_to_start(id, ssl=True): dict_domain = get_domain(id) xml = dict_domain['xml'] x = DomainXML(xml) ##### actions to customize xml # spice password if ssl is True: x.reset_viewer_passwd() else: # only for test purposes, not use in production x.spice_remove_passwd_nossl() # redo network try: list_interfaces = dict_domain['create_dict']['hardware']['interfaces'] except KeyError: list_interfaces = [] log.info('domain {} withouth key interfaces in crate_dict'.format(id)) mac_address = [] for interface_index in range(len(x.vm_dict['interfaces'])): mac_address.append(x.vm_dict['interfaces'][interface_index]['mac']) x.remove_interface(order=interface_index) interface_index = 0 for id_interface in list_interfaces: d_interface = get_interface(id_interface) x.add_interface(type=d_interface['kind'], id=d_interface['ifname'], model_type=d_interface['model'], mac=mac_address[interface_index]) interface_index += 1 x.remove_selinux_options() #remove boot order in disk definition that conflict with /os/boot order in xml x.remove_boot_order_from_disks() x.dict_from_xml() # INFO TO DEVELOPER, OJO, PORQUE AQUI SE PIERDE EL BACKING CHAIN?? update_domain_dict_hardware(id, x.vm_dict, xml=xml) if 'viewer_passwd' in x.__dict__.keys(): update_domain_viewer_started_values(id, passwd=x.viewer_passwd) log.debug("updated viewer password {} in domain {}".format(x.viewer_passwd, id)) xml = x.return_xml() # log.debug('#####################################################') # log.debug(xml) # log.debug('#####################################################') return xml
def create_template_in_db(self, id_domain): domain_dict = get_domain(id_domain) template_dict = domain_dict['create_dict']['template_dict'] template_dict['status'] = 'CreatingNewTemplateInDB' template_id = template_dict['id'] if insert_domain(template_dict)['inserted'] == 1: hw_dict = domain_dict['hardware'].copy() for i in range(len(hw_dict['disks'])): hw_dict['disks'][i]['file'] = template_dict['create_dict'][ 'hardware']['disks'][i]['file'] update_table_field('domains', template_id, 'hardware', hw_dict, merge_dict=False) xml_parsed = update_xml_from_dict_domain(id_domain=template_id, xml=domain_dict['xml']) if xml_parsed is False: update_domain_status( status='Failed', id_domain=template_id, hyp_id=False, detail='XML Parser Error, xml is not valid') return False remove_disk_template_created_list_in_domain(id_domain) remove_dict_new_template_from_domain(id_domain) if 'parents' in domain_dict.keys(): domain_parents_chain_update = domain_dict['parents'].copy() else: domain_parents_chain_update = [] domain_parents_chain_update.append(template_id) update_table_field('domains', id_domain, 'parents', domain_parents_chain_update) update_origin_and_parents_to_new_template(id_domain, template_id) # update_table_field('domains', template_id, 'xml', xml_parsed, merge_dict=False) update_domain_status( status='Stopped', id_domain=template_id, hyp_id=False, detail= 'Template created, ready to create domains from this template') update_domain_status( status='Stopped', id_domain=id_domain, hyp_id=False, detail= 'Template created from this domain, now domain is ready to start again' ) else: log.error( 'template {} can not be inserted in rethink, domain_id duplicated??' .format(template_id)) return False
def _get_hyp_domain_running(self, domain_id): d = get_domain(domain_id) assert d['status'] == "Started" hyp_id = d["hyp_started"] try: hyp = list(filter(lambda h: h.id == hyp_id, self.hyps))[0] except: hmlog.debug("Hyp_id: {}".format(hyp_id)) hmlog.debug(format_exc()) template_id = d['create_dict']['origin'] return hyp_id, hyp, template_id
def get_next(self, args): domain_id = args.get("domain_id") for hyp_id, hyp in self.hyps.items(): cpu_free, cpu_power, cpu_ratio, ram_free = self._get_stats(hyp) ps = self._calcule_ps(cpu_free, cpu_power, cpu_ratio, ram_free) hyp.ps = ps hyp_id_best_ps, hyp = max(self.hyps.items(), key=lambda v: v[1].ps) if domain_id: d = get_domain(domain_id) self._recalcule_stats(hyp, d) return hyp_id_best_ps
def _create_eval_domain(self, id_t, i): d = DICT_CREATE.copy() t = get_domain(id_t) id_domain = "_eval_{}_{}".format(id_t, i) disk_path = "{}/{}/{}/{}.qcow2".format(self.user['category'], self.user['group'], self.user['id'], id_domain) d['create_dict']['hardware']['disks'][0]['file'] = disk_path d['create_dict']['hardware']['disks'][0]['parent'] = t['disks_info'][0]['filename'] d['create_dict']['hardware']['memory'] = t['create_dict']['hardware']['memory'] d['create_dict']['hardware']['currentMemory'] = t['create_dict']['hardware']['memory'] # / 0,7? => +30 % d['create_dict']['origin'] = t['id'] d['id'] = id_domain d['name'] = id_domain[1:] # remove first char d['icon'] = t['icon'] d['os'] = t['os'] insert_domain(d)
def _create_eval_domain(self, id_t, i): d = DICT_CREATE.copy() t = get_domain(id_t) id_domain = "_eval_{}_{}".format(id_t, i) disk_path = "{}/{}/{}/{}.qcow2".format(self.user['category'], self.user['group'], self.user['id'], id_domain) d['create_dict']['hardware']['disks'][0]['file'] = disk_path d['create_dict']['hardware']['disks'][0]['parent'] = t['disks_info'][ 0]['filename'] d['create_dict']['hardware']['memory'] = t['create_dict']['hardware'][ 'memory'] d['create_dict']['hardware']['currentMemory'] = t['create_dict'][ 'hardware']['memory'] # / 0,7? => +30 % d['create_dict']['origin'] = t['id'] d['id'] = id_domain d['name'] = id_domain[1:] # remove first char d['icon'] = t['icon'] d['os'] = t['os'] insert_domain(d)
def create_template_in_db(self, id_domain): domain_dict = get_domain(id_domain) template_dict = domain_dict['create_dict']['template_dict'] template_dict['status'] = 'CreatingNewTemplateInDB' template_id = template_dict['id'] if insert_domain(template_dict)['inserted'] == 1: hw_dict = domain_dict['hardware'].copy() for i in range(len(hw_dict['disks'])): hw_dict['disks'][i]['file'] = template_dict['create_dict']['hardware']['disks'][i]['file'] update_table_field('domains', template_id, 'hardware', hw_dict, merge_dict=False) xml_parsed = update_xml_from_dict_domain(id_domain=template_id, xml=domain_dict['xml']) if xml_parsed is False: update_domain_status(status='Failed', id_domain=template_id, hyp_id=False, detail='XML Parser Error, xml is not valid') return False remove_disk_template_created_list_in_domain(id_domain) remove_dict_new_template_from_domain(id_domain) if 'parents' in domain_dict.keys(): domain_parents_chain_update = domain_dict['parents'].copy() else: domain_parents_chain_update = [] domain_parents_chain_update.append(template_id) update_table_field('domains', id_domain, 'parents', domain_parents_chain_update) update_origin_and_parents_to_new_template(id_domain,template_id) # update_table_field('domains', template_id, 'xml', xml_parsed, merge_dict=False) update_domain_status(status='Stopped', id_domain=template_id, hyp_id=False, detail='Template created, ready to create domains from this template') update_domain_status(status='Stopped', id_domain=id_domain, hyp_id=False, detail='Template created from this domain, now domain is ready to start again') else: log.error('template {} can not be inserted in rethink, domain_id duplicated??'.format(template_id)) return False
def new_template_from_domain(name, description, original_domain_id, user, group, category, kind='public_template'): id = '_' + user + '_' + name dir_disk = category + '/' + group + '/' + name disk_filename = name + '.qcow2' relative_dir = dir_disk + '/' + disk_filename old_domain = get_domain(original_domain_id) new_backing_chain = [relative_dir] new_backing_chain.append(old_domain['hardware']['disks'][0]['file']) new_hardware_dict = old_domain['hardware'] new_hardware_dict['disks'][0]['file'] = relative_dir new_hardware_dict['disks'][0]['backing_chain'] = new_backing_chain new_hardware_dict['name'] = id new_hardware_dict['uuid'] = None template_field = {'id': id, 'kind': kind, 'user': user, 'status': 'Creating', 'detail': None, 'category': category, 'group': group, 'server': False, 'hardware': new_hardware_dict, 'hypervisors_pools': old_domain['hypervisors_pools'], 'xml': None, 'name': name, 'description': description, 'icon': old_domain['icon'], 'os': old_domain['icon']} result = update_domain_createing_template(original_domain_id, template_field) if result['errors'] > 0: log.error('error when inserting new domain {} in db, duplicate id??'.format(id)) return False else: return id
def new_domain_from_template(name, description, template_origin, user, group, category): id = '_' + user + '_' + name dir_disk = category + '/' + group + '/' + name disk_filename = name + '.qcow2' relative_path = dir_disk + '/' + disk_filename template = get_domain(template_origin) # new_backing_chain = [relative_dir] # new_backing_chain.append(template['hardware']['disks'][0]['file']) base_disk_path = template['hardware']['disks'][0]['file'] new_hardware_dict = template['hardware'].copy() new_hardware_dict['disks'][0]['file'] = relative_path new_hardware_dict['disks'][0]['parent'] = base_disk_path new_hardware_dict['name'] = id new_hardware_dict['uuid'] = None domain = {'id': id, 'kind': 'desktop', 'user': user, 'status': 'Creating', 'detail': None, 'category': category, 'group': group, 'server': False, 'hardware': new_hardware_dict, 'hypervisors_pools': template['hypervisors_pools'], 'xml': template['xml'], 'name': name, 'description': description, 'icon': template['icon'], 'os': template['icon']} result = insert_domain(domain) if result['errors'] > 0: log.error('error when inserting new domain {} in db, duplicate id??'.format(id)) return False else: return id
def run(self): self.tid = get_tid() logs.changes.info('starting thread: {} (TID {})'.format( self.name, self.tid)) logs.changes.debug( '^^^^^^^^^^^^^^^^^^^ DOMAIN CHANGES THREAD ^^^^^^^^^^^^^^^^^') ui = UiActions(self.manager) self.r_conn = new_rethink_connection() cursor = r.table('domains').pluck('id', 'kind', 'status', 'detail').merge({'table': 'domains'}).changes().\ union(r.table('engine').pluck('threads', 'status_all_threads').merge({'table': 'engine'}).changes()).\ run(self.r_conn) for c in cursor: if self.stop is True: break if c.get('new_val', None) is not None: if c['new_val']['table'] == 'engine': if c['new_val']['status_all_threads'] == 'Stopping': break else: continue logs.changes.debug('domain changes detected in main thread') detail_msg_if_no_hyps_online = 'No hypervisors Online in pool' if self.manager.check_actions_domains_enabled() is False: if c.get('new_val', None) is not None: if c.get('old_val', None) is not None: if c['new_val']['status'][-3:] == 'ing': update_domain_status( c['old_val']['status'], c['old_val']['id'], detail=detail_msg_if_no_hyps_online) #if no hypervisor availables no check status changes continue new_domain = False new_status = False old_status = False import pprint logs.changes.debug(pprint.pformat(c)) # action deleted if c.get('new_val', None) is None: pass # action created if c.get('old_val', None) is None: new_domain = True new_status = c['new_val']['status'] domain_id = c['new_val']['id'] logs.changes.debug('domain_id: {}'.format(new_domain)) # if engine is stopped/restarting or not hypervisors online if self.manager.check_actions_domains_enabled() is False: continue pass if c.get('new_val', None) is not None and c.get( 'old_val', None) is not None: old_status = c['old_val']['status'] new_status = c['new_val']['status'] new_detail = c['new_val']['detail'] domain_id = c['new_val']['id'] logs.changes.debug('domain_id: {}'.format(domain_id)) # if engine is stopped/restarting or not hypervisors online if old_status != new_status: # print('&&&&&&& ID DOMAIN {} - old_status: {} , new_status: {}, detail: {}'.format(domain_id,old_status,new_status, new_detail)) # if new_status[-3:] == 'ing': if 1 > 0: date_now = datetime.now() update_domain_history_from_id_domain( domain_id, new_status, new_detail, date_now) else: # print('&&&&&&&ESTADOS IGUALES OJO &&&&&&&\n&&&&&&&& ID DOMAIN {} - old_status: {} , new_status: {}, detail: {}'. # format(domain_id,old_status,new_status,new_detail)) pass if (new_domain is True and new_status == "CreatingDiskFromScratch") or \ (old_status == 'FailedCreatingDomain' and new_status == "CreatingDiskFromScratch"): ui.creating_disk_from_scratch(domain_id) if (new_domain is True and new_status == "Creating") or \ (old_status == 'FailedCreatingDomain' and new_status == "Creating"): ui.creating_disks_from_template(domain_id) if (new_domain is True and new_status == "CreatingAndStarting"): update_domain_start_after_created(domain_id) ui.creating_disks_from_template(domain_id) # INFO TO DEVELOPER # recoger template de la que hay que derivar # verificar que realmente es una template # hay que recoger ram?? cpu?? o si no hay nada copiamos de la template?? if (new_domain is True and new_status == "CreatingFromBuilder") or \ (old_status == 'FailedCreatingDomain' and new_status == "CreatingFromBuilder"): ui.creating_disk_from_virtbuilder(domain_id) if (old_status in ['CreatingDisk','CreatingDiskFromScratch'] and new_status == "CreatingDomain") or \ (old_status == 'RunningVirtBuilder' and new_status == "CreatingDomainFromBuilder"): logs.changes.debug( 'llamo a creating_and_test_xml con domain id {}'. format(domain_id)) if new_status == "CreatingDomainFromBuilder": ui.creating_and_test_xml_start( domain_id, creating_from_create_dict=True, xml_from_virt_install=True) if new_status == "CreatingDomain": ui.creating_and_test_xml_start( domain_id, creating_from_create_dict=True) if old_status == 'Stopped' and new_status == "CreatingTemplate": ui.create_template_disks_from_domain(domain_id) if old_status == 'Stopped' and new_status == "Deleting": ui.deleting_disks_from_domain(domain_id) if (old_status == 'Stopped' and new_status == "Updating") or \ (old_status == 'Downloaded' and new_status == "Updating"): ui.updating_from_create_dict(domain_id) if old_status == 'DeletingDomainDisk' and new_status == "DiskDeleted": logs.changes.debug( 'disk deleted, mow remove domain form database') remove_domain(domain_id) if get_domain(domain_id) is None: logs.changes.info( 'domain {} deleted from database'.format( domain_id)) else: update_domain_status( 'Failed', id_domain, detail='domain {} can not be deleted from database' .format(domain_id)) if old_status == 'CreatingTemplateDisk' and new_status == "TemplateDiskCreated": # create_template_from_dict(dict_new_template) if get_if_all_disk_template_created(domain_id): ui.create_template_in_db(domain_id) else: # INFO TO DEVELOPER, este else no se si tiene mucho sentido, hay que hacer pruebas con la # creación de una template con dos discos y ver si pasa por aquí # waiting to create other disks update_domain_status( status='CreatingTemplateDisk', id_domain=domain_id, hyp_id=False, detail='Waiting to create more disks for template') if (old_status == 'Stopped' and new_status == "Starting") or \ (old_status == 'Failed' and new_status == "Starting"): ui.start_domain_from_id(id=domain_id, ssl=True) if (old_status == 'Started' and new_status == "Stopping" ) or \ (old_status == 'Suspended' and new_status == "Stopping" ): # INFO TO DEVELOPER Esto es lo que debería ser, pero hay líos con el hyp_started # ui.stop_domain_from_id(id=domain_id) hyp_started = get_domain_hyp_started(domain_id) if hyp_started: ui.stop_domain(id_domain=domain_id, hyp_id=hyp_started) else: logs.main.error( 'domain without hyp_started can not be stopped: {}. ' .format(domain_id)) if (old_status == 'Started' and new_status == "StoppingAndDeleting" ) or \ (old_status == 'Suspended' and new_status == "StoppingAndDeleting" ): # INFO TO DEVELOPER Esto es lo que debería ser, pero hay líos con el hyp_started # ui.stop_domain_from_id(id=domain_id) hyp_started = get_domain_hyp_started(domain_id) print(hyp_started) ui.stop_domain(id_domain=domain_id, hyp_id=hyp_started, delete_after_stopped=True) logs.main.info('finalished thread domain changes')
def run(self): # if self.table == 'domains': # type_path_selected = 'groups' # elif self.table in ['isos']: # type_path_selected = 'isos' # else: # type_path_selected = 'media' # # new_file, path_selected = get_path_to_disk(self.path, pool=self.pool, type_path=type_path_selected) # logs.downloads.debug("PATHS ___________________________________________________________________") # logs.downloads.debug(new_file) # logs.downloads.debug(path_selected) # logs.downloads.debug(pprint.pformat(self.__dict__)) # # hyp_to_disk_create = get_host_disk_operations_from_path(path_selected, pool=self.pool, # type_path=type_path_selected) header_template = "--header '{header_key}: {header_value}' " headers = '' for k, v in self.dict_header.items(): headers += header_template.format(header_key=k, header_value=v) ssh_template = """ssh -oBatchMode=yes -p {port} {user}@{hostname} """ \ """ "mkdir -p '{path_dir}'; curl -L -o '{path}' {headers} '{url}' " """ print(ssh_template) ssh_command = ssh_template.format(port=self.port, user=self.user, hostname=self.hostname, path=self.path, path_dir=dirname(self.path), headers=headers, url=self.url) print(ssh_command) logs.downloads.debug("SSH COMMAND: {}".format(ssh_command)) p = subprocess.Popen(ssh_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) rc = p.poll() update_status_table( self.table, 'Downloading', self.id, "downloading in hypervisor: {}".format(self.hostname)) while rc != 0: header = p.stderr.readline().decode('utf8') header2 = p.stderr.readline().decode('utf8') keys = [ 'total_percent', 'total', 'received_percent', 'received', 'xferd_percent', 'xferd', 'speed_download_average', 'speed_upload_average', 'time_total', 'time_spent', 'time_left', 'speed_current' ] line = "" while True: c = p.stderr.read(1).decode('utf8') if self.stop is True: update_domain_status(self.table, 'FailedDownload', id, detail="download aborted") break if not c: break if c == '\r': if len(line) > 60: logs.downloads.debug(line) values = line.split() print(self.url) print(line) d_progress = dict(zip(keys, values)) d_progress['total_percent'] = int( float(d_progress['total_percent'])) d_progress['received_percent'] = int( float(d_progress['received_percent'])) update_download_percent(d_progress, self.table, self.id) line = p.stderr.read(60).decode('utf8') else: line = line + c rc = p.poll() logs.downloads.info('File downloaded: {}'.format(self.path)) assert rc == 0 if self.table == 'domains': #update_table_field(self.table, self.id, 'path_downloaded', self.path) d_update_domain = get_domain(self.id)['create_dict'] #d_update_domain = {'hardware': {'disks': [{}]}} d_update_domain['hardware']['disks'][0]['file'] = self.path update_domain_dict_create_dict(self.id, d_update_domain) self.finalished_threads.append(self.path) update_domain_status('Downloaded', self.id, detail="downloaded disk") update_domain_status('Updating', self.id, detail="downloaded disk") else: self.finalished_threads.append(self.path) update_table_field(self.table, self.id, 'path_downloaded', self.path) update_status_table(self.table, 'Downloaded', self.id)
def domain_from_template(self, id_template, id_new, user, category, group, name, description, cpu, ram, current_ram=-1, id_net=None, force_server=None, only_cmds=False, path_to_disk_dir=None, disk_filename=None, create_domain_in_db=True): # INFO TO DEVELOPER: falta verificar que el id no existe y si existe salir enseguida, ya que si no haríamos updates y # creaciónes de disco peligrosas dict_domain_template = get_domain(id_template) dict_domain_new = dict_domain_template.copy() dict_domain_new['id'] = id_new dict_domain_new['user'] = user dict_domain_new['category'] = category dict_domain_new['group'] = group dict_domain_new['kind'] = 'desktop' dict_domain_new['name'] = name dict_domain_new['description'] = description dict_domain_new['status'] = 'CreatingDisk' dict_domain_new['detail'] = 'Defining new domain' if force_server == True: dict_domain_new['server'] = True elif force_server == False: dict_domain_new['server'] = False else: dict_domain_new['server'] = dict_domain_template['server'] x = DomainXML(dict_domain_template['xml']) x.set_name(id_new) x.set_title(name) x.set_description(description) old_path_disk = dict_domain_template['hardware']['disks'][0]['file'] old_path_dir = extract_dir_path(old_path_disk) DEFAULT_GROUP_DIR = CONFIG_DICT['REMOTEOPERATIONS'][ 'default_group_dir'] if path_to_disk_dir is None: path_to_disk_dir = DEFAULT_GROUP_DIR + '/' + \ dict_domain_template['category'] + '/' + \ dict_domain_template['group'] + '/' + \ dict_domain_template['user'] if len(old_path_disk[len(old_path_dir) + 1:-1].split('.')) > 1: extension = old_path_disk[len(old_path_dir) + 1:-1].split('.')[1] else: extension = 'qcow' if disk_filename is None: disk_filename = id_new + '.' + extension new_path_disk = path_to_disk_dir + '/' + disk_filename x.set_vcpu(cpu) x.set_memory(ram, current=current_ram) x.set_vdisk(new_path_disk) x.randomize_vm() dict_domain_new['hardware'] = x.vm_dict dict_domain_new['xml'] = x.return_xml() cmds = create_cmds_disk_from_base( old_path_disk, new_path_disk, ) if only_cmds is True: dict_domain_new['status'] = 'Crashed' dict_domain_new[ 'detail'] = 'Disk not created, only for testing ui purpose, create command is not launched' return dict_domain_new, cmds else: action = {} action['type'] = 'create_disk' action['disk_path'] = new_path_disk action['domain'] = id_new action['ssh_commands'] = cmds if hasattr(self.pool, 'queue_disk_operation'): self.pool.queue_disk_operation.put(action) # err,out = create_disk_from_base(old_path_disk,new_path_disk) dict_domain_new['status'] = 'CreatingDisk' dict_domain_new[ 'detail'] = 'Creating disk operation is launched ({} operations in queue)'.format( self.pool.queue_disk_operation.qsize()) # list_backing_chain = backing_chain(new_path_disk) # dict_domain_new['backing_chain'] = list_backing_chain else: log.error('queue disk operation is not created') dict_domain_new['status'] = 'Crashed' dict_domain_new[ 'detail'] = 'Disk not created, queue for disk creation does not exist' if create_domain_in_db is True: insert_domain(dict_domain_new) return dict_domain_new
def creating_disks_from_template(self, id_new): dict_domain = get_domain(id_new) if 'create_dict' in dict_domain.keys(): dict_to_create = dict_domain['create_dict'] pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] # INFO TO DEVELOPER DEBERÍA SER UN FOR PARA CADA DISCO # y si el disco no tiene backing_chain, crear un disco vacío # del tamño que marcase # d['hardware']['disks'][0]['size'] # el backing_file debería estar asociado a cada disco: # d['hardware']['disks'][0]['backing_file'] for index_disk in range(len(dict_to_create['hardware']['disks'])): relative_path = dict_to_create['hardware']['disks'][index_disk][ 'file'] new_file, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN dict_to_create['hardware']['disks'][index_disk]['file'] = new_file dict_to_create['hardware']['disks'][index_disk][ 'path_selected'] = path_selected update_table_field('domains', id_new, 'create_dict', dict_to_create) #TODO: REVISAR SI RELAMENTE ES NECESARIO o esta acción responde a versiones antiguas de nuestras funciones de creación hardware_update = {} hardware_update['disks'] = dict_to_create['hardware']['disks'] update_domain_dict_hardware(id_new, hardware_update) ################## for index_disk in range(len(dict_to_create['hardware']['disks'])): backing_file = dict_to_create['hardware']['disks'][index_disk][ 'parent'] new_file = dict_to_create['hardware']['disks'][index_disk]['file'] path_selected = dict_to_create['hardware']['disks'][index_disk][ 'path_selected'] hyp_to_disk_create = get_host_disk_operations_from_path( path_selected, pool=pool_id, type_path='groups') cmds = create_cmds_disk_from_base(path_base=backing_file, path_new=new_file) log.debug( 'commands to disk create to launch in disk_operations: \n{}'. format('\n'.join(cmds))) action = {} action['type'] = 'create_disk' action['disk_path'] = new_file action['index_disk'] = index_disk action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status( status='CreatingDisk', id_domain=id_new, hyp_id=False, detail= 'Creating disk operation is launched in hypervisor {} ({} operations in queue)' .format( hyp_to_disk_create, self.manager. q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status( status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail= 'Creating disk operation failed when insert action in queue for disk operations' ) log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}' .format(e))
def creating_disk_from_scratch(self, id_new): dict_domain = get_domain(id_new) pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] dict_to_create = dict_domain['create_dict'] if 'disks' in dict_to_create['hardware'].keys(): if len(dict_to_create['hardware']['disks']) > 0: # for index_disk in range(len(dict_to_create['hardware']['disks'])): # relative_path = dict_to_create['hardware']['disks'][index_disk]['file'] # path_new_file, path_selected = get_path_to_disk(relative_path, pool=pool_id) # # UPDATE PATH IN DOMAIN # dict_to_create['hardware']['disks'][index_disk]['file'] = new_file # dict_to_create['hardware']['disks'][index_disk]['path_selected'] = path_selected relative_path = dict_to_create['hardware']['disks'][0]['file'] path_new_disk, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN d_update_domain = {'hardware': {'disks': [{}]}} d_update_domain['hardware']['disks'][0]['file'] = path_new_disk d_update_domain['hardware']['disks'][0][ 'path_selected'] = path_selected update_domain_dict_hardware(id_new, d_update_domain) update_domain_dict_create_dict(id_new, d_update_domain) size_str = dict_to_create['hardware']['disks'][0]['size'] hyp_to_disk_create = get_host_disk_operations_from_path( path_selected, pool=pool_id, type_path='groups') cmds = create_cmd_disk_from_scratch( path_new_disk=path_new_disk, size_str=size_str) action = {} action['type'] = 'create_disk_from_scratch' action['disk_path'] = path_new_disk action['index_disk'] = 0 action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status( status='CreatingDiskFromScratch', id_domain=id_new, hyp_id=False, detail= 'Creating disk commands are launched in hypervisor {} ({} operations in queue)' .format( hyp_to_disk_create, self.manager. q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put( action) except Exception as e: update_domain_status( status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail= 'Creating disk operation failed when insert action in queue for disk operations' ) log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}' .format(e))
def creating_disks_from_template(self, id_new): dict_domain = get_domain(id_new) if 'create_dict' in dict_domain.keys(): dict_to_create = dict_domain['create_dict'] pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] # INFO TO DEVELOPER DEBERÍA SER UN FOR PARA CADA DISCO # y si el disco no tiene backing_chain, crear un disco vacío # del tamño que marcase # d['hardware']['disks'][0]['size'] # el backing_file debería estar asociado a cada disco: # d['hardware']['disks'][0]['backing_file'] for index_disk in range(len(dict_to_create['hardware']['disks'])): relative_path = dict_to_create['hardware']['disks'][index_disk]['file'] new_file, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN dict_to_create['hardware']['disks'][index_disk]['file'] = new_file dict_to_create['hardware']['disks'][index_disk]['path_selected'] = path_selected update_table_field('domains',id_new,'create_dict',dict_to_create) #TODO: REVISAR SI RELAMENTE ES NECESARIO o esta acción responde a versiones antiguas de nuestras funciones de creación hardware_update = {} hardware_update['disks'] = dict_to_create['hardware']['disks'] update_domain_dict_hardware(id_new, hardware_update) ################## for index_disk in range(len(dict_to_create['hardware']['disks'])): backing_file = dict_to_create['hardware']['disks'][index_disk]['parent'] new_file = dict_to_create['hardware']['disks'][index_disk]['file'] path_selected = dict_to_create['hardware']['disks'][index_disk]['path_selected'] hyp_to_disk_create = get_host_disk_operations_from_path(path_selected, pool=pool_id, type_path='groups') cmds = create_cmds_disk_from_base(path_base=backing_file, path_new=new_file) log.debug('commands to disk create to launch in disk_operations: \n{}'.format('\n'.join(cmds))) action = {} action['type'] = 'create_disk' action['disk_path'] = new_file action['index_disk'] = index_disk action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status(status='CreatingDisk', id_domain=id_new, hyp_id=False, detail='Creating disk operation is launched in hypervisor {} ({} operations in queue)'.format( hyp_to_disk_create, self.manager.q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status(status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail='Creating disk operation failed when insert action in queue for disk operations') log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}'.format( e))
def creating_and_test_xml_start(self, id_domain, creating_from_create_dict=False, xml_from_virt_install=False, xml_string=None,ssl=True): if creating_from_create_dict is True: try: populate_dict_hardware_from_create_dict(id_domain) except Exception as e: log.error('error when populate dict hardware from create dict in domain {}'.format(id_domain)) log.error('Traceback: \n .{}'.format(traceback.format_exc())) log.error('Exception message: {}'.format(e)) domain = get_domain(id_domain) #create_dict_hw = domain['create_dict']['hardware'] # for media in ['isos','floppies'] # if 'isos' in create_dict_hw.keys(): # for index_disk in range(len(create_dict_hw['isos'])): # update_hw['hardware']['isos'][index_disk]['file'] = new_file if type(xml_string) is str: xml_from = xml_string elif 'create_from_virt_install_xml' in domain['create_dict']: xml_from = get_dict_from_item_in_table('virt_install',domain['create_dict']['create_from_virt_install_xml'])['xml'] elif xml_from_virt_install is False: id_template = domain['create_dict']['origin'] template = get_domain(id_template) xml_from = template['xml'] parents_chain = template.get('parents',[]) + domain.get('parents',[]) #when creating template from domain, the domain would be inserted as a parent while template is creating # parent_chain never can't have id_domain as parent if id_domain in parents_chain: for i in range(parents_chain.count('a')): parents_chain.remove(id_domain) update_table_field('domains', id_domain, 'parents', parents_chain) elif xml_from_virt_install is True: xml_from = domain['xml_virt_install'] else: return False update_table_field('domains', id_domain, 'xml', xml_from) xml_raw = update_xml_from_dict_domain(id_domain) if xml_raw is False: update_domain_status(status='FailedCreatingDomain', id_domain=id_domain, detail='XML Parser Error, xml is not valid') return False update_domain_status('CreatingDomain', id_domain, detail='xml and hardware dict updated, waiting to test if domain start paused in hypervisor') pool_id = get_pool_from_domain(id_domain) if 'start_after_created' in domain.keys(): if domain['start_after_created'] is True: update_domain_status('StartingDomainDisposable', id_domain, detail='xml and hardware dict updated, starting domain disposable') self.start_domain_from_id(id_domain) else: #change viewer password, remove selinux options and recreate network interfaces try: cpu_host_model = self.manager.pools[pool_id].conf.get('cpu_host_model', DEFAULT_HOST_MODE) xml = recreate_xml_to_start(id_domain,ssl,cpu_host_model) except Exception as e: log.error('recreate_xml_to_start in domain {}'.format(id_domain)) log.error('Traceback: \n .{}'.format(traceback.format_exc())) log.error('Exception message: {}'.format(e)) xml = False if xml is False: update_domain_status('Failed', id_domain, detail="DomainXML can't parse and modify xml to start") else: self.start_paused_domain_from_xml(xml=xml, id_domain=id_domain, pool_id=pool_id)
def run(self): self.tid = get_tid() logs.changes.info('starting thread: {} (TID {})'.format(self.name, self.tid)) logs.changes.debug('^^^^^^^^^^^^^^^^^^^ DOMAIN CHANGES THREAD ^^^^^^^^^^^^^^^^^') ui = UiActions(self.manager) self.r_conn = new_rethink_connection() cursor = r.table('domains').pluck('id', 'kind', 'status', 'detail').merge({'table': 'domains'}).changes().\ union(r.table('engine').pluck('threads', 'status_all_threads').merge({'table': 'engine'}).changes()).\ run(self.r_conn) for c in cursor: if self.stop is True: break if c.get('new_val', None) is not None: if c['new_val']['table'] == 'engine': if c['new_val']['status_all_threads'] == 'Stopping': break else: continue logs.changes.debug('domain changes detected in main thread') detail_msg_if_no_hyps_online = 'No hypervisors Online in pool' if self.manager.check_actions_domains_enabled() is False: if c.get('new_val', None) is not None: if c.get('old_val', None) is not None: if c['new_val']['status'][-3:] == 'ing': update_domain_status(c['old_val']['status'], c['old_val']['id'], detail=detail_msg_if_no_hyps_online) #if no hypervisor availables no check status changes continue new_domain = False new_status = False old_status = False logs.changes.debug(pprint.pformat(c)) # action deleted if c.get('new_val', None) is None: pass # action created if c.get('old_val', None) is None: new_domain = True new_status = c['new_val']['status'] domain_id = c['new_val']['id'] logs.changes.debug('domain_id: {}'.format(new_domain)) # if engine is stopped/restarting or not hypervisors online if self.manager.check_actions_domains_enabled() is False: continue pass if c.get('new_val', None) is not None and c.get('old_val', None) is not None: old_status = c['old_val']['status'] new_status = c['new_val']['status'] new_detail = c['new_val']['detail'] domain_id = c['new_val']['id'] logs.changes.debug('domain_id: {}'.format(domain_id)) # if engine is stopped/restarting or not hypervisors online if old_status != new_status: # print('&&&&&&& ID DOMAIN {} - old_status: {} , new_status: {}, detail: {}'.format(domain_id,old_status,new_status, new_detail)) # if new_status[-3:] == 'ing': if 1 > 0: date_now = datetime.now() update_domain_history_from_id_domain(domain_id, new_status, new_detail, date_now) else: # print('&&&&&&&ESTADOS IGUALES OJO &&&&&&&\n&&&&&&&& ID DOMAIN {} - old_status: {} , new_status: {}, detail: {}'. # format(domain_id,old_status,new_status,new_detail)) pass if (new_domain is True and new_status == "CreatingDiskFromScratch") or \ (old_status == 'FailedCreatingDomain' and new_status == "CreatingDiskFromScratch"): ui.creating_disk_from_scratch(domain_id) if (new_domain is True and new_status == "Creating") or \ (old_status == 'FailedCreatingDomain' and new_status == "Creating"): ui.creating_disks_from_template(domain_id) if (new_domain is True and new_status == "CreatingAndStarting"): update_domain_start_after_created(domain_id) ui.creating_disks_from_template(domain_id) # INFO TO DEVELOPER # recoger template de la que hay que derivar # verificar que realmente es una template # hay que recoger ram?? cpu?? o si no hay nada copiamos de la template?? if (new_domain is True and new_status == "CreatingFromBuilder") or \ (old_status == 'FailedCreatingDomain' and new_status == "CreatingFromBuilder"): ui.creating_disk_from_virtbuilder(domain_id) if (old_status in ['CreatingDisk','CreatingDiskFromScratch'] and new_status == "CreatingDomain") or \ (old_status == 'RunningVirtBuilder' and new_status == "CreatingDomainFromBuilder"): logs.changes.debug('llamo a creating_and_test_xml con domain id {}'.format(domain_id)) if new_status == "CreatingDomainFromBuilder": ui.creating_and_test_xml_start(domain_id, creating_from_create_dict=True, xml_from_virt_install=True,ssl=True) if new_status == "CreatingDomain": ui.creating_and_test_xml_start(domain_id, creating_from_create_dict=True,ssl=True) if old_status == 'Stopped' and new_status == "CreatingTemplate": ui.create_template_disks_from_domain(domain_id) if old_status != 'Started' and new_status == "Deleting": # or \ # old_status == 'Failed' and new_status == "Deleting" or \ # old_status == 'Downloaded' and new_status == "Deleting": ui.deleting_disks_from_domain(domain_id) if (old_status == 'Stopped' and new_status == "Updating") or \ (old_status == 'Downloaded' and new_status == "Updating"): ui.updating_from_create_dict(domain_id,ssl=True) if old_status == 'DeletingDomainDisk' and new_status == "DiskDeleted": logs.changes.debug('disk deleted, mow remove domain form database') remove_domain(domain_id) if get_domain(domain_id) is None: logs.changes.info('domain {} deleted from database'.format(domain_id)) else: update_domain_status('Failed', domain_id, detail='domain {} can not be deleted from database'.format(domain_id)) if old_status == 'CreatingTemplateDisk' and new_status == "TemplateDiskCreated": # create_template_from_dict(dict_new_template) if get_if_all_disk_template_created(domain_id): ui.create_template_in_db(domain_id) else: # INFO TO DEVELOPER, este else no se si tiene mucho sentido, hay que hacer pruebas con la # creación de una template con dos discos y ver si pasa por aquí # waiting to create other disks update_domain_status(status='CreatingTemplateDisk', id_domain=domain_id, hyp_id=False, detail='Waiting to create more disks for template') if (old_status == 'Stopped' and new_status == "Starting") or \ (old_status == 'Failed' and new_status == "Starting"): ui.start_domain_from_id(id=domain_id, ssl=True) if (old_status == 'Started' and new_status == "Stopping" ) or \ (old_status == 'Suspended' and new_status == "Stopping" ): # INFO TO DEVELOPER Esto es lo que debería ser, pero hay líos con el hyp_started # ui.stop_domain_from_id(id=domain_id) hyp_started = get_domain_hyp_started(domain_id) if hyp_started: ui.stop_domain(id_domain=domain_id, hyp_id=hyp_started) else: logs.main.error('domain without hyp_started can not be stopped: {}. '.format(domain_id)) if (old_status == 'Started' and new_status == "StoppingAndDeleting" ) or \ (old_status == 'Suspended' and new_status == "StoppingAndDeleting" ): # INFO TO DEVELOPER Esto es lo que debería ser, pero hay líos con el hyp_started # ui.stop_domain_from_id(id=domain_id) hyp_started = get_domain_hyp_started(domain_id) print(hyp_started) ui.stop_domain(id_domain=domain_id, hyp_id=hyp_started, delete_after_stopped=True) logs.main.info('finalished thread domain changes')
def populate_dict_hardware_from_create_dict(id_domain): domain = get_domain(id_domain) create_dict = domain['create_dict'] new_hardware_dict = {} if 'origin' in create_dict.keys(): template_origin = create_dict['origin'] template = get_domain(template_origin) new_hardware_dict = template['hardware'].copy() else: # TODO domain from iso or new pass if 'hardware' in create_dict.keys(): if 'disks' in create_dict['hardware'].keys(): new_hardware_dict['disks'] = create_dict['hardware']['disks'].copy() for media_type in ['isos','floppies']: if media_type in create_dict['hardware'].keys(): new_hardware_dict[media_type] = [] for d in create_dict['hardware'][media_type]: new_media_dict = {} media = get_media(d['id']) new_media_dict['path'] = media['path_downloaded'] new_hardware_dict[media_type].append(new_media_dict) new_hardware_dict['name'] = id_domain new_hardware_dict['uuid'] = None # MEMORY and CPUS new_hardware_dict['vcpus'] = create_dict['hardware']['vcpus'] new_hardware_dict['currentMemory'] = create_dict['hardware'].get('currentMemory',int(create_dict['hardware']['memory'] * DEFAULT_BALLOON)) new_hardware_dict['memory'] = create_dict['hardware']['memory'] new_hardware_dict['currentMemory_unit'] = 'KiB' new_hardware_dict['memory_unit'] = 'KiB' # VIDEO id_video = create_dict['hardware']['videos'][0] new_hardware_dict['video'] = create_dict_video_from_id(id_video) # GRAPHICS id_graphics = create_dict['hardware']['graphics'][0] pool_var = domain['hypervisors_pools'] id_pool = pool_var if type(pool_var) is str else pool_var[0] new_hardware_dict['graphics'] = create_dict_graphics_from_id(id_graphics, id_pool) # INTERFACES list_ids_interfaces = create_dict['hardware']['interfaces'] new_hardware_dict['interfaces'] = create_list_interfaces_from_list_ids(list_ids_interfaces) # BOOT MENU if 'hardware' in create_dict.keys(): if 'boot_order' in create_dict['hardware'].keys(): new_hardware_dict['boot_order'] = create_dict['hardware']['boot_order'] if 'boot_menu_enable' in create_dict['hardware'].keys(): new_hardware_dict['boot_menu_enable'] = create_dict['hardware']['boot_menu_enable'] #import pprint #pprint.pprint(new_hardware_dict) #print('############### domain {}'.format(id_domain)) update_table_field('domains', id_domain, 'hardware', new_hardware_dict, merge_dict=False)
def update_xml_from_dict_domain(id_domain, xml=None): d = get_domain(id_domain) hw = d['hardware'] if xml is None: v = DomainXML(d['xml']) else: v = DomainXML(xml) if v.parser is False: return False # v.set_memory(memory=hw['currentMemory'],unit=hw['currentMemory_unit']) v.set_memory(memory=hw['memory'], unit=hw['memory_unit'],current=int(hw.get('currentMemory',hw['memory'])*DEFAULT_BALLOON)) total_disks_in_xml = len(v.tree.xpath('/domain/devices/disk[@device="disk"]')) total_cdroms_in_xml = len(v.tree.xpath('/domain/devices/disk[@device="cdrom"]')) total_floppies_in_xml = len(v.tree.xpath('/domain/devices/disk[@device="floppy"]')) if 'boot_order' in hw.keys(): if 'boot_menu_enable' in hw.keys(): v.update_boot_order(hw['boot_order'], hw['boot_menu_enable']) else: v.update_boot_order(hw['boot_order']) if 'disks' in hw.keys(): num_remove_disks = total_disks_in_xml - len(hw['disks']) if num_remove_disks > 0: for i in range(num_remove_disks): v.remove_disk() for i in range(len(hw['disks'])): s=hw['disks'][i]['file'] if s[s.rfind('.'):].lower().find('qcow') == 1: type_disk = 'qcow2' else: type_disk = 'raw' if i >= total_disks_in_xml: force_bus = hw['disks'][i].get('bus', False) if force_bus is False: force_bus = 'virtio' v.add_disk(index=i,path_disk=hw['disks'][i]['file'],type_disk=type_disk,bus=force_bus) else: force_bus = hw['disks'][i].get('bus', False) if force_bus is False: v.set_vdisk(hw['disks'][i]['file'], index=i,type_disk=type_disk) else: v.set_vdisk(hw['disks'][i]['file'], index=i, type_disk=type_disk, force_bus=force_bus) elif total_disks_in_xml > 0: for i in range(total_disks_in_xml): v.remove_disk() if 'isos' in hw.keys(): num_remove_cdroms = total_cdroms_in_xml - len(hw['isos']) if num_remove_cdroms > 0: for i in range(num_remove_cdroms): v.remove_cdrom() for i in range(len(hw['isos'])): if i >= total_cdroms_in_xml: v.add_cdrom(index=i, path_cdrom=hw['isos'][i]['path']) else: v.set_cdrom(hw['isos'][i]['path'], index=i) elif total_cdroms_in_xml > 0: for i in range(total_cdroms_in_xml): v.remove_cdrom() if 'floppies' in hw.keys(): num_remove_floppies = total_floppies_in_xml - len(hw['floppies']) if num_remove_floppies > 0: for i in range(num_remove_floppies): v.remove_floppy() for i in range(len(hw['floppies'])): if i >= total_floppies_in_xml: v.add_floppy(index=i, path_floppy=hw['floppies'][i]['path']) else: v.set_floppy(hw['floppies'][i]['path'], index=i) elif total_floppies_in_xml > 0: for i in range(total_floppies_in_xml): v.remove_floppy() v.set_name(id_domain) # INFO TO DEVELOPER, deberíamos poder usar la funcion v.set_description(para poner algo) # INFO TO DEVELOPER, estaría bien guardar la plantilla de la que deriva en algún campo de rethink, # la puedo sacar a partir de hw['name'], hay que decidir como le llamamos al campo # es importante para poder filtrar y saber cuantas máquinas han derivado, # aunque la información que vale de verdad es la backing-chain del disco template_name = hw['name'] # TODO FALTA AÑADIR RED, Y PUEDE HABER MÁS DE UNA, # SE PUEDE HACER UN REMOVE DE TODAS LAS REDES Y LUEGO AÑADIR # CON v.add_interface() for interface_index in range(len(v.vm_dict['interfaces'])): v.remove_interface(order=interface_index) if 'interfaces' in hw.keys(): for d_interface in hw['interfaces']: v.add_interface(type=d_interface['type'], id=d_interface['id'], model_type=d_interface['model']) v.set_vcpu(hw['vcpus']) v.set_graphics_type(hw['graphics']['type']) v.set_video_type(hw['video']['type']) # INFO TO DEVELOPER, falta hacer un v.set_network_id (para ver contra que red hace bridge o se conecta # INFO TO DEVELOPER, falta hacer un v.set_netowk_type (para seleccionar si quiere virtio o realtek por ejemplo) v.randomize_vm() v.remove_selinux_options() v.remove_boot_order_from_disks() # v.print_xml() xml_raw = v.return_xml() hw_updated = v.dict_from_xml() update_domain_dict_hardware(id_domain, hw_updated, xml=xml_raw) return xml_raw
def recreate_xml_to_start(id, ssl=True, cpu_host_model=False): dict_domain = get_domain(id) xml = dict_domain['xml'] x = DomainXML(xml) if x.parser is False: #error when parsing xml return False ##### actions to customize xml if dict_domain.get('not_change_cpu_section',False) is False: x.set_cpu_host_model(cpu_host_model) # spice password x.add_spice_graphics_if_not_exist() if ssl is True: #recreate random password in x.viewer_passwd x.reset_viewer_passwd() else: # only for test purposes, not use in production x.spice_remove_passwd_nossl() #add vlc access x.add_vlc_with_websockets() # redo network try: list_interfaces = dict_domain['create_dict']['hardware']['interfaces'] except KeyError: list_interfaces = [] log.info('domain {} withouth key interfaces in create_dict'.format(id)) mac_address = [] for interface_index in range(len(x.vm_dict['interfaces'])): mac_address.append(x.vm_dict['interfaces'][interface_index]['mac']) x.remove_interface(order=interface_index) interface_index = 0 for id_interface in list_interfaces: d_interface = get_interface(id_interface) x.add_interface(type=d_interface['kind'], id=d_interface['ifname'], model_type=d_interface['model'], mac=mac_address[interface_index]) interface_index += 1 x.remove_selinux_options() #remove boot order in disk definition that conflict with /os/boot order in xml x.remove_boot_order_from_disks() x.dict_from_xml() # INFO TO DEVELOPER, OJO, PORQUE AQUI SE PIERDE EL BACKING CHAIN?? update_domain_dict_hardware(id, x.vm_dict, xml=xml) if 'viewer_passwd' in x.__dict__.keys(): #update password in database update_domain_viewer_started_values(id, passwd=x.viewer_passwd) log.debug("updated viewer password {} in domain {}".format(x.viewer_passwd, id)) xml = x.return_xml() # log.debug('#####################################################') # log.debug(xml) # log.debug('#####################################################') return xml
def create_template_disks_from_domain(self, id_domain): dict_domain = get_domain(id_domain) create_dict = dict_domain['create_dict'] pool_var = create_dict['template_dict']['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] try: dict_new_template = create_dict['template_dict'] except KeyError as e: update_domain_status( status='Stopped', id_domain=id_domain, hyp_id=False, detail= 'Action Creating Template from domain failed. No template_json in domain dictionary' ) log.error( 'No template_dict in keys of domain dictionary, when creating template form domain {}. Exception: {}' .format(id_domain, str(e))) return False disk_index_in_bus = 0 if 'disks' in dict_domain['hardware']: list_disk_template_path_relative = [ d['file'] for d in create_dict['hardware']['disks'] ] create_disk_template_created_list_in_domain(id_domain) for i in range(len(list_disk_template_path_relative)): # for disk in dict_domain['hardware']['disks']: path_domain_disk = dict_domain['hardware']['disks'][i]['file'] try: # path_template_disk_relative = dict_new_template['create_dict']['hardware']['disks'][i]['file'] path_template_disk_relative = list_disk_template_path_relative[ i] except KeyError as e: update_domain_status( status='Stopped', id_domain=id_domain, hyp_id=False, detail= 'Action Creating Template from domain failed. No disks in template_json in domain dictionary' ) log.error( 'No disks in template_json in keys of domain dictionary, when creating template form domain {}. Exception: {}' .format(id_domain, str(e))) return False if dict_new_template['kind'] == 'base': type_path_selected = 'bases' else: type_path_selected = 'templates' new_file, path_selected = get_path_to_disk( path_template_disk_relative, pool=pool_id, type_path=type_path_selected) path_absolute_template_disk = new_file = new_file.replace( '//', '/') dict_new_template['create_dict']['hardware']['disks'][i][ 'file'] = new_file dict_new_template['create_dict']['hardware']['disks'][i][ 'path_selected'] = path_selected update_table_field('domains', id_domain, 'create_dict', create_dict) action = {} action['id_domain'] = id_domain action['type'] = 'create_template_disk_from_domain' action['path_template_disk'] = path_absolute_template_disk action['path_domain_disk'] = path_domain_disk action['disk_index'] = disk_index_in_bus hyp_to_disk_create = get_host_disk_operations_from_path( path_selected, pool=pool_id, type_path=type_path_selected) # INFO TO DEVELOPER: falta terminar de ver que hacemos con el pool para crear # discos, debería haber un disk operations por pool try: update_domain_status( status='CreatingTemplateDisk', id_domain=id_domain, hyp_id=False, detail= 'Creating template disk operation is launched in hostname {} ({} operations in queue)' .format( hyp_to_disk_create, self.manager. q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put( action) except Exception as e: update_domain_status( status='Stopped', id_domain=id_domain, hyp_id=False, detail= 'Creating template operation failed when insert action in queue for disk operations' ) log.error( 'Creating disk operation failed when insert action in queue for disk operations in host {}. Exception: {}' .format(hyp_to_disk_create, e)) return False disk_index_in_bus = disk_index_in_bus + 1 return True
def run(self): # if self.table == 'domains': # type_path_selected = 'groups' # elif self.table in ['isos']: # type_path_selected = 'isos' # else: # type_path_selected = 'media' # # new_file, path_selected = get_path_to_disk(self.path, pool=self.pool, type_path=type_path_selected) # logs.downloads.debug("PATHS ___________________________________________________________________") # logs.downloads.debug(new_file) # logs.downloads.debug(path_selected) # logs.downloads.debug(pprint.pformat(self.__dict__)) # # hyp_to_disk_create = get_host_disk_operations_from_path(path_selected, pool=self.pool, # type_path=type_path_selected) header_template = "--header '{header_key}: {header_value}' " headers = '' if URL_DOWNLOAD_INSECURE_SSL == True: insecure_option = '--insecure' else: insecure_option = '' for k, v in self.dict_header.items(): headers += header_template.format(header_key=k, header_value=v) curl_template = "curl {insecure_option} -L -o '{path}' {headers} '{url}'" ssh_template = """ssh -oBatchMode=yes -p {port} {user}@{hostname} """ \ """ "mkdir -p '{path_dir}'; """ + curl_template + '"' logs.downloads.debug(ssh_template) ssh_command = ssh_template.format(port=self.port, user=self.user, hostname=self.hostname, path=self.path, path_dir=dirname(self.path), headers=headers, url=self.url, insecure_option=insecure_option) logs.downloads.debug("SSH COMMAND: {}".format(ssh_command)) p = subprocess.Popen(ssh_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid) rc = p.poll() update_status_table( self.table, 'Downloading', self.id, "downloading in hypervisor: {}".format(self.hostname)) while rc != 0: header = p.stderr.readline().decode('utf8') header2 = p.stderr.readline().decode('utf8') keys = [ 'total_percent', 'total', 'received_percent', 'received', 'xferd_percent', 'xferd', 'speed_download_average', 'speed_upload_average', 'time_total', 'time_spent', 'time_left', 'speed_current' ] line = "" while True: c = p.stderr.read(1).decode('utf8') if self.stop is True: curl_cmd = curl_template.format( path=self.path, headers=headers, url=self.url, insecure_option=insecure_option) #for pkill curl order is cleaned curl_cmd = curl_cmd.replace("'", "") curl_cmd = curl_cmd.replace(" ", " ") ssh_cmd_kill_curl = """ssh -p {port} {user}@{hostname} "pkill -f \\"^{curl_cmd}\\" " """.format( port=self.port, user=self.user, hostname=self.hostname, curl_cmd=curl_cmd) logs.downloads.info( 'download {} aborted, ready to send ssh kill to curl in hypervisor {}' .format(self.path, self.hostname)) #destroy curl in hypervisor p_kill_curl = subprocess.Popen(ssh_cmd_kill_curl, shell=True) p_kill_curl.wait(timeout=5) #destroy ssh command try: os.killpg(os.getpgid(p.pid), signal.SIGTERM) except Exception as e: logs.downloads.debug( 'ssh process not killed, has finalished') if self.table == 'media': remove_media(self.id) if self.table == 'domains': delete_domain(self.id) #update_status_table(self.table, 'FailedDownload', self.id, detail="download aborted") return False if not c: break if c == '\r': if len(line) > 60: logs.downloads.debug(line) values = line.split() logs.downloads.debug(self.url) logs.downloads.debug(line) d_progress = dict(zip(keys, values)) d_progress['total_percent'] = int( float(d_progress['total_percent'])) d_progress['received_percent'] = int( float(d_progress['received_percent'])) update_download_percent(d_progress, self.table, self.id) line = p.stderr.read(60).decode('utf8') else: line = line + c rc = p.poll() if self.stop is True: return False else: logs.downloads.info('File downloaded: {}'.format(self.path)) assert rc == 0 if self.table == 'domains': #update_table_field(self.table, self.id, 'path_downloaded', self.path) d_update_domain = get_domain(self.id)['create_dict'] #d_update_domain = {'hardware': {'disks': [{}]}} d_update_domain['hardware']['disks'][0]['file'] = self.path update_domain_dict_create_dict(self.id, d_update_domain) self.finalished_threads.append(self.path) update_domain_status('Downloaded', self.id, detail="downloaded disk") update_domain_status('Updating', self.id, detail="downloaded disk") else: self.finalished_threads.append(self.path) update_table_field(self.table, self.id, 'path_downloaded', self.path) update_status_table(self.table, 'Downloaded', self.id)
def creating_disk_from_virtbuilder(self, id_new): dict_domain = get_domain(id_new) pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] dict_to_create = dict_domain['create_dict'] relative_path = dict_to_create['hardware']['disks'][0]['file'] path_new_disk, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN dict_to_create['hardware']['disks'][0]['file'] = path_new_disk dict_to_create['hardware']['disks'][0]['path_selected'] = path_selected size_str = dict_to_create['hardware']['disks'][0]['size'] memory_in_mb = int(dict_to_create['hardware']['memory'] / 1024) options_virt_builder = dict_to_create['builder']['options'] options_virt_install = dict_to_create['install']['options'] id_domains_virt_builder = dict_to_create['builder']['id'] id_os_virt_install = dict_to_create['install']['id'] # UPDATE HARDWARE DICT hardware_update = {} hardware_update['disks'] = dict_to_create['hardware']['disks'] update_domain_dict_hardware(id_new, hardware_update) hyp_to_disk_create = get_host_long_operations_from_path( path_selected, pool=pool_id, type_path='groups') cmds = create_cmd_disk_from_virtbuilder( path_new_qcow=path_new_disk, os_version=id_domains_virt_builder, id_os_virt_install=id_os_virt_install, name_domain_in_xml=id_new, size_str=size_str, memory_in_mb=memory_in_mb, options_cmd=options_virt_builder) # cmds = [{'cmd':'ls -lah > /tmp/prova.txt','title':'es un ls'}] action = {} action['type'] = 'create_disk_virt_builder' action['disk_path'] = path_new_disk action['index_disk'] = 0 action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status( status='RunningVirtBuilder', id_domain=id_new, hyp_id=False, detail= 'Creating virt-builder image operation is launched in hypervisor {} ({} operations in queue)' .format( hyp_to_disk_create, self.manager. q_long_operations[hyp_to_disk_create].qsize())) self.manager.q_long_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status( status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail= 'Creating disk operation failed when insert action in queue for disk operations' ) log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}' .format(e))
def populate_dict_hardware_from_create_dict(id_domain): domain = get_domain(id_domain) create_dict = domain['create_dict'] new_hardware_dict = {} if 'origin' in create_dict.keys(): template_origin = create_dict['origin'] template = get_domain(template_origin) new_hardware_dict = template['hardware'].copy() else: # TODO domain from iso or new pass if 'hardware' in create_dict.keys(): if 'disks' in create_dict['hardware'].keys(): new_hardware_dict['disks'] = create_dict['hardware']['disks'].copy( ) for media_type in ['isos', 'floppies']: if media_type in create_dict['hardware'].keys(): new_hardware_dict[media_type] = [] for d in create_dict['hardware'][media_type]: new_media_dict = {} media = get_media(d['id']) new_media_dict['path'] = media['path_downloaded'] new_hardware_dict[media_type].append(new_media_dict) new_hardware_dict['name'] = id_domain new_hardware_dict['uuid'] = None # MEMORY and CPUS new_hardware_dict['vcpus'] = create_dict['hardware']['vcpus'] new_hardware_dict['currentMemory'] = create_dict['hardware'].get( 'currentMemory', int(create_dict['hardware']['memory'] * DEFAULT_BALLOON)) new_hardware_dict['memory'] = create_dict['hardware']['memory'] new_hardware_dict['currentMemory_unit'] = 'KiB' new_hardware_dict['memory_unit'] = 'KiB' # VIDEO id_video = create_dict['hardware']['videos'][0] new_hardware_dict['video'] = create_dict_video_from_id(id_video) # GRAPHICS id_graphics = create_dict['hardware']['graphics'][0] pool_var = domain['hypervisors_pools'] id_pool = pool_var if type(pool_var) is str else pool_var[0] new_hardware_dict['graphics'] = create_dict_graphics_from_id( id_graphics, id_pool) # INTERFACES list_ids_interfaces = create_dict['hardware']['interfaces'] new_hardware_dict['interfaces'] = create_list_interfaces_from_list_ids( list_ids_interfaces) # BOOT MENU if 'hardware' in create_dict.keys(): if 'boot_order' in create_dict['hardware'].keys(): new_hardware_dict['boot_order'] = create_dict['hardware'][ 'boot_order'] if 'boot_menu_enable' in create_dict['hardware'].keys(): new_hardware_dict['boot_menu_enable'] = create_dict['hardware'][ 'boot_menu_enable'] #import pprint #pprint.pprint(new_hardware_dict) #print('############### domain {}'.format(id_domain)) update_table_field('domains', id_domain, 'hardware', new_hardware_dict, merge_dict=False)
def creating_and_test_xml_start(self, id_domain, creating_from_create_dict=False, xml_from_virt_install=False, xml_string=None): if creating_from_create_dict is True: try: populate_dict_hardware_from_create_dict(id_domain) except Exception as e: log.error( 'error when populate dict hardware from create dict in domain {}' .format(id_domain)) log.error('Traceback: \n .{}'.format(traceback.format_exc())) log.error('Exception message: {}'.format(e)) domain = get_domain(id_domain) #create_dict_hw = domain['create_dict']['hardware'] # for media in ['isos','floppies'] # if 'isos' in create_dict_hw.keys(): # for index_disk in range(len(create_dict_hw['isos'])): # update_hw['hardware']['isos'][index_disk]['file'] = new_file if type(xml_string) is str: xml_from = xml_string elif 'create_from_virt_install_xml' in domain['create_dict']: xml_from = get_dict_from_item_in_table( 'virt_install', domain['create_dict']['create_from_virt_install_xml'])['xml'] elif xml_from_virt_install is False: id_template = domain['create_dict']['origin'] template = get_domain(id_template) xml_from = template['xml'] elif xml_from_virt_install is True: xml_from = domain['xml_virt_install'] else: return False update_table_field('domains', id_domain, 'xml', xml_from) xml_raw = update_xml_from_dict_domain(id_domain) update_domain_status( 'CreatingDomain', id_domain, detail= 'xml and hardware dict updated, waiting to test if domain start paused in hypervisor' ) pool_id = get_pool_from_domain(id_domain) if 'start_after_created' in domain.keys(): if domain['start_after_created'] is True: update_domain_status( 'StartingDomainDisposable', id_domain, detail= 'xml and hardware dict updated, starting domain disposable' ) self.start_domain_from_id(id_domain) else: #change viewer password, remove selinux options and recreate network interfaces xml = recreate_xml_to_start(id_domain) self.start_paused_domain_from_xml(xml=xml, id_domain=id_domain, pool_id=pool_id)
def creating_disk_from_virtbuilder(self, id_new): dict_domain = get_domain(id_new) pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] dict_to_create = dict_domain['create_dict'] relative_path = dict_to_create['hardware']['disks'][0]['file'] path_new_disk, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN dict_to_create['hardware']['disks'][0]['file'] = path_new_disk dict_to_create['hardware']['disks'][0]['path_selected'] = path_selected size_str = dict_to_create['hardware']['disks'][0]['size'] memory_in_mb = int(dict_to_create['hardware']['memory'] / 1024) options_virt_builder = dict_to_create['builder']['options'] options_virt_install = dict_to_create['install']['options'] id_domains_virt_builder = dict_to_create['builder']['id'] id_os_virt_install = dict_to_create['install']['id'] # UPDATE HARDWARE DICT hardware_update = {} hardware_update['disks'] = dict_to_create['hardware']['disks'] update_domain_dict_hardware(id_new, hardware_update) hyp_to_disk_create = get_host_long_operations_from_path(path_selected, pool=pool_id, type_path='groups') cmds = create_cmd_disk_from_virtbuilder(path_new_qcow=path_new_disk, os_version=id_domains_virt_builder, id_os_virt_install=id_os_virt_install, name_domain_in_xml=id_new, size_str=size_str, memory_in_mb=memory_in_mb, options_cmd=options_virt_builder) # cmds = [{'cmd':'ls -lah > /tmp/prova.txt','title':'es un ls'}] action = {} action['type'] = 'create_disk_virt_builder' action['disk_path'] = path_new_disk action['index_disk'] = 0 action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status(status='RunningVirtBuilder', id_domain=id_new, hyp_id=False, detail='Creating virt-builder image operation is launched in hypervisor {} ({} operations in queue)'.format( hyp_to_disk_create, self.manager.q_long_operations[hyp_to_disk_create].qsize())) self.manager.q_long_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status(status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail='Creating disk operation failed when insert action in queue for disk operations') log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}'.format( e))
def creating_disk_from_scratch(self,id_new): dict_domain = get_domain(id_new) pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] dict_to_create = dict_domain['create_dict'] if 'disks' in dict_to_create['hardware'].keys(): if len(dict_to_create['hardware']['disks']) > 0: # for index_disk in range(len(dict_to_create['hardware']['disks'])): # relative_path = dict_to_create['hardware']['disks'][index_disk]['file'] # path_new_file, path_selected = get_path_to_disk(relative_path, pool=pool_id) # # UPDATE PATH IN DOMAIN # dict_to_create['hardware']['disks'][index_disk]['file'] = new_file # dict_to_create['hardware']['disks'][index_disk]['path_selected'] = path_selected relative_path = dict_to_create['hardware']['disks'][0]['file'] path_new_disk, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN d_update_domain = {'hardware':{'disks':[{}]}} if len(dict_to_create['hardware']['disks']) > 0: ## supplementary disks for i,dict_other_disk in enumerate(dict_to_create['hardware']['disks'][1:]): path_other_disk, path_other_disk_selected = get_path_to_disk(dict_other_disk['file'], pool=pool_id, type_path=dict_other_disk['type_path']) d_update_domain['hardware']['disks'].append({}) d_update_domain['hardware']['disks'][i+1]['file'] = path_other_disk d_update_domain['hardware']['disks'][i+1]['path_selected'] = path_other_disk_selected d_update_domain['hardware']['disks'][i + 1]['bus'] = dict_other_disk.get('bus','virtio') if dict_other_disk.get('readonly',True) is True: d_update_domain['hardware']['disks'][i + 1]['readonly'] = True else: pass # TODO # update_media_write_access_by_domain(id_media,id_domain) d_update_domain['hardware']['disks'][0]['file'] = path_new_disk d_update_domain['hardware']['disks'][0]['path_selected'] = path_selected d_update_domain['hardware']['disks'][0]['size'] = dict_to_create['hardware']['disks'][0]['size'] if 'bus' in dict_to_create['hardware']['disks'][0].keys(): if dict_to_create['hardware']['disks'][0]['bus'] in BUS_TYPES: d_update_domain['hardware']['disks'][0]['bus'] = dict_to_create['hardware']['disks'][0]['bus'] update_domain_dict_hardware(id_new, d_update_domain) update_domain_dict_create_dict(id_new, d_update_domain) size_str = dict_to_create['hardware']['disks'][0]['size'] hyp_to_disk_create = get_host_disk_operations_from_path(path_selected, pool=pool_id, type_path='groups') cmds = create_cmd_disk_from_scratch(path_new_disk=path_new_disk, size_str=size_str) action = {} action['type'] = 'create_disk_from_scratch' action['disk_path'] = path_new_disk action['index_disk'] = 0 action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status(status='CreatingDiskFromScratch', id_domain=id_new, hyp_id=False, detail='Creating disk commands are launched in hypervisor {} ({} operations in queue)'.format( hyp_to_disk_create, self.manager.q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status(status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail='Creating disk operation failed when insert action in queue for disk operations') log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}'.format( e)) else: update_domain_status(status='CreatingDomain', id_domain=id_new, hyp_id=False, detail='Creating domain withouth disks')
def creating_disk_from_scratch(self, id_new): dict_domain = get_domain(id_new) pool_var = dict_domain['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] dict_to_create = dict_domain['create_dict'] if 'disks' in dict_to_create['hardware'].keys(): if len(dict_to_create['hardware']['disks']) > 0: # for index_disk in range(len(dict_to_create['hardware']['disks'])): # relative_path = dict_to_create['hardware']['disks'][index_disk]['file'] # path_new_file, path_selected = get_path_to_disk(relative_path, pool=pool_id) # # UPDATE PATH IN DOMAIN # dict_to_create['hardware']['disks'][index_disk]['file'] = new_file # dict_to_create['hardware']['disks'][index_disk]['path_selected'] = path_selected relative_path = dict_to_create['hardware']['disks'][0]['file'] path_new_disk, path_selected = get_path_to_disk(relative_path, pool=pool_id) # UPDATE PATH IN DOMAIN d_update_domain = {'hardware': {'disks': [{}]}} if len(dict_to_create['hardware']['disks']) > 0: ## supplementary disks for i, dict_other_disk in enumerate( dict_to_create['hardware']['disks'][1:]): path_other_disk, path_other_disk_selected = get_path_to_disk( dict_other_disk['file'], pool=pool_id, type_path=dict_other_disk['type_path']) d_update_domain['hardware']['disks'].append({}) d_update_domain['hardware']['disks'][ i + 1]['file'] = path_other_disk d_update_domain['hardware']['disks'][ i + 1]['path_selected'] = path_other_disk_selected d_update_domain['hardware']['disks'][ i + 1]['bus'] = dict_other_disk.get( 'bus', 'virtio') if dict_other_disk.get('readonly', True) is True: d_update_domain['hardware']['disks'][ i + 1]['readonly'] = True else: pass # TODO # update_media_write_access_by_domain(id_media,id_domain) d_update_domain['hardware']['disks'][0]['file'] = path_new_disk d_update_domain['hardware']['disks'][0][ 'path_selected'] = path_selected d_update_domain['hardware']['disks'][0][ 'size'] = dict_to_create['hardware']['disks'][0]['size'] if 'bus' in dict_to_create['hardware']['disks'][0].keys(): if dict_to_create['hardware']['disks'][0][ 'bus'] in BUS_TYPES: d_update_domain['hardware']['disks'][0][ 'bus'] = dict_to_create['hardware']['disks'][0][ 'bus'] update_domain_dict_hardware(id_new, d_update_domain) update_domain_dict_create_dict(id_new, d_update_domain) size_str = dict_to_create['hardware']['disks'][0]['size'] hyp_to_disk_create = get_host_disk_operations_from_path( path_selected, pool=pool_id, type_path='groups') cmds = create_cmd_disk_from_scratch( path_new_disk=path_new_disk, size_str=size_str) action = {} action['type'] = 'create_disk_from_scratch' action['disk_path'] = path_new_disk action['index_disk'] = 0 action['domain'] = id_new action['ssh_commands'] = cmds try: update_domain_status( status='CreatingDiskFromScratch', id_domain=id_new, hyp_id=False, detail= 'Creating disk commands are launched in hypervisor {} ({} operations in queue)' .format( hyp_to_disk_create, self.manager. q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put( action) except Exception as e: update_domain_status( status='FailedCreatingDomain', id_domain=id_new, hyp_id=False, detail= 'Creating disk operation failed when insert action in queue for disk operations' ) log.error( 'Creating disk operation failed when insert action in queue for disk operations. Exception: {}' .format(e)) else: update_domain_status(status='CreatingDomain', id_domain=id_new, hyp_id=False, detail='Creating domain withouth disks')
def create_template_disks_from_domain(self, id_domain): dict_domain = get_domain(id_domain) create_dict = dict_domain['create_dict'] pool_var = create_dict['template_dict']['hypervisors_pools'] pool_id = pool_var if type(pool_var) is str else pool_var[0] try: dict_new_template = create_dict['template_dict'] except KeyError as e: update_domain_status(status='Stopped', id_domain=id_domain, hyp_id=False, detail='Action Creating Template from domain failed. No template_json in domain dictionary') log.error( 'No template_dict in keys of domain dictionary, when creating template form domain {}. Exception: {}'.format( id_domain, str(e))) return False disk_index_in_bus = 0 if 'disks' in dict_domain['hardware']: list_disk_template_path_relative = [d['file'] for d in create_dict['hardware']['disks']] create_disk_template_created_list_in_domain(id_domain) for i in range(len(list_disk_template_path_relative)): # for disk in dict_domain['hardware']['disks']: path_domain_disk = dict_domain['hardware']['disks'][i]['file'] try: # path_template_disk_relative = dict_new_template['create_dict']['hardware']['disks'][i]['file'] path_template_disk_relative = list_disk_template_path_relative[i] except KeyError as e: update_domain_status(status='Stopped', id_domain=id_domain, hyp_id=False, detail='Action Creating Template from domain failed. No disks in template_json in domain dictionary') log.error( 'No disks in template_json in keys of domain dictionary, when creating template form domain {}. Exception: {}'.format( id_domain, str(e))) return False if dict_new_template['kind'] == 'base': type_path_selected = 'bases' else: type_path_selected = 'templates' new_file, path_selected = get_path_to_disk(path_template_disk_relative, pool=pool_id, type_path=type_path_selected) path_absolute_template_disk = new_file = new_file.replace('//', '/') dict_new_template['create_dict']['hardware']['disks'][i]['file'] = new_file dict_new_template['create_dict']['hardware']['disks'][i]['path_selected'] = path_selected update_table_field('domains', id_domain, 'create_dict', create_dict) action = {} action['id_domain'] = id_domain action['type'] = 'create_template_disk_from_domain' action['path_template_disk'] = path_absolute_template_disk action['path_domain_disk'] = path_domain_disk action['disk_index'] = disk_index_in_bus hyp_to_disk_create = get_host_disk_operations_from_path(path_selected, pool=pool_id, type_path=type_path_selected) # INFO TO DEVELOPER: falta terminar de ver que hacemos con el pool para crear # discos, debería haber un disk operations por pool try: update_domain_status(status='CreatingTemplateDisk', id_domain=id_domain, hyp_id=False, detail='Creating template disk operation is launched in hostname {} ({} operations in queue)'.format( hyp_to_disk_create, self.manager.q_disk_operations[hyp_to_disk_create].qsize())) self.manager.q_disk_operations[hyp_to_disk_create].put(action) except Exception as e: update_domain_status(status='Stopped', id_domain=id_domain, hyp_id=False, detail='Creating template operation failed when insert action in queue for disk operations') log.error( 'Creating disk operation failed when insert action in queue for disk operations in host {}. Exception: {}'.format( hyp_to_disk_create, e)) return False disk_index_in_bus = disk_index_in_bus + 1 return True
def creating_and_test_xml_start(self, id_domain, creating_from_create_dict=False, xml_from_virt_install=False, xml_string=None): if creating_from_create_dict is True: try: populate_dict_hardware_from_create_dict(id_domain) except Exception as e: log.error( 'error when populate dict hardware from create dict in domain {}' .format(id_domain)) log.error('Traceback: \n .{}'.format(traceback.format_exc())) log.error('Exception message: {}'.format(e)) domain = get_domain(id_domain) #create_dict_hw = domain['create_dict']['hardware'] # for media in ['isos','floppies'] # if 'isos' in create_dict_hw.keys(): # for index_disk in range(len(create_dict_hw['isos'])): # update_hw['hardware']['isos'][index_disk]['file'] = new_file if type(xml_string) is str: xml_from = xml_string elif 'create_from_virt_install_xml' in domain['create_dict']: xml_from = get_dict_from_item_in_table( 'virt_install', domain['create_dict']['create_from_virt_install_xml'])['xml'] elif xml_from_virt_install is False: id_template = domain['create_dict']['origin'] template = get_domain(id_template) xml_from = template['xml'] parents_chain = template.get('parents', []) + domain.get( 'parents', []) #when creating template from domain, the domain would be inserted as a parent while template is creating # parent_chain never can't have id_domain as parent if id_domain in parents_chain: for i in range(parents_chain.count('a')): parents_chain.remove(id_domain) update_table_field('domains', id_domain, 'parents', parents_chain) elif xml_from_virt_install is True: xml_from = domain['xml_virt_install'] else: return False update_table_field('domains', id_domain, 'xml', xml_from) xml_raw = update_xml_from_dict_domain(id_domain) if xml_raw is False: update_domain_status(status='FailedCreatingDomain', id_domain=id_domain, detail='XML Parser Error, xml is not valid') return False update_domain_status( 'CreatingDomain', id_domain, detail= 'xml and hardware dict updated, waiting to test if domain start paused in hypervisor' ) pool_id = get_pool_from_domain(id_domain) if 'start_after_created' in domain.keys(): if domain['start_after_created'] is True: update_domain_status( 'StartingDomainDisposable', id_domain, detail= 'xml and hardware dict updated, starting domain disposable' ) self.start_domain_from_id(id_domain) else: #change viewer password, remove selinux options and recreate network interfaces try: xml = recreate_xml_to_start(id_domain) except Exception as e: log.error( 'recreate_xml_to_start in domain {}'.format(id_domain)) log.error('Traceback: \n .{}'.format(traceback.format_exc())) log.error('Exception message: {}'.format(e)) xml = False if xml is False: update_domain_status( 'Failed', id_domain, detail="DomainXML can't parse and modify xml to start") else: self.start_paused_domain_from_xml(xml=xml, id_domain=id_domain, pool_id=pool_id)
def create_domain_from_template(name_normalized, id_template, id_user, description = '', only_dict = False): regex = re.compile("^[a-zA-Z0-9-_.]*$") if regex.match(name_normalized) is None: logs.bulk.error('name {} for domain is not normalized, only lower chars, letters and _ are allowed'.format(name_normalized)) return False id_new_domain = '_' + id_user + '_' + name_normalized dict_template = t = get_domain(id_template) if dict_template is None: logs.bulk.error('template {} does not exist in database'.format(id_template)) return False if dict_template['kind'] == 'desktop': logs.bulk.error('domain {} is a desktop, can not derivate from a desktop only from template or base'.format(id_template)) return False if get_domain(id_new_domain) is not None: logs.bulk.error('domain {} can not be created because it already exists in database'.format(id_new_domain)) return False dict_user = u = get_user(id_user) if dict_user is None: logs.bulk.error('user {} does not exist in database, can not create domains '.format(id_user)) return False d_new = {} d_new["allowed"] = {"categories": False, "groups": False, "roles": False, "users": False } d_new['category'] = u['category'] d_new['create_dict'] = t['create_dict'] d_new['description'] = description d_new['detail'] = '' d_new['group'] = u['group'] d_new['hypervisors_pools'] = t['hypervisors_pools'] d_new['icon'] = t['icon'] d_new['id'] = id_new_domain d_new['kind'] = 'desktop' d_new['name'] = name_normalized d_new['os'] = t['os'] d_new['server'] = False d_new['status'] = 'Creating' d_new['user'] = id_user d_new['xml'] = '' # modify create_dict path_relative_disk = '{}/{}/{}/{}.qcow2'.format(u['category'], u['group'], id_user, name_normalized) d_new['create_dict']['origin'] = id_template try: d_new['create_dict'].pop('hypervisors_pools') except KeyError: pass d_new['create_dict']['hardware']['disks'][0]['parent'] = t['hardware']['disks'][0]['file'] d_new['create_dict']['hardware']['disks'][0]['file'] = path_relative_disk if only_dict is True: return d_new else: result = insert_domain(d_new) if result['inserted'] == 1: logs.bulk.info('domain {} created from bulk operation'.format(id_new_domain)) return True else: logs.bulk.error('error inserting domain {} in database'.format(id_new_domain)) return False
def domain_from_template(self, id_template, id_new, user, category, group, name, description, cpu, ram, current_ram=-1, id_net=None, force_server=None, only_cmds=False, path_to_disk_dir=None, disk_filename=None, create_domain_in_db=True): # INFO TO DEVELOPER: falta verificar que el id no existe y si existe salir enseguida, ya que si no haríamos updates y # creaciónes de disco peligrosas dict_domain_template = get_domain(id_template) dict_domain_new = dict_domain_template.copy() dict_domain_new['id'] = id_new dict_domain_new['user'] = user dict_domain_new['category'] = category dict_domain_new['group'] = group dict_domain_new['kind'] = 'desktop' dict_domain_new['name'] = name dict_domain_new['description'] = description dict_domain_new['status'] = 'CreatingDisk' dict_domain_new['detail'] = 'Defining new domain' if force_server == True: dict_domain_new['server'] = True elif force_server == False: dict_domain_new['server'] = False else: dict_domain_new['server'] = dict_domain_template['server'] x = DomainXML(dict_domain_template['xml']) if x.parser is False: log.error('error when parsing xml') dict_domain_new['status'] = 'FailedCreatingDomain' dict_domain_new['detail'] = 'XML Parser have failed, xml with errors' return False x.set_name(id_new) x.set_title(name) x.set_description(description) old_path_disk = dict_domain_template['hardware']['disks'][0]['file'] old_path_dir = extract_dir_path(old_path_disk) #DEFAULT_GROUP_DIR = CONFIG_DICT['REMOTEOPERATIONS']['default_group_dir'] if path_to_disk_dir is None: path_to_disk_dir = DEFAULT_GROUP_DIR + '/' + \ dict_domain_template['category'] + '/' + \ dict_domain_template['group'] + '/' + \ dict_domain_template['user'] if len(old_path_disk[len(old_path_dir) + 1:-1].split('.')) > 1: extension = old_path_disk[len(old_path_dir) + 1:-1].split('.')[1] else: extension = 'qcow' if disk_filename is None: disk_filename = id_new + '.' + extension new_path_disk = path_to_disk_dir + '/' + disk_filename x.set_vcpu(cpu) x.set_memory(ram,current=current_ram) x.set_vdisk(new_path_disk) x.randomize_vm() dict_domain_new['hardware'] = x.vm_dict dict_domain_new['xml'] = x.return_xml() cmds = create_cmds_disk_from_base(old_path_disk, new_path_disk, ) if only_cmds is True: dict_domain_new['status'] = 'Crashed' dict_domain_new['detail'] = 'Disk not created, only for testing ui purpose, create command is not launched' return dict_domain_new, cmds else: action = {} action['type'] = 'create_disk' action['disk_path'] = new_path_disk action['domain'] = id_new action['ssh_commands'] = cmds if hasattr(self.pool, 'queue_disk_operation'): self.pool.queue_disk_operation.put(action) # err,out = create_disk_from_base(old_path_disk,new_path_disk) dict_domain_new['status'] = 'CreatingDisk' dict_domain_new['detail'] = 'Creating disk operation is launched ({} operations in queue)'.format( self.pool.queue_disk_operation.qsize()) # list_backing_chain = backing_chain(new_path_disk) # dict_domain_new['backing_chain'] = list_backing_chain else: log.error('queue disk operation is not created') dict_domain_new['status'] = 'Crashed' dict_domain_new['detail'] = 'Disk not created, queue for disk creation does not exist' if create_domain_in_db is True: insert_domain(dict_domain_new) return dict_domain_new
def update_xml_from_dict_domain(id_domain, xml=None): d = get_domain(id_domain) hw = d['hardware'] if xml is None: v = DomainXML(d['xml']) else: v = DomainXML(xml) if v.parser is False: return False # v.set_memory(memory=hw['currentMemory'],unit=hw['currentMemory_unit']) v.set_memory(memory=hw['memory'], unit=hw['memory_unit'], current=int( hw.get('currentMemory', hw['memory']) * DEFAULT_BALLOON)) total_disks_in_xml = len( v.tree.xpath('/domain/devices/disk[@device="disk"]')) total_cdroms_in_xml = len( v.tree.xpath('/domain/devices/disk[@device="cdrom"]')) total_floppies_in_xml = len( v.tree.xpath('/domain/devices/disk[@device="floppy"]')) if 'boot_order' in hw.keys(): if 'boot_menu_enable' in hw.keys(): v.update_boot_order(hw['boot_order'], hw['boot_menu_enable']) else: v.update_boot_order(hw['boot_order']) if 'disks' in hw.keys(): num_remove_disks = total_disks_in_xml - len(hw['disks']) if num_remove_disks > 0: for i in range(num_remove_disks): v.remove_disk() for i in range(len(hw['disks'])): s = hw['disks'][i]['file'] if s[s.rfind('.'):].lower().find('qcow') == 1: type_disk = 'qcow2' else: type_disk = 'raw' if i >= total_disks_in_xml: force_bus = hw['disks'][i].get('bus', False) if force_bus is False: force_bus = 'virtio' v.add_disk(index=i, path_disk=hw['disks'][i]['file'], type_disk=type_disk, bus=force_bus) else: force_bus = hw['disks'][i].get('bus', False) if force_bus is False: v.set_vdisk(hw['disks'][i]['file'], index=i, type_disk=type_disk) else: v.set_vdisk(hw['disks'][i]['file'], index=i, type_disk=type_disk, force_bus=force_bus) elif total_disks_in_xml > 0: for i in range(total_disks_in_xml): v.remove_disk() if 'isos' in hw.keys(): num_remove_cdroms = total_cdroms_in_xml - len(hw['isos']) if num_remove_cdroms > 0: for i in range(num_remove_cdroms): v.remove_cdrom() for i in range(len(hw['isos'])): if i >= total_cdroms_in_xml: v.add_cdrom(index=i, path_cdrom=hw['isos'][i]['path']) else: v.set_cdrom(hw['isos'][i]['path'], index=i) elif total_cdroms_in_xml > 0: for i in range(total_cdroms_in_xml): v.remove_cdrom() if 'floppies' in hw.keys(): num_remove_floppies = total_floppies_in_xml - len(hw['floppies']) if num_remove_floppies > 0: for i in range(num_remove_floppies): v.remove_floppy() for i in range(len(hw['floppies'])): if i >= total_floppies_in_xml: v.add_floppy(index=i, path_floppy=hw['floppies'][i]['path']) else: v.set_floppy(hw['floppies'][i]['path'], index=i) elif total_floppies_in_xml > 0: for i in range(total_floppies_in_xml): v.remove_floppy() v.set_name(id_domain) # INFO TO DEVELOPER, deberíamos poder usar la funcion v.set_description(para poner algo) # INFO TO DEVELOPER, estaría bien guardar la plantilla de la que deriva en algún campo de rethink, # la puedo sacar a partir de hw['name'], hay que decidir como le llamamos al campo # es importante para poder filtrar y saber cuantas máquinas han derivado, # aunque la información que vale de verdad es la backing-chain del disco template_name = hw['name'] # TODO FALTA AÑADIR RED, Y PUEDE HABER MÁS DE UNA, # SE PUEDE HACER UN REMOVE DE TODAS LAS REDES Y LUEGO AÑADIR # CON v.add_interface() for interface_index in range(len(v.vm_dict['interfaces'])): v.remove_interface(order=interface_index) if 'interfaces' in hw.keys(): for d_interface in hw['interfaces']: v.add_interface(type=d_interface['type'], id=d_interface['id'], model_type=d_interface['model']) v.set_vcpu(hw['vcpus']) v.set_graphics_type(hw['graphics']['type']) v.set_video_type(hw['video']['type']) # INFO TO DEVELOPER, falta hacer un v.set_network_id (para ver contra que red hace bridge o se conecta # INFO TO DEVELOPER, falta hacer un v.set_netowk_type (para seleccionar si quiere virtio o realtek por ejemplo) v.randomize_vm() v.remove_selinux_options() v.remove_boot_order_from_disks() # v.print_xml() xml_raw = v.return_xml() hw_updated = v.dict_from_xml() update_domain_dict_hardware(id_domain, hw_updated, xml=xml_raw) return xml_raw
def recreate_xml_to_start(id, ssl=True, cpu_host_model=False): dict_domain = get_domain(id) xml = dict_domain['xml'] x = DomainXML(xml) if x.parser is False: #error when parsing xml return False ##### actions to customize xml if dict_domain.get('not_change_cpu_section', False) is False: x.set_cpu_host_model(cpu_host_model) # spice video compression #x.add_spice_graphics_if_not_exist() x.set_spice_video_options() # spice password if ssl is True: #recreate random password in x.viewer_passwd x.reset_viewer_passwd() else: # only for test purposes, not use in production x.spice_remove_passwd_nossl() #add vlc access x.add_vlc_with_websockets() # redo network try: list_interfaces = dict_domain['create_dict']['hardware']['interfaces'] except KeyError: list_interfaces = [] log.info('domain {} withouth key interfaces in create_dict'.format(id)) mac_address = [] for interface_index in range(len(x.vm_dict['interfaces'])): mac_address.append(x.vm_dict['interfaces'][interface_index]['mac']) x.remove_interface(order=interface_index) interface_index = 0 for id_interface in list_interfaces: d_interface = get_interface(id_interface) x.add_interface(type=d_interface['kind'], id=d_interface['ifname'], model_type=d_interface['model'], mac=mac_address[interface_index]) interface_index += 1 x.remove_selinux_options() #remove boot order in disk definition that conflict with /os/boot order in xml x.remove_boot_order_from_disks() x.dict_from_xml() # INFO TO DEVELOPER, OJO, PORQUE AQUI SE PIERDE EL BACKING CHAIN?? update_domain_dict_hardware(id, x.vm_dict, xml=xml) if 'viewer_passwd' in x.__dict__.keys(): #update password in database update_domain_viewer_started_values(id, passwd=x.viewer_passwd) log.debug("updated viewer password {} in domain {}".format( x.viewer_passwd, id)) xml = x.return_xml() # log.debug('#####################################################') # log.debug(xml) # log.debug('#####################################################') return xml