From 3364de050373aab4cff07e394287cbae2f937eb0 Mon Sep 17 00:00:00 2001
From: wangshj40 <1026749812@qq.com>
Date: Thu, 18 May 2023 16:32:03 +0800
Subject: [PATCH] 1
---
...irt-MacOS.spec => EulerLauncher-MacOS.spec | 10 +-
OmniVirtd-Mac.spec => EulerLauncherd-Mac.spec | 4 +-
cli.spec | 4 +-
docs/developer-manual.md | 22 +-
docs/mac-user-manual.md | 66 +--
docs/win-user-manual.md | 54 +--
...nivirt-win.conf => eulerlauncher-win.conf} | 10 +-
etc/{omnivirt.conf => eulerlauncher.conf} | 18 +-
{omnivirt => eulerlauncher}/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
.../backends/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
.../backends/mac/image_handler.py | 236 +++++------
.../backends/mac/instance_handler.py | 354 ++++++++--------
.../backends/mac/qemu.py | 60 +--
.../backends/win/__init__.py | 0
.../win/__pycache__/__init__.cpython-310.pyc | Bin
.../backends/win/image_handler.py | 246 +++++------
.../backends/win/instance_handler.py | 400 +++++++++---------
.../backends/win/powershell.py | 98 ++---
.../backends/win/vmops.py | 362 ++++++++--------
{omnivirt => eulerlauncher}/cli.py | 286 ++++++-------
.../eulerlauncherd.py | 296 ++++++-------
{omnivirt => eulerlauncher}/grpcs/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
{omnivirt => eulerlauncher}/grpcs/client.py | 190 ++++-----
{omnivirt => eulerlauncher}/grpcs/images.py | 58 +--
.../grpcs/instances.py | 46 +-
.../grpcs/omnivirt_grpc/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
.../grpcs/omnivirt_grpc/images.proto | 92 ++--
.../grpcs/omnivirt_grpc/images_pb2.py | 0
.../grpcs/omnivirt_grpc/images_pb2_grpc.py | 0
.../grpcs/omnivirt_grpc/instances.proto | 96 ++---
.../grpcs/omnivirt_grpc/instances_pb2.py | 0
.../grpcs/omnivirt_grpc/instances_pb2_grpc.py | 0
{omnivirt => eulerlauncher}/install.py | 0
{omnivirt => eulerlauncher}/macos-gui.py | 0
.../services/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
.../services/imager_service.py | 212 +++++-----
.../services/instance_service.py | 162 +++----
{omnivirt => eulerlauncher}/utils/__init__.py | 0
.../__pycache__/__init__.cpython-310.pyc | Bin
.../utils/constants.py | 72 ++--
.../utils/exceptions.py | 120 +++---
{omnivirt => eulerlauncher}/utils/objs.py | 108 ++---
{omnivirt => eulerlauncher}/utils/utils.py | 188 ++++----
install.spec | 6 +-
setup.cfg | 8 +-
50 files changed, 1942 insertions(+), 1942 deletions(-)
rename OmniVirt-MacOS.spec => EulerLauncher-MacOS.spec (73%)
rename OmniVirtd-Mac.spec => EulerLauncherd-Mac.spec (91%)
rename etc/{omnivirt-win.conf => eulerlauncher-win.conf} (95%)
rename etc/{omnivirt.conf => eulerlauncher.conf} (91%)
rename {omnivirt => eulerlauncher}/__init__.py (100%)
rename {omnivirt => eulerlauncher}/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/backends/__init__.py (100%)
rename {omnivirt => eulerlauncher}/backends/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/backends/mac/image_handler.py (97%)
rename {omnivirt => eulerlauncher}/backends/mac/instance_handler.py (97%)
rename {omnivirt => eulerlauncher}/backends/mac/qemu.py (97%)
rename {omnivirt => eulerlauncher}/backends/win/__init__.py (100%)
rename {omnivirt => eulerlauncher}/backends/win/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/backends/win/image_handler.py (97%)
rename {omnivirt => eulerlauncher}/backends/win/instance_handler.py (97%)
rename {omnivirt => eulerlauncher}/backends/win/powershell.py (97%)
rename {omnivirt => eulerlauncher}/backends/win/vmops.py (97%)
rename {omnivirt => eulerlauncher}/cli.py (64%)
rename omnivirt/omnivirtd.py => eulerlauncher/eulerlauncherd.py (85%)
rename {omnivirt => eulerlauncher}/grpcs/__init__.py (100%)
rename {omnivirt => eulerlauncher}/grpcs/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/grpcs/client.py (96%)
rename {omnivirt => eulerlauncher}/grpcs/images.py (97%)
rename {omnivirt => eulerlauncher}/grpcs/instances.py (97%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/__init__.py (100%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/images.proto (94%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/images_pb2.py (100%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/images_pb2_grpc.py (100%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/instances.proto (94%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/instances_pb2.py (100%)
rename {omnivirt => eulerlauncher}/grpcs/omnivirt_grpc/instances_pb2_grpc.py (100%)
rename {omnivirt => eulerlauncher}/install.py (100%)
rename {omnivirt => eulerlauncher}/macos-gui.py (100%)
rename {omnivirt => eulerlauncher}/services/__init__.py (100%)
rename {omnivirt => eulerlauncher}/services/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/services/imager_service.py (97%)
rename {omnivirt => eulerlauncher}/services/instance_service.py (98%)
rename {omnivirt => eulerlauncher}/utils/__init__.py (100%)
rename {omnivirt => eulerlauncher}/utils/__pycache__/__init__.cpython-310.pyc (100%)
rename {omnivirt => eulerlauncher}/utils/constants.py (95%)
rename {omnivirt => eulerlauncher}/utils/exceptions.py (96%)
rename {omnivirt => eulerlauncher}/utils/objs.py (96%)
rename {omnivirt => eulerlauncher}/utils/utils.py (95%)
diff --git a/OmniVirt-MacOS.spec b/EulerLauncher-MacOS.spec
similarity index 73%
rename from OmniVirt-MacOS.spec
rename to EulerLauncher-MacOS.spec
index 12a5e61..758124f 100644
--- a/OmniVirt-MacOS.spec
+++ b/EulerLauncher-MacOS.spec
@@ -5,10 +5,10 @@ block_cipher = None
a = Analysis(
- ['omnivirt/macos-gui.py'],
+ ['eulerlauncher/macos-gui.py'],
pathex=[],
- binaries=[('dist/OmniVirtd', './bin')],
- datas=[('etc/omnivirt.conf', './etc'), ('etc/images/favicon.png', './etc'), ('resources/qemu/edk2-aarch64-code.fd', './etc'), ('resources/qemu/edk2-x86_64-code.fd', './etc')],
+ binaries=[('dist/EulerLauncherd', './bin')],
+ datas=[('etc/eulerlauncher.conf', './etc'), ('etc/images/favicon.png', './etc'), ('resources/qemu/edk2-aarch64-code.fd', './etc'), ('resources/qemu/edk2-x86_64-code.fd', './etc')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
@@ -28,7 +28,7 @@ exe = EXE(
a.zipfiles,
a.datas,
[],
- name='OmniVirt',
+ name='EulerLauncher',
debug=False,
bootloader_ignore_signals=False,
strip=False,
@@ -46,7 +46,7 @@ exe = EXE(
)
app = BUNDLE(
exe,
- name='OmniVirt.app',
+ name='EulerLauncher.app',
icon='etc/images/favicon.ico',
bundle_identifier=None,
)
diff --git a/OmniVirtd-Mac.spec b/EulerLauncherd-Mac.spec
similarity index 91%
rename from OmniVirtd-Mac.spec
rename to EulerLauncherd-Mac.spec
index 3a8748b..f6cc372 100644
--- a/OmniVirtd-Mac.spec
+++ b/EulerLauncherd-Mac.spec
@@ -5,7 +5,7 @@ block_cipher = None
a = Analysis(
- ['omnivirt/omnivirtd.py'],
+ ['eulerlauncher/eulerlauncherd.py'],
pathex=[],
binaries=[],
datas=[],
@@ -28,7 +28,7 @@ exe = EXE(
a.zipfiles,
a.datas,
[],
- name='OmniVirtd',
+ name='EulerLauncherd',
debug=False,
bootloader_ignore_signals=False,
strip=False,
diff --git a/cli.spec b/cli.spec
index bfaf66d..574d7c7 100644
--- a/cli.spec
+++ b/cli.spec
@@ -5,7 +5,7 @@ block_cipher = None
a = Analysis(
- ['omnivirt/cli.py'],
+ ['eulerlauncher/cli.py'],
pathex=[],
binaries=[],
datas=[],
@@ -28,7 +28,7 @@ exe = EXE(
a.zipfiles,
a.datas,
[],
- name='omnivirt',
+ name='eulerlauncher',
debug=False,
bootloader_ignore_signals=False,
strip=False,
diff --git a/docs/developer-manual.md b/docs/developer-manual.md
index 86c398e..3e7177f 100644
--- a/docs/developer-manual.md
+++ b/docs/developer-manual.md
@@ -46,28 +46,28 @@ pip3 install -r requirements.txt
EulerLauncher可执行文件包括以下几个部分:
-1. EulerLauncherd: omnivirt守护进程,以root权限运行在后台,与调用虚拟化组件(Qemu、HyperV、KVM等)及镜像组件进行相关操作;
-2. EulerLauncher.app: OmniVirt服务端主程序,将omnivirtd及其他相关程序、数据、文件等打包为MacOS APP软件包,便于分发和使用。
-3. EulerLauncher: MacOS可执行文件,OmniVirt客户端CLI工具,用于与服务端交互。
-4. install: MacOS可执行文件,将OmniVirt运行所需配置文件及相关数据文件安装至`Application Support`文件夹。
+1. EulerLauncherd: eulerlauncher守护进程,以root权限运行在后台,与调用虚拟化组件(Qemu、HyperV、KVM等)及镜像组件进行相关操作;
+2. EulerLauncher.app: EulerLauncher服务端主程序,将eulerlauncherd及其他相关程序、数据、文件等打包为MacOS APP软件包,便于分发和使用。
+3. EulerLauncher: MacOS可执行文件,EulerLauncher客户端CLI工具,用于与服务端交互。
+4. install: MacOS可执行文件,将EulerLauncher运行所需配置文件及相关数据文件安装至`Application Support`文件夹。
由于`EulerLauncher.app`对`EulerLauncherd`有依赖关系,请严格按照以下顺序构建`EulerLauncherd`及`EulerLauncher.app`:
1. EulerLauncherd:
- 项目源码中已包含用于构建OmniVirtd的Spec脚本`OmniVirtd-Mac.spec`, 若非必要,请勿修改该文件,使用一下命令开始构建:
+ 项目源码中已包含用于构建EulerLauncherd的Spec脚本`EulerLauncherd-Mac.spec`, 若非必要,请勿修改该文件,使用一下命令开始构建:
``` Shell
- pyinstaller --clean --noconfirm OmniVirtd-Mac.spec
+ pyinstaller --clean --noconfirm EulerLauncherd-Mac.spec
```
2. EulerLauncher.app:
- 项目源码中已包含用于构建OmniVirt的Spec脚本`OmniVirt-MacOS.spec`, 若非必要,请勿修改该文件,使用一下命令开始构建:
+ 项目源码中已包含用于构建EulerLauncher的Spec脚本`EulerLauncher-MacOS.spec`, 若非必要,请勿修改该文件,使用一下命令开始构建:
``` Shell
- pyinstaller --clean --noconfirm OmniVirt-MacOS.spec
+ pyinstaller --clean --noconfirm EulerLauncher-MacOS.spec
```
-构建`omnivirt` CLI 及 `install` 脚本, cli与install之间有依赖关系,请严格按照下面的顺序进行构建:
+构建`eulerlauncher` CLI 及 `install` 脚本, cli与install之间有依赖关系,请严格按照下面的顺序进行构建:
``` Shell
pyinstaller --clean --noconfirm cli.spec
@@ -79,12 +79,12 @@ pyinstaller --clean --noconfirm install.spec
首先,我们创建一个新目录并将文件移动到其中。
``` Shell
mkdir -p dist/dmg
-cp -R dist/OmniVirt.app dist/dmg
+cp -R dist/EulerLauncher.app dist/dmg
```
然后,我们可以使用下面的命令来制作磁盘镜像文件:
``` Shell
-create-dmg --volname "OmniVirt" --volicon "etc/images/favicon.png" --window-pos 200 120 --window-size 600 300 --icon-size 100 --icon "OmniVirt.app" 175 120 --hide-extension "OmniVirt.app" --app-drop-link 425 120 "dist/OmniVirt.dmg" "dist/dmg/"
+create-dmg --volname "EulerLauncher" --volicon "etc/images/favicon.png" --window-pos 200 120 --window-size 600 300 --icon-size 100 --icon "EulerLauncher.app" 175 120 --hide-extension "EulerLauncher.app" --app-drop-link 425 120 "dist/EulerLauncher.dmg" "dist/dmg/"
```
`EulerLauncher.dmg`中将只包含`EulerLauncher.app`主程序,需要将`install`脚本及`EulerLauncher` CLI工具一并压缩后再进行分发。
diff --git a/docs/mac-user-manual.md b/docs/mac-user-manual.md
index a73ed41..7356a70 100644
--- a/docs/mac-user-manual.md
+++ b/docs/mac-user-manual.md
@@ -1,4 +1,4 @@
-# 在MacOS下安装与运行OmniVirt
+# 在MacOS下安装与运行EulerLauncher
## 准备工作
@@ -23,7 +23,7 @@ Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载
### 安装Qemu及wget
-**OmniVirt**在MacOS上运行依赖于`QEMU`,镜像下载依赖于`wget`,使用`Homebrew`可以非常方便的下载和管理此类软件,使用以下命令进行安装:
+**EulerLauncher**在MacOS上运行依赖于`QEMU`,镜像下载依赖于`wget`,使用`Homebrew`可以非常方便的下载和管理此类软件,使用以下命令进行安装:
``` Shell
brew install qemu
@@ -32,7 +32,7 @@ brew install wget
### 配置sudo免密码权限
-**OmniVirt**在MacOS上运行依赖于`QEMU`,为了使用户的网络体验更加优秀,因此采用了MacOS的[vmnet framework][1]来提供虚拟机的网络能力,当前`vmnet`使用时需要使用管理员权限,因此在使用`QEMU`后端创建带有`vmnet`类型网络设备的虚拟机时,需要启用管理员权限,OmniVirt在启动时会自动使用`sudo`命令来实现这一过程,因此需要为当前用户配置`sudo`免密码使用权限,如您介意此配置,请停止使用OmniVirt。
+**EulerLauncher**在MacOS上运行依赖于`QEMU`,为了使用户的网络体验更加优秀,因此采用了MacOS的[vmnet framework][1]来提供虚拟机的网络能力,当前`vmnet`使用时需要使用管理员权限,因此在使用`QEMU`后端创建带有`vmnet`类型网络设备的虚拟机时,需要启用管理员权限,OmniVirt在启动时会自动使用`sudo`命令来实现这一过程,因此需要为当前用户配置`sudo`免密码使用权限,如您介意此配置,请停止使用EulerLauncher。
1. 在MacOS桌面下敲击 `command` + `shift` + `u` 组合键,打开`访达`中的`实用工具`,并找到`终端.app`
@@ -44,19 +44,19 @@ brew install wget
4. 敲击`ESC`,再输入`:WQ`进行保存
-## 安装OmniVirt
+## 安装EulerLauncher
-**OmniVirt**当前支持MacOS Ventura, 支持Apple Silicon芯片版及x86芯片版,前往[OmniVirt最新版下载][1]下载MacOS版软件包并解压到期望的位置。
+**EulerLauncher**当前支持MacOS Ventura, 支持Apple Silicon芯片版及x86芯片版,前往[EulerLauncher最新版下载][1]下载MacOS版软件包并解压到期望的位置。
解压后的目录包含以下文件:
-其中`install`可执行文件为安装文件,用于将**OmniVirt**所需支持文件安装到指定位置,`OmniVirt.dmg`为主程序的磁盘映象。
+其中`install`可执行文件为安装文件,用于将**EulerLauncher**所需支持文件安装到指定位置,`EulerLauncher.dmg`为主程序的磁盘映象。
1. 安装支持文件(本操作需要sudo权限,请先完成前面的步骤):双击`install`可执行文件,等待程序完成执行。
-2. 配置**OmniVirt**:
+2. 配置**EulerLauncher**:
- 查看`qemu`及`wget`所处位置,`qemu`二进制文件在不同架构下名称不同,请根据自身情况选择正确的名称(Apple Silicon: qemu-system-aarch64; Intel: qemu-system-x86_64):
``` Shell
@@ -70,16 +70,16 @@ brew install wget
```
查看完成后,记录路径结果,在接下来的步骤中将会使用到。
- - 打开`omnivirt.conf`并进行配置:
+ - 打开`eulerlauncher.conf`并进行配置:
``` Shell
- sudo vi /Library/Application\ Support/org.openeuler.omnivirt/omnivirt.conf
+ sudo vi /Library/Application\ Support/org.openeuler.eulerlauncher/eulerlauncher.conf
```
- omnivirt的配置如下
+ eulerlauncher的配置如下
```
[default]
log_dir = # 日志文件位置(xxx.log)
- work_dir = # omnivirt工作目录,用于存储虚拟机镜像、虚拟机文件等
+ work_dir = # eulerlauncher工作目录,用于存储虚拟机镜像、虚拟机文件等
wget_dir = # wget的可执行文件路径,请参考上一步的内容进行配置
qemu_dir = # qemu的可执行文件路径,请参考上一步的内容进行配置
debug = True
@@ -89,27 +89,27 @@ brew install wget
memory = 1024 # 配置虚拟机的内存大小,单位为M,M1用户请勿配置超过2048
```
-3. 安装**OmniVirt.app**:
+3. 安装**EulerLauncher.app**:
- - 双击`OmniVirt.dmg`,在弹出的窗口中用鼠标将`OmniVirt.app`拖动到`Applications`中,即可完成安装,并可在应用程序中找到`OmniVirt.app`
+ - 双击`EulerLauncher.dmg`,在弹出的窗口中用鼠标将`EulerLauncher.app`拖动到`Applications`中,即可完成安装,并可在应用程序中找到`EulerLauncher.app`
-## 使用OmniVirt
+## 使用EulerLauncher
-1. 在应用程序中找到`OmniVirt.app`,单击启动程序。
+1. 在应用程序中找到`EulerLauncher.app`,单击启动程序。
-2. OmniVirt需要访问网络,在弹出如下窗口时点击`允许`:
+2. EulerLauncher需要访问网络,在弹出如下窗口时点击`允许`:
-3. OmniVirt当前仅支持命令行方式进行访问,请打开`终端.app`,使用命令行进行操作。
+3. EulerLauncher当前仅支持命令行方式进行访问,请打开`终端.app`,使用命令行进行操作。
### 镜像操作
1. 获取可用镜像列表:
```Shell
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -120,12 +120,12 @@ omnivirt images
+-----------+----------+--------------+
```
-**OmniVirt**镜像有两种位置属性:1)远端镜像 2)本地镜像,只有处于本地且状态为 `Ready` 的镜像可以直接用来创建虚拟机,位于远端的镜像需要下载后才能够使用;你也可以加载已经预先下载好的本地镜像到**OmniVirt**中,具体操作方法可以参考接下来的操作指导。
+**EulerLauncher**镜像有两种位置属性:1)远端镜像 2)本地镜像,只有处于本地且状态为 `Ready` 的镜像可以直接用来创建虚拟机,位于远端的镜像需要下载后才能够使用;你也可以加载已经预先下载好的本地镜像到**EulerLauncher**中,具体操作方法可以参考接下来的操作指导。
2. 下载远端镜像
```Shell
-omnivirt download-image 22.03-LTS
+eulerlauncher download-image 22.03-LTS
Downloading: 22.03-LTS, this might take a while, please check image status with "images" command.
```
@@ -133,7 +133,7 @@ Downloading: 22.03-LTS, this might take a while, please check image status with
镜像下载请求是一个异步请求,具体的下载动作将在后台完成,具体耗时与你的网络情况相关,整体的镜像下载流程包括下载、解压缩、格式转换等相关子流程,在下载过程中可以通过 `image` 命令随时查看下载进展与镜像状态:
```Shell
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -148,7 +148,7 @@ omnivirt images
当镜像状态转变为 `Ready` 时,表示镜像下载完成,处于 `Ready` 状态的镜像可被用来创建虚拟机:
```Shell
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -161,10 +161,10 @@ omnivirt images
3. 加载本地镜像
-用户也可以加载自定义镜像或预先下载到本地的镜像到OmniVirt中用于创建自定义虚拟机:
+用户也可以加载自定义镜像或预先下载到本地的镜像到EulerLauncher中用于创建自定义虚拟机:
```Shell
-omnivirt load-image --path {image_file_path} IMAGE_NAME
+eulerlauncher load-image --path {image_file_path} IMAGE_NAME
```
当前支持加载的镜像格式有 `xxx.qcow2.xz`,`xxx.qcow2`
@@ -172,7 +172,7 @@ omnivirt load-image --path {image_file_path} IMAGE_NAME
例如:
```Shell
-omnivirt load-image --path /opt/openEuler-22.03-LTS-x86_64.qcow2.xz 2203-load
+eulerlauncher load-image --path /opt/openEuler-22.03-LTS-x86_64.qcow2.xz 2203-load
Loading: 2203-load, this might take a while, please check image status with "images" command.
```
@@ -180,7 +180,7 @@ Loading: 2203-load, this might take a while, please check image status with "ima
将位于 `/opt` 目录下的 `openEuler-22.03-LTS-x86_64.qcow2.xz` 加载到OmniVirt系统中,并命名为 `2203-load`,与下载命令一样,加载命令也是一个异步命令,用户需要用镜像列表命令查询镜像状态直到显示为 `Ready`, 但相对于直接下载镜像,加载镜像的速度会快很多:
```Shell
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -190,7 +190,7 @@ omnivirt images
| 2203-load | Local | Loading |
+-----------+----------+--------------+
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -203,10 +203,10 @@ omnivirt images
4. 删除镜像:
-通过下面的命令将镜像从OmniVirt系统中删除:
+通过下面的命令将镜像从EulerLauncher系统中删除:
```Shell
-omnivirt delete-image 2203-load
+eulerlauncher delete-image 2203-load
Image: 2203-load has been successfully deleted.
```
@@ -216,7 +216,7 @@ Image: 2203-load has been successfully deleted.
1. 获取虚拟机列表:
```shell
-omnivirt list
+eulerlauncher list
+----------+-----------+---------+---------------+
| Name | Image | State | IP |
@@ -241,17 +241,17 @@ ssh root@{instance_ip}
3. 创建虚拟机
```Shell
-omnivirt launch --image {image_name} {instance_name}
+eulerlauncher launch --image {image_name} {instance_name}
```
通过 `--image` 指定镜像,同时指定虚拟机名称。
4. 删除虚拟机
```Shell
-omnivirt delete-instance {instance_name}
+eulerlauncher delete-instance {instance_name}
```
根据虚拟机名称删除指定的虚拟机。
[1]: https://developer.apple.com/documentation/vmnet
-[2]: https://gitee.com/openeuler/omnivirt/releases
\ No newline at end of file
+[2]: https://gitee.com/openeuler/eulerlauncher/releases
\ No newline at end of file
diff --git a/docs/win-user-manual.md b/docs/win-user-manual.md
index 6329c7a..55631c1 100644
--- a/docs/win-user-manual.md
+++ b/docs/win-user-manual.md
@@ -6,40 +6,40 @@
**EulerLauncher**解压后包含以下几个部分:
-- omnivirtd.exe:OmniVirt的主进程,是运行在后台的守护进程,负责与各类虚拟化后端交互,管理虚拟机、容器以及镜像的生命周期,omnivirtd.exe是运行在后台的守护进程。
-- onivirt.exe:OmniVirt的CLI客户端,用户通过该客户端与omnivirtd守护进程交互,对虚拟机、镜像等进行相关操作。
-- omnivirt-win.conf:OmniVirt配置文件,需与omnivirtd.exe放置于同一目录下,参考下面配置进行相应配置:
+- eulerlauncherd.exe:EulerLauncher的主进程,是运行在后台的守护进程,负责与各类虚拟化后端交互,管理虚拟机、容器以及镜像的生命周期,eulerlauncherd.exe是运行在后台的守护进程。
+- eulerlauncher.exe:EulerLauncher的CLI客户端,用户通过该客户端与eulerlauncherd守护进程交互,对虚拟机、镜像等进行相关操作。
+- eulerlauncher-win.conf:EulerLauncher配置文件,需与eulerlauncherd.exe放置于同一目录下,参考下面配置进行相应配置:
```Conf
[default]
# 配置日志文件的存储目录
-log_dir = D:\omnivirt-workdir\logs
+log_dir = D:\eulerlauncher-workdir\logs
# 配置日志等级是否开启Debug
debug = True
-# 配置OmniVirt的工作目录
-work_dir = D:\omnivirt-workdir
-# 配置OmniVirt的镜像目录,镜像目录为对工作目录的相对目录
+# 配置EulerLauncher的工作目录
+work_dir = D:\eulerlauncher-workdir
+# 配置EulerLauncher的镜像目录,镜像目录为对工作目录的相对目录
image_dir = images
-# 配置OmniVirt的虚拟机文件目录,虚拟机文件目录为对工作目录的相对目录
+# 配置EulerLauncher的虚拟机文件目录,虚拟机文件目录为对工作目录的相对目录
instance_dir = instances
```
-配置完成后请右键点击omnivirtd.exe,选择以管理员身份运行,点击后omnivird.exe将以守护进程的形式在后台运行。
+配置完成后请右键点击eulerlauncherd.exe,选择以管理员身份运行,点击后eulerlauncherd.exe将以守护进程的形式在后台运行。
打开 `PowerShell` 或 `Terminal` ,准备进行对应的操作。
### Windows下退出EulerLauncherd后台进程
-当omnivirtd.exe运行后,会在操作系统右下角托盘区域生成omnivirtd托盘图标:
+当eulerlauncherd.exe运行后,会在操作系统右下角托盘区域生成eulerlauncherd托盘图标:
-鼠标右键点击托盘图标,并选择 `Exit OmniVirt` 即可退出omnivirtd后台进程。
+鼠标右键点击托盘图标,并选择 `Exit EulerLauncher` 即可退出eulerlauncherd后台进程。
### 镜像操作
1. 获取可用镜像列表:
```PowerShell
-omnivirt.exe images
+eulerlauncher.exe images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -50,12 +50,12 @@ omnivirt.exe images
+-----------+----------+--------------+
```
-**EulerLauncher**镜像有两种位置属性:1)远端镜像 2)本地镜像,只有处于本地且状态为 `Ready` 的镜像可以直接用来创建虚拟机,位于远端的镜像需要下载后才能够使用;你也可以加载已经预先下载好的本地镜像到**OmniVirt**中,具体操作方法可以参考接下来的操作指导。
+**EulerLauncher**镜像有两种位置属性:1)远端镜像 2)本地镜像,只有处于本地且状态为 `Ready` 的镜像可以直接用来创建虚拟机,位于远端的镜像需要下载后才能够使用;你也可以加载已经预先下载好的本地镜像到**EulerLauncher**中,具体操作方法可以参考接下来的操作指导。
2. 下载远端镜像
```PowerShell
-omnivirt.exe download-image 22.03-LTS
+eulerlauncher.exe download-image 22.03-LTS
Downloading: 22.03-LTS, this might take a while, please check image status with "images" command.
```
@@ -63,7 +63,7 @@ Downloading: 22.03-LTS, this might take a while, please check image status with
镜像下载请求是一个异步请求,具体的下载动作将在后台完成,具体耗时与你的网络情况相关,整体的镜像下载流程包括下载、解压缩、格式转换等相关子流程,在下载过程中可以通过 `image` 命令随时查看下载进展与镜像状态:
```PowerShell
-omnivirt.exe images
+eulerlauncher.exe images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -78,7 +78,7 @@ omnivirt.exe images
当镜像状态转变为 `Ready` 时,表示镜像下载完成,处于 `Ready` 状态的镜像可被用来创建虚拟机:
```PowerShell
-omnivirt.exe images
+eulerlauncher.exe images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -91,10 +91,10 @@ omnivirt.exe images
3. 加载本地镜像
-用户也可以加载自定义镜像或预先下载到本地的镜像到OmniVirt中用于创建自定义虚拟机:
+用户也可以加载自定义镜像或预先下载到本地的镜像到EulerLauncher中用于创建自定义虚拟机:
```PowerShell
-omnivirt.exe load-image --path {image_file_path} IMAGE_NAME
+eulerlauncher.exe load-image --path {image_file_path} IMAGE_NAME
```
当前支持加载的镜像格式有 `xxx.qcow2.xz`,`xxx.qcow2`
@@ -102,15 +102,15 @@ omnivirt.exe load-image --path {image_file_path} IMAGE_NAME
例如:
```PowerShell
-omnivirt.exe load-image --path D:\openEuler-22.03-LTS-x86_64.qcow2.xz 2203-load
+eulerlauncher.exe load-image --path D:\openEuler-22.03-LTS-x86_64.qcow2.xz 2203-load
Loading: 2203-load, this might take a while, please check image status with "images" command.
```
-将位于 `D:\` 目录下的 `openEuler-22.03-LTS-x86_64.qcow2.xz` 加载到OmniVirt系统中,并命名为 `2203-load`,与下载命令一样,加载命令也是一个异步命令,用户需要用镜像列表命令查询镜像状态直到显示为 `Ready`, 但相对于直接下载镜像,加载镜像的速度会快很多:
+将位于 `D:\` 目录下的 `openEuler-22.03-LTS-x86_64.qcow2.xz` 加载到EulerLauncher系统中,并命名为 `2203-load`,与下载命令一样,加载命令也是一个异步命令,用户需要用镜像列表命令查询镜像状态直到显示为 `Ready`, 但相对于直接下载镜像,加载镜像的速度会快很多:
```PowerShell
-omnivirt.exe images
+eulerlauncher.exe images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -120,7 +120,7 @@ omnivirt.exe images
| 2203-load | Local | Loading |
+-----------+----------+--------------+
-omnivirt images
+eulerlauncher images
+-----------+----------+--------------+
| Images | Location | Status |
@@ -136,7 +136,7 @@ omnivirt images
通过下面的命令将镜像从OmniVirt系统中删除:
```PowerShell
-omnivirt.exe delete-image 2203-load
+eulerlauncher.exe delete-image 2203-load
Image: 2203-load has been successfully deleted.
```
@@ -146,7 +146,7 @@ Image: 2203-load has been successfully deleted.
1. 获取虚拟机列表:
```Powershell
-omnivirt.exe list
+eulerlauncher.exe list
+----------+-----------+---------+---------------+
| Name | Image | State | IP |
@@ -171,16 +171,16 @@ ssh root@{instance_ip}
3. 创建虚拟机
```PowerShell
-omnivirt.exe launch --image {image_name} {instance_name}
+eulerlauncher.exe launch --image {image_name} {instance_name}
```
通过 `--image` 指定镜像,同时指定虚拟机名称。
4. 删除虚拟机
```PowerShell
-omnivirt.exe delete-instance {instance_name}
+eulerlauncher.exe delete-instance {instance_name}
```
根据虚拟机名称删除指定的虚拟机。
-[1]: https://gitee.com/openeuler/omnivirt/releases
+[1]: https://gitee.com/openeuler/eulerlauncher/releases
[2]: https://learn.microsoft.com/zh-cn/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v
\ No newline at end of file
diff --git a/etc/omnivirt-win.conf b/etc/eulerlauncher-win.conf
similarity index 95%
rename from etc/omnivirt-win.conf
rename to etc/eulerlauncher-win.conf
index 423681a..817262a 100644
--- a/etc/omnivirt-win.conf
+++ b/etc/eulerlauncher-win.conf
@@ -1,6 +1,6 @@
-[default]
-log_dir = D:\workdir\logs
-debug = True
-work_dir = D:\workdir
-image_dir = images
+[default]
+log_dir = D:\workdir\logs
+debug = True
+work_dir = D:\workdir
+image_dir = images
instance_dir = instances
\ No newline at end of file
diff --git a/etc/omnivirt.conf b/etc/eulerlauncher.conf
similarity index 91%
rename from etc/omnivirt.conf
rename to etc/eulerlauncher.conf
index a101a51..07ac1c6 100644
--- a/etc/omnivirt.conf
+++ b/etc/eulerlauncher.conf
@@ -1,10 +1,10 @@
-[default]
-log_dir =
-work_dir =
-wget_dir =
-qemu_dir =
-debug = True
-
-[vm]
-cpu_num = 1
+[default]
+log_dir =
+work_dir =
+wget_dir =
+qemu_dir =
+debug = True
+
+[vm]
+cpu_num = 1
memory = 1024
\ No newline at end of file
diff --git a/omnivirt/__init__.py b/eulerlauncher/__init__.py
similarity index 100%
rename from omnivirt/__init__.py
rename to eulerlauncher/__init__.py
diff --git a/omnivirt/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/backends/__init__.py b/eulerlauncher/backends/__init__.py
similarity index 100%
rename from omnivirt/backends/__init__.py
rename to eulerlauncher/backends/__init__.py
diff --git a/omnivirt/backends/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/backends/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/backends/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/backends/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/backends/mac/image_handler.py b/eulerlauncher/backends/mac/image_handler.py
similarity index 97%
rename from omnivirt/backends/mac/image_handler.py
rename to eulerlauncher/backends/mac/image_handler.py
index c11f03d..9329456 100644
--- a/omnivirt/backends/mac/image_handler.py
+++ b/eulerlauncher/backends/mac/image_handler.py
@@ -1,118 +1,118 @@
-import copy
-import lzma
-import wget
-import os
-import subprocess
-import shutil
-import ssl
-
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omni_utils
-from omnivirt.utils import objs
-
-
-ssl._create_default_https_context = ssl._create_unverified_context
-
-
-class MacImageHandler(object):
-
- def __init__(self, conf, work_dir, image_dir, image_record_file,
- logger, base_dir) -> None:
- self.conf = conf
- self.work_dir = work_dir
- self.image_dir = image_dir
- self.image_record_file = image_record_file
- self.base_dir = base_dir
- self.wget_bin = conf.conf.get('default', 'wget_dir')
- self.LOG = logger
-
-
- def download_and_transform(self, images, img_to_download):
-
- # Download the image
- img_name = wget.filename_from_url(images['remote'][img_to_download]['path'])
- img_dict = copy.deepcopy(images['remote'][img_to_download])
-
- if not os.path.exists(os.path.join(self.image_dir, img_name)):
- self.LOG.debug(f'Downloading image: {img_to_download} from remote repo ...')
- img_dict['location'] = constants.IMAGE_LOCATION_LOCAL
- img_dict['status'] = constants.IMAGE_STATUS_DOWNLOADING
- images['local'][img_to_download] = img_dict
- omni_utils.save_json_data(self.image_record_file, images)
-
- download_cmd = [self.wget_bin, images['remote'][img_to_download]['path'],
- '-O', os.path.join(self.image_dir, img_name), '--no-check-certificate']
- self.LOG.debug(' '.join(download_cmd))
- subprocess.call(' '.join(download_cmd), shell=True)
- #wget.download(url=images['remote'][img_to_download]['path'], out=os.path.join(self.image_dir, img_name), bar=None)
- self.LOG.debug(f'Image: {img_to_download} succesfully downloaded from remote repo ...')
-
- # Decompress the image
- self.LOG.debug(f'Decompressing image file: {img_name} ...')
- qcow2_name = img_name[:-3]
- 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)
-
- self.LOG.debug(f'Cleanup temp files ...')
- os.remove(os.path.join(self.image_dir, img_name))
-
- # Record local image
- img_dict['status'] = constants.IMAGE_STATUS_READY
- img_dict['path'] = os.path.join(self.image_dir, qcow2_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 ...')
-
-
- def delete_image(self, images, img_to_delete):
- if img_to_delete not in images['local'].keys():
- return 1
- else:
- return self._delete_image(images, img_to_delete)
-
- def _delete_image(self, images, img_to_delete):
- img_path = images['local'][img_to_delete]['path']
- # TODO: Raise error message if image file not exists
- if os.path.exists(img_path):
- self.LOG.debug(f'Deleting: {img_path} ...')
- os.remove(img_path)
-
- self.LOG.debug(f'Deleting: {img_to_delete} from image database ...')
- del images['local'][img_to_delete]
- omni_utils.save_json_data(self.image_record_file, images)
-
- return 0
-
- def load_and_transform(self, images, img_to_load, path, fmt, update=False):
-
- if update:
- self._delete_image(images, img_to_load)
-
- image = objs.Image()
- image.name = img_to_load
- image.path = ''
- image.location = constants.IMAGE_LOCATION_LOCAL
- image.status = constants.IMAGE_STATUS_LOADING
- images['local'][image.name] = image.to_dict()
- omni_utils.save_json_data(self.image_record_file, images)
-
- 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)
-
- # Record local image
- image.path = os.path.join(self.image_dir, qcow2_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: {qcow2_name} is ready ...')
+import copy
+import lzma
+import wget
+import os
+import subprocess
+import shutil
+import ssl
+
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omni_utils
+from omnivirt.utils import objs
+
+
+ssl._create_default_https_context = ssl._create_unverified_context
+
+
+class MacImageHandler(object):
+
+ def __init__(self, conf, work_dir, image_dir, image_record_file,
+ logger, base_dir) -> None:
+ self.conf = conf
+ self.work_dir = work_dir
+ self.image_dir = image_dir
+ self.image_record_file = image_record_file
+ self.base_dir = base_dir
+ self.wget_bin = conf.conf.get('default', 'wget_dir')
+ self.LOG = logger
+
+
+ def download_and_transform(self, images, img_to_download):
+
+ # Download the image
+ img_name = wget.filename_from_url(images['remote'][img_to_download]['path'])
+ img_dict = copy.deepcopy(images['remote'][img_to_download])
+
+ if not os.path.exists(os.path.join(self.image_dir, img_name)):
+ self.LOG.debug(f'Downloading image: {img_to_download} from remote repo ...')
+ img_dict['location'] = constants.IMAGE_LOCATION_LOCAL
+ img_dict['status'] = constants.IMAGE_STATUS_DOWNLOADING
+ images['local'][img_to_download] = img_dict
+ omni_utils.save_json_data(self.image_record_file, images)
+
+ download_cmd = [self.wget_bin, images['remote'][img_to_download]['path'],
+ '-O', os.path.join(self.image_dir, img_name), '--no-check-certificate']
+ self.LOG.debug(' '.join(download_cmd))
+ subprocess.call(' '.join(download_cmd), shell=True)
+ #wget.download(url=images['remote'][img_to_download]['path'], out=os.path.join(self.image_dir, img_name), bar=None)
+ self.LOG.debug(f'Image: {img_to_download} succesfully downloaded from remote repo ...')
+
+ # Decompress the image
+ self.LOG.debug(f'Decompressing image file: {img_name} ...')
+ qcow2_name = img_name[:-3]
+ 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)
+
+ self.LOG.debug(f'Cleanup temp files ...')
+ os.remove(os.path.join(self.image_dir, img_name))
+
+ # Record local image
+ img_dict['status'] = constants.IMAGE_STATUS_READY
+ img_dict['path'] = os.path.join(self.image_dir, qcow2_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 ...')
+
+
+ def delete_image(self, images, img_to_delete):
+ if img_to_delete not in images['local'].keys():
+ return 1
+ else:
+ return self._delete_image(images, img_to_delete)
+
+ def _delete_image(self, images, img_to_delete):
+ img_path = images['local'][img_to_delete]['path']
+ # TODO: Raise error message if image file not exists
+ if os.path.exists(img_path):
+ self.LOG.debug(f'Deleting: {img_path} ...')
+ os.remove(img_path)
+
+ self.LOG.debug(f'Deleting: {img_to_delete} from image database ...')
+ del images['local'][img_to_delete]
+ omni_utils.save_json_data(self.image_record_file, images)
+
+ return 0
+
+ def load_and_transform(self, images, img_to_load, path, fmt, update=False):
+
+ if update:
+ self._delete_image(images, img_to_load)
+
+ image = objs.Image()
+ image.name = img_to_load
+ image.path = ''
+ image.location = constants.IMAGE_LOCATION_LOCAL
+ image.status = constants.IMAGE_STATUS_LOADING
+ images['local'][image.name] = image.to_dict()
+ omni_utils.save_json_data(self.image_record_file, images)
+
+ 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)
+
+ # Record local image
+ image.path = os.path.join(self.image_dir, qcow2_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: {qcow2_name} is ready ...')
diff --git a/omnivirt/backends/mac/instance_handler.py b/eulerlauncher/backends/mac/instance_handler.py
similarity index 97%
rename from omnivirt/backends/mac/instance_handler.py
rename to eulerlauncher/backends/mac/instance_handler.py
index a7aa10d..208c580 100644
--- a/omnivirt/backends/mac/instance_handler.py
+++ b/eulerlauncher/backends/mac/instance_handler.py
@@ -1,177 +1,177 @@
-import os
-import psutil
-import shutil
-import signal
-import subprocess
-import sys
-import time
-
-from oslo_utils import uuidutils
-
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omni_utils
-from omnivirt.utils import objs
-from omnivirt.backends.mac import qemu
-
-
-class MacInstanceHandler(object):
-
- 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
- self.instance_record_file = os.path.join(instance_dir, 'instances.json')
- self.image_dir = image_dir
- self.image_record_file = image_record_file
- self.driver = qemu.QemuDriver(self.conf, logger)
- self.running_instances = {}
- self.instance_pids = []
- self.base_dir = base_dir
- self.LOG = logger
-
- def list_instances(self):
- instances = omni_utils.load_json_data(self.instance_record_file)['instances']
- vm_list = []
-
- 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 = self._check_vm_state(instance)
- if not instance['ip_address']:
- ip_address = self._parse_ip_addr(vm.mac)
- vm.ip = ip_address
- else:
- vm.ip = instance['ip_address']
- vm.image = instance['image']
- vm_list.append(vm)
-
- return vm_list
-
- 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' and \
- psutil.Process(instance_pid).name().startswith('qemu'):
- return constants.VM_STATE_MAP[2]
- else:
- return constants.VM_STATE_MAP[3]
- else:
- return constants.VM_STATE_MAP[99]
-
- def _parse_ip_addr(self, mac_addr):
- ip = ''
- cmd = 'arp -a'
- start_time = time.time()
- while(ip == '' and time.time() - start_time < 20):
- pr = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
- arp_result = pr.stdout.decode('utf-8').split('\n')
- founded = False
- for str in 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 = str.split(' ')[1].replace("(", "").replace(")", "")
- mac = str.split(' ')[3].replace("(", "").replace(")", "")
- except IndexError:
- continue
- mac_list = mac.split(':')
- for i in range(0, len(mac_list)):
- if len(mac_list[i]) == 1:
- mac_list[i] = '0' + mac_list[i]
- mac_0 = ':'.join(mac_list)
- if mac_addr == mac_0:
- ip = arp_ip
- founded = True
- break
- if founded:
- break
-
- return ip
-
- def check_names(self, name, all_instances):
- try:
- all_instances['instances'][name]
- return 1
- except KeyError:
- return 0
-
- def create_instance(self, name, image_id, instance_record, all_instances, all_images):
- # Create dir for the instance
- vm_uuid = uuidutils.generate_uuid()
- vm_dict = {
- 'name': name,
- 'uuid': vm_uuid,
- 'image': image_id,
- 'vm_state': constants.VM_STATE_MAP[99],
- 'ip_address': 'N/A',
- 'mac_address': omni_utils.generate_mac(),
- 'identification': {
- 'type': 'pid',
- 'id': None
- }
- }
-
- 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'))
-
- vm_process = self.driver.create_vm(name, vm_uuid, vm_dict['mac_address'], root_disk_path)
-
- self.running_instances[vm_process.pid] = vm_process
- self.instance_pids.append(vm_process.pid)
-
- vm_dict['identification']['id'] = vm_process.pid
-
- vm_ip = self._parse_ip_addr(vm_dict['mac_address'])
- vm_dict['ip_address'] = vm_ip
-
- instance_record_dict = {
- 'name': name,
- 'uuid': vm_dict['uuid'],
- 'image': image_id,
- 'path': instance_path,
- 'mac_address': vm_dict['mac_address'],
- 'ip_address': vm_dict['ip_address'],
- 'identification': vm_dict['identification']
- }
-
- all_instances['instances'][name] = instance_record_dict
- omni_utils.save_json_data(instance_record, all_instances)
-
- return {
- 'name': name,
- 'vm_state': self._check_vm_state(vm_dict),
- 'image': image_id,
- 'ip_address': vm_dict['ip_address']
- }
-
- def delete_instance(self, name, instance_record, all_instances):
- # Delete instance process
- instance = all_instances['instances'][name]
- if instance['identification']['type'] == 'pid':
- instance_pid = instance['identification']['id']
- if instance_pid in psutil.pids() and \
- psutil.Process(instance_pid).is_running():
- psutil.Process(instance_pid).kill()
- self.LOG.debug(f'Instance: {name} with PID {instance_pid} succesfully killed ...')
- else:
- self.LOG.debug(f'Instance: {name} with PID {instance_pid} already stopped, skip ...')
- else:
- self.LOG.debug(f'Instance: {name} unable to handled, skip ...')
-
- # Cleanup files and records
- instance_dir = instance['path']
- shutil.rmtree(instance_dir)
- del all_instances['instances'][name]
-
- omni_utils.save_json_data(instance_record, all_instances)
-
- return 0
-
+import os
+import psutil
+import shutil
+import signal
+import subprocess
+import sys
+import time
+
+from oslo_utils import uuidutils
+
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omni_utils
+from omnivirt.utils import objs
+from omnivirt.backends.mac import qemu
+
+
+class MacInstanceHandler(object):
+
+ 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
+ self.instance_record_file = os.path.join(instance_dir, 'instances.json')
+ self.image_dir = image_dir
+ self.image_record_file = image_record_file
+ self.driver = qemu.QemuDriver(self.conf, logger)
+ self.running_instances = {}
+ self.instance_pids = []
+ self.base_dir = base_dir
+ self.LOG = logger
+
+ def list_instances(self):
+ instances = omni_utils.load_json_data(self.instance_record_file)['instances']
+ vm_list = []
+
+ 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 = self._check_vm_state(instance)
+ if not instance['ip_address']:
+ ip_address = self._parse_ip_addr(vm.mac)
+ vm.ip = ip_address
+ else:
+ vm.ip = instance['ip_address']
+ vm.image = instance['image']
+ vm_list.append(vm)
+
+ return vm_list
+
+ 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' and \
+ psutil.Process(instance_pid).name().startswith('qemu'):
+ return constants.VM_STATE_MAP[2]
+ else:
+ return constants.VM_STATE_MAP[3]
+ else:
+ return constants.VM_STATE_MAP[99]
+
+ def _parse_ip_addr(self, mac_addr):
+ ip = ''
+ cmd = 'arp -a'
+ start_time = time.time()
+ while(ip == '' and time.time() - start_time < 20):
+ pr = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE)
+ arp_result = pr.stdout.decode('utf-8').split('\n')
+ founded = False
+ for str in 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 = str.split(' ')[1].replace("(", "").replace(")", "")
+ mac = str.split(' ')[3].replace("(", "").replace(")", "")
+ except IndexError:
+ continue
+ mac_list = mac.split(':')
+ for i in range(0, len(mac_list)):
+ if len(mac_list[i]) == 1:
+ mac_list[i] = '0' + mac_list[i]
+ mac_0 = ':'.join(mac_list)
+ if mac_addr == mac_0:
+ ip = arp_ip
+ founded = True
+ break
+ if founded:
+ break
+
+ return ip
+
+ def check_names(self, name, all_instances):
+ try:
+ all_instances['instances'][name]
+ return 1
+ except KeyError:
+ return 0
+
+ def create_instance(self, name, image_id, instance_record, all_instances, all_images):
+ # Create dir for the instance
+ vm_uuid = uuidutils.generate_uuid()
+ vm_dict = {
+ 'name': name,
+ 'uuid': vm_uuid,
+ 'image': image_id,
+ 'vm_state': constants.VM_STATE_MAP[99],
+ 'ip_address': 'N/A',
+ 'mac_address': omni_utils.generate_mac(),
+ 'identification': {
+ 'type': 'pid',
+ 'id': None
+ }
+ }
+
+ 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'))
+
+ vm_process = self.driver.create_vm(name, vm_uuid, vm_dict['mac_address'], root_disk_path)
+
+ self.running_instances[vm_process.pid] = vm_process
+ self.instance_pids.append(vm_process.pid)
+
+ vm_dict['identification']['id'] = vm_process.pid
+
+ vm_ip = self._parse_ip_addr(vm_dict['mac_address'])
+ vm_dict['ip_address'] = vm_ip
+
+ instance_record_dict = {
+ 'name': name,
+ 'uuid': vm_dict['uuid'],
+ 'image': image_id,
+ 'path': instance_path,
+ 'mac_address': vm_dict['mac_address'],
+ 'ip_address': vm_dict['ip_address'],
+ 'identification': vm_dict['identification']
+ }
+
+ all_instances['instances'][name] = instance_record_dict
+ omni_utils.save_json_data(instance_record, all_instances)
+
+ return {
+ 'name': name,
+ 'vm_state': self._check_vm_state(vm_dict),
+ 'image': image_id,
+ 'ip_address': vm_dict['ip_address']
+ }
+
+ def delete_instance(self, name, instance_record, all_instances):
+ # Delete instance process
+ instance = all_instances['instances'][name]
+ if instance['identification']['type'] == 'pid':
+ instance_pid = instance['identification']['id']
+ if instance_pid in psutil.pids() and \
+ psutil.Process(instance_pid).is_running():
+ psutil.Process(instance_pid).kill()
+ self.LOG.debug(f'Instance: {name} with PID {instance_pid} succesfully killed ...')
+ else:
+ self.LOG.debug(f'Instance: {name} with PID {instance_pid} already stopped, skip ...')
+ else:
+ self.LOG.debug(f'Instance: {name} unable to handled, skip ...')
+
+ # Cleanup files and records
+ instance_dir = instance['path']
+ shutil.rmtree(instance_dir)
+ del all_instances['instances'][name]
+
+ omni_utils.save_json_data(instance_record, all_instances)
+
+ return 0
+
diff --git a/omnivirt/backends/mac/qemu.py b/eulerlauncher/backends/mac/qemu.py
similarity index 97%
rename from omnivirt/backends/mac/qemu.py
rename to eulerlauncher/backends/mac/qemu.py
index 732bd3f..2f3ce0a 100644
--- a/omnivirt/backends/mac/qemu.py
+++ b/eulerlauncher/backends/mac/qemu.py
@@ -1,30 +1,30 @@
-import platform
-import subprocess
-import os
-
-from omnivirt.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('/Library/Application\ Support/org.openeuler.omnivirt/','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.LOG = logger
-
- def create_vm(self, vm_name, vm_uuid, vm_mac, vm_root_disk):
- qemu_cmd = [
- self.qemu_bin, '-machine', 'virt,highmem=off', '-name', vm_name, '-uuid', vm_uuid,
- '-accel hvf', '-drive', 'file=' + self.uefi_file + self.uefi_params, '-cpu host',
- '-nic', 'vmnet-shared,model=virtio-net-pci,mac=' + vm_mac,
- '-drive', 'file=' + vm_root_disk, '-device', 'virtio-scsi-pci,id=scsi0',
- '-smp', self.vm_cpu, '-m', self.vm_ram + 'M', '-monitor none -chardev null,id=char0',
- '-serial chardev:char0 -nographic']
- self.LOG.debug(' '.join(qemu_cmd))
- instance_process = subprocess.Popen(' '.join(qemu_cmd), shell=True)
- return instance_process
+import platform
+import subprocess
+import os
+
+from omnivirt.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('/Library/Application\ Support/org.openeuler.omnivirt/','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.LOG = logger
+
+ def create_vm(self, vm_name, vm_uuid, vm_mac, vm_root_disk):
+ qemu_cmd = [
+ self.qemu_bin, '-machine', 'virt,highmem=off', '-name', vm_name, '-uuid', vm_uuid,
+ '-accel hvf', '-drive', 'file=' + self.uefi_file + self.uefi_params, '-cpu host',
+ '-nic', 'vmnet-shared,model=virtio-net-pci,mac=' + vm_mac,
+ '-drive', 'file=' + vm_root_disk, '-device', 'virtio-scsi-pci,id=scsi0',
+ '-smp', self.vm_cpu, '-m', self.vm_ram + 'M', '-monitor none -chardev null,id=char0',
+ '-serial chardev:char0 -nographic']
+ self.LOG.debug(' '.join(qemu_cmd))
+ instance_process = subprocess.Popen(' '.join(qemu_cmd), shell=True)
+ return instance_process
diff --git a/omnivirt/backends/win/__init__.py b/eulerlauncher/backends/win/__init__.py
similarity index 100%
rename from omnivirt/backends/win/__init__.py
rename to eulerlauncher/backends/win/__init__.py
diff --git a/omnivirt/backends/win/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/backends/win/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/backends/win/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/backends/win/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/backends/win/image_handler.py b/eulerlauncher/backends/win/image_handler.py
similarity index 97%
rename from omnivirt/backends/win/image_handler.py
rename to eulerlauncher/backends/win/image_handler.py
index be040fe..b04ecdd 100644
--- a/omnivirt/backends/win/image_handler.py
+++ b/eulerlauncher/backends/win/image_handler.py
@@ -1,123 +1,123 @@
-import copy
-import lzma
-import wget
-import os
-import shutil
-import ssl
-
-from omnivirt.backends.win import powershell
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omni_utils
-from omnivirt.utils import objs
-
-
-ssl._create_default_https_context = ssl._create_unverified_context
-
-
-class WinImageHandler(object):
-
- def __init__(self, conf, work_dir, image_dir, image_record_file, logger) -> None:
- self.conf = conf
- self.work_dir = work_dir
- self.image_dir = image_dir
- self.image_record_file = image_record_file
- self.LOG = logger
-
- def download_and_transform(self, images, img_to_download):
-
- # Download the image
- img_name = wget.filename_from_url(images['remote'][img_to_download]['path'])
- img_dict = copy.deepcopy(images['remote'][img_to_download])
-
- if not os.path.exists(os.path.join(self.image_dir, img_name)):
- self.LOG.debug(f'Downloading image: {img_to_download} from remote repo ...')
- img_dict['location'] = constants.IMAGE_LOCATION_LOCAL
- img_dict['status'] = constants.IMAGE_STATUS_DOWNLOADING
- images['local'][img_to_download] = img_dict
- omni_utils.save_json_data(self.image_record_file, images)
- wget.download(url=images['remote'][img_to_download]['path'], out=os.path.join(self.image_dir, img_name), bar=None)
- self.LOG.debug(f'Image: {img_to_download} succesfully downloaded from remote repo ...')
-
- # Decompress the image
- self.LOG.debug(f'Decompressing image file: {img_name} ...')
- qcow2_name = img_name[:-3]
- 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))
-
- # Record local image
- img_dict['status'] = constants.IMAGE_STATUS_READY
- img_dict['path'] = os.path.join(self.image_dir, vhdx_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 ...')
-
- def delete_image(self, images, img_to_delete):
- if img_to_delete not in images['local'].keys():
- return 1
- else:
- return self._delete_image(images, img_to_delete)
-
- def _delete_image(self, images, img_to_delete):
- img_path = images['local'][img_to_delete]['path']
- if os.path.exists(img_path):
- self.LOG.debug(f'Deleting: {img_path} ...')
- os.remove(img_path)
-
- self.LOG.debug(f'Deleting: {img_to_delete} from image database ...')
- del images['local'][img_to_delete]
- omni_utils.save_json_data(self.image_record_file, images)
-
- return 0
-
- def load_and_transform(self, images, img_to_load, path, fmt, update=False):
-
- if update:
- self._delete_image(images, img_to_load)
-
- image = objs.Image()
- image.name = img_to_load
- image.path = ''
- image.location = constants.IMAGE_LOCATION_LOCAL
- image.status = constants.IMAGE_STATUS_LOADING
- images['local'][image.name] = image.to_dict()
- omni_utils.save_json_data(self.image_record_file, images)
-
- 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))
-
- # Record local image
- image.path = os.path.join(self.image_dir, vhdx_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 ...')
+import copy
+import lzma
+import wget
+import os
+import shutil
+import ssl
+
+from omnivirt.backends.win import powershell
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omni_utils
+from omnivirt.utils import objs
+
+
+ssl._create_default_https_context = ssl._create_unverified_context
+
+
+class WinImageHandler(object):
+
+ def __init__(self, conf, work_dir, image_dir, image_record_file, logger) -> None:
+ self.conf = conf
+ self.work_dir = work_dir
+ self.image_dir = image_dir
+ self.image_record_file = image_record_file
+ self.LOG = logger
+
+ def download_and_transform(self, images, img_to_download):
+
+ # Download the image
+ img_name = wget.filename_from_url(images['remote'][img_to_download]['path'])
+ img_dict = copy.deepcopy(images['remote'][img_to_download])
+
+ if not os.path.exists(os.path.join(self.image_dir, img_name)):
+ self.LOG.debug(f'Downloading image: {img_to_download} from remote repo ...')
+ img_dict['location'] = constants.IMAGE_LOCATION_LOCAL
+ img_dict['status'] = constants.IMAGE_STATUS_DOWNLOADING
+ images['local'][img_to_download] = img_dict
+ omni_utils.save_json_data(self.image_record_file, images)
+ wget.download(url=images['remote'][img_to_download]['path'], out=os.path.join(self.image_dir, img_name), bar=None)
+ self.LOG.debug(f'Image: {img_to_download} succesfully downloaded from remote repo ...')
+
+ # Decompress the image
+ self.LOG.debug(f'Decompressing image file: {img_name} ...')
+ qcow2_name = img_name[:-3]
+ 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))
+
+ # Record local image
+ img_dict['status'] = constants.IMAGE_STATUS_READY
+ img_dict['path'] = os.path.join(self.image_dir, vhdx_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 ...')
+
+ def delete_image(self, images, img_to_delete):
+ if img_to_delete not in images['local'].keys():
+ return 1
+ else:
+ return self._delete_image(images, img_to_delete)
+
+ def _delete_image(self, images, img_to_delete):
+ img_path = images['local'][img_to_delete]['path']
+ if os.path.exists(img_path):
+ self.LOG.debug(f'Deleting: {img_path} ...')
+ os.remove(img_path)
+
+ self.LOG.debug(f'Deleting: {img_to_delete} from image database ...')
+ del images['local'][img_to_delete]
+ omni_utils.save_json_data(self.image_record_file, images)
+
+ return 0
+
+ def load_and_transform(self, images, img_to_load, path, fmt, update=False):
+
+ if update:
+ self._delete_image(images, img_to_load)
+
+ image = objs.Image()
+ image.name = img_to_load
+ image.path = ''
+ image.location = constants.IMAGE_LOCATION_LOCAL
+ image.status = constants.IMAGE_STATUS_LOADING
+ images['local'][image.name] = image.to_dict()
+ omni_utils.save_json_data(self.image_record_file, images)
+
+ 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))
+
+ # Record local image
+ image.path = os.path.join(self.image_dir, vhdx_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 ...')
diff --git a/omnivirt/backends/win/instance_handler.py b/eulerlauncher/backends/win/instance_handler.py
similarity index 97%
rename from omnivirt/backends/win/instance_handler.py
rename to eulerlauncher/backends/win/instance_handler.py
index bbcc0e3..dcdd739 100644
--- a/omnivirt/backends/win/instance_handler.py
+++ b/eulerlauncher/backends/win/instance_handler.py
@@ -1,200 +1,200 @@
-import os
-import shutil
-import time
-
-from oslo_utils import uuidutils
-from os_win import constants as os_win_const
-from os_win import exceptions as os_win_exc
-
-from omnivirt.backends.win import powershell
-from omnivirt.backends.win import vmops
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omni_utils
-from omnivirt.utils import objs
-
-
-_vmops = vmops.VMOps()
-
-class WinInstanceHandler(object):
-
- def __init__(self, conf, work_dir, instance_dir, image_dir, image_record_file, logger) -> None:
- self.conf = conf
- self.work_dir = work_dir
- self.instance_dir = instance_dir
- self.instance_record_file = os.path.join(instance_dir, 'instances.json')
- self.image_dir = image_dir
- self.image_record_file = image_record_file
- self.LOG = logger
-
- 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):
- # Create dir for the instance
- 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
- }
- }
-
- 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
-
- instance_record_dict = {
- 'name': name,
- 'uuid': vm_dict['uuid'],
- 'image': image_id,
- 'path': instance_path,
- 'mac_address': vm_dict['mac_address'],
- 'ip_address': vm_dict['ip_address'],
- 'identification': vm_dict['identification']
- }
-
- all_instances['instances'][name] = instance_record_dict
- omni_utils.save_json_data(instance_record, all_instances)
-
- return {
- 'name': name,
- 'vm_state': 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)
-
- # Cleanup files and records
- instance_dir = all_instances['instances'][name]['path']
- shutil.rmtree(instance_dir)
- del all_instances['instances'][name]
-
- omni_utils.save_json_data(instance_record, all_instances)
-
- return 0
-
- def reboot(self, instance, reboot_type='soft'):
- """Reboot the specified instance."""
- self.LOG.debug("Rebooting instance", instance=instance)
-
- if reboot_type == 'soft':
- if self._soft_shutdown(instance):
- self.power_on(instance)
- return
-
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_REBOOT)
-
- def _soft_shutdown(self, instance,
- timeout=5,
- retry_interval=1):
- """Perform a soft shutdown on the VM.
-
- :return: True if the instance was shutdown within time limit,
- False otherwise.
- """
- self.LOG.debug("Performing Soft shutdown on instance", instance=instance)
-
- while timeout > 0:
- # Perform a soft shutdown on the instance.
- # Wait maximum timeout for the instance to be shutdown.
- # If it was not shutdown, retry until it succeeds or a maximum of
- # time waited is equal to timeout.
- wait_time = min(retry_interval, timeout)
- try:
- self.LOG.debug("Soft shutdown instance, timeout remaining: %d",
- timeout, instance=instance)
- self._vmutils.soft_shutdown_vm(instance.name)
- if self._wait_for_power_off(instance.name, wait_time):
- self.LOG.info("Soft shutdown succeeded.",
- instance=instance)
- return True
- except os_win_exc.HyperVException as e:
- # Exception is raised when trying to shutdown the instance
- # while it is still booting.
- self.LOG.debug("Soft shutdown failed: %s", e, instance=instance)
- time.sleep(wait_time)
-
- timeout -= retry_interval
-
- self.LOG.warning("Timed out while waiting for soft shutdown.",
- instance=instance)
- return False
-
- def pause(self, instance):
- """Pause VM instance."""
- self.LOG.debug("Pause instance", instance=instance)
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_PAUSED)
-
- def unpause(self, instance):
- """Unpause paused VM instance."""
- self.LOG.debug("Unpause instance", instance=instance)
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_ENABLED)
-
- def suspend(self, instance):
- """Suspend the specified instance."""
- self.LOG.debug("Suspend instance", instance=instance)
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_SUSPENDED)
-
- def resume(self, instance):
- """Resume the suspended VM instance."""
- self.LOG.debug("Resume instance", instance=instance)
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_ENABLED)
-
- def power_off(self, instance, timeout=0, retry_interval=0):
- """Power off the specified instance."""
- self.LOG.debug("Power off instance", instance=instance)
-
- # We must make sure that the console log workers are stopped,
- # otherwise we won't be able to delete or move the VM log files.
- self._serial_console_ops.stop_console_handler(instance.name)
-
- if retry_interval <= 0:
- retry_interval = SHUTDOWN_TIME_INCREMENT
-
- try:
- if timeout and self._soft_shutdown(instance,
- timeout,
- retry_interval):
- return
-
- self._set_vm_state(instance,
- os_win_const.HYPERV_VM_STATE_DISABLED)
- except os_win_exc.HyperVVMNotFoundException:
- # The manager can call the stop API after receiving instance
- # power off events. If this is triggered when the instance
- # is being deleted, it might attempt to power off an unexisting
- # instance. We'll just pass in this case.
- self.LOG.debug("Instance not found. Skipping power off",
- instance=instance)
-
- def power_on(self, instance):
- """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)
+import os
+import shutil
+import time
+
+from oslo_utils import uuidutils
+from os_win import constants as os_win_const
+from os_win import exceptions as os_win_exc
+
+from omnivirt.backends.win import powershell
+from omnivirt.backends.win import vmops
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omni_utils
+from omnivirt.utils import objs
+
+
+_vmops = vmops.VMOps()
+
+class WinInstanceHandler(object):
+
+ def __init__(self, conf, work_dir, instance_dir, image_dir, image_record_file, logger) -> None:
+ self.conf = conf
+ self.work_dir = work_dir
+ self.instance_dir = instance_dir
+ self.instance_record_file = os.path.join(instance_dir, 'instances.json')
+ self.image_dir = image_dir
+ self.image_record_file = image_record_file
+ self.LOG = logger
+
+ 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):
+ # Create dir for the instance
+ 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
+ }
+ }
+
+ 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
+
+ instance_record_dict = {
+ 'name': name,
+ 'uuid': vm_dict['uuid'],
+ 'image': image_id,
+ 'path': instance_path,
+ 'mac_address': vm_dict['mac_address'],
+ 'ip_address': vm_dict['ip_address'],
+ 'identification': vm_dict['identification']
+ }
+
+ all_instances['instances'][name] = instance_record_dict
+ omni_utils.save_json_data(instance_record, all_instances)
+
+ return {
+ 'name': name,
+ 'vm_state': 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)
+
+ # Cleanup files and records
+ instance_dir = all_instances['instances'][name]['path']
+ shutil.rmtree(instance_dir)
+ del all_instances['instances'][name]
+
+ omni_utils.save_json_data(instance_record, all_instances)
+
+ return 0
+
+ def reboot(self, instance, reboot_type='soft'):
+ """Reboot the specified instance."""
+ self.LOG.debug("Rebooting instance", instance=instance)
+
+ if reboot_type == 'soft':
+ if self._soft_shutdown(instance):
+ self.power_on(instance)
+ return
+
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_REBOOT)
+
+ def _soft_shutdown(self, instance,
+ timeout=5,
+ retry_interval=1):
+ """Perform a soft shutdown on the VM.
+
+ :return: True if the instance was shutdown within time limit,
+ False otherwise.
+ """
+ self.LOG.debug("Performing Soft shutdown on instance", instance=instance)
+
+ while timeout > 0:
+ # Perform a soft shutdown on the instance.
+ # Wait maximum timeout for the instance to be shutdown.
+ # If it was not shutdown, retry until it succeeds or a maximum of
+ # time waited is equal to timeout.
+ wait_time = min(retry_interval, timeout)
+ try:
+ self.LOG.debug("Soft shutdown instance, timeout remaining: %d",
+ timeout, instance=instance)
+ self._vmutils.soft_shutdown_vm(instance.name)
+ if self._wait_for_power_off(instance.name, wait_time):
+ self.LOG.info("Soft shutdown succeeded.",
+ instance=instance)
+ return True
+ except os_win_exc.HyperVException as e:
+ # Exception is raised when trying to shutdown the instance
+ # while it is still booting.
+ self.LOG.debug("Soft shutdown failed: %s", e, instance=instance)
+ time.sleep(wait_time)
+
+ timeout -= retry_interval
+
+ self.LOG.warning("Timed out while waiting for soft shutdown.",
+ instance=instance)
+ return False
+
+ def pause(self, instance):
+ """Pause VM instance."""
+ self.LOG.debug("Pause instance", instance=instance)
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_PAUSED)
+
+ def unpause(self, instance):
+ """Unpause paused VM instance."""
+ self.LOG.debug("Unpause instance", instance=instance)
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_ENABLED)
+
+ def suspend(self, instance):
+ """Suspend the specified instance."""
+ self.LOG.debug("Suspend instance", instance=instance)
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_SUSPENDED)
+
+ def resume(self, instance):
+ """Resume the suspended VM instance."""
+ self.LOG.debug("Resume instance", instance=instance)
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_ENABLED)
+
+ def power_off(self, instance, timeout=0, retry_interval=0):
+ """Power off the specified instance."""
+ self.LOG.debug("Power off instance", instance=instance)
+
+ # We must make sure that the console log workers are stopped,
+ # otherwise we won't be able to delete or move the VM log files.
+ self._serial_console_ops.stop_console_handler(instance.name)
+
+ if retry_interval <= 0:
+ retry_interval = SHUTDOWN_TIME_INCREMENT
+
+ try:
+ if timeout and self._soft_shutdown(instance,
+ timeout,
+ retry_interval):
+ return
+
+ self._set_vm_state(instance,
+ os_win_const.HYPERV_VM_STATE_DISABLED)
+ except os_win_exc.HyperVVMNotFoundException:
+ # The manager can call the stop API after receiving instance
+ # power off events. If this is triggered when the instance
+ # is being deleted, it might attempt to power off an unexisting
+ # instance. We'll just pass in this case.
+ self.LOG.debug("Instance not found. Skipping power off",
+ instance=instance)
+
+ def power_on(self, instance):
+ """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/omnivirt/backends/win/powershell.py b/eulerlauncher/backends/win/powershell.py
similarity index 97%
rename from omnivirt/backends/win/powershell.py
rename to eulerlauncher/backends/win/powershell.py
index ac6a60d..289572a 100644
--- a/omnivirt/backends/win/powershell.py
+++ b/eulerlauncher/backends/win/powershell.py
@@ -1,49 +1,49 @@
-import os
-from glob import glob
-import subprocess as sp
-
-
-class PowerShell:
- # from scapy
- def __init__(self, coding, ):
- cmd = [self._where('PowerShell.exe'),
- "-NoLogo", "-NonInteractive", # Do not print headers
- "-Command", "-"] # Listen commands from stdin
- startupinfo = sp.STARTUPINFO()
- startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
- self.popen = sp.Popen(cmd, stdout=sp.PIPE, stdin=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo)
- self.coding = coding
-
- def __enter__(self):
- return self
-
- def __exit__(self, a, b, c):
- self.popen.kill()
-
- def run(self, cmd, timeout=15):
- b_cmd = cmd.encode(encoding=self.coding)
- try:
- b_outs, errs = self.popen.communicate(b_cmd, timeout=timeout)
- except sp.TimeoutExpired:
- self.popen.kill()
- b_outs, errs = self.popen.communicate()
- outs = b_outs.decode(encoding=self.coding)
- return outs, errs
-
- @staticmethod
- def _where(filename, dirs=None, env="PATH"):
- """Find file in current dir, in deep_lookup cache or in system path"""
- if dirs is None:
- dirs = []
- if not isinstance(dirs, list):
- dirs = [dirs]
- if glob(filename):
- return filename
- paths = [os.curdir] + os.environ[env].split(os.path.pathsep) + dirs
- try:
- return next(os.path.normpath(match)
- for path in paths
- for match in glob(os.path.join(path, filename))
- if match)
- except (StopIteration, RuntimeError):
- raise IOError("File not found: %s" % filename)
+import os
+from glob import glob
+import subprocess as sp
+
+
+class PowerShell:
+ # from scapy
+ def __init__(self, coding, ):
+ cmd = [self._where('PowerShell.exe'),
+ "-NoLogo", "-NonInteractive", # Do not print headers
+ "-Command", "-"] # Listen commands from stdin
+ startupinfo = sp.STARTUPINFO()
+ startupinfo.dwFlags |= sp.STARTF_USESHOWWINDOW
+ self.popen = sp.Popen(cmd, stdout=sp.PIPE, stdin=sp.PIPE, stderr=sp.STDOUT, startupinfo=startupinfo)
+ self.coding = coding
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, a, b, c):
+ self.popen.kill()
+
+ def run(self, cmd, timeout=15):
+ b_cmd = cmd.encode(encoding=self.coding)
+ try:
+ b_outs, errs = self.popen.communicate(b_cmd, timeout=timeout)
+ except sp.TimeoutExpired:
+ self.popen.kill()
+ b_outs, errs = self.popen.communicate()
+ outs = b_outs.decode(encoding=self.coding)
+ return outs, errs
+
+ @staticmethod
+ def _where(filename, dirs=None, env="PATH"):
+ """Find file in current dir, in deep_lookup cache or in system path"""
+ if dirs is None:
+ dirs = []
+ if not isinstance(dirs, list):
+ dirs = [dirs]
+ if glob(filename):
+ return filename
+ paths = [os.curdir] + os.environ[env].split(os.path.pathsep) + dirs
+ try:
+ return next(os.path.normpath(match)
+ for path in paths
+ for match in glob(os.path.join(path, filename))
+ if match)
+ except (StopIteration, RuntimeError):
+ raise IOError("File not found: %s" % filename)
diff --git a/omnivirt/backends/win/vmops.py b/eulerlauncher/backends/win/vmops.py
similarity index 97%
rename from omnivirt/backends/win/vmops.py
rename to eulerlauncher/backends/win/vmops.py
index 6882803..f376943 100644
--- a/omnivirt/backends/win/vmops.py
+++ b/eulerlauncher/backends/win/vmops.py
@@ -1,181 +1,181 @@
-import json
-
-from os_win import constants as os_win_const
-from os_win import exceptions as os_win_exc
-from os_win.utils.compute import vmutils10
-from os_win import utilsfactory
-from oslo_utils import uuidutils
-
-from omnivirt.utils import objs
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omni_utils
-from omnivirt.backends.win import powershell
-
-SWITCH_NAME = 'Default Switch'
-
-
-class VMUtils_omni(vmutils10.VMUtils10):
-
- def __init__(self) -> None:
- super().__init__()
-
- def get_instance_notes(self, instance_name):
- instance_notes = self._get_instance_notes(instance_name)
- return instance_notes
-
- def get_vm_nic_uids(self, vm_name):
- nics = self._get_vm_nics(vm_name)
- return nics
-
-class VMOps(object):
- _ROOT_DISK_CTRL_ADDR = 0
-
- def __init__(self, virtapi=None):
- self._virtapi = virtapi
- self._vmutils = VMUtils_omni()
- self._netutils = utilsfactory.get_networkutils()
- self._hostutils = utilsfactory.get_hostutils()
-
- def _set_vm_state(self, instance, req_state):
- instance_name = instance.name
- self._vmutils.set_vm_state(instance_name, req_state)
-
- def list_instance_uuids(self):
- instance_uuids = []
- for (instance_name, notes) in self._vmutils.list_instance_notes():
- if notes and uuidutils.is_uuid_like(notes[0]):
- instance_uuids.append(str(notes[0]))
- else:
- pass
- #LOG.debug("Notes not found or not resembling a GUID for "
- # "instance: %s", instance_name)
- return instance_uuids
-
- def check_all_instance_names(self, name):
- instance_names = self._vmutils.list_instances()
- if name in instance_names:
- return 1
- else:
- return 0
-
- def list_instances(self):
- instance_names = self._vmutils.list_instances()
- vm_list = []
- for instance_name in instance_names:
- vm = objs.Instance(name=instance_name)
- meta = self.get_meta(instance_name)
- if not meta or not meta['creator'] == 'omnivirt':
- continue
- else:
- vm.metadata = meta
- vm.uuid = meta['uuid']
- info = self.get_info(instance_name)
- vm.info = info
- vm.vm_state = constants.VM_STATE_MAP[info['EnabledState']]
- ip_address = self.get_instance_ip_addr(instance_name)
- vm.ip = ip_address
- vm.image = meta['image']
- vm_list.append(vm)
-
- return vm_list
-
-
- def get_instance_ip_addr(self, instance_name):
- nic_name = instance_name + '_eth0'
- nic = self.get_vm_nics(instance_name, nic_name)
- mac_address = omni_utils.format_mac_addr(nic.Address)
- with powershell.PowerShell('GBK') as ps:
- outs, errs = ps.run('arp -a | findstr /i {}'.format(mac_address))
- ip_address = outs.strip(' ').split(' ')[0]
-
- return ip_address
-
-
- def get_info(self, instance):
- """Get information about the VM."""
- # LOG.debug("get_info called for instance", instance=instance)
-
- instance_name = instance
- if not self._vmutils.vm_exists(instance_name):
- raise # exception.InstanceNotFound(instance_id=instance.uuid)
-
- info = self._vmutils.get_vm_summary_info(instance_name)
-
- return info
-
- def create_vm(self, vm_name, vnuma_enabled, vm_gen, instance_path,
- meta_data):
- self._vmutils.create_vm(vm_name,
- vnuma_enabled,
- vm_gen,
- instance_path,
- [json.dumps(meta_data)])
-
- def build_and_run_vm(self, vm_name, uuid, image_name, vnuma_enabled, vm_gen, instance_path, root_disk_path):
- meta_data = {
- 'uuid': uuid,
- 'image': image_name,
- 'creator': 'omnivirt'
- }
-
- # Create an instance
- self.create_vm(vm_name, vnuma_enabled, vm_gen, instance_path, meta_data)
- # Create a scsi controller for this instance
- self._vmutils.create_scsi_controller(vm_name)
- # Attach the root disk to the driver
- self.attach_disk(vm_name, root_disk_path, constants.DISK)
- # Start the instance
- self.power_up(vm_name)
- nic_name = vm_name + '_eth0'
- self.add_nic(vm_name, nic_name)
- self.connect_vnic_to_switch(SWITCH_NAME, nic_name)
- return 0
-
- def get_meta(self, instance_name, expect_existing=False):
- try:
- instance_notes = self._vmutils.get_instance_notes(instance_name)
- if instance_notes:
- return json.loads(instance_notes[0])
- else:
- return instance_notes
- except os_win_exc.HyperVVMNotFoundException:
- raise
-
- def delete_instance(self, vm_name):
- # Stop the VM first.
- self._vmutils.stop_vm_jobs(vm_name)
- self._vmutils.set_vm_state(vm_name, os_win_const.HYPERV_VM_STATE_DISABLED)
- self._vmutils.destroy_vm(vm_name)
-
- while(1):
- if not self._vmutils.vm_exists(vm_name):
- break
- return 0
-
- def get_vm_disks(self, vm_name):
- return self._vmutils.get_vm_disks(vm_name)
-
- def attach_disk(self, instance_name, path, drive_type):
- self._vmutils.attach_scsi_drive(instance_name, path, drive_type)
-
- def power_up(self, instance_name):
- req_state = os_win_const.HYPERV_VM_STATE_ENABLED
- self._vmutils.set_vm_state(instance_name, req_state)
-
- def add_nic(self, instance_name, nic_name):
- self._vmutils.create_nic(instance_name, nic_name)
-
- def get_vm_nics(self, instance_name, nic_name):
- return self._vmutils._get_nic_data_by_name(nic_name)
-
- def list_switch_ports(self, switch_name):
- return self._netutils.get_switch_ports(switch_name)
-
- def connect_vnic_to_switch(self, switch_name, vnic_name):
- self._netutils.connect_vnic_to_vswitch(switch_name, vnic_name)
-
- def get_switch_port(self, switch_name, port_id):
- return self._netutils.get_port_by_id(port_id, switch_name)
-
- def get_host_ips(self):
- return self._hostutils.get_local_ips()
+import json
+
+from os_win import constants as os_win_const
+from os_win import exceptions as os_win_exc
+from os_win.utils.compute import vmutils10
+from os_win import utilsfactory
+from oslo_utils import uuidutils
+
+from omnivirt.utils import objs
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omni_utils
+from omnivirt.backends.win import powershell
+
+SWITCH_NAME = 'Default Switch'
+
+
+class VMUtils_omni(vmutils10.VMUtils10):
+
+ def __init__(self) -> None:
+ super().__init__()
+
+ def get_instance_notes(self, instance_name):
+ instance_notes = self._get_instance_notes(instance_name)
+ return instance_notes
+
+ def get_vm_nic_uids(self, vm_name):
+ nics = self._get_vm_nics(vm_name)
+ return nics
+
+class VMOps(object):
+ _ROOT_DISK_CTRL_ADDR = 0
+
+ def __init__(self, virtapi=None):
+ self._virtapi = virtapi
+ self._vmutils = VMUtils_omni()
+ self._netutils = utilsfactory.get_networkutils()
+ self._hostutils = utilsfactory.get_hostutils()
+
+ def _set_vm_state(self, instance, req_state):
+ instance_name = instance.name
+ self._vmutils.set_vm_state(instance_name, req_state)
+
+ def list_instance_uuids(self):
+ instance_uuids = []
+ for (instance_name, notes) in self._vmutils.list_instance_notes():
+ if notes and uuidutils.is_uuid_like(notes[0]):
+ instance_uuids.append(str(notes[0]))
+ else:
+ pass
+ #LOG.debug("Notes not found or not resembling a GUID for "
+ # "instance: %s", instance_name)
+ return instance_uuids
+
+ def check_all_instance_names(self, name):
+ instance_names = self._vmutils.list_instances()
+ if name in instance_names:
+ return 1
+ else:
+ return 0
+
+ def list_instances(self):
+ instance_names = self._vmutils.list_instances()
+ vm_list = []
+ for instance_name in instance_names:
+ vm = objs.Instance(name=instance_name)
+ meta = self.get_meta(instance_name)
+ if not meta or not meta['creator'] == 'omnivirt':
+ continue
+ else:
+ vm.metadata = meta
+ vm.uuid = meta['uuid']
+ info = self.get_info(instance_name)
+ vm.info = info
+ vm.vm_state = constants.VM_STATE_MAP[info['EnabledState']]
+ ip_address = self.get_instance_ip_addr(instance_name)
+ vm.ip = ip_address
+ vm.image = meta['image']
+ vm_list.append(vm)
+
+ return vm_list
+
+
+ def get_instance_ip_addr(self, instance_name):
+ nic_name = instance_name + '_eth0'
+ nic = self.get_vm_nics(instance_name, nic_name)
+ mac_address = omni_utils.format_mac_addr(nic.Address)
+ with powershell.PowerShell('GBK') as ps:
+ outs, errs = ps.run('arp -a | findstr /i {}'.format(mac_address))
+ ip_address = outs.strip(' ').split(' ')[0]
+
+ return ip_address
+
+
+ def get_info(self, instance):
+ """Get information about the VM."""
+ # LOG.debug("get_info called for instance", instance=instance)
+
+ instance_name = instance
+ if not self._vmutils.vm_exists(instance_name):
+ raise # exception.InstanceNotFound(instance_id=instance.uuid)
+
+ info = self._vmutils.get_vm_summary_info(instance_name)
+
+ return info
+
+ def create_vm(self, vm_name, vnuma_enabled, vm_gen, instance_path,
+ meta_data):
+ self._vmutils.create_vm(vm_name,
+ vnuma_enabled,
+ vm_gen,
+ instance_path,
+ [json.dumps(meta_data)])
+
+ def build_and_run_vm(self, vm_name, uuid, image_name, vnuma_enabled, vm_gen, instance_path, root_disk_path):
+ meta_data = {
+ 'uuid': uuid,
+ 'image': image_name,
+ 'creator': 'omnivirt'
+ }
+
+ # Create an instance
+ self.create_vm(vm_name, vnuma_enabled, vm_gen, instance_path, meta_data)
+ # Create a scsi controller for this instance
+ self._vmutils.create_scsi_controller(vm_name)
+ # Attach the root disk to the driver
+ self.attach_disk(vm_name, root_disk_path, constants.DISK)
+ # Start the instance
+ self.power_up(vm_name)
+ nic_name = vm_name + '_eth0'
+ self.add_nic(vm_name, nic_name)
+ self.connect_vnic_to_switch(SWITCH_NAME, nic_name)
+ return 0
+
+ def get_meta(self, instance_name, expect_existing=False):
+ try:
+ instance_notes = self._vmutils.get_instance_notes(instance_name)
+ if instance_notes:
+ return json.loads(instance_notes[0])
+ else:
+ return instance_notes
+ except os_win_exc.HyperVVMNotFoundException:
+ raise
+
+ def delete_instance(self, vm_name):
+ # Stop the VM first.
+ self._vmutils.stop_vm_jobs(vm_name)
+ self._vmutils.set_vm_state(vm_name, os_win_const.HYPERV_VM_STATE_DISABLED)
+ self._vmutils.destroy_vm(vm_name)
+
+ while(1):
+ if not self._vmutils.vm_exists(vm_name):
+ break
+ return 0
+
+ def get_vm_disks(self, vm_name):
+ return self._vmutils.get_vm_disks(vm_name)
+
+ def attach_disk(self, instance_name, path, drive_type):
+ self._vmutils.attach_scsi_drive(instance_name, path, drive_type)
+
+ def power_up(self, instance_name):
+ req_state = os_win_const.HYPERV_VM_STATE_ENABLED
+ self._vmutils.set_vm_state(instance_name, req_state)
+
+ def add_nic(self, instance_name, nic_name):
+ self._vmutils.create_nic(instance_name, nic_name)
+
+ def get_vm_nics(self, instance_name, nic_name):
+ return self._vmutils._get_nic_data_by_name(nic_name)
+
+ def list_switch_ports(self, switch_name):
+ return self._netutils.get_switch_ports(switch_name)
+
+ def connect_vnic_to_switch(self, switch_name, vnic_name):
+ self._netutils.connect_vnic_to_vswitch(switch_name, vnic_name)
+
+ def get_switch_port(self, switch_name, port_id):
+ return self._netutils.get_port_by_id(port_id, switch_name)
+
+ def get_host_ips(self):
+ return self._hostutils.get_local_ips()
diff --git a/omnivirt/cli.py b/eulerlauncher/cli.py
similarity index 64%
rename from omnivirt/cli.py
rename to eulerlauncher/cli.py
index 5d6217b..11ceae0 100644
--- a/omnivirt/cli.py
+++ b/eulerlauncher/cli.py
@@ -1,144 +1,144 @@
-import click
-import prettytable as pt
-
-from omnivirt.grpcs import client
-from omnivirt.utils import utils as omni_utils
-from omnivirt.utils import exceptions
-
-
-omnivirt_client = client.Client()
-
-# List all instances on the host
-@click.command()
-def list():
-
- try:
- ret = omnivirt_client.list_instances()
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- tb = pt.PrettyTable()
-
- tb.field_names = ["Name", "Image", "State", "IP"]
-
- try:
- for instance in ret['instances']:
- tb.add_row(
- [instance['name'],
- instance['image'],
- instance['vmState'],
- instance['ipAddress']])
- except KeyError:
- pass
-
- print(tb)
-
-
-# List all usable images
-@click.command()
-def images():
-
- try:
- ret = omnivirt_client.list_images()
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- tb = pt.PrettyTable()
-
- tb.field_names = ["Images", "Location", "Status"]
-
- for image in ret['images']:
- tb.add_row(
- [image['name'], image['location'], image['status']])
-
- print(tb)
-
-
-@click.command()
-@click.argument('name')
-def download_image(name):
-
- try:
- ret = omnivirt_client.download_image(name)
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- print(ret['msg'])
-
-
-@click.command()
-@click.argument('name')
-@click.option('--path', help='Image file to load')
-def load_image(name, path):
-
- try:
- ret = omnivirt_client.load_image(name, path)
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- print(ret['msg'])
-
-
-@click.command()
-@click.argument('name')
-def delete_image(name):
-
- try:
- ret = omnivirt_client.delete_image(name)
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- print(ret['msg'])
-
-
-@click.command()
-@click.argument('name')
-def delete_instance(name):
-
- try:
- ret = omnivirt_client.delete_instance(name)
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
- print(ret['msg'])
-
-@click.command()
-@click.argument('vm_name')
-@click.option('--image', help='Image to build vm')
-def launch(vm_name, image):
-
- try:
- ret = omnivirt_client.create_instance(vm_name, image)
- except Exception:
- print('Calling to OmniVirtd daemon failed, please check OmniVirtd daemon status ...')
- else:
-
- if ret['ret'] == 1:
- tb = pt.PrettyTable()
- tb.field_names = ["Name", "Image", "State", "IP"]
- tb.add_row(
- [ret['instance']['name'],
- ret['instance']['image'],
- ret['instance']['vmState'],
- ret['instance']['ipAddress']])
-
- print(tb)
-
- else:
- print(ret['msg'])
-
-
-@click.group()
-def cli():
- pass
-
-
-if __name__ == '__main__':
- cli.add_command(list)
- cli.add_command(images)
- cli.add_command(download_image)
- cli.add_command(load_image)
- cli.add_command(launch)
- cli.add_command(delete_image)
- cli.add_command(delete_instance)
+import click
+import prettytable as pt
+
+from eulerlauncher.grpcs import client
+from eulerlauncher.utils import utils as omni_utils
+from eulerlauncher.utils import exceptions
+
+
+eulerlauncher_client = client.Client()
+
+# List all instances on the host
+@click.command()
+def list():
+
+ try:
+ ret = eulerlauncher_client.list_instances()
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ tb = pt.PrettyTable()
+
+ tb.field_names = ["Name", "Image", "State", "IP"]
+
+ try:
+ for instance in ret['instances']:
+ tb.add_row(
+ [instance['name'],
+ instance['image'],
+ instance['vmState'],
+ instance['ipAddress']])
+ except KeyError:
+ pass
+
+ print(tb)
+
+
+# List all usable images
+@click.command()
+def images():
+
+ try:
+ ret = eulerlauncher_client.list_images()
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ tb = pt.PrettyTable()
+
+ tb.field_names = ["Images", "Location", "Status"]
+
+ for image in ret['images']:
+ tb.add_row(
+ [image['name'], image['location'], image['status']])
+
+ print(tb)
+
+
+@click.command()
+@click.argument('name')
+def download_image(name):
+
+ try:
+ ret = eulerlauncher_client.download_image(name)
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ print(ret['msg'])
+
+
+@click.command()
+@click.argument('name')
+@click.option('--path', help='Image file to load')
+def load_image(name, path):
+
+ try:
+ ret = eulerlauncher_client.load_image(name, path)
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ print(ret['msg'])
+
+
+@click.command()
+@click.argument('name')
+def delete_image(name):
+
+ try:
+ ret = eulerlauncher_client.delete_image(name)
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ print(ret['msg'])
+
+
+@click.command()
+@click.argument('name')
+def delete_instance(name):
+
+ try:
+ ret = eulerlauncher_client.delete_instance(name)
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+ print(ret['msg'])
+
+@click.command()
+@click.argument('vm_name')
+@click.option('--image', help='Image to build vm')
+def launch(vm_name, image):
+
+ try:
+ ret = eulerlauncher_client.create_instance(vm_name, image)
+ except Exception:
+ print('Calling to EulerLauncherd daemon failed, please check EulerLauncherd daemon status ...')
+ else:
+
+ if ret['ret'] == 1:
+ tb = pt.PrettyTable()
+ tb.field_names = ["Name", "Image", "State", "IP"]
+ tb.add_row(
+ [ret['instance']['name'],
+ ret['instance']['image'],
+ ret['instance']['vmState'],
+ ret['instance']['ipAddress']])
+
+ print(tb)
+
+ else:
+ print(ret['msg'])
+
+
+@click.group()
+def cli():
+ pass
+
+
+if __name__ == '__main__':
+ cli.add_command(list)
+ cli.add_command(images)
+ cli.add_command(download_image)
+ cli.add_command(load_image)
+ cli.add_command(launch)
+ cli.add_command(delete_image)
+ cli.add_command(delete_instance)
cli()
\ No newline at end of file
diff --git a/omnivirt/omnivirtd.py b/eulerlauncher/eulerlauncherd.py
similarity index 85%
rename from omnivirt/omnivirtd.py
rename to eulerlauncher/eulerlauncherd.py
index 08b7a60..4744b25 100644
--- a/omnivirt/omnivirtd.py
+++ b/eulerlauncher/eulerlauncherd.py
@@ -1,148 +1,148 @@
-import argparse
-from concurrent import futures
-import grpc
-import logging
-import os
-import PIL.Image
-import platform
-import pystray
-import requests
-import signal
-import subprocess
-import sys
-import time
-
-from omnivirt.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
-from omnivirt.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
-from omnivirt.services import imager_service, instance_service
-from omnivirt.utils import constants
-from omnivirt.utils import objs
-from omnivirt.utils import utils
-
-
-IMG_URL = 'https://gitee.com/openeuler/omnivirt/raw/master/etc/supported_images.json'
-
-# Avoid create zombie children in MacOS and Linux
-signal.signal(signal.SIGCHLD, signal.SIG_IGN)
-
-parser = argparse.ArgumentParser()
-parser.add_argument('conf_file', help='Configuration file for the application', type=str)
-parser.add_argument('base_dir', help='The base work directory of the daemon')
-
-
-def config_logging(config):
- log_dir = config.conf.get('default', 'log_dir')
- debug = config.conf.get('default', 'debug')
-
- if not os.path.exists(log_dir):
- os.makedirs(log_dir)
-
- log_file = os.path.join(log_dir, 'omnivirt.log')
-
- if debug == 'True':
- log_level = logging.DEBUG
- else:
- log_level = logging.INFO
- logging.basicConfig(
- format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
- filename=log_file, level=log_level, filemode='a+')
-
-
-def init(arch, config, LOG):
- work_dir = config.conf.get('default', 'work_dir')
- image_dir = os.path.join(work_dir, 'images')
- instance_dir = os.path.join(work_dir, 'instances')
- instance_record_file = os.path.join(instance_dir, 'instances.json')
- img_record_file = os.path.join(image_dir, 'images.json')
-
- LOG.debug('Initializing OmniVirtd ...')
- LOG.debug('Checking for work directory ...')
- if not os.path.exists(work_dir):
- LOG.debug('Create %s as working directory ...' % work_dir)
- os.makedirs(work_dir)
- LOG.debug('Checking for instances directory ...')
- if not os.path.exists(instance_dir):
- LOG.debug('Create %s as working directory ...' % work_dir)
- os.makedirs(instance_dir)
- LOG.debug('Checking for instance database ...')
- if not os.path.exists(instance_record_file):
- instances = {
- 'instances': {}
- }
- utils.save_json_data(instance_record_file, instances)
-
- LOG.debug('Checking for image directory ...')
- if not os.path.exists(image_dir):
- LOG.debug('Create %s as image directory ...' % image_dir)
- os.makedirs(image_dir)
-
- LOG.debug('Checking for image database ...')
- remote_img_resp = requests.get(IMG_URL, verify=False)
- remote_imgs = remote_img_resp.json()[arch]
- if not os.path.exists(img_record_file):
- images = {}
- for name, path in remote_imgs.items():
- image = objs.Image()
- image.name = name
- image.path = path
- image.location = constants.IMAGE_LOCATION_REMOTE
- image.status = constants.IMAGE_STATUS_DOWLOADABLE
- images[image.name] = image.to_dict()
-
- image_body = {
- 'remote': images,
- 'local': {}
- }
- utils.save_json_data(img_record_file, image_body)
-
-def serve(arch, host_os, CONF, LOG, base_dir):
- '''
- Run the Omnivirtd Service
- '''
- server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
- images_pb2_grpc.add_ImageGrpcServiceServicer_to_server(imager_service.ImagerService(arch, host_os, CONF, base_dir), server)
- instances_pb2_grpc.add_InstanceGrpcServiceServicer_to_server(instance_service.InstanceService(arch, host_os, CONF, base_dir), server)
- server.add_insecure_port('[::]:50052')
- server.start()
- LOG.debug('OmniVirtd Service Started ...')
-
- def term_handler(signum, frame):
- pid = os.getpid()
- os.killpg(os.getpgid(pid), signal.SIGKILL)
-
- # Avoid create orphan children in MacOS and Linux
- signal.signal(signal.SIGTERM, term_handler)
-
- while True:
- time.sleep(1)
-
-def init_omnivirtd(conf, base_dir):
- CONF = objs.Conf(conf)
-
- config_logging(CONF)
- LOG = logging.getLogger(__name__)
-
- host_arch_raw = platform.uname().machine
- host_os_raw = platform.uname().system
-
- host_arch = constants.ARCH_MAP[host_arch_raw]
- host_os = constants.OS_MAP[host_os_raw]
-
- try:
- init(host_arch, CONF, LOG)
- except Exception as e:
- LOG.debug('Error: ' + str(e))
- return str(e)
- else:
- serve(host_arch, host_os, CONF, LOG, base_dir)
-
-
-if __name__ == '__main__':
- args = parser.parse_args()
- conf_file = args.conf_file
- try:
- pass
- except Exception as e:
- print('Error: ' + str(e))
- else:
- init_omnivirtd(conf_file, args.base_dir)
+import argparse
+from concurrent import futures
+import grpc
+import logging
+import os
+import PIL.Image
+import platform
+import pystray
+import requests
+import signal
+import subprocess
+import sys
+import time
+
+from eulerlauncher.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
+from eulerlauncher.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
+from eulerlauncher.services import imager_service, instance_service
+from eulerlauncher.utils import constants
+from eulerlauncher.utils import objs
+from eulerlauncher.utils import utils
+
+
+IMG_URL = 'https://gitee.com/openeuler/omnivirt/raw/master/etc/supported_images.json'
+
+# Avoid create zombie children in MacOS and Linux
+signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+
+parser = argparse.ArgumentParser()
+parser.add_argument('conf_file', help='Configuration file for the application', type=str)
+parser.add_argument('base_dir', help='The base work directory of the daemon')
+
+
+def config_logging(config):
+ log_dir = config.conf.get('default', 'log_dir')
+ debug = config.conf.get('default', 'debug')
+
+ if not os.path.exists(log_dir):
+ os.makedirs(log_dir)
+
+ log_file = os.path.join(log_dir, 'eulerlauncher.log')
+
+ if debug == 'True':
+ log_level = logging.DEBUG
+ else:
+ log_level = logging.INFO
+ logging.basicConfig(
+ format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
+ filename=log_file, level=log_level, filemode='a+')
+
+
+def init(arch, config, LOG):
+ work_dir = config.conf.get('default', 'work_dir')
+ image_dir = os.path.join(work_dir, 'images')
+ instance_dir = os.path.join(work_dir, 'instances')
+ instance_record_file = os.path.join(instance_dir, 'instances.json')
+ img_record_file = os.path.join(image_dir, 'images.json')
+
+ LOG.debug('Initializing EulerLauncherd ...')
+ LOG.debug('Checking for work directory ...')
+ if not os.path.exists(work_dir):
+ LOG.debug('Create %s as working directory ...' % work_dir)
+ os.makedirs(work_dir)
+ LOG.debug('Checking for instances directory ...')
+ if not os.path.exists(instance_dir):
+ LOG.debug('Create %s as working directory ...' % work_dir)
+ os.makedirs(instance_dir)
+ LOG.debug('Checking for instance database ...')
+ if not os.path.exists(instance_record_file):
+ instances = {
+ 'instances': {}
+ }
+ utils.save_json_data(instance_record_file, instances)
+
+ LOG.debug('Checking for image directory ...')
+ if not os.path.exists(image_dir):
+ LOG.debug('Create %s as image directory ...' % image_dir)
+ os.makedirs(image_dir)
+
+ LOG.debug('Checking for image database ...')
+ remote_img_resp = requests.get(IMG_URL, verify=False)
+ remote_imgs = remote_img_resp.json()[arch]
+ if not os.path.exists(img_record_file):
+ images = {}
+ for name, path in remote_imgs.items():
+ image = objs.Image()
+ image.name = name
+ image.path = path
+ image.location = constants.IMAGE_LOCATION_REMOTE
+ image.status = constants.IMAGE_STATUS_DOWLOADABLE
+ images[image.name] = image.to_dict()
+
+ image_body = {
+ 'remote': images,
+ 'local': {}
+ }
+ utils.save_json_data(img_record_file, image_body)
+
+def serve(arch, host_os, CONF, LOG, base_dir):
+ '''
+ Run the EulerLauncherd Service
+ '''
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ images_pb2_grpc.add_ImageGrpcServiceServicer_to_server(imager_service.ImagerService(arch, host_os, CONF, base_dir), server)
+ instances_pb2_grpc.add_InstanceGrpcServiceServicer_to_server(instance_service.InstanceService(arch, host_os, CONF, base_dir), server)
+ server.add_insecure_port('[::]:50052')
+ server.start()
+ LOG.debug('EulerLauncherd Service Started ...')
+
+ def term_handler(signum, frame):
+ pid = os.getpid()
+ os.killpg(os.getpgid(pid), signal.SIGKILL)
+
+ # Avoid create orphan children in MacOS and Linux
+ signal.signal(signal.SIGTERM, term_handler)
+
+ while True:
+ time.sleep(1)
+
+def init_eulerlauncherd(conf, base_dir):
+ CONF = objs.Conf(conf)
+
+ config_logging(CONF)
+ LOG = logging.getLogger(__name__)
+
+ host_arch_raw = platform.uname().machine
+ host_os_raw = platform.uname().system
+
+ host_arch = constants.ARCH_MAP[host_arch_raw]
+ host_os = constants.OS_MAP[host_os_raw]
+
+ try:
+ init(host_arch, CONF, LOG)
+ except Exception as e:
+ LOG.debug('Error: ' + str(e))
+ return str(e)
+ else:
+ serve(host_arch, host_os, CONF, LOG, base_dir)
+
+
+if __name__ == '__main__':
+ args = parser.parse_args()
+ conf_file = args.conf_file
+ try:
+ pass
+ except Exception as e:
+ print('Error: ' + str(e))
+ else:
+ init_eulerlauncherd(conf_file, args.base_dir)
diff --git a/omnivirt/grpcs/__init__.py b/eulerlauncher/grpcs/__init__.py
similarity index 100%
rename from omnivirt/grpcs/__init__.py
rename to eulerlauncher/grpcs/__init__.py
diff --git a/omnivirt/grpcs/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/grpcs/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/grpcs/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/grpcs/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/grpcs/client.py b/eulerlauncher/grpcs/client.py
similarity index 96%
rename from omnivirt/grpcs/client.py
rename to eulerlauncher/grpcs/client.py
index fe4c065..f57cc67 100644
--- a/omnivirt/grpcs/client.py
+++ b/eulerlauncher/grpcs/client.py
@@ -1,95 +1,95 @@
-import grpc
-import os
-
-from omnivirt.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
-from omnivirt.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
-from omnivirt.grpcs import images, instances
-from omnivirt.utils import constants
-from omnivirt.utils import utils as omnivirt_utils
-
-
-class Client(object):
- def __init__(self, channel_target=None):
- if not channel_target:
- channel_target = 'localhost:50052'
- channel = grpc.insecure_channel(channel_target)
-
- images_client = images_pb2_grpc.ImageGrpcServiceStub(channel)
- instances_client = instances_pb2_grpc.InstanceGrpcServiceStub(channel)
-
- self._images = images.Image(images_client)
- self._instances = instances.Instance(instances_client)
-
- @omnivirt_utils.response2dict
- def list_images(self, filters=None):
- """ [IMAGE] List images
-
- :param filters(list): None
- :return: dict -- list of images' info
- """
-
- return self._images.list()
-
- @omnivirt_utils.response2dict
- def download_image(self, name):
- """ Download image
- """
-
- return self._images.download(name)
-
- @omnivirt_utils.response2dict
- def load_image(self, name, path):
- """ Load local image file
- """
-
- if not os.path.exists(path):
- err_msg = {
- 'ret': 1,
- 'msg': f'No such file or directory: {path}, please check again.'
- }
- return err_msg
-
- supported = False
- for tp in constants.IMAGE_LOAD_SUPPORTED_TYPES:
- if path.endswith(tp):
- supported = True
- break
-
- if not supported:
- err_msg = {
- 'ret': 1,
- 'msg': f'Image file format does not supported: {path}, please check again.'
- }
- return err_msg
-
- return self._images.load(name, path)
-
- @omnivirt_utils.response2dict
- def delete_image(self, name):
- """ Delete the requested image
- """
-
- return self._images.delete(name)
-
- @omnivirt_utils.response2dict
- def list_instances(self):
- """ List instances
- :return: dict -- list of instances' info
- """
-
- return self._instances.list()
-
- @omnivirt_utils.response2dict
- def create_instance(self, name, image):
- """ Create instance
- :return: dict -- dict of instance's info
- """
-
- return self._instances.create(name, image)
-
- @omnivirt_utils.response2dict
- def delete_instance(self, name):
- """ Delete the requested instance
- """
-
- return self._instances.delete(name)
+import grpc
+import os
+
+from omnivirt.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
+from omnivirt.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
+from omnivirt.grpcs import images, instances
+from omnivirt.utils import constants
+from omnivirt.utils import utils as omnivirt_utils
+
+
+class Client(object):
+ def __init__(self, channel_target=None):
+ if not channel_target:
+ channel_target = 'localhost:50052'
+ channel = grpc.insecure_channel(channel_target)
+
+ images_client = images_pb2_grpc.ImageGrpcServiceStub(channel)
+ instances_client = instances_pb2_grpc.InstanceGrpcServiceStub(channel)
+
+ self._images = images.Image(images_client)
+ self._instances = instances.Instance(instances_client)
+
+ @omnivirt_utils.response2dict
+ def list_images(self, filters=None):
+ """ [IMAGE] List images
+
+ :param filters(list): None
+ :return: dict -- list of images' info
+ """
+
+ return self._images.list()
+
+ @omnivirt_utils.response2dict
+ def download_image(self, name):
+ """ Download image
+ """
+
+ return self._images.download(name)
+
+ @omnivirt_utils.response2dict
+ def load_image(self, name, path):
+ """ Load local image file
+ """
+
+ if not os.path.exists(path):
+ err_msg = {
+ 'ret': 1,
+ 'msg': f'No such file or directory: {path}, please check again.'
+ }
+ return err_msg
+
+ supported = False
+ for tp in constants.IMAGE_LOAD_SUPPORTED_TYPES:
+ if path.endswith(tp):
+ supported = True
+ break
+
+ if not supported:
+ err_msg = {
+ 'ret': 1,
+ 'msg': f'Image file format does not supported: {path}, please check again.'
+ }
+ return err_msg
+
+ return self._images.load(name, path)
+
+ @omnivirt_utils.response2dict
+ def delete_image(self, name):
+ """ Delete the requested image
+ """
+
+ return self._images.delete(name)
+
+ @omnivirt_utils.response2dict
+ def list_instances(self):
+ """ List instances
+ :return: dict -- list of instances' info
+ """
+
+ return self._instances.list()
+
+ @omnivirt_utils.response2dict
+ def create_instance(self, name, image):
+ """ Create instance
+ :return: dict -- dict of instance's info
+ """
+
+ return self._instances.create(name, image)
+
+ @omnivirt_utils.response2dict
+ def delete_instance(self, name):
+ """ Delete the requested instance
+ """
+
+ return self._instances.delete(name)
diff --git a/omnivirt/grpcs/images.py b/eulerlauncher/grpcs/images.py
similarity index 97%
rename from omnivirt/grpcs/images.py
rename to eulerlauncher/grpcs/images.py
index ba452d3..44deff7 100644
--- a/omnivirt/grpcs/images.py
+++ b/eulerlauncher/grpcs/images.py
@@ -1,30 +1,30 @@
-from omnivirt.grpcs.omnivirt_grpc import images_pb2
-
-
-class Image(object):
- def __init__(self, client):
- self.client = client
-
- def list(self):
- """Get list of images"""
- request = images_pb2.ListImageRequest()
- response = self.client.list_images(request)
- return response
-
- def download(self, name):
- """Download the requested image"""
- request = images_pb2.DownloadImageRequest(name=name)
- response = self.client.download_image(request)
- return response
-
- 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
-
- def delete(self, name):
- """Delete the requested image"""
- request = images_pb2.DeleteImageRequest(name=name)
- response = self.client.delete_image(request)
+from omnivirt.grpcs.omnivirt_grpc import images_pb2
+
+
+class Image(object):
+ def __init__(self, client):
+ self.client = client
+
+ def list(self):
+ """Get list of images"""
+ request = images_pb2.ListImageRequest()
+ response = self.client.list_images(request)
+ return response
+
+ def download(self, name):
+ """Download the requested image"""
+ request = images_pb2.DownloadImageRequest(name=name)
+ response = self.client.download_image(request)
+ return response
+
+ 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
+
+ def delete(self, name):
+ """Delete the requested image"""
+ request = images_pb2.DeleteImageRequest(name=name)
+ response = self.client.delete_image(request)
return response
\ No newline at end of file
diff --git a/omnivirt/grpcs/instances.py b/eulerlauncher/grpcs/instances.py
similarity index 97%
rename from omnivirt/grpcs/instances.py
rename to eulerlauncher/grpcs/instances.py
index b630a7f..0bc2cac 100644
--- a/omnivirt/grpcs/instances.py
+++ b/eulerlauncher/grpcs/instances.py
@@ -1,23 +1,23 @@
-from omnivirt.grpcs.omnivirt_grpc import instances_pb2
-
-class Instance(object):
- def __init__(self, client):
- self.client = client
-
- def list(self):
- """Get list of instance"""
- request = instances_pb2.ListInstancesRequest()
- response = self.client.list_instances(request)
- return response
-
- def create(self, name, image):
- """Create instance"""
- request = instances_pb2.CreateInstanceRequest(name=name, image=image)
- response = self.client.create_instance(request)
- return response
-
- def delete(self, name):
- """Delete instance"""
- request = instances_pb2.DeleteInstanceRequest(name=name)
- response = self.client.delete_instance(request)
- return response
+from omnivirt.grpcs.omnivirt_grpc import instances_pb2
+
+class Instance(object):
+ def __init__(self, client):
+ self.client = client
+
+ def list(self):
+ """Get list of instance"""
+ request = instances_pb2.ListInstancesRequest()
+ response = self.client.list_instances(request)
+ return response
+
+ def create(self, name, image):
+ """Create instance"""
+ request = instances_pb2.CreateInstanceRequest(name=name, image=image)
+ response = self.client.create_instance(request)
+ return response
+
+ def delete(self, name):
+ """Delete instance"""
+ request = instances_pb2.DeleteInstanceRequest(name=name)
+ response = self.client.delete_instance(request)
+ return response
diff --git a/omnivirt/grpcs/omnivirt_grpc/__init__.py b/eulerlauncher/grpcs/omnivirt_grpc/__init__.py
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/__init__.py
rename to eulerlauncher/grpcs/omnivirt_grpc/__init__.py
diff --git a/omnivirt/grpcs/omnivirt_grpc/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/grpcs/omnivirt_grpc/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/grpcs/omnivirt_grpc/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/grpcs/omnivirt_grpc/images.proto b/eulerlauncher/grpcs/omnivirt_grpc/images.proto
similarity index 94%
rename from omnivirt/grpcs/omnivirt_grpc/images.proto
rename to eulerlauncher/grpcs/omnivirt_grpc/images.proto
index 26996d9..b86f978 100644
--- a/omnivirt/grpcs/omnivirt_grpc/images.proto
+++ b/eulerlauncher/grpcs/omnivirt_grpc/images.proto
@@ -1,46 +1,46 @@
-syntax = "proto3";
-package omnivirt;
-
-option cc_generic_services = true;
-
-
-service ImageGrpcService {
- rpc list_images (ListImageRequest) returns (ListImageResponse) {}
- rpc download_image (DownloadImageRequest) returns (GeneralImageResponse) {}
- rpc load_image (LoadImageRequest) returns (GeneralImageResponse) {}
- rpc delete_image (DeleteImageRequest) returns (GeneralImageResponse) {}
-}
-
-
-message Image {
- string name = 1;
- string location = 2;
- string status = 3;
-}
-
-
-message ListImageRequest {
-}
-
-
-message ListImageResponse {
- repeated Image images = 1;
-}
-
-message DownloadImageRequest {
- string name = 1;
-}
-
-message LoadImageRequest {
- string name = 1;
- string path = 2;
-}
-
-message DeleteImageRequest {
- string name = 1;
-}
-
-message GeneralImageResponse {
- uint32 ret = 1;
- string msg = 2;
-}
+syntax = "proto3";
+package omnivirt;
+
+option cc_generic_services = true;
+
+
+service ImageGrpcService {
+ rpc list_images (ListImageRequest) returns (ListImageResponse) {}
+ rpc download_image (DownloadImageRequest) returns (GeneralImageResponse) {}
+ rpc load_image (LoadImageRequest) returns (GeneralImageResponse) {}
+ rpc delete_image (DeleteImageRequest) returns (GeneralImageResponse) {}
+}
+
+
+message Image {
+ string name = 1;
+ string location = 2;
+ string status = 3;
+}
+
+
+message ListImageRequest {
+}
+
+
+message ListImageResponse {
+ repeated Image images = 1;
+}
+
+message DownloadImageRequest {
+ string name = 1;
+}
+
+message LoadImageRequest {
+ string name = 1;
+ string path = 2;
+}
+
+message DeleteImageRequest {
+ string name = 1;
+}
+
+message GeneralImageResponse {
+ uint32 ret = 1;
+ string msg = 2;
+}
diff --git a/omnivirt/grpcs/omnivirt_grpc/images_pb2.py b/eulerlauncher/grpcs/omnivirt_grpc/images_pb2.py
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/images_pb2.py
rename to eulerlauncher/grpcs/omnivirt_grpc/images_pb2.py
diff --git a/omnivirt/grpcs/omnivirt_grpc/images_pb2_grpc.py b/eulerlauncher/grpcs/omnivirt_grpc/images_pb2_grpc.py
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/images_pb2_grpc.py
rename to eulerlauncher/grpcs/omnivirt_grpc/images_pb2_grpc.py
diff --git a/omnivirt/grpcs/omnivirt_grpc/instances.proto b/eulerlauncher/grpcs/omnivirt_grpc/instances.proto
similarity index 94%
rename from omnivirt/grpcs/omnivirt_grpc/instances.proto
rename to eulerlauncher/grpcs/omnivirt_grpc/instances.proto
index c2e751c..e2e592c 100644
--- a/omnivirt/grpcs/omnivirt_grpc/instances.proto
+++ b/eulerlauncher/grpcs/omnivirt_grpc/instances.proto
@@ -1,48 +1,48 @@
-syntax = "proto3";
-package omnivirt;
-
-option cc_generic_services = true;
-
-
-service InstanceGrpcService {
- rpc list_instances (ListInstancesRequest) returns (ListInstancesResponse) {}
- rpc create_instance (CreateInstanceRequest) returns (CreateInstanceResponse) {}
- rpc delete_instance (DeleteInstanceRequest) returns (DeleteInstanceResponse) {}
-}
-
-
-message Instance {
- string name = 1;
- string image = 2;
- string vm_state = 3;
- string ip_address = 4;
-}
-
-
-message ListInstancesRequest {
-}
-
-
-message ListInstancesResponse {
- repeated Instance instances = 1;
-}
-
-message CreateInstanceRequest {
- string name = 1;
- string image = 2;
-}
-
-message CreateInstanceResponse {
- uint32 ret = 1;
- string msg = 2;
- optional Instance instance = 3;
-}
-
-message DeleteInstanceRequest {
- string name = 1;
-}
-
-message DeleteInstanceResponse {
- uint32 ret = 1;
- string msg = 2;
-}
+syntax = "proto3";
+package omnivirt;
+
+option cc_generic_services = true;
+
+
+service InstanceGrpcService {
+ rpc list_instances (ListInstancesRequest) returns (ListInstancesResponse) {}
+ rpc create_instance (CreateInstanceRequest) returns (CreateInstanceResponse) {}
+ rpc delete_instance (DeleteInstanceRequest) returns (DeleteInstanceResponse) {}
+}
+
+
+message Instance {
+ string name = 1;
+ string image = 2;
+ string vm_state = 3;
+ string ip_address = 4;
+}
+
+
+message ListInstancesRequest {
+}
+
+
+message ListInstancesResponse {
+ repeated Instance instances = 1;
+}
+
+message CreateInstanceRequest {
+ string name = 1;
+ string image = 2;
+}
+
+message CreateInstanceResponse {
+ uint32 ret = 1;
+ string msg = 2;
+ optional Instance instance = 3;
+}
+
+message DeleteInstanceRequest {
+ string name = 1;
+}
+
+message DeleteInstanceResponse {
+ uint32 ret = 1;
+ string msg = 2;
+}
diff --git a/omnivirt/grpcs/omnivirt_grpc/instances_pb2.py b/eulerlauncher/grpcs/omnivirt_grpc/instances_pb2.py
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/instances_pb2.py
rename to eulerlauncher/grpcs/omnivirt_grpc/instances_pb2.py
diff --git a/omnivirt/grpcs/omnivirt_grpc/instances_pb2_grpc.py b/eulerlauncher/grpcs/omnivirt_grpc/instances_pb2_grpc.py
similarity index 100%
rename from omnivirt/grpcs/omnivirt_grpc/instances_pb2_grpc.py
rename to eulerlauncher/grpcs/omnivirt_grpc/instances_pb2_grpc.py
diff --git a/omnivirt/install.py b/eulerlauncher/install.py
similarity index 100%
rename from omnivirt/install.py
rename to eulerlauncher/install.py
diff --git a/omnivirt/macos-gui.py b/eulerlauncher/macos-gui.py
similarity index 100%
rename from omnivirt/macos-gui.py
rename to eulerlauncher/macos-gui.py
diff --git a/omnivirt/services/__init__.py b/eulerlauncher/services/__init__.py
similarity index 100%
rename from omnivirt/services/__init__.py
rename to eulerlauncher/services/__init__.py
diff --git a/omnivirt/services/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/services/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/services/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/services/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/services/imager_service.py b/eulerlauncher/services/imager_service.py
similarity index 97%
rename from omnivirt/services/imager_service.py
rename to eulerlauncher/services/imager_service.py
index c2d6f28..994236f 100644
--- a/omnivirt/services/imager_service.py
+++ b/eulerlauncher/services/imager_service.py
@@ -1,106 +1,106 @@
-import logging
-import os
-
-from omnivirt.backends.mac import image_handler as mac_image_handler
-from omnivirt.backends.win import image_handler as win_image_handler
-from omnivirt.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
-from omnivirt.utils import constants as omni_constants
-from omnivirt.utils import utils as omni_utils
-
-
-LOG = logging.getLogger(__name__)
-
-
-class ImagerService(images_pb2_grpc.ImageGrpcServiceServicer):
- '''
- The Imager GRPC Handler
- '''
-
- def __init__(self, arch, host_os, conf, svc_base_dir) -> None:
- self.CONF = conf
- self.svc_base_dir = svc_base_dir
- self.work_dir = self.CONF.conf.get('default', 'work_dir')
- self.image_dir = os.path.join(self.work_dir, 'images')
- self.img_record_file = os.path.join(self.image_dir, 'images.json')
- if host_os == 'Win':
- self.backend = win_image_handler.WinImageHandler(
- self.CONF, self.work_dir, self.image_dir, self.img_record_file, LOG)
- elif host_os == 'MacOS':
- self.backend = mac_image_handler.MacImageHandler(
- self.CONF, self.work_dir, self.image_dir, self.img_record_file,
- LOG, self.svc_base_dir)
-
- def list_images(self, request, context):
- LOG.debug(f"Get request to list images ...")
- all_images = omni_utils.load_json_data(self.img_record_file)
-
- ret = []
- for _, images in all_images.items():
- for _, img in images.items():
- image = images_pb2.Image()
- image.name = img['name']
- image.location = img['location']
- image.status = img['status']
- ret.append(image)
- LOG.debug(f"Responded: {ret}")
- return images_pb2.ListImageResponse(images=ret)
-
- def download_image(self, request, context):
- LOG.debug(f"Get request to download image: {request.name} ...")
- all_images = omni_utils.load_json_data(self.img_record_file)
-
- if request.name not in all_images['remote'].keys():
- LOG.debug(f'Image: {request.name} not valid for download')
- msg = f'Error: Image {request.name} is valid for download, please check image name from REMOTE IMAGE LIST using "images" command ...'
- return images_pb2.GeneralImageResponse(ret=1, msg=msg)
-
- @omni_utils.asyncwrapper
- def do_download(images, name):
- self.backend.download_and_transform(images, name)
-
- do_download(all_images, request.name)
-
- msg = f'Downloading: {request.name}, this might take a while, please check image status with "images" command.'
- 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(
- request.path, omni_constants.IMAGE_LOAD_SUPPORTED_TYPES)
-
- if not supported:
- supported_fmt = ', '.join(omni_constants.IMAGE_LOAD_SUPPORTED_TYPES)
- msg = f'Unsupported image format, the current supported format are: {supported_fmt}.'
-
- return images_pb2.GeneralImageResponse(ret=1, msg=msg)
-
- all_images = omni_utils.load_json_data(self.img_record_file)
-
- msg = f'Loading: {request.name}, this might take a while, please check image status with "images" command.'
- update = False
-
- local_images = all_images['local']
- if request.name in local_images.keys():
- LOG.debug(f"Image: {request.name} already existed, replace it with: {request.path} ...")
- msg = f'Replacing: {request.name}, with new image file: {request.path}, this might take a while, please check image status with "images" command.'
- update = True
-
- @omni_utils.asyncwrapper
- def do_load(images, name, path, fmt, update):
- self.backend.load_and_transform(images, name, path, fmt, update)
-
- do_load(all_images, request.name, request.path, fmt, update)
-
- return images_pb2.GeneralImageResponse(ret=0, msg=msg)
-
- def delete_image(self, request, context):
- LOG.debug(f"Get request to delete image: {request.name} ...")
- images = omni_utils.load_json_data(self.img_record_file)
- ret = self.backend.delete_image(images, request.name)
- if ret == 0:
- msg = f'Image: {request.name} has been successfully deleted.'
- elif ret == 1:
- msg = f'Image: {request.name} does not exist, please check again.'
-
- return images_pb2.GeneralImageResponse(ret=1, msg=msg)
+import logging
+import os
+
+from omnivirt.backends.mac import image_handler as mac_image_handler
+from omnivirt.backends.win import image_handler as win_image_handler
+from omnivirt.grpcs.omnivirt_grpc import images_pb2, images_pb2_grpc
+from omnivirt.utils import constants as omni_constants
+from omnivirt.utils import utils as omni_utils
+
+
+LOG = logging.getLogger(__name__)
+
+
+class ImagerService(images_pb2_grpc.ImageGrpcServiceServicer):
+ '''
+ The Imager GRPC Handler
+ '''
+
+ def __init__(self, arch, host_os, conf, svc_base_dir) -> None:
+ self.CONF = conf
+ self.svc_base_dir = svc_base_dir
+ self.work_dir = self.CONF.conf.get('default', 'work_dir')
+ self.image_dir = os.path.join(self.work_dir, 'images')
+ self.img_record_file = os.path.join(self.image_dir, 'images.json')
+ if host_os == 'Win':
+ self.backend = win_image_handler.WinImageHandler(
+ self.CONF, self.work_dir, self.image_dir, self.img_record_file, LOG)
+ elif host_os == 'MacOS':
+ self.backend = mac_image_handler.MacImageHandler(
+ self.CONF, self.work_dir, self.image_dir, self.img_record_file,
+ LOG, self.svc_base_dir)
+
+ def list_images(self, request, context):
+ LOG.debug(f"Get request to list images ...")
+ all_images = omni_utils.load_json_data(self.img_record_file)
+
+ ret = []
+ for _, images in all_images.items():
+ for _, img in images.items():
+ image = images_pb2.Image()
+ image.name = img['name']
+ image.location = img['location']
+ image.status = img['status']
+ ret.append(image)
+ LOG.debug(f"Responded: {ret}")
+ return images_pb2.ListImageResponse(images=ret)
+
+ def download_image(self, request, context):
+ LOG.debug(f"Get request to download image: {request.name} ...")
+ all_images = omni_utils.load_json_data(self.img_record_file)
+
+ if request.name not in all_images['remote'].keys():
+ LOG.debug(f'Image: {request.name} not valid for download')
+ msg = f'Error: Image {request.name} is valid for download, please check image name from REMOTE IMAGE LIST using "images" command ...'
+ return images_pb2.GeneralImageResponse(ret=1, msg=msg)
+
+ @omni_utils.asyncwrapper
+ def do_download(images, name):
+ self.backend.download_and_transform(images, name)
+
+ do_download(all_images, request.name)
+
+ msg = f'Downloading: {request.name}, this might take a while, please check image status with "images" command.'
+ 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(
+ request.path, omni_constants.IMAGE_LOAD_SUPPORTED_TYPES)
+
+ if not supported:
+ supported_fmt = ', '.join(omni_constants.IMAGE_LOAD_SUPPORTED_TYPES)
+ msg = f'Unsupported image format, the current supported format are: {supported_fmt}.'
+
+ return images_pb2.GeneralImageResponse(ret=1, msg=msg)
+
+ all_images = omni_utils.load_json_data(self.img_record_file)
+
+ msg = f'Loading: {request.name}, this might take a while, please check image status with "images" command.'
+ update = False
+
+ local_images = all_images['local']
+ if request.name in local_images.keys():
+ LOG.debug(f"Image: {request.name} already existed, replace it with: {request.path} ...")
+ msg = f'Replacing: {request.name}, with new image file: {request.path}, this might take a while, please check image status with "images" command.'
+ update = True
+
+ @omni_utils.asyncwrapper
+ def do_load(images, name, path, fmt, update):
+ self.backend.load_and_transform(images, name, path, fmt, update)
+
+ do_load(all_images, request.name, request.path, fmt, update)
+
+ return images_pb2.GeneralImageResponse(ret=0, msg=msg)
+
+ def delete_image(self, request, context):
+ LOG.debug(f"Get request to delete image: {request.name} ...")
+ images = omni_utils.load_json_data(self.img_record_file)
+ ret = self.backend.delete_image(images, request.name)
+ if ret == 0:
+ msg = f'Image: {request.name} has been successfully deleted.'
+ elif ret == 1:
+ msg = f'Image: {request.name} does not exist, please check again.'
+
+ return images_pb2.GeneralImageResponse(ret=1, msg=msg)
diff --git a/omnivirt/services/instance_service.py b/eulerlauncher/services/instance_service.py
similarity index 98%
rename from omnivirt/services/instance_service.py
rename to eulerlauncher/services/instance_service.py
index e4125e9..be912df 100644
--- a/omnivirt/services/instance_service.py
+++ b/eulerlauncher/services/instance_service.py
@@ -1,81 +1,81 @@
-import logging
-import os
-
-from omnivirt.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
-from omnivirt.utils import utils
-
-
-LOG = logging.getLogger(__name__)
-
-class InstanceService(instances_pb2_grpc.InstanceGrpcServiceServicer):
- '''
- The Instance GRPC Handler
- '''
-
- def __init__(self, arch, host_os, conf, svc_base_dir) -> None:
- self.CONF = conf
- self.svc_base_dir = svc_base_dir
- self.work_dir = self.CONF.conf.get('default', 'work_dir')
- self.instance_dir = os.path.join(self.work_dir, 'instances')
- 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')
- if host_os == 'Win':
- from omnivirt.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)
- elif host_os == 'MacOS':
- from omnivirt.backends.mac import instance_handler as mac_instance_handler
- self.backend = mac_instance_handler.MacInstanceHandler(
- self.CONF, self.work_dir, self.instance_dir, self.image_dir,
- self.img_record_file, LOG, self.svc_base_dir)
-
- def list_instances(self, request, context):
- LOG.debug(f"Get request to list instances ...")
- instances_obj = self.backend.list_instances()
-
- ret = []
- for vm_obj in instances_obj:
- instance_dict = {
- 'name': vm_obj.name,
- 'image': vm_obj.image,
- 'vm_state': vm_obj.vm_state,
- 'ip_address': vm_obj.ip if vm_obj.ip else 'N/A'
- }
- ret.append(instance_dict)
-
- return instances_pb2.ListInstancesResponse(instances=ret)
-
- def create_instance(self, request, context):
- LOG.debug(f"Get request to create instance: {request.name} with image {request.image} ...")
-
- 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)
-
- 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.'
- return instances_pb2.CreateInstanceResponse(ret=2, msg=msg)
-
- check_result = self.backend.check_names(request.name, all_instances)
- if check_result == 1:
- msg = f'Error: Instance with name {request.name} already exist in exixting Hyper-V or Qemu backend, please specify another name.'
- 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)
- msg = f'Successfully created {request.name} with image {request.image}'
- return instances_pb2.CreateInstanceResponse(ret=1, msg=msg, instance=vm)
-
- def delete_instance(self, request, context):
- LOG.debug(f"Get request to delete instance: {request.name} ...")
- all_instances = utils.load_json_data(self.instance_record_file)
- if request.name not in all_instances['instances'].keys():
- msg = f'Error: Instance with name {request.name} does not exist.'
- return instances_pb2.DeleteInstanceResponse(ret=2, msg=msg)
-
- self.backend.delete_instance(request.name, self.instance_record_file, all_instances)
- msg = f'Successfully deleted instance: {request.name}.'
- return instances_pb2.DeleteInstanceResponse(ret=1, msg=msg)
+import logging
+import os
+
+from omnivirt.grpcs.omnivirt_grpc import instances_pb2, instances_pb2_grpc
+from omnivirt.utils import utils
+
+
+LOG = logging.getLogger(__name__)
+
+class InstanceService(instances_pb2_grpc.InstanceGrpcServiceServicer):
+ '''
+ The Instance GRPC Handler
+ '''
+
+ def __init__(self, arch, host_os, conf, svc_base_dir) -> None:
+ self.CONF = conf
+ self.svc_base_dir = svc_base_dir
+ self.work_dir = self.CONF.conf.get('default', 'work_dir')
+ self.instance_dir = os.path.join(self.work_dir, 'instances')
+ 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')
+ if host_os == 'Win':
+ from omnivirt.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)
+ elif host_os == 'MacOS':
+ from omnivirt.backends.mac import instance_handler as mac_instance_handler
+ self.backend = mac_instance_handler.MacInstanceHandler(
+ self.CONF, self.work_dir, self.instance_dir, self.image_dir,
+ self.img_record_file, LOG, self.svc_base_dir)
+
+ def list_instances(self, request, context):
+ LOG.debug(f"Get request to list instances ...")
+ instances_obj = self.backend.list_instances()
+
+ ret = []
+ for vm_obj in instances_obj:
+ instance_dict = {
+ 'name': vm_obj.name,
+ 'image': vm_obj.image,
+ 'vm_state': vm_obj.vm_state,
+ 'ip_address': vm_obj.ip if vm_obj.ip else 'N/A'
+ }
+ ret.append(instance_dict)
+
+ return instances_pb2.ListInstancesResponse(instances=ret)
+
+ def create_instance(self, request, context):
+ LOG.debug(f"Get request to create instance: {request.name} with image {request.image} ...")
+
+ 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)
+
+ 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.'
+ return instances_pb2.CreateInstanceResponse(ret=2, msg=msg)
+
+ check_result = self.backend.check_names(request.name, all_instances)
+ if check_result == 1:
+ msg = f'Error: Instance with name {request.name} already exist in exixting Hyper-V or Qemu backend, please specify another name.'
+ 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)
+ msg = f'Successfully created {request.name} with image {request.image}'
+ return instances_pb2.CreateInstanceResponse(ret=1, msg=msg, instance=vm)
+
+ def delete_instance(self, request, context):
+ LOG.debug(f"Get request to delete instance: {request.name} ...")
+ all_instances = utils.load_json_data(self.instance_record_file)
+ if request.name not in all_instances['instances'].keys():
+ msg = f'Error: Instance with name {request.name} does not exist.'
+ return instances_pb2.DeleteInstanceResponse(ret=2, msg=msg)
+
+ self.backend.delete_instance(request.name, self.instance_record_file, all_instances)
+ msg = f'Successfully deleted instance: {request.name}.'
+ return instances_pb2.DeleteInstanceResponse(ret=1, msg=msg)
diff --git a/omnivirt/utils/__init__.py b/eulerlauncher/utils/__init__.py
similarity index 100%
rename from omnivirt/utils/__init__.py
rename to eulerlauncher/utils/__init__.py
diff --git a/omnivirt/utils/__pycache__/__init__.cpython-310.pyc b/eulerlauncher/utils/__pycache__/__init__.cpython-310.pyc
similarity index 100%
rename from omnivirt/utils/__pycache__/__init__.cpython-310.pyc
rename to eulerlauncher/utils/__pycache__/__init__.cpython-310.pyc
diff --git a/omnivirt/utils/constants.py b/eulerlauncher/utils/constants.py
similarity index 95%
rename from omnivirt/utils/constants.py
rename to eulerlauncher/utils/constants.py
index 9383d2d..dc0ed20 100644
--- a/omnivirt/utils/constants.py
+++ b/eulerlauncher/utils/constants.py
@@ -1,37 +1,37 @@
-STORAGE_PROTOCOL_ISCSI = 'iscsi'
-STORAGE_PROTOCOL_FC = 'fibre_channel'
-STORAGE_PROTOCOL_SMBFS = 'smbfs'
-STORAGE_PROTOCOL_RBD = 'rbd'
-
-DISK = "VHD"
-
-IMAGE_LOCATION_REMOTE = 'Remote'
-IMAGE_LOCATION_LOCAL = 'Local'
-
-IMAGE_STATUS_INIT = 'N/A'
-IMAGE_STATUS_DOWLOADABLE = 'Downloadable'
-IMAGE_STATUS_DOWNLOADING = 'Downloading'
-IMAGE_STATUS_LOADING = 'Loading'
-IMAGE_STATUS_READY = 'Ready'
-
-IMAGE_LOAD_SUPPORTED_TYPES = ['qcow2.xz', 'qcow2']
-
-ARCH_MAP = {
- 'AMD64': 'x86_64',
- 'arm64': 'aarch64',
- 'x86_64': 'x86_64'
-}
-
-VM_STATE_MAP = {
- 2: 'Running',
- 3: 'Stopped',
- 10: 'Rebooting',
- 32768: 'Paused',
- 32769: 'Suspended',
- 99: 'N/A'
- }
-
-OS_MAP = {
- 'Darwin': 'MacOS',
- 'Windows': 'Win'
+STORAGE_PROTOCOL_ISCSI = 'iscsi'
+STORAGE_PROTOCOL_FC = 'fibre_channel'
+STORAGE_PROTOCOL_SMBFS = 'smbfs'
+STORAGE_PROTOCOL_RBD = 'rbd'
+
+DISK = "VHD"
+
+IMAGE_LOCATION_REMOTE = 'Remote'
+IMAGE_LOCATION_LOCAL = 'Local'
+
+IMAGE_STATUS_INIT = 'N/A'
+IMAGE_STATUS_DOWLOADABLE = 'Downloadable'
+IMAGE_STATUS_DOWNLOADING = 'Downloading'
+IMAGE_STATUS_LOADING = 'Loading'
+IMAGE_STATUS_READY = 'Ready'
+
+IMAGE_LOAD_SUPPORTED_TYPES = ['qcow2.xz', 'qcow2']
+
+ARCH_MAP = {
+ 'AMD64': 'x86_64',
+ 'arm64': 'aarch64',
+ 'x86_64': 'x86_64'
+}
+
+VM_STATE_MAP = {
+ 2: 'Running',
+ 3: 'Stopped',
+ 10: 'Rebooting',
+ 32768: 'Paused',
+ 32769: 'Suspended',
+ 99: 'N/A'
+ }
+
+OS_MAP = {
+ 'Darwin': 'MacOS',
+ 'Windows': 'Win'
}
\ No newline at end of file
diff --git a/omnivirt/utils/exceptions.py b/eulerlauncher/utils/exceptions.py
similarity index 96%
rename from omnivirt/utils/exceptions.py
rename to eulerlauncher/utils/exceptions.py
index 3f671e1..47a1caa 100644
--- a/omnivirt/utils/exceptions.py
+++ b/eulerlauncher/utils/exceptions.py
@@ -1,61 +1,61 @@
-"""OmniVirt Base Exceptions.
-"""
-
-import logging
-
-LOG = logging.getLogger(__name__)
-
-class OmniVirtException(Exception):
- """Base OmniVirt Exception
- To correctly use this class, inherit from it and define
- a 'msg_fmt' property. That msg_fmt will get printf'd
- with the keyword arguments provided to the constructor.
- """
- msg_fmt = "An unknown exception occurred."
- code = 500
- headers = {}
- safe = False
-
- def __init__(self, message=None, **kwargs):
- self.kwargs = kwargs
-
- if 'code' not in self.kwargs:
- try:
- self.kwargs['code'] = self.code
- except AttributeError:
- pass
-
- try:
- if not message:
- message = self.msg_fmt % kwargs
- else:
- message = str(message)
- except Exception:
- self._log_exception()
- message = self.msg_fmt
-
- self.message = message
- super(OmniVirtException, self).__init__(message)
-
- def _log_exception(self):
- LOG.exception('Exception in string format operation')
- for name, value in self.kwargs.items():
- LOG.error("%s: %s" % (name, value)) # noqa
-
- def format_message(self):
- return self.args[0]
-
- def __repr__(self):
- dict_repr = self.__dict__
- dict_repr['class'] = self.__class__.__name__
- return str(dict_repr)
-
-
-class NoSuchFile(OmniVirtException):
- msg_fmt = "No Such File or Directory: %(file)s"
-
-class NoConfigFileProvided(OmniVirtException):
- msg_fmt = "Config File Should Be Provided"
-
-class OmniVirtdNotAvailable(OmniVirtException):
+"""OmniVirt Base Exceptions.
+"""
+
+import logging
+
+LOG = logging.getLogger(__name__)
+
+class OmniVirtException(Exception):
+ """Base OmniVirt Exception
+ To correctly use this class, inherit from it and define
+ a 'msg_fmt' property. That msg_fmt will get printf'd
+ with the keyword arguments provided to the constructor.
+ """
+ msg_fmt = "An unknown exception occurred."
+ code = 500
+ headers = {}
+ safe = False
+
+ def __init__(self, message=None, **kwargs):
+ self.kwargs = kwargs
+
+ if 'code' not in self.kwargs:
+ try:
+ self.kwargs['code'] = self.code
+ except AttributeError:
+ pass
+
+ try:
+ if not message:
+ message = self.msg_fmt % kwargs
+ else:
+ message = str(message)
+ except Exception:
+ self._log_exception()
+ message = self.msg_fmt
+
+ self.message = message
+ super(OmniVirtException, self).__init__(message)
+
+ def _log_exception(self):
+ LOG.exception('Exception in string format operation')
+ for name, value in self.kwargs.items():
+ LOG.error("%s: %s" % (name, value)) # noqa
+
+ def format_message(self):
+ return self.args[0]
+
+ def __repr__(self):
+ dict_repr = self.__dict__
+ dict_repr['class'] = self.__class__.__name__
+ return str(dict_repr)
+
+
+class NoSuchFile(OmniVirtException):
+ msg_fmt = "No Such File or Directory: %(file)s"
+
+class NoConfigFileProvided(OmniVirtException):
+ msg_fmt = "Config File Should Be Provided"
+
+class OmniVirtdNotAvailable(OmniVirtException):
msg_fmt = "OmniVirtd Daemon is not available"
\ No newline at end of file
diff --git a/omnivirt/utils/objs.py b/eulerlauncher/utils/objs.py
similarity index 96%
rename from omnivirt/utils/objs.py
rename to eulerlauncher/utils/objs.py
index 9cb2004..e26f37e 100644
--- a/omnivirt/utils/objs.py
+++ b/eulerlauncher/utils/objs.py
@@ -1,54 +1,54 @@
-import os
-import configparser
-
-from omnivirt.utils import exceptions
-from omnivirt.utils import constants
-
-class Instance(object):
-
- def __init__(self, name='') -> None:
- self.name = name
- self.uuid = ''
- self.identifier = {}
- self.metadata = None
- self.vm_state = None
- self.vcpu = None
- self.ram = None
- self.disk = None
- self.info = None
- self.image = None
- self.ip = 'N/A'
- self.mac = 'N/A'
-
-
-class Image(object):
-
- def __init__(self) -> None:
- self.name = ''
- self.location = ''
- self.status = constants.IMAGE_STATUS_INIT
- self.path = ''
-
- def to_dict(self):
- image_dict = {
- 'name': self.name,
- 'location': self.location,
- 'status': self.status,
- 'path': self.path
- }
- return image_dict
-
- def from_dict(self, img_dict):
- self.name = img_dict['name']
- self.location = img_dict['location']
- self.status = img_dict['status']
- self.path = img_dict['path']
-
-
-class Conf(object):
-
- def __init__(self, config_file) -> None:
- self.conf = configparser.ConfigParser()
- if not os.path.exists(config_file):
- raise exceptions.NoSuchFile(file=config_file)
- self.conf.read(config_file)
+import os
+import configparser
+
+from omnivirt.utils import exceptions
+from omnivirt.utils import constants
+
+class Instance(object):
+
+ def __init__(self, name='') -> None:
+ self.name = name
+ self.uuid = ''
+ self.identifier = {}
+ self.metadata = None
+ self.vm_state = None
+ self.vcpu = None
+ self.ram = None
+ self.disk = None
+ self.info = None
+ self.image = None
+ self.ip = 'N/A'
+ self.mac = 'N/A'
+
+
+class Image(object):
+
+ def __init__(self) -> None:
+ self.name = ''
+ self.location = ''
+ self.status = constants.IMAGE_STATUS_INIT
+ self.path = ''
+
+ def to_dict(self):
+ image_dict = {
+ 'name': self.name,
+ 'location': self.location,
+ 'status': self.status,
+ 'path': self.path
+ }
+ return image_dict
+
+ def from_dict(self, img_dict):
+ self.name = img_dict['name']
+ self.location = img_dict['location']
+ self.status = img_dict['status']
+ self.path = img_dict['path']
+
+
+class Conf(object):
+
+ def __init__(self, config_file) -> None:
+ self.conf = configparser.ConfigParser()
+ if not os.path.exists(config_file):
+ raise exceptions.NoSuchFile(file=config_file)
+ self.conf.read(config_file)
diff --git a/omnivirt/utils/utils.py b/eulerlauncher/utils/utils.py
similarity index 95%
rename from omnivirt/utils/utils.py
rename to eulerlauncher/utils/utils.py
index b6f10c9..9840688 100644
--- a/omnivirt/utils/utils.py
+++ b/eulerlauncher/utils/utils.py
@@ -1,94 +1,94 @@
-import functools
-import json
-import os
-import random
-from threading import Thread
-import uuid
-
-
-from google.protobuf.json_format import MessageToDict
-
-from omnivirt.utils import exceptions
-from omnivirt.utils import objs
-
-
-def asyncwrapper(fn):
- def wrapper(*args, **kwargs):
- thr = Thread(target=fn, args=args, kwargs=kwargs)
- thr.start()
-
- return wrapper
-
-
-def response2dict(fn):
- @functools.wraps(fn)
- def wrap(*args, **kwargs):
- response = fn(*args, **kwargs)
- response = MessageToDict(response)
- return response
-
- return wrap
-
-
-def parse_config(args):
- if len(args) != 2 or args[0] != '--config-file':
- raise exceptions.NoConfigFileProvided
- if not os.path.exists(args[1]):
- raise exceptions.NoSuchFile(file=args[1])
-
- return objs.Conf(args[1])
-
-
-def format_mac_addr(mac_str):
- ret = ''
- if len(mac_str) != 12:
- return ret
- mac_low = mac_str.lower()
- for i in range(0, 5):
- ret = ret + mac_low[2 * i] + mac_low[2 * i + 1] + '-'
- ret = ret + mac_low[-2] + mac_low[-1]
-
- return ret
-
-def load_json_data(json_file):
- with open(json_file, 'r', encoding='utf-8') as fr:
- data = json.load(fr)
-
- return data
-
-def save_json_data(json_file, data):
- with open(json_file, 'w', encoding='utf-8') as fw:
- json.dump(data, fw, indent=4, ensure_ascii=False)
-
-def generate_mac():
- local_mac = uuid.uuid1().hex[-12:]
-
- mac = [random.randint(0x00, 0xff), random.randint(0x00, 0xff)]
- s = [local_mac[0:2], local_mac[2:4], local_mac[4:6], local_mac[6:8]]
- for item in mac:
- s.append(str("%02x" % item))
-
- return (':'.join(s))
-
-def catch_exception(func):
-
- def wrap(*args, **kwargs):
- try:
- return func(*args, **kwargs)
- except Exception:
- raise exceptions.OmniVirtdNotAvailable
-
- return wrap
-
-def check_file_tail(file_name, to_check):
-
- ret = False
- ret_fmt = None
-
- for fmt in to_check:
- if file_name.endswith(fmt):
- ret = True
- ret_fmt = fmt
- break
-
- return ret, ret_fmt
+import functools
+import json
+import os
+import random
+from threading import Thread
+import uuid
+
+
+from google.protobuf.json_format import MessageToDict
+
+from omnivirt.utils import exceptions
+from omnivirt.utils import objs
+
+
+def asyncwrapper(fn):
+ def wrapper(*args, **kwargs):
+ thr = Thread(target=fn, args=args, kwargs=kwargs)
+ thr.start()
+
+ return wrapper
+
+
+def response2dict(fn):
+ @functools.wraps(fn)
+ def wrap(*args, **kwargs):
+ response = fn(*args, **kwargs)
+ response = MessageToDict(response)
+ return response
+
+ return wrap
+
+
+def parse_config(args):
+ if len(args) != 2 or args[0] != '--config-file':
+ raise exceptions.NoConfigFileProvided
+ if not os.path.exists(args[1]):
+ raise exceptions.NoSuchFile(file=args[1])
+
+ return objs.Conf(args[1])
+
+
+def format_mac_addr(mac_str):
+ ret = ''
+ if len(mac_str) != 12:
+ return ret
+ mac_low = mac_str.lower()
+ for i in range(0, 5):
+ ret = ret + mac_low[2 * i] + mac_low[2 * i + 1] + '-'
+ ret = ret + mac_low[-2] + mac_low[-1]
+
+ return ret
+
+def load_json_data(json_file):
+ with open(json_file, 'r', encoding='utf-8') as fr:
+ data = json.load(fr)
+
+ return data
+
+def save_json_data(json_file, data):
+ with open(json_file, 'w', encoding='utf-8') as fw:
+ json.dump(data, fw, indent=4, ensure_ascii=False)
+
+def generate_mac():
+ local_mac = uuid.uuid1().hex[-12:]
+
+ mac = [random.randint(0x00, 0xff), random.randint(0x00, 0xff)]
+ s = [local_mac[0:2], local_mac[2:4], local_mac[4:6], local_mac[6:8]]
+ for item in mac:
+ s.append(str("%02x" % item))
+
+ return (':'.join(s))
+
+def catch_exception(func):
+
+ def wrap(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception:
+ raise exceptions.OmniVirtdNotAvailable
+
+ return wrap
+
+def check_file_tail(file_name, to_check):
+
+ ret = False
+ ret_fmt = None
+
+ for fmt in to_check:
+ if file_name.endswith(fmt):
+ ret = True
+ ret_fmt = fmt
+ break
+
+ return ret, ret_fmt
diff --git a/install.spec b/install.spec
index cac4aec..8655401 100644
--- a/install.spec
+++ b/install.spec
@@ -5,10 +5,10 @@ block_cipher = None
a = Analysis(
- ['omnivirt/install.py'],
+ ['eulerlauncher/install.py'],
pathex=[],
- binaries=[('dist/omnivirt', './etc')],
- datas=[('etc/omnivirt.conf', './etc'), ('resources/qemu/edk2-aarch64-code.fd', './etc'), ('resources/qemu/edk2-x86_64-code.fd', './etc')],
+ binaries=[('dist/eulerlauncher', './etc')],
+ datas=[('etc/eulerlauncher.conf', './etc'), ('resources/qemu/edk2-aarch64-code.fd', './etc'), ('resources/qemu/edk2-x86_64-code.fd', './etc')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
diff --git a/setup.cfg b/setup.cfg
index 6a95db9..bd3854e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
[metadata]
-name = omnivirt
+name = eulerlauncher
version = 0.1
summary = A tool to run openEuler instances on all platforms
description_file =
@@ -10,7 +10,7 @@ python_requires = >=3.8
url = https://github.com/ZhengZhenyu/omnivirt.git
classifiers =
Development Status :: 3 - Alpha
- Environment :: OmniVirt
+ Environment :: EulerLauncher
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Mulan PSL v2
@@ -25,8 +25,8 @@ classifiers =
[files]
packages =
- omnivirt
+ eulerlauncher
[entry_points]
console_scripts =
- omnivirt = omnivirt.cli:main
\ No newline at end of file
+ eulerlauncher = eulerlauncher.cli:main
\ No newline at end of file
--
Gitee