diff --git a/docs/developer-manual.md b/docs/developer-manual.md index 01ff36e4963a68ca89d89007414817be9ad1fee6..45a60a495a30098461ab2efcf3a2131873de709a 100644 --- a/docs/developer-manual.md +++ b/docs/developer-manual.md @@ -135,10 +135,12 @@ EulerLauncher可执行文件包括以下几个部分: 2. 构建`eulerlauncher.exe`: ``` Shell -pyinstaller --clean --noconfirm specs\\cli-mac.spec +pyinstaller --clean --noconfirm specs\\cli-win.spec ``` -3. 将`etc\bin`目录下的`config-env.bat`及`qemu-img`文件夹拷贝到制品目录,并进行压缩。 +3. 将`etc\bin`目录下的`config-env.bat`,`qemu`及`qemu-img`文件夹拷贝到制品目录。 + +4. 在制品目录创建`etc`文件夹,将`logos\favicon.png`复制到该目录下,并在该目录下创建`eulerlauncher.conf`文件,最后将制品目录压缩打包 [1]: https://www.python.org/ [2]: https://brew.sh/ \ No newline at end of file diff --git a/docs/win-user-manual.md b/docs/win-user-manual.md index 9744400b05f9898d900833e127aa5085a29e495e..831f360150423c817c67318ea95d5e56d11e80df 100644 --- a/docs/win-user-manual.md +++ b/docs/win-user-manual.md @@ -2,7 +2,11 @@ **EulerLauncher**当前支持Windows11/10,前往[EulerLauncher最新版下载][1]下载Windows版软件包并解压到期望的位置。 右键点击 `config-env.bat` 并选择**以管理员身份运行**,该脚本将进行环境变量相关的配置,将当前目录添加到系统环境变量 `path`中,如果使用者掌握如何配置环境变量,或配置脚本出现问题,也可以进行手动配置,将当前脚本所在目录及 `qemu-img` 子目录添加至系统环境变量 `path` 中。 -**EulerLauncher**在Windows上运行需要对接 `Hyper-V` 虚拟化后端,`Hyper-V` 是 Microsoft 的硬件虚拟化产品,可以为Windows上的虚拟机提供更为出色的性能。在运行**EulerLauncher**前,请先检查你的系统是否开启了 `Hyper-V`,具体检查及开启方法请参考[Hyper-V开启指导][2]或其他网络资源。 +**EulerLauncher**在Windows上运行需要对接 `Hyper-V` 或者`qemu`虚拟化后端,`Hyper-V` 是 Microsoft 的硬件虚拟化产品,可以为Windows上的虚拟机提供更为出色的性能。在运行**EulerLauncher**前,请先检查你的系统是否开启了 `Hyper-V`,具体检查及开启方法请参考[Hyper-V开启指导][2]或其他网络资源; `qmue`需要在[[qemu官网](https://qemu.weilnetz.de/w64/)]下载安装,然后在[[openvpn官网](https://build.openvpn.net/downloads/releases/)] 下载tap-windows网络适配器,修改名称为tap0并设置tap0的ipv4网络信息,然后将tap0设置为主机网络的共享网络,当tap0的ipv4连接显示Internet则说明配置成功,否则配置失败虚拟机无法分配ip地址。 + + + + **EulerLauncher**解压后包含以下几个部分: @@ -12,16 +16,17 @@ ```Conf [default] -# 配置日志文件的存储目录 -log_dir = D:\eulerlauncher-workdir\logs -# 配置日志等级是否开启Debug +log_dir = D:\workdir-test\logs debug = True -# 配置EulerLauncher的工作目录 -work_dir = D:\eulerlauncher-workdir -# 配置EulerLauncher的镜像目录,镜像目录为对工作目录的相对目录 +work_dir = D:\workdir-test image_dir = images -# 配置EulerLauncher的虚拟机文件目录,虚拟机文件目录为对工作目录的相对目录 instance_dir = instances +qemu_dir = C:\Progra~1\qemu +pattern = qemu + +[vm] +cpu_num = 2 +memory = 8G ``` 配置完成后请右键点击eulerlauncherd.exe,选择以管理员身份运行,点击后eulerlauncherd.exe将以守护进程的形式在后台运行。 diff --git a/etc/bin/qemu/QEMU_EFI.fd b/etc/bin/qemu/QEMU_EFI.fd new file mode 100644 index 0000000000000000000000000000000000000000..fe5de30871ba0ccc9d32830bc59d54388b07aefc Binary files /dev/null and b/etc/bin/qemu/QEMU_EFI.fd differ diff --git a/etc/eulerlauncher-win.conf b/etc/eulerlauncher-win.conf index 423681ab919544d283a7a7d43ce87a450ab5104a..b8fc42dc735aeea68ff2af2d97618e40e7110684 100644 --- a/etc/eulerlauncher-win.conf +++ b/etc/eulerlauncher-win.conf @@ -3,4 +3,10 @@ log_dir = D:\workdir\logs debug = True work_dir = D:\workdir image_dir = images -instance_dir = instances \ No newline at end of file +instance_dir = instances +qemu_dir = +pattern = hyper-v + +[vm] +cpu_num = 2 +memory = 8G \ No newline at end of file diff --git a/eulerlauncher/backends/mac/instance_handler.py b/eulerlauncher/backends/mac/instance_handler.py index a53e78d81925ece983d717e04f3151860cc6b26e..d9f5ba97ff3624ad12cd572043230343bfdb8ebe 100644 --- a/eulerlauncher/backends/mac/instance_handler.py +++ b/eulerlauncher/backends/mac/instance_handler.py @@ -100,7 +100,7 @@ class MacInstanceHandler(object): except KeyError: return 0 - def create_instance(self, name, image_id, instance_record, all_instances, all_images): + def create_instance(self, name, image_id, instance_record, all_instances, all_images, arch='x86'): # Create dir for the instance vm_uuid = uuidutils.generate_uuid() vm_dict = { diff --git a/eulerlauncher/backends/win/image_handler.py b/eulerlauncher/backends/win/image_handler.py index 9f09f4d13bcea66cc39a418e200ccabfdcd582dd..00530fdaf2d1eebb96d5984764c2dfd7bc79a9b4 100644 --- a/eulerlauncher/backends/win/image_handler.py +++ b/eulerlauncher/backends/win/image_handler.py @@ -22,6 +22,7 @@ class WinImageHandler(object): self.image_dir = image_dir self.image_record_file = image_record_file self.LOG = logger + self.pattern = conf.conf.get('default', 'pattern') def download_and_transform(self, images, img_to_download): @@ -40,25 +41,31 @@ class WinImageHandler(object): # Decompress the image self.LOG.debug(f'Decompressing image file: {img_name} ...') - qcow2_name = img_name[:-3] + qcow2_name = img_to_download + '.qcow2' with open(os.path.join(self.image_dir, img_name), 'rb') as pr, open(os.path.join(self.image_dir, qcow2_name), 'wb') as pw: data = pr.read() data_dec = lzma.decompress(data) pw.write(data_dec) - - # Convert the qcow2 img to vhdx - vhdx_name = img_to_download + '.vhdx' - self.LOG.debug(f'Converting image file: {img_name} to {vhdx_name} ...') - with powershell.PowerShell('GBK') as ps: - cmd = 'qemu-img convert -O vhdx {0} {1}' - outs, errs = ps.run(cmd.format(os.path.join(self.image_dir, qcow2_name), os.path.join(self.image_dir, vhdx_name))) - self.LOG.debug(f'Cleanup temp files ...') - os.remove(os.path.join(self.image_dir, qcow2_name)) + image_name = "" + if self.pattern == "hyper-v": + # Convert the qcow2 img to vhdx + + vhdx_name = img_to_download + '.vhdx' + image_name = vhdx_name + self.LOG.debug(f'Converting image file: {img_name} to {vhdx_name} ...') + with powershell.PowerShell('GBK') as ps: + cmd = 'qemu-img convert -O vhdx {0} {1}' + outs, errs = ps.run(cmd.format(os.path.join(self.image_dir, qcow2_name), os.path.join(self.image_dir, vhdx_name))) + + self.LOG.debug(f'Cleanup temp files ...') + os.remove(os.path.join(self.image_dir, qcow2_name)) + elif self.pattern == 'qemu': + image_name = qcow2_name # Record local image img_dict['status'] = constants.IMAGE_STATUS_READY - img_dict['path'] = os.path.join(self.image_dir, vhdx_name) + img_dict['path'] = os.path.join(self.image_dir, image_name) images['local'][img_to_download] = img_dict omni_utils.save_json_data(self.image_record_file, images) self.LOG.debug(f'Image: {img_to_download} is ready ...') @@ -93,31 +100,33 @@ class WinImageHandler(object): image.status = constants.IMAGE_STATUS_LOADING images['local'][image.name] = image.to_dict() omni_utils.save_json_data(self.image_record_file, images) - + qcow2_name = f'{img_to_load}.qcow2' if fmt == 'qcow2': - qcow2_name = f'{img_to_load}.qcow2' shutil.copyfile(path, os.path.join(self.image_dir, qcow2_name)) else: # Decompress the image self.LOG.debug(f'Decompressing image file: {path} ...') - qcow2_name = f'{img_to_load}.qcow2' with open(path, 'rb') as pr, open(os.path.join(self.image_dir, qcow2_name), 'wb') as pw: data = pr.read() data_dec = lzma.decompress(data) pw.write(data_dec) - - # Convert the qcow2 img to vhdx - vhdx_name = img_to_load + '.vhdx' - self.LOG.debug(f'Converting image file: {qcow2_name} to {vhdx_name} ...') - with powershell.PowerShell('GBK') as ps: - cmd = 'qemu-img convert -O vhdx {0} {1}' - outs, errs = ps.run(cmd.format(os.path.join(self.image_dir, qcow2_name), os.path.join(self.image_dir, vhdx_name))) - self.LOG.debug(f'Cleanup temp files ...') - os.remove(os.path.join(self.image_dir, qcow2_name)) + image_name = '' + if self.pattern == 'hyper-v': + # Convert the qcow2 img to vhdx + vhdx_name = img_to_load + '.vhdx' + self.LOG.debug(f'Converting image file: {qcow2_name} to {vhdx_name} ...') + with powershell.PowerShell('GBK') as ps: + cmd = 'qemu-img convert -O vhdx {0} {1}' + outs, errs = ps.run(cmd.format(os.path.join(self.image_dir, qcow2_name), os.path.join(self.image_dir, vhdx_name))) + self.LOG.debug(f'Cleanup temp files ...') + os.remove(os.path.join(self.image_dir, qcow2_name)) + image_name = vhdx_name + elif self.pattern == 'qemu': + image_name = qcow2_name # Record local image - image.path = os.path.join(self.image_dir, vhdx_name) + image.path = os.path.join(self.image_dir, image_name) image.status = constants.IMAGE_STATUS_READY images['local'][image.name] = image.to_dict() omni_utils.save_json_data(self.image_record_file, images) - self.LOG.debug(f'Image: {vhdx_name} is ready ...') + self.LOG.debug(f'Image: {image_name} is ready ...') diff --git a/eulerlauncher/backends/win/instance_handler.py b/eulerlauncher/backends/win/instance_handler.py index 7b27055300490a449c7efdfa61fdb997e03cc2c0..689139ea4794f3171aef61c08104d9b8741a39f2 100644 --- a/eulerlauncher/backends/win/instance_handler.py +++ b/eulerlauncher/backends/win/instance_handler.py @@ -1,6 +1,7 @@ import os import shutil import time +import psutil from oslo_utils import uuidutils from os_win import constants as os_win_const @@ -11,13 +12,15 @@ from eulerlauncher.backends.win import vmops from eulerlauncher.utils import constants from eulerlauncher.utils import utils as omni_utils from eulerlauncher.utils import objs +from eulerlauncher.backends.win import qemu + _vmops = vmops.VMOps() class WinInstanceHandler(object): - def __init__(self, conf, work_dir, instance_dir, image_dir, image_record_file, logger) -> None: + def __init__(self, conf, work_dir, instance_dir, image_dir, image_record_file, logger, base_dir) -> None: self.conf = conf self.work_dir = work_dir self.instance_dir = instance_dir @@ -25,43 +28,78 @@ class WinInstanceHandler(object): self.image_dir = image_dir self.image_record_file = image_record_file self.LOG = logger + self.driver = qemu.QemuDriver(self.conf, logger) + self.running_instances = {} + self.instance_pids = [] + self.base_dir = base_dir + self.pattern = conf.conf.get('default', 'pattern') - def list_instances(self): - vms = _vmops.list_instances() - return vms + # def list_instances(self): + # vms = _vmops.list_instances() + # return vms def check_names(self, name, all_instances): ret = _vmops.check_all_instance_names(name) return ret - - def create_instance(self, name, image_id, instance_record, all_instances, all_images): + + + def list_instances(self): + + instances = omni_utils.load_json_data(self.instance_record_file)['instances'] + vm_list = [] + + if self.pattern == 'qemu': + for instance in instances.values(): + vm = objs.Instance(name=instance['name']) + vm.uuid = instance['uuid'] + vm.mac = instance['mac_address'] + vm.info = None + vm.vm_state = _vmops.check_vm_state(instance) + if vm.vm_state == constants.VM_STATE_MAP[2] and (not instance['ip_address'] or instance['ip_address'] == 'N/A'): + ip_address = _vmops.parse_ip_addr(vm.mac) + vm.ip = ip_address + else: + vm.ip = instance['ip_address'] + vm.image = instance['image'] + vm_list.append(vm) + elif self.pattern == 'hyper-v': + vm_list = _vmops.list_instances() + return vm_list + + def create_instance(self, name, image_id, instance_record, all_instances, all_images, arch='x86'): # Create dir for the instance + instance_path = os.path.join(self.instance_dir, name) + os.makedirs(instance_path) + img_path = all_images['local'][image_id]['path'] + + root_disk_path = shutil.copyfile(img_path, os.path.join(instance_path, image_id + '.qcow2')) if self.pattern == 'qemu' \ + else shutil.copyfile(img_path, os.path.join(instance_path, image_id + '.vhdx')) + vm_ip = '' vm_dict = { 'name': name, 'uuid': uuidutils.generate_uuid(), 'image': image_id, 'vm_state': constants.VM_STATE_MAP[99], 'ip_address': 'N/A', - 'mac_address': 'N/A', - 'identification': { - 'type': 'name', - 'id': name - } + 'mac_address': omni_utils.generate_mac() if self.pattern == 'qemu' else 'N/A', + 'identification': {'type': 'pid','id': None} if self.pattern == 'qemu' else {'type': 'name','id': name} } - - instance_path = os.path.join(self.instance_dir, name) - os.makedirs(instance_path) - img_path = all_images['local'][image_id]['path'] - - root_disk_path = shutil.copyfile(img_path, os.path.join(instance_path, image_id + '.vhdx')) - _vmops.build_and_run_vm(name, vm_dict['uuid'], image_id, False, 2, instance_path, root_disk_path) - - info = _vmops.get_info(name) - vm_dict['vm_state'] = constants.VM_STATE_MAP[info['EnabledState']] - ip = _vmops.get_instance_ip_addr(name) - if ip: - vm_dict['ip_address'] = ip - + if self.pattern == 'qemu': + vm_uuid = uuidutils.generate_uuid() + vm_process = self.driver.create_vm(name, vm_uuid, vm_dict['mac_address'], root_disk_path, arch) + self.running_instances[vm_process.pid] = vm_process + #self.LOG.debug(vm_process.returncode) + #self.LOG.debug(vm_process.pid) + self.instance_pids.append(vm_process.pid) + vm_dict['identification']['id'] = vm_process.pid + vm_ip = _vmops.parse_ip_addr(vm_dict['mac_address']) + elif self.pattern == 'hyper-v': + _vmops.build_and_run_vm(name, vm_dict['uuid'], image_id, False, 2, instance_path, root_disk_path) + info = _vmops.get_info(name) + vm_dict['vm_state'] = constants.VM_STATE_MAP[info['EnabledState']] + vm_ip = _vmops.get_instance_ip_addr(name) + if vm_ip: + vm_dict['ip_address'] = vm_ip instance_record_dict = { 'name': name, 'uuid': vm_dict['uuid'], @@ -77,18 +115,38 @@ class WinInstanceHandler(object): return { 'name': name, - 'vm_state': vm_dict['vm_state'], + 'vm_state': _vmops.check_vm_state(vm_dict) if self.pattern == 'qemu' else vm_dict['vm_state'], 'image': image_id, 'ip_address': vm_dict['ip_address'] } - + + def delete_instance(self, name, instance_record, all_instances): - # Delete instance - _vmops.delete_instance(name) + # Delete instance process + instance = all_instances['instances'][name] + if self.pattern == 'qemu': + processes = [] + if instance['identification']['type'] == 'pid': + instance_pid = instance['identification']['id'] + if instance_pid in psutil.pids(): + processes = psutil.Process(instance_pid).children(recursive=True) + processes.append(psutil.Process(instance_pid)) + for child in processes: + if child.pid in psutil.pids() and \ + child.is_running(): + child.kill() + self.LOG.debug(f'Instance: {child.name()} with PID {child.pid} succesfully killed ...') + else: + self.LOG.debug(f'Instance: {child.name()} with PID {child.pid} already stopped, skip ...') + else: + self.LOG.debug(f'Instance: {name} unable to handled, skip ...') + elif self.pattern == 'hyper-v': + _vmops.delete_instance(name) # Cleanup files and records - instance_dir = all_instances['instances'][name]['path'] - shutil.rmtree(instance_dir) + instance_dir = instance['path'] + if os.path.exists(instance_dir): + shutil.rmtree(instance_dir) del all_instances['instances'][name] omni_utils.save_json_data(instance_record, all_instances) @@ -198,3 +256,4 @@ class WinInstanceHandler(object): """Power on the specified instance.""" self.LOG.debug("Power on instance", instance=instance) self._set_vm_state(instance, os_win_const.HYPERV_VM_STATE_ENABLED) + diff --git a/eulerlauncher/backends/win/qemu.py b/eulerlauncher/backends/win/qemu.py new file mode 100644 index 0000000000000000000000000000000000000000..669cf7d6cd2e2e9ffd4a30d36f9d61f5543dac10 --- /dev/null +++ b/eulerlauncher/backends/win/qemu.py @@ -0,0 +1,51 @@ +import platform +import subprocess +import os + +from eulerlauncher.utils import constants + + +class QemuDriver(object): + + def __init__(self, conf, logger) -> None: + host_arch_raw = platform.uname().machine + host_arch = constants.ARCH_MAP[host_arch_raw] + self.qemu_bin = conf.conf.get('default', 'qemu_dir') + self.uefi_file = os.path.join('C:/Users\WSJ\Desktop\eulerlauncher-v0.3/resources\qemu/', + 'edk2-' + host_arch + '-code.fd') + self.uefi_params = ',if=pflash,format=raw,readonly=on' + self.vm_cpu = conf.conf.get('vm', 'cpu_num') + self.vm_ram = conf.conf.get('vm', 'memory') + self.path = os.getcwd() + self.LOG = logger + + def create_vm(self, vm_name, vm_uuid, vm_mac, vm_root_disk, arch='x86'): + if arch == 'x86': + qemu_cmd = [self.qemu_bin+'\qemu-system-x86_64', + '-name', vm_name, '-uuid', vm_uuid, + '-net nic,macaddr=' + vm_mac, + '-net tap,ifname=tap0,script=no,downscript=no', + '-drive', 'file=' + vm_root_disk+',id=hd0,format=qcow2,media=disk', + '-smp', self.vm_cpu, '-m', self.vm_ram, '-monitor none -chardev null,id=char0', + '-serial chardev:char0 -nographic'] + else: + qemu_cmd = [self.qemu_bin+'\qemu-system-aarch64', + '-name', vm_name, '-uuid', vm_uuid, + '-net nic,macaddr=' + vm_mac, + '-net tap,ifname=tap0,script=no,downscript=no', + '-drive if=virtio,file='+vm_root_disk+',id=hd0,format=qcow2,media=disk', + '-smp', self.vm_cpu, '-m', self.vm_ram, '-cpu cortex-a72 --accel tcg,thread=multi -M virt', + '-device VGA', '-bios', self.path+'\qemu\QEMU_EFI.fd', + '-device nec-usb-xhci -device usb-tablet -device usb-kbd -nographic'] + #qemu_cmd = ' '.join(qemu_cmd) + #powershell_cmd = ['powershell.exe','Start-Process -WindowStyle hidden -FilePath', '"'+self.qemu_bin+'"', '-ArgumentList', '{'+qemu_cmd+'}'] + #self.LOG.debug(' '.join(powershell_cmd)) + #instance_process = subprocess.run(' '.join(powershell_cmd), shell=True) + + #self.LOG.debug(instance_process.Id) + # si = subprocess.STARTUPINFO() + # si.dwFlags |= subprocess.STARTF_USESHOWWINDOW + instance_process = subprocess.Popen(' '.join(qemu_cmd), shell=True) + self.LOG.debug(' '.join(qemu_cmd)) + # self.LOG.debug(self.path) + return instance_process diff --git a/eulerlauncher/backends/win/vmops.py b/eulerlauncher/backends/win/vmops.py index b8e4c75d4193bf3e7a807104b25b580bf98c27ae..2f1340c6ade5b6ccb8e3b3930ec88f5b75363e3f 100644 --- a/eulerlauncher/backends/win/vmops.py +++ b/eulerlauncher/backends/win/vmops.py @@ -1,4 +1,8 @@ import json +import subprocess +import time +import psutil + from os_win import constants as os_win_const from os_win import exceptions as os_win_exc @@ -181,3 +185,43 @@ class VMOps(object): def get_host_ips(self): return self._hostutils.get_local_ips() + + def parse_ip_addr(self, mac_addr): + ip = '' + macs = mac_addr.split(':') + mac_addr1 = '-'.join(macs) + cmd = f'arp -a|findstr {mac_addr1}' + start_time = time.time() + while (ip == '' and time.time() - start_time < 30): + pr = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE) + arp_result = pr.stdout.decode('gbk').strip() + founded = False + if arp_result: + # The result for 'arp -a' in MacOS is different with Linux, it erase + # the first 0 if the first digit is 0 for this mac section, add it + # back before compare + try: + arp_ip = arp_result.split()[0] + mac = arp_result.split()[1] + except IndexError: + continue + if mac_addr1 == mac: + ip = arp_ip + founded = True + if founded: + break + + return ip + + def check_vm_state(self, instance): + if instance['identification']['type'] == 'pid': + instance_pid = instance['identification']['id'] + if instance_pid in psutil.pids() and \ + psutil.Process(instance_pid).status() == 'running': + children = psutil.Process(instance_pid).children(recursive=True) + for chird in children: + if chird.name().startswith('qemu') and chird.is_running(): + return constants.VM_STATE_MAP[2] + return constants.VM_STATE_MAP[3] + else: + return constants.VM_STATE_MAP[99] diff --git a/eulerlauncher/cli.py b/eulerlauncher/cli.py index 56972a1573780b1c5660695f3e7a3cc55009d430..0dcb03f05640f9967df2fbdee123928c742c1177 100644 --- a/eulerlauncher/cli.py +++ b/eulerlauncher/cli.py @@ -68,7 +68,6 @@ def download_image(name): @click.argument('name') @click.option('--path', help='Image file to load') def load_image(name, path): - try: ret = launcher_client.load_image(name, path) except Exception: @@ -103,10 +102,11 @@ def delete_instance(name): @click.command() @click.argument('vm_name') @click.option('--image', help='Image to build vm') -def launch(vm_name, image): +@click.option('--arch', default='x86', type=click.Choice(['x86', 'arm'], case_sensitive=False), help='Architecture of instance') +def launch(vm_name, image, arch): try: - ret = launcher_client.create_instance(vm_name, image) + ret = launcher_client.create_instance(vm_name, image, arch) except Exception: print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...') else: @@ -126,11 +126,20 @@ def launch(vm_name, image): print(ret['msg']) +# @click.command() +# @click.option('--count', default=1, help='Number of greetings.') +# @click.option('--name', prompt='Your name', help='The person to greet.') +# def hello(count, name): +# """Simple program that greets NAME for a total of COUNT times.""" +# for x in range(count): +# click.echo('Hello %s!' % name) + @click.group() def cli(): pass + if __name__ == '__main__': cli.add_command(list) cli.add_command(images) @@ -139,4 +148,5 @@ if __name__ == '__main__': cli.add_command(launch) cli.add_command(delete_image) cli.add_command(delete_instance) - cli() \ No newline at end of file + cli() + diff --git a/eulerlauncher/eulerlauncherd.py b/eulerlauncher/eulerlauncherd.py index 4bd0be7542a1457d53209c23dc5428ae0fb9b252..adb18ccb3e3f561dfd0d9aa806c13d307c467c30 100644 --- a/eulerlauncher/eulerlauncherd.py +++ b/eulerlauncher/eulerlauncherd.py @@ -148,6 +148,7 @@ if __name__ == '__main__': args = parser.parse_args() conf_file = args.conf_file base_dir = args.base_dir + print(base_dir) else: conf_file = os.path.join(os.getcwd(), 'etc', 'eulerlauncher.conf') base_dir = None diff --git a/eulerlauncher/grpcs/client.py b/eulerlauncher/grpcs/client.py index 66adb9afa25f9ddfecc4e33297e7d7cea29ddfaf..dd21b2fbecb2cd3bf84717587902972308f0f54d 100644 --- a/eulerlauncher/grpcs/client.py +++ b/eulerlauncher/grpcs/client.py @@ -41,7 +41,7 @@ class Client(object): def load_image(self, name, path): """ Load local image file """ - + if not os.path.exists(path): err_msg = { 'ret': 1, @@ -80,12 +80,13 @@ class Client(object): return self._instances.list() @omnivirt_utils.response2dict - def create_instance(self, name, image): + def create_instance(self, name, image, arch): """ Create instance :return: dict -- dict of instance's info """ - return self._instances.create(name, image) + + return self._instances.create(name, image, arch) @omnivirt_utils.response2dict def delete_instance(self, name): diff --git a/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2.py b/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2.py index 6b2f860ebc20149da3530d08e18adeca7a89c574..2ddc442a536e4f4b15d53d76925d674db0564362 100644 --- a/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2.py +++ b/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: images.proto +# source: eulerlauncher/grpcs/eulerlauncher_grpc/images.proto """Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -13,28 +13,29 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cimages.proto\x12\x08omnivirt\"7\n\x05Image\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08location\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\"\x12\n\x10ListImageRequest\"4\n\x11ListImageResponse\x12\x1f\n\x06images\x18\x01 \x03(\x0b\x32\x0f.omnivirt.Image\"$\n\x14\x44ownloadImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\".\n\x10LoadImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\"\"\n\x12\x44\x65leteImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"0\n\x14GeneralImageResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t2\xcc\x02\n\x10ImageGrpcService\x12H\n\x0blist_images\x12\x1a.omnivirt.ListImageRequest\x1a\x1b.omnivirt.ListImageResponse\"\x00\x12R\n\x0e\x64ownload_image\x12\x1e.omnivirt.DownloadImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x12J\n\nload_image\x12\x1a.omnivirt.LoadImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x12N\n\x0c\x64\x65lete_image\x12\x1c.omnivirt.DeleteImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x42\x03\x80\x01\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n3eulerlauncher/grpcs/eulerlauncher_grpc/images.proto\x12\x08omnivirt\"7\n\x05Image\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x10\n\x08location\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\"\x12\n\x10ListImageRequest\"4\n\x11ListImageResponse\x12\x1f\n\x06images\x18\x01 \x03(\x0b\x32\x0f.omnivirt.Image\"$\n\x14\x44ownloadImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\".\n\x10LoadImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\"\"\n\x12\x44\x65leteImageRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"0\n\x14GeneralImageResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t2\xcc\x02\n\x10ImageGrpcService\x12H\n\x0blist_images\x12\x1a.omnivirt.ListImageRequest\x1a\x1b.omnivirt.ListImageResponse\"\x00\x12R\n\x0e\x64ownload_image\x12\x1e.omnivirt.DownloadImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x12J\n\nload_image\x12\x1a.omnivirt.LoadImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x12N\n\x0c\x64\x65lete_image\x12\x1c.omnivirt.DeleteImageRequest\x1a\x1e.omnivirt.GeneralImageResponse\"\x00\x42\x03\x80\x01\x01\x62\x06proto3') -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'images_pb2', globals()) +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'eulerlauncher.grpcs.eulerlauncher_grpc.images_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\200\001\001' - _IMAGE._serialized_start=26 - _IMAGE._serialized_end=81 - _LISTIMAGEREQUEST._serialized_start=83 - _LISTIMAGEREQUEST._serialized_end=101 - _LISTIMAGERESPONSE._serialized_start=103 - _LISTIMAGERESPONSE._serialized_end=155 - _DOWNLOADIMAGEREQUEST._serialized_start=157 - _DOWNLOADIMAGEREQUEST._serialized_end=193 - _LOADIMAGEREQUEST._serialized_start=195 - _LOADIMAGEREQUEST._serialized_end=241 - _DELETEIMAGEREQUEST._serialized_start=243 - _DELETEIMAGEREQUEST._serialized_end=277 - _GENERALIMAGERESPONSE._serialized_start=279 - _GENERALIMAGERESPONSE._serialized_end=327 - _IMAGEGRPCSERVICE._serialized_start=330 - _IMAGEGRPCSERVICE._serialized_end=662 + _globals['_IMAGE']._serialized_start=65 + _globals['_IMAGE']._serialized_end=120 + _globals['_LISTIMAGEREQUEST']._serialized_start=122 + _globals['_LISTIMAGEREQUEST']._serialized_end=140 + _globals['_LISTIMAGERESPONSE']._serialized_start=142 + _globals['_LISTIMAGERESPONSE']._serialized_end=194 + _globals['_DOWNLOADIMAGEREQUEST']._serialized_start=196 + _globals['_DOWNLOADIMAGEREQUEST']._serialized_end=232 + _globals['_LOADIMAGEREQUEST']._serialized_start=234 + _globals['_LOADIMAGEREQUEST']._serialized_end=280 + _globals['_DELETEIMAGEREQUEST']._serialized_start=282 + _globals['_DELETEIMAGEREQUEST']._serialized_end=316 + _globals['_GENERALIMAGERESPONSE']._serialized_start=318 + _globals['_GENERALIMAGERESPONSE']._serialized_end=366 + _globals['_IMAGEGRPCSERVICE']._serialized_start=369 + _globals['_IMAGEGRPCSERVICE']._serialized_end=701 # @@protoc_insertion_point(module_scope) diff --git a/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2_grpc.py b/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2_grpc.py index 28eb2df9c2085b818c685fe2958f4ffc8bc90904..3eccb9dadd0a1629efbf8b5b450c9d4d323c1847 100644 --- a/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2_grpc.py +++ b/eulerlauncher/grpcs/eulerlauncher_grpc/images_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from eulerlauncher.grpcs.eulerlauncher_grpc import images_pb2 as images__pb2 +from eulerlauncher.grpcs.eulerlauncher_grpc import images_pb2 as eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2 class ImageGrpcServiceStub(object): @@ -16,23 +16,23 @@ class ImageGrpcServiceStub(object): """ self.list_images = channel.unary_unary( '/omnivirt.ImageGrpcService/list_images', - request_serializer=images__pb2.ListImageRequest.SerializeToString, - response_deserializer=images__pb2.ListImageResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageResponse.FromString, ) self.download_image = channel.unary_unary( '/omnivirt.ImageGrpcService/download_image', - request_serializer=images__pb2.DownloadImageRequest.SerializeToString, - response_deserializer=images__pb2.GeneralImageResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DownloadImageRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, ) self.load_image = channel.unary_unary( '/omnivirt.ImageGrpcService/load_image', - request_serializer=images__pb2.LoadImageRequest.SerializeToString, - response_deserializer=images__pb2.GeneralImageResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.LoadImageRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, ) self.delete_image = channel.unary_unary( '/omnivirt.ImageGrpcService/delete_image', - request_serializer=images__pb2.DeleteImageRequest.SerializeToString, - response_deserializer=images__pb2.GeneralImageResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DeleteImageRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, ) @@ -68,23 +68,23 @@ def add_ImageGrpcServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'list_images': grpc.unary_unary_rpc_method_handler( servicer.list_images, - request_deserializer=images__pb2.ListImageRequest.FromString, - response_serializer=images__pb2.ListImageResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageResponse.SerializeToString, ), 'download_image': grpc.unary_unary_rpc_method_handler( servicer.download_image, - request_deserializer=images__pb2.DownloadImageRequest.FromString, - response_serializer=images__pb2.GeneralImageResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DownloadImageRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.SerializeToString, ), 'load_image': grpc.unary_unary_rpc_method_handler( servicer.load_image, - request_deserializer=images__pb2.LoadImageRequest.FromString, - response_serializer=images__pb2.GeneralImageResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.LoadImageRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.SerializeToString, ), 'delete_image': grpc.unary_unary_rpc_method_handler( servicer.delete_image, - request_deserializer=images__pb2.DeleteImageRequest.FromString, - response_serializer=images__pb2.GeneralImageResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DeleteImageRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -108,8 +108,8 @@ class ImageGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.ImageGrpcService/list_images', - images__pb2.ListImageRequest.SerializeToString, - images__pb2.ListImageResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.ListImageResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @@ -125,8 +125,8 @@ class ImageGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.ImageGrpcService/download_image', - images__pb2.DownloadImageRequest.SerializeToString, - images__pb2.GeneralImageResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DownloadImageRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @@ -142,8 +142,8 @@ class ImageGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.ImageGrpcService/load_image', - images__pb2.LoadImageRequest.SerializeToString, - images__pb2.GeneralImageResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.LoadImageRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @@ -159,7 +159,7 @@ class ImageGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.ImageGrpcService/delete_image', - images__pb2.DeleteImageRequest.SerializeToString, - images__pb2.GeneralImageResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.DeleteImageRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_images__pb2.GeneralImageResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto b/eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto index c2e751cb2fc354d7f0903a9bc7529f278501167d..7d160f65444547c2b18e38196601e5086f4f7c3f 100644 --- a/eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto +++ b/eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto @@ -30,6 +30,7 @@ message ListInstancesResponse { message CreateInstanceRequest { string name = 1; string image = 2; + string arch = 3; } message CreateInstanceResponse { diff --git a/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2.py b/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2.py index 9877833f058ff6798506e937cee9f7ce7d1e555e..49a9e3350b252c998067ce6db4b749e9f0efcb6b 100644 --- a/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2.py +++ b/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: instances.proto +# source: eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto """Generated protocol buffer code.""" -from google.protobuf.internal import builder as _builder from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -13,28 +13,29 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0finstances.proto\x12\x08omnivirt\"M\n\x08Instance\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\x12\x10\n\x08vm_state\x18\x03 \x01(\t\x12\x12\n\nip_address\x18\x04 \x01(\t\"\x16\n\x14ListInstancesRequest\">\n\x15ListInstancesResponse\x12%\n\tinstances\x18\x01 \x03(\x0b\x32\x12.omnivirt.Instance\"4\n\x15\x43reateInstanceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\"j\n\x16\x43reateInstanceResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t\x12)\n\x08instance\x18\x03 \x01(\x0b\x32\x12.omnivirt.InstanceH\x00\x88\x01\x01\x42\x0b\n\t_instance\"%\n\x15\x44\x65leteInstanceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"2\n\x16\x44\x65leteInstanceResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t2\x9a\x02\n\x13InstanceGrpcService\x12S\n\x0elist_instances\x12\x1e.omnivirt.ListInstancesRequest\x1a\x1f.omnivirt.ListInstancesResponse\"\x00\x12V\n\x0f\x63reate_instance\x12\x1f.omnivirt.CreateInstanceRequest\x1a .omnivirt.CreateInstanceResponse\"\x00\x12V\n\x0f\x64\x65lete_instance\x12\x1f.omnivirt.DeleteInstanceRequest\x1a .omnivirt.DeleteInstanceResponse\"\x00\x42\x03\x80\x01\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n6eulerlauncher/grpcs/eulerlauncher_grpc/instances.proto\x12\x08omnivirt\"M\n\x08Instance\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\x12\x10\n\x08vm_state\x18\x03 \x01(\t\x12\x12\n\nip_address\x18\x04 \x01(\t\"\x16\n\x14ListInstancesRequest\">\n\x15ListInstancesResponse\x12%\n\tinstances\x18\x01 \x03(\x0b\x32\x12.omnivirt.Instance\"B\n\x15\x43reateInstanceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05image\x18\x02 \x01(\t\x12\x0c\n\x04\x61rch\x18\x03 \x01(\t\"j\n\x16\x43reateInstanceResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t\x12)\n\x08instance\x18\x03 \x01(\x0b\x32\x12.omnivirt.InstanceH\x00\x88\x01\x01\x42\x0b\n\t_instance\"%\n\x15\x44\x65leteInstanceRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"2\n\x16\x44\x65leteInstanceResponse\x12\x0b\n\x03ret\x18\x01 \x01(\r\x12\x0b\n\x03msg\x18\x02 \x01(\t2\x9a\x02\n\x13InstanceGrpcService\x12S\n\x0elist_instances\x12\x1e.omnivirt.ListInstancesRequest\x1a\x1f.omnivirt.ListInstancesResponse\"\x00\x12V\n\x0f\x63reate_instance\x12\x1f.omnivirt.CreateInstanceRequest\x1a .omnivirt.CreateInstanceResponse\"\x00\x12V\n\x0f\x64\x65lete_instance\x12\x1f.omnivirt.DeleteInstanceRequest\x1a .omnivirt.DeleteInstanceResponse\"\x00\x42\x03\x80\x01\x01\x62\x06proto3') -_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'instances_pb2', globals()) +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'eulerlauncher.grpcs.eulerlauncher_grpc.instances_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\200\001\001' - _INSTANCE._serialized_start=29 - _INSTANCE._serialized_end=106 - _LISTINSTANCESREQUEST._serialized_start=108 - _LISTINSTANCESREQUEST._serialized_end=130 - _LISTINSTANCESRESPONSE._serialized_start=132 - _LISTINSTANCESRESPONSE._serialized_end=194 - _CREATEINSTANCEREQUEST._serialized_start=196 - _CREATEINSTANCEREQUEST._serialized_end=248 - _CREATEINSTANCERESPONSE._serialized_start=250 - _CREATEINSTANCERESPONSE._serialized_end=356 - _DELETEINSTANCEREQUEST._serialized_start=358 - _DELETEINSTANCEREQUEST._serialized_end=395 - _DELETEINSTANCERESPONSE._serialized_start=397 - _DELETEINSTANCERESPONSE._serialized_end=447 - _INSTANCEGRPCSERVICE._serialized_start=450 - _INSTANCEGRPCSERVICE._serialized_end=732 + _globals['_INSTANCE']._serialized_start=68 + _globals['_INSTANCE']._serialized_end=145 + _globals['_LISTINSTANCESREQUEST']._serialized_start=147 + _globals['_LISTINSTANCESREQUEST']._serialized_end=169 + _globals['_LISTINSTANCESRESPONSE']._serialized_start=171 + _globals['_LISTINSTANCESRESPONSE']._serialized_end=233 + _globals['_CREATEINSTANCEREQUEST']._serialized_start=235 + _globals['_CREATEINSTANCEREQUEST']._serialized_end=301 + _globals['_CREATEINSTANCERESPONSE']._serialized_start=303 + _globals['_CREATEINSTANCERESPONSE']._serialized_end=409 + _globals['_DELETEINSTANCEREQUEST']._serialized_start=411 + _globals['_DELETEINSTANCEREQUEST']._serialized_end=448 + _globals['_DELETEINSTANCERESPONSE']._serialized_start=450 + _globals['_DELETEINSTANCERESPONSE']._serialized_end=500 + _globals['_INSTANCEGRPCSERVICE']._serialized_start=503 + _globals['_INSTANCEGRPCSERVICE']._serialized_end=785 # @@protoc_insertion_point(module_scope) diff --git a/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2_grpc.py b/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2_grpc.py index 970781c046dbdda278277ff639fd0e0addcb983a..f2cbb38fa634b797392c6bb303036580c9e9be30 100644 --- a/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2_grpc.py +++ b/eulerlauncher/grpcs/eulerlauncher_grpc/instances_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from eulerlauncher.grpcs.eulerlauncher_grpc import instances_pb2 as instances__pb2 +from eulerlauncher.grpcs.eulerlauncher_grpc import instances_pb2 as eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2 class InstanceGrpcServiceStub(object): @@ -16,18 +16,18 @@ class InstanceGrpcServiceStub(object): """ self.list_instances = channel.unary_unary( '/omnivirt.InstanceGrpcService/list_instances', - request_serializer=instances__pb2.ListInstancesRequest.SerializeToString, - response_deserializer=instances__pb2.ListInstancesResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesResponse.FromString, ) self.create_instance = channel.unary_unary( '/omnivirt.InstanceGrpcService/create_instance', - request_serializer=instances__pb2.CreateInstanceRequest.SerializeToString, - response_deserializer=instances__pb2.CreateInstanceResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceResponse.FromString, ) self.delete_instance = channel.unary_unary( '/omnivirt.InstanceGrpcService/delete_instance', - request_serializer=instances__pb2.DeleteInstanceRequest.SerializeToString, - response_deserializer=instances__pb2.DeleteInstanceResponse.FromString, + request_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceRequest.SerializeToString, + response_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceResponse.FromString, ) @@ -57,18 +57,18 @@ def add_InstanceGrpcServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'list_instances': grpc.unary_unary_rpc_method_handler( servicer.list_instances, - request_deserializer=instances__pb2.ListInstancesRequest.FromString, - response_serializer=instances__pb2.ListInstancesResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesResponse.SerializeToString, ), 'create_instance': grpc.unary_unary_rpc_method_handler( servicer.create_instance, - request_deserializer=instances__pb2.CreateInstanceRequest.FromString, - response_serializer=instances__pb2.CreateInstanceResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceResponse.SerializeToString, ), 'delete_instance': grpc.unary_unary_rpc_method_handler( servicer.delete_instance, - request_deserializer=instances__pb2.DeleteInstanceRequest.FromString, - response_serializer=instances__pb2.DeleteInstanceResponse.SerializeToString, + request_deserializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceRequest.FromString, + response_serializer=eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -92,8 +92,8 @@ class InstanceGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.InstanceGrpcService/list_instances', - instances__pb2.ListInstancesRequest.SerializeToString, - instances__pb2.ListInstancesResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.ListInstancesResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @@ -109,8 +109,8 @@ class InstanceGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.InstanceGrpcService/create_instance', - instances__pb2.CreateInstanceRequest.SerializeToString, - instances__pb2.CreateInstanceResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.CreateInstanceResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @@ -126,7 +126,7 @@ class InstanceGrpcService(object): timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/omnivirt.InstanceGrpcService/delete_instance', - instances__pb2.DeleteInstanceRequest.SerializeToString, - instances__pb2.DeleteInstanceResponse.FromString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceRequest.SerializeToString, + eulerlauncher_dot_grpcs_dot_eulerlauncher__grpc_dot_instances__pb2.DeleteInstanceResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/eulerlauncher/grpcs/images.py b/eulerlauncher/grpcs/images.py index 98b6611044e039fbe8fa815c5f808406624fb5da..f1871d7cebddb421075d689ad7dc95a576094214 100644 --- a/eulerlauncher/grpcs/images.py +++ b/eulerlauncher/grpcs/images.py @@ -19,7 +19,9 @@ class Image(object): def load(self, name, path): """Load local image file""" + request = images_pb2.LoadImageRequest(name=name, path=path) + response = self.client.load_image(request) return response diff --git a/eulerlauncher/grpcs/instances.py b/eulerlauncher/grpcs/instances.py index ec6bc292e07034c3048cb506ae546462e468b134..0e4c7f072f076babf51138c7e836eccf573ef04e 100644 --- a/eulerlauncher/grpcs/instances.py +++ b/eulerlauncher/grpcs/instances.py @@ -10,9 +10,9 @@ class Instance(object): response = self.client.list_instances(request) return response - def create(self, name, image): + def create(self, name, image, arch): """Create instance""" - request = instances_pb2.CreateInstanceRequest(name=name, image=image) + request = instances_pb2.CreateInstanceRequest(name=name, image=image, arch=arch) response = self.client.create_instance(request) return response diff --git a/eulerlauncher/services/imager_service.py b/eulerlauncher/services/imager_service.py index 0d1fb8eb82d23aa81d1b05117536a59856cc39e9..331e7d89e7e61a635d686b4b681927fe11cf8ec2 100644 --- a/eulerlauncher/services/imager_service.py +++ b/eulerlauncher/services/imager_service.py @@ -64,6 +64,7 @@ class ImagerService(images_pb2_grpc.ImageGrpcServiceServicer): return images_pb2.GeneralImageResponse(ret=0, msg=msg) def load_image(self, request, context): + LOG.debug(f"Get request to load image: {request.name} from path: {request.path} ...") supported, fmt = omni_utils.check_file_tail( diff --git a/eulerlauncher/services/instance_service.py b/eulerlauncher/services/instance_service.py index bea002e913f7bceab9ce1b0dea845477c430938b..7d6c85bad7bddfb2d3fd06e514532068eae65b3e 100644 --- a/eulerlauncher/services/instance_service.py +++ b/eulerlauncher/services/instance_service.py @@ -20,10 +20,12 @@ class InstanceService(instances_pb2_grpc.InstanceGrpcServiceServicer): self.instance_record_file = os.path.join(self.instance_dir, 'instances.json') self.image_dir = os.path.join(self.work_dir, 'images') self.img_record_file = os.path.join(self.image_dir, 'images.json') + self.pattern = self.CONF.conf.get('default', 'pattern') + self.host_os = host_os if host_os == 'Win': from eulerlauncher.backends.win import instance_handler as win_instance_handler self.backend = win_instance_handler.WinInstanceHandler( - self.CONF, self.work_dir, self.instance_dir, self.image_dir, self.img_record_file, LOG) + self.CONF, self.work_dir, self.instance_dir, self.image_dir, self.img_record_file, LOG, self.svc_base_dir) elif host_os == 'MacOS': from eulerlauncher.backends.mac import instance_handler as mac_instance_handler self.backend = mac_instance_handler.MacInstanceHandler( @@ -48,12 +50,22 @@ class InstanceService(instances_pb2_grpc.InstanceGrpcServiceServicer): def create_instance(self, request, context): LOG.debug(f"Get request to create instance: {request.name} with image {request.image} ...") - + # LOG.debug(self.pattern) + if self.host_os == 'Win': + if self.pattern == 'hyper-v' and request.arch == 'arm': + msg = f'Error: The pattern of hyper-v can not create the instance with the arm architecture, please choose correct argument : "--arch"' + return instances_pb2.CreateInstanceResponse(ret=2, msg=msg) all_img = utils.load_json_data(self.img_record_file) if request.image not in all_img['local'].keys(): msg = f'Error: Image "{request.image}" is not available locally, please check again or (down)load it before using ...' return instances_pb2.CreateInstanceResponse(ret=2, msg=msg) - + # LOG.debug(os.path.splitext(all_img['local'][request.image]['path'])) + # LOG.debug(request.arch) + if self.host_os == 'Win': + format = os.path.splitext(all_img['local'][request.image]['path'])[-1] + if (format == '.vhdx' and self.pattern == 'qemu') or (format == '.qcow2' and self.pattern == 'hyper-v'): + msg = f'Error: Image "{request.image}" is "{format}" format but pattern is {self.pattern}, please choose correct pattern or correct image.' + return instances_pb2.CreateInstanceResponse(ret=2, msg=msg) all_instances = utils.load_json_data(self.instance_record_file) if request.name in all_instances['instances'].keys(): msg = f'Error: Instance with name {request.name} already exist, please specify another name.' @@ -65,7 +77,7 @@ class InstanceService(instances_pb2_grpc.InstanceGrpcServiceServicer): return instances_pb2.CreateInstanceResponse(ret=2, msg=msg) vm = self.backend.create_instance( - request.name, request.image, self.instance_record_file, all_instances, all_img) + request.name, request.image, self.instance_record_file, all_instances, all_img, request.arch) msg = f'Successfully created {request.name} with image {request.image}' return instances_pb2.CreateInstanceResponse(ret=1, msg=msg, instance=vm)