1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-24 23:25:24 +00:00

fix instance create error handling

This commit is contained in:
catborise 2020-08-17 09:58:42 +03:00
parent 6d52587e60
commit 83ba6da572
2 changed files with 163 additions and 164 deletions

View file

@ -1242,186 +1242,184 @@ def create_instance(request, compute_id, arch, machine):
flavors = Flavor.objects.filter().order_by('id') flavors = Flavor.objects.filter().order_by('id')
appsettings = AppSettings.objects.all() appsettings = AppSettings.objects.all()
conn = wvmCreate(compute.hostname, compute.login, compute.password, compute.type) try:
conn = wvmCreate(compute.hostname, compute.login, compute.password, compute.type)
default_firmware = app_settings.INSTANCE_FIRMWARE_DEFAULT_TYPE default_firmware = app_settings.INSTANCE_FIRMWARE_DEFAULT_TYPE
default_cpu_mode = app_settings.INSTANCE_CPU_DEFAULT_MODE default_cpu_mode = app_settings.INSTANCE_CPU_DEFAULT_MODE
instances = conn.get_instances() instances = conn.get_instances()
videos = conn.get_video_models(arch, machine) videos = conn.get_video_models(arch, machine)
cache_modes = sorted(conn.get_cache_modes().items()) cache_modes = sorted(conn.get_cache_modes().items())
default_cache = app_settings.INSTANCE_VOLUME_DEFAULT_CACHE default_cache = app_settings.INSTANCE_VOLUME_DEFAULT_CACHE
default_io = app_settings.INSTANCE_VOLUME_DEFAULT_IO default_io = app_settings.INSTANCE_VOLUME_DEFAULT_IO
default_zeroes = app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES default_zeroes = app_settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES
default_discard = app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD default_discard = app_settings.INSTANCE_VOLUME_DEFAULT_DISCARD
default_disk_format = app_settings.INSTANCE_VOLUME_DEFAULT_FORMAT default_disk_format = app_settings.INSTANCE_VOLUME_DEFAULT_FORMAT
default_disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID) default_disk_owner_uid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_UID)
default_disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID) default_disk_owner_gid = int(app_settings.INSTANCE_VOLUME_DEFAULT_OWNER_GID)
default_scsi_disk_model = app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER default_scsi_disk_model = app_settings.INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER
listener_addr = settings.QEMU_CONSOLE_LISTEN_ADDRESSES listener_addr = settings.QEMU_CONSOLE_LISTEN_ADDRESSES
mac_auto = util.randomMAC() mac_auto = util.randomMAC()
disk_devices = conn.get_disk_device_types(arch, machine) disk_devices = conn.get_disk_device_types(arch, machine)
disk_buses = conn.get_disk_bus_types(arch, machine) disk_buses = conn.get_disk_bus_types(arch, machine)
default_bus = app_settings.INSTANCE_VOLUME_DEFAULT_BUS default_bus = app_settings.INSTANCE_VOLUME_DEFAULT_BUS
networks = sorted(conn.get_networks()) networks = sorted(conn.get_networks())
nwfilters = conn.get_nwfilters() nwfilters = conn.get_nwfilters()
storages = sorted(conn.get_storages(only_actives=True)) storages = sorted(conn.get_storages(only_actives=True))
default_graphics = app_settings.QEMU_CONSOLE_DEFAULT_TYPE default_graphics = app_settings.QEMU_CONSOLE_DEFAULT_TYPE
dom_caps = conn.get_dom_capabilities(arch, machine) dom_caps = conn.get_dom_capabilities(arch, machine)
caps = conn.get_capabilities(arch) caps = conn.get_capabilities(arch)
virtio_support = conn.is_supports_virtio(arch, machine) virtio_support = conn.is_supports_virtio(arch, machine)
hv_supports_uefi = conn.supports_uefi_xml(dom_caps["loader_enums"]) hv_supports_uefi = conn.supports_uefi_xml(dom_caps["loader_enums"])
# Add BIOS # Add BIOS
label = conn.label_for_firmware_path(arch, None) label = conn.label_for_firmware_path(arch, None)
if label: firmwares.append(label) if label: firmwares.append(label)
# Add UEFI # Add UEFI
loader_path = conn.find_uefi_path_for_arch(arch, dom_caps["loaders"]) loader_path = conn.find_uefi_path_for_arch(arch, dom_caps["loaders"])
label = conn.label_for_firmware_path(arch, loader_path) label = conn.label_for_firmware_path(arch, loader_path)
if label: firmwares.append(label) if label: firmwares.append(label)
firmwares = list(set(firmwares)) firmwares = list(set(firmwares))
flavor_form = FlavorForm() flavor_form = FlavorForm()
if conn: if conn:
if not storages: if not storages:
msg = _("You haven't defined any storage pools") raise libvirtError(_("You haven't defined any storage pools"))
messages.error(request, msg) if not networks:
if not networks: raise libvirtError(_("You haven't defined any network pools"))
msg = _("You haven't defined any network pools")
messages.error(request, msg)
if request.method == 'POST': if request.method == 'POST':
if 'create' in request.POST: if 'create' in request.POST:
firmware = dict() firmware = dict()
volume_list = list() volume_list = list()
is_disk_created = False is_disk_created = False
clone_path = "" clone_path = ""
form = NewVMForm(request.POST) form = NewVMForm(request.POST)
if form.is_valid(): if form.is_valid():
data = form.cleaned_data data = form.cleaned_data
if data['meta_prealloc']: if data['meta_prealloc']:
meta_prealloc = True meta_prealloc = True
if instances: if instances:
if data['name'] in instances: if data['name'] in instances:
msg = _("A virtual machine with this name already exists") raise libvirtError(_("A virtual machine with this name already exists"))
messages.error(request, msg) if Instance.objects.filter(name__exact=data['name']):
if Instance.objects.filter(name__exact=data['name']): raise libvirtError(_("There is an instance with same name. Remove it and try again!"))
messages.warning(request, _("There is an instance with same name. Are you sure?"))
if data['hdd_size']:
if not data['mac']:
error_msg = _("No Virtual Machine MAC has been entered")
messages.error(request, msg)
else:
path = conn.create_volume(data['storage'], data['name'], data['hdd_size'], default_disk_format,
meta_prealloc, default_disk_owner_uid, default_disk_owner_gid)
volume = dict()
volume['device'] = 'disk'
volume['path'] = path
volume['type'] = conn.get_volume_type(path)
volume['cache_mode'] = data['cache_mode']
volume['bus'] = default_bus
if volume['bus'] == 'scsi':
volume['scsi_model'] = default_scsi_disk_model
volume['discard_mode'] = default_discard
volume['detect_zeroes_mode'] = default_zeroes
volume['io_mode'] = default_io
volume_list.append(volume) if data['hdd_size']:
is_disk_created = True if not data['mac']:
raise libvirtError(_("No Virtual Machine MAC has been entered"))
elif data['template']: else:
templ_path = conn.get_volume_path(data['template']) path = conn.create_volume(data['storage'], data['name'], data['hdd_size'], default_disk_format,
dest_vol = conn.get_volume_path(data["name"] + ".img", data['storage']) meta_prealloc, default_disk_owner_uid, default_disk_owner_gid)
if dest_vol:
error_msg = _("Image has already exist. Please check volumes or change instance name")
messages.error(request, error_msg)
else:
clone_path = conn.clone_from_template(data['name'], templ_path, data['storage'], meta_prealloc,
default_disk_owner_uid, default_disk_owner_gid)
volume = dict()
volume['path'] = clone_path
volume['type'] = conn.get_volume_type(clone_path)
volume['device'] = 'disk'
volume['cache_mode'] = data['cache_mode']
volume['bus'] = default_bus
if volume['bus'] == 'scsi':
volume['scsi_model'] = default_scsi_disk_model
volume['discard_mode'] = default_discard
volume['detect_zeroes_mode'] = default_zeroes
volume['io_mode'] = default_io
volume_list.append(volume)
is_disk_created = True
else:
if not data['images']:
error_msg = _("First you need to create or select an image")
messages.error(request, error_msg)
else:
for idx, vol in enumerate(data['images'].split(',')):
path = conn.get_volume_path(vol)
volume = dict() volume = dict()
volume['device'] = 'disk'
volume['path'] = path volume['path'] = path
volume['type'] = conn.get_volume_type(path) volume['type'] = conn.get_volume_type(path)
volume['device'] = request.POST.get('device' + str(idx), '') volume['cache_mode'] = data['cache_mode']
volume['bus'] = request.POST.get('bus' + str(idx), '') volume['bus'] = default_bus
if volume['bus'] == 'scsi': if volume['bus'] == 'scsi':
volume['scsi_model'] = default_scsi_disk_model volume['scsi_model'] = default_scsi_disk_model
volume['cache_mode'] = data['cache_mode']
volume['discard_mode'] = default_discard volume['discard_mode'] = default_discard
volume['detect_zeroes_mode'] = default_zeroes volume['detect_zeroes_mode'] = default_zeroes
volume['io_mode'] = default_io volume['io_mode'] = default_io
volume_list.append(volume) volume_list.append(volume)
if data['cache_mode'] not in conn.get_cache_modes(): is_disk_created = True
error_msg = _("Invalid cache mode")
messages.error(request ,error_msg)
if 'UEFI' in data["firmware"]: elif data['template']:
firmware["loader"] = data["firmware"].split(":")[1].strip() templ_path = conn.get_volume_path(data['template'])
firmware["secure"] = 'no' dest_vol = conn.get_volume_path(data["name"] + ".img", data['storage'])
firmware["readonly"] = 'yes' if dest_vol:
firmware["type"] = 'pflash' raise libvirtError(_("Image has already exist. Please check volumes or change instance name"))
if 'secboot' in firmware["loader"] and machine != 'q35': else:
messages.warning( clone_path = conn.clone_from_template(data['name'], templ_path, data['storage'], meta_prealloc,
request, "Changing machine type from '%s' to 'q35' " default_disk_owner_uid, default_disk_owner_gid)
"which is required for UEFI secure boot." % machine) volume = dict()
machine = 'q35' volume['path'] = clone_path
firmware["secure"] = 'yes' volume['type'] = conn.get_volume_type(clone_path)
volume['device'] = 'disk'
volume['cache_mode'] = data['cache_mode']
volume['bus'] = default_bus
if volume['bus'] == 'scsi':
volume['scsi_model'] = default_scsi_disk_model
volume['discard_mode'] = default_discard
volume['detect_zeroes_mode'] = default_zeroes
volume['io_mode'] = default_io
uuid = util.randomUUID() volume_list.append(volume)
try: is_disk_created = True
conn.create_instance(name=data['name'], else:
memory=data['memory'], if not data['images']:
vcpu=data['vcpu'], raise libvirtError(_("First you need to create or select an image"))
vcpu_mode=data['vcpu_mode'], else:
uuid=uuid, for idx, vol in enumerate(data['images'].split(',')):
arch=arch, path = conn.get_volume_path(vol)
machine=machine, volume = dict()
firmware=firmware, volume['path'] = path
volumes=volume_list, volume['type'] = conn.get_volume_type(path)
networks=data['networks'], volume['device'] = request.POST.get('device' + str(idx), '')
virtio=data['virtio'], volume['bus'] = request.POST.get('bus' + str(idx), '')
listen_addr=data["listener_addr"], if volume['bus'] == 'scsi':
nwfilter=data["nwfilter"], volume['scsi_model'] = default_scsi_disk_model
graphics=data["graphics"], volume['cache_mode'] = data['cache_mode']
video=data["video"], volume['discard_mode'] = default_discard
console_pass=data["console_pass"], volume['detect_zeroes_mode'] = default_zeroes
mac=data['mac'], volume['io_mode'] = default_io
qemu_ga=data['qemu_ga'])
create_instance = Instance(compute_id=compute_id, name=data['name'], uuid=uuid) volume_list.append(volume)
create_instance.save() if data['cache_mode'] not in conn.get_cache_modes():
msg = _("Instance is created") error_msg = _("Invalid cache mode")
messages.success(request, msg) raise libvirtError
addlogmsg(request.user.username, create_instance.name, msg)
return redirect(reverse('instances:instance', args=[create_instance.id])) if 'UEFI' in data["firmware"]:
except libvirtError as lib_err: firmware["loader"] = data["firmware"].split(":")[1].strip()
if data['hdd_size'] or len(volume_list) > 0: firmware["secure"] = 'no'
if is_disk_created: firmware["readonly"] = 'yes'
for vol in volume_list: firmware["type"] = 'pflash'
conn.delete_volume(vol['path']) if 'secboot' in firmware["loader"] and machine != 'q35':
messages.error(request, lib_err) messages.warning(
conn.close() request, "Changing machine type from '%s' to 'q35' "
"which is required for UEFI secure boot." % machine)
machine = 'q35'
firmware["secure"] = 'yes'
uuid = util.randomUUID()
try:
conn.create_instance(name=data['name'],
memory=data['memory'],
vcpu=data['vcpu'],
vcpu_mode=data['vcpu_mode'],
uuid=uuid,
arch=arch,
machine=machine,
firmware=firmware,
volumes=volume_list,
networks=data['networks'],
virtio=data['virtio'],
listen_addr=data["listener_addr"],
nwfilter=data["nwfilter"],
graphics=data["graphics"],
video=data["video"],
console_pass=data["console_pass"],
mac=data['mac'],
qemu_ga=data['qemu_ga'])
create_instance = Instance(compute_id=compute_id, name=data['name'], uuid=uuid)
create_instance.save()
msg = _("Instance is created")
messages.success(request, msg)
addlogmsg(request.user.username, create_instance.name, msg)
return redirect(reverse('instances:instance', args=[create_instance.id]))
except libvirtError as lib_err:
if data['hdd_size'] or len(volume_list) > 0:
if is_disk_created:
for vol in volume_list:
conn.delete_volume(vol['path'])
messages.error(request, lib_err)
conn.close()
except libvirtError as lib_err:
messages.error(request, lib_err)
return render(request, 'create_instance_w2.html', locals()) return render(request, 'create_instance_w2.html', locals())

View file

@ -283,6 +283,10 @@ class wvmCreate(wvmConnect):
else: else:
xml += """<target dev='sd%s'/>""" % sd_disk_letters.pop(0) xml += """<target dev='sd%s'/>""" % sd_disk_letters.pop(0)
xml += """</disk>""" xml += """</disk>"""
if volume.get('bus') == 'scsi':
xml += f"""<controller type='scsi' model='{volume.get('scsi_model')}'/>"""
if add_cd: if add_cd:
xml += """<disk type='file' device='cdrom'> xml += """<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/> <driver name='qemu' type='raw'/>
@ -298,9 +302,6 @@ class wvmCreate(wvmConnect):
xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), 'virtio') xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), 'virtio')
xml += """</disk>""" xml += """</disk>"""
if volume.get('bus') == 'scsi':
xml += f"""<controller type='scsi' model='{volume.get('scsi_model')}'/>"""
for net in networks.split(','): for net in networks.split(','):
xml += """<interface type='network'>""" xml += """<interface type='network'>"""
if mac: if mac: