diff --git a/README.md b/README.md index 031fd1d..acba181 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ The Unikraft VSCode Extension extension facilitates the development of Unikraft The command `Unikraft: Initialize project` from the command palette allows creating a new project in the opened directory. It can create the following project types: -#### Application + #### Library @@ -29,18 +29,9 @@ The user has to provide the extension with the following information in order to The Unikraft hierarchy will be in `./.unikraft`, the library source code will be in `./unikraft/libs/$lib_name`, whereas the application for testing the library will be in the opened directory. -#### Core - -The opened directory will be populated with the Unikraft hierarchy: -* archs -* apps -* libs -* plats -* unikraft. - ### Project configuration -The command `Unikraft: Configure project` from the command palette allows configuring the project from the `kraft.yaml` file or interactively by opening a terminal with `menuconfig`. +The command `Unikraft: Configure project` from the command palette allows configuring the project interactively by opening a terminal with `menu`. ### Project building @@ -55,13 +46,13 @@ If there are multiple images, the user has to choose one of them. ### External dependencies inspection The `External libraries` view allows inspecting various types of external libraries: -* the ones that are specified in `kraft.yaml` and are also present in the project hierarchy (U icon); -* the ones that are only specified in `kraft.yaml` (red icon); -* the ones that are only present in the project hierarchy (green icon). +* the ones that are specified in `kraft.yaml` and are also present in the project hierarchy (represented with U icon); +* the ones that are only specified in `kraft.yaml` (represented with red icon); +* the ones that are only present in the project hierarchy (represented with green icon). ![libs](https://github.com/unikraft/ide-vscode/blob/prototype/media/libs.gif) -A new library can be added to the project from this view by clicking the `+` button and selecting the library and its version from a drop-down list. +A new library and core can be added to the project from this view by clicking the `+` button and selecting the library and its version from a drop-down list. A library can either be removed from the project (it will still be stored on disk) or purged by clicking right on it. @@ -88,33 +79,45 @@ A `.env` file is created and it contains the path to the Python source code. How The following packages are required for `kraft`: ``` sudo apt-get install -y --no-install-recommends build-essential \ - libncurses-dev libyaml-dev flex git wget bison \ - unzip uuid-runtime + libncurses-dev \ + libyaml-dev \ + flex \ + wget \ + socat \ + bison \ + unzip \ + uuid-runtime \ + python3 \ + python3-setuptools \ + python3-pip \ + qemu-kvm \ + qemu-system-x86 \ + qemu-system-arm \ + sgabios \ + curl ``` -The package `kraft` is also required: +The CLI `kraft` is also required: ``` -pip install git+https://github.com/unikraft/kraft.git +curl --proto '=https' --tlsv1.2 -sSf https://get.kraftkit.sh | sh ``` -These are automatically installed if the `.kraftrc` file is not present in the user's home. +These are automatically installed if the `Kraftkit` is not installed on this system. ## Extension Settings This extension contributes the following settings: -* `unikraft.githubToken`: contains the Github Token used by kraft -* `unikraft.ukWorkdir`: contains the UK_WORKDIR; its value is overridden by `Unikraft initialize` - -* `unikraft.paused`: whether to start the unikernel in paused state (default is False) -* `unikraft.debug`: whether to start the unikernel in debug mode (default is False) -* `unikraft.gdb`: whether to attach gdb (default is False) -* `unikraft.gdb_port`: port for gdb (default is 4123) -* `unikraft.bridged`: whether to use a bridge or not (default is False) -* `unikraft.bridge_name`: bridge name (default is virbr0) -* `unikraft.ip4`: IP of the unikernel (default is 172.44.0.2) -* `unikraft.gateway_ip4`: IP of the gateway (default is 172.44.0) -* `unikraft.netmask4`: network mask (default is 255.255.255.0) +* `unikraft.sources`: Sets the environment variable `KRAFTKIT_PATHS_SOURCES` by default set by `~/.config/kraftkit/config.yaml` or ENV `KRAFTKIT_PATHS_SOURCES` that is further used by extension for `kraft` commands. +* `unikraft.manifests`: Sets the environment variable `KRAFTKIT_PATHS_MANIFESTS` by default set by `~/.config/kraftkit/config.yaml` or ENV `KRAFTKIT_PATHS_MANIFESTS` that is further used by extension for `kraft` commands. +* `unikraft.detach`: Whether to run unikernel in background (default is False). +* `unikraft.disableAccel`: Whether to disable acceleration of CPU (usually enables TCG) when running `kraft run` (default is False). +* `unikraft.symbolic`: Whether to use the debuggable (symbolic) unikernel when running `kraft run` (default is False). +* `unikraft.remove`: Whether to automatically remove the unikernel when it shutsdown (default is False). +* `unikraft.ip`: Assign the provided IP address when running `kraft run`. +* `unikraft.memory`: Assign MB memory to the unikernel (default is 64M) when running. +* `unikraft.network`: Attach instance to the provided network in the format `:` when running `kraft run`. +* `unikraft.ports`: Publish a machine's port(s) to the host (An array of strings e.g ["8080"]) when running `kraft run`. ![helloworld](https://github.com/unikraft/ide-vscode/blob/prototype/media/httpreply.gif) @@ -123,11 +126,9 @@ Besides using `settings.json`, these settings can also be edited when clicking C ## Known Issues * The `External libraries` view is not automatically updated when the following are changed manually: - - `ukWorkdir`; - - `kraft.yaml`; + - `kraft.yaml`. - the project hierarchy. * The output of a shell command is not logged until the command exits. -* `Unikraft: Initialize project` sets `UK_WORKDIR` to a directory either from the project structure, or from the home of the user; it currently does not support initializing a project with a different `UK_WORKDIR`. * Intellisense does not work yet in C for code portions from guarded definitions. * Intellisense does not work in Python unless at least one build is performed. Moreover, for packages installed after the build, it does not work at all. * At the moment, Intellisense works by parsing the directory structure and not by parsing `kraft.yaml` and the configuration files. diff --git a/package.json b/package.json index f414dce..e2324c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "unikraft-ide-vscode", "displayName": "Unikraft VSCode Extension", - "description": "Seamlessly build and manage Unikraft components from within VSCode!", + "description": "Seamlessly build and manage Unikraft components from within VSCode!", "version": "0.1.1", "publisher": "unikraft", "license": "MIT", @@ -9,7 +9,7 @@ "type": "git", "url": "https://github.com/unikraft/ide-vscode.git" }, - "homepage": "https://github.com/unikraft/ide-vscode/main/README.md", + "homepage": "https://github.com/unikraft/ide-vscode/main/README.md", "engines": { "vscode": "^1.59.0" }, @@ -23,77 +23,67 @@ "activationEvents": [ "onView:externalLibraries" ], - "icon": "media/unikraft-logo.png", - "galleryBanner": { - "color": "#0E2F5F", - "theme": "dark" - }, + "icon": "media/unikraft-logo.png", + "galleryBanner": { + "color": "#0E2F5F", + "theme": "dark" + }, "main": "./out/extension.js", "contributes": { "configuration": { "type": "object", "title": "Unikraft", "properties": { - "unikraft.githubToken": { + "unikraft.sources": { "type": "string", "default": "", - "description": "Specifies the Github Token used by kraft." + "description": "Specifies the directory where all the packages are stored, By default it is set by environment variable KRAFTKIT_PATHS_SOURCES or file `$HOME/.config/kraftkit/config.yaml`." }, - "unikraft.ukWorkdir": { + "unikraft.manifests": { "type": "string", "default": "", - "description": "Specifies UK_WORKDIR." + "description": "Specifies the directory where all the manifests are stored, By default it is set by environment variable KRAFTKIT_PATHS_MANIFESTS or file `$HOME/.config/kraftkit/config.yaml`." + }, + "unikraft.detach": { + "type": "boolean", + "default": false, + "description": "Whether to run unikernel in background" + }, + "unikraft.disableAccel": { + "type": "boolean", + "default": false, + "description": "Whether to disable acceleration of CPU (usually enables TCG)" }, - "unikraft.paused": { - "type": "boolean", - "default": false, - "description": "Whether to start the unikernel in paused state." - }, - "unikraft.debug": { - "type": "boolean", - "default": false, - "description": "Whether to start the unikernel in debug mode." - }, - "unikraft.gdb": { - "type": "boolean", - "default": false, - "description": "Whether to attach gdb." - }, - "unikraft.gdb_port": { - "type": "number", - "default": 4123, - "description": "Port for gdb." - }, - "unikraft.create_bridge": { - "type": "boolean", - "default": false, - "description": "Whether to create a new bridge." - }, - "unikraft.bridged": { - "type": "boolean", - "default": false, - "description": "Whether to use a bridge or not." - }, - "unikraft.bridge_name": { - "type": "string", - "default": "virbr0", - "description": "Bridge name." - }, - "unikraft.ip4": { - "type": "string", - "default": "172.44.0.2", - "description": "IP of the unikernel." - }, - "unikraft.gateway_ip4": { - "type": "string", - "default": "172.44.0.1", - "description": "IP of the gateway." - }, - "unikraft.netmask4": { - "type": "string", - "default": "255.255.255.0", - "description": "Network mask." - } + "unikraft.symbolic": { + "type": "boolean", + "default": false, + "description": "Whether to use the debuggable (symbolic) unikernel" + }, + "unikraft.remove": { + "type": "boolean", + "default": false, + "description": "Whether to automatically remove the unikernel when it shutsdown" + }, + "unikraft.ip": { + "type": "string", + "default": "", + "description": "Assign the provided IP address" + }, + "unikraft.memory": { + "type": "string", + "default": "64M", + "description": "Assign MB memory to the unikernel" + }, + "unikraft.network": { + "type": "string", + "default": "", + "description": "Attach instance to the provided network in the format :" + }, + "unikraft.ports": { + "type": "array", + "default": [], + "description": "Publish a machine's port(s) to the host" + } } }, "viewsContainers": { @@ -165,11 +155,6 @@ "title": "Update", "category": "Unikraft" }, - { - "command": "unikraft.editToken", - "title": "Edit the Github token", - "category": "Unikraft" - }, { "command": "externalLibraries.addLibrary", "title": "Add library", @@ -208,9 +193,6 @@ "lint": "eslint src --ext ts", "test": "node ./out/test/runTest.js" }, - "dependencies": { - "js-yaml": "^4.0.0" - }, "devDependencies": { "@types/glob": "^7.1.3", "@types/mocha": "^8.2.2", @@ -224,5 +206,10 @@ "typescript": "^4.3.2", "vscode-test": "^1.5.2", "winston": "^3.3.3" + }, + "dependencies": { + "command-exists": "^1.2.9", + "js-yaml": "^4.1.0", + "yaml": "^2.3.1" } } diff --git a/resources/dark/lib_no_dir.svg b/resources/dark/kraft_no_lib.svg similarity index 100% rename from resources/dark/lib_no_dir.svg rename to resources/dark/kraft_no_lib.svg diff --git a/resources/light/lib_no_dir.svg b/resources/light/kraft_no_lib.svg similarity index 100% rename from resources/light/lib_no_dir.svg rename to resources/light/kraft_no_lib.svg diff --git a/src/ExternalLibrariesProvider.ts b/src/ExternalLibrariesProvider.ts index c21f9d3..2703c3c 100644 --- a/src/ExternalLibrariesProvider.ts +++ b/src/ExternalLibrariesProvider.ts @@ -1,13 +1,17 @@ /* SPDX-License-Identifier: BSD-3-Clause */ import { Event, EventEmitter, OutputChannel, StatusBarItem, TreeDataProvider, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; -import { existsSync, lstatSync, readFileSync } from 'fs'; +import { existsSync, readFileSync, readdirSync, rmdirSync, writeFile, writeFileSync } from 'fs'; import { join } from 'path'; import { execSync } from 'child_process'; -import { getProjectPath, getUkWorkdir, refreshViews } from './commands/utils'; +import { + getProjectPath, refreshViews, removeCore, getSourcesDir, getManifestsDir, showErrorMessage, getKraftYaml, getKraftYamlPath, removeCoreProjectDir, showInfoMessage +} from './commands/utils'; import { Command } from './commands/Command'; +import { string } from 'yaml/dist/schema/common/string'; const yaml = require('js-yaml'); +const YAML = require('yaml') export class ExternalLibrariesProvider implements TreeDataProvider { @@ -16,25 +20,41 @@ export class ExternalLibrariesProvider implements TreeDataProvider { constructor( private projectPath: string | undefined, - private _ukWorkdir: string | undefined) { + private _sourcesDir: string, + private _manifestsDir: string + ) { } + + public get sourcesDir(): string { + return this._sourcesDir; + } + + public get manifestsDir(): string { + return this._manifestsDir; } - public get ukWorkdir(): string | undefined { - return this._ukWorkdir; + public set sourcesDir(value: string) { + this._sourcesDir = value; + this.kraftEnv['KRAFTKIT_PATHS_SOURCES'] = value; } - public set ukWorkdir(value: string | undefined) { - this._ukWorkdir = value; - this.kraftEnv['UK_WORKDIR'] = value; + + public set manifestsDir(value: string) { + this._manifestsDir = value; + this.kraftEnv['KRAFTKIT_PATHS_MANIFESTS'] = value } private kraftEnv = Object.assign( process.env, - { 'UK_WORKDIR': this._ukWorkdir } + { + 'KRAFTKIT_PATHS_MANIFESTS': this._manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': this._sourcesDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }, ); refresh(): void { this.projectPath = getProjectPath(); - this.ukWorkdir = getUkWorkdir(); + this.sourcesDir = getSourcesDir(); + this.manifestsDir = getManifestsDir(); this._onDidChangeTreeData.fire(); } @@ -43,7 +63,7 @@ export class ExternalLibrariesProvider implements TreeDataProvider { } getChildren(element?: Library): Thenable { - if (!this._ukWorkdir || !this.projectPath) { + if (!this.projectPath) { window.showInformationMessage('No library in empty workspace'); return Promise.resolve([]); } @@ -52,12 +72,9 @@ export class ExternalLibrariesProvider implements TreeDataProvider { return Promise.resolve(this.getData(element)); } - const kraftYaml = this.getKraftYaml( - join(this.projectPath, 'kraft.yaml') - ); + const kraftYaml = getKraftYaml(this.projectPath); const core = this.getCore(kraftYaml); const presentLibs = this.getPresentLibs(kraftYaml); - return Promise.resolve(core.concat(presentLibs)); } @@ -65,12 +82,19 @@ export class ExternalLibrariesProvider implements TreeDataProvider { kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem ) { - if (!this.projectPath || !this._ukWorkdir) { + if (!this.projectPath) { + showErrorMessage(kraftChannel, kraftStatusBarItem, "No workspace.") return; } const options = { cwd: this.projectPath, env: this.kraftEnv }; - const libs = this.getLibs(); + let libs = this.getLibs(); + + const jsonCore = execSync('kraft pkg list -C -o=json', { env: this.kraftEnv }).toString() + const core: Library[] = JSON.parse(jsonCore) + .map((core: { format: string, latest: string, package: string, type: string }) => + this.toLib({ meta: { name: core.package }, data: core }, '', false)) + libs = libs.concat(core) const lib = await window.showQuickPick( libs.map(lib => lib.name), @@ -79,69 +103,85 @@ export class ExternalLibrariesProvider implements TreeDataProvider { if (!lib) { return; } - + let versions: string[] = this.getLibVersions(lib); const version = await window.showQuickPick( - this.getLibVersions(lib), + versions, { placeHolder: 'Choose the library version' } ); if (!version) { return; } + kraftChannel.show(true); + + let pullCommand + if (lib.toLowerCase() == "unikraft") { + removeCoreProjectDir(kraftChannel, kraftStatusBarItem, this.projectPath) + pullCommand = new Command( + `kraft pkg pull ${lib}:${version}`, + options, + `Pulled ${lib} with ${version} version.`, + refreshViews + ); - const command = new Command( - `kraft lib add ${lib}@${version.split('-')[1]}`, - options, - `Added ${lib}-${version} to the project.` - ); - const pullCommand = new Command( - `kraft list pull ${lib}@${version.split('-')[1]}`, - options, - `Pulled ${lib}-${version}.`, - refreshViews - ); - - command.execute(kraftChannel, kraftStatusBarItem, [pullCommand]); - } - - private getKraftYaml(kraftYamlPath: string): any { - if (!existsSync(kraftYamlPath)) { - return {}; + let kraftYamlPath = getKraftYamlPath(this.projectPath); + if (!kraftYamlPath) { + showErrorMessage(kraftChannel, kraftStatusBarItem, "Kraftfile not found.") + return; + } + let kraftYaml = getKraftYaml(this.projectPath) + if (!kraftYaml.unikraft) { + kraftYaml.unikraft = {} + } + kraftYaml.unikraft.version = version + writeFileSync(kraftYamlPath, YAML.stringify(kraftYaml)) + } else { + pullCommand = new Command( + `kraft pkg add ${lib}:${version}`, + options, + `Added ${lib} with ${version} version.`, + refreshViews + ); } - return yaml.load(readFileSync(kraftYamlPath, 'utf-8')); + pullCommand.execute(kraftChannel, kraftStatusBarItem); } private getCore(kraftYaml: any): Library[] { - const jsonCore = execSync('kraft list -c -j', { env: this.kraftEnv }) - .toString(); - - const core = JSON.parse(jsonCore).unikraft[0]; + const jsonCore = execSync('kraft pkg list -C -o=json', { env: this.kraftEnv }).toString() + const core = JSON.parse(jsonCore)[0]; const isInKraftYaml = Object.keys(kraftYaml).includes('unikraft'); - return [this.toLib( - core, - isInKraftYaml ? this.getKraftVersion(kraftYaml.unikraft) : '', + { + meta: { + name: core.package + }, + data: core + }, + isInKraftYaml ? this.getKraftVersion(kraftYaml.unikraft) : core.latest, isInKraftYaml ? true : false - )]; + )].filter(lib => lib.isPresent()); } - private getPresentLibs(kraftYaml: any): any { + private getPresentLibs(kraftYaml: any): Library[] { const rawLibs = this.listLibs(); - const kraftLibs = Object.keys(kraftYaml).includes('libraries') ? - Object.keys(kraftYaml.libraries) : []; - - const libs = rawLibs.map(lib => { - const libIndex = kraftLibs.indexOf(lib.meta.name); + const kraftLibs = Object.keys(kraftYaml).includes('libraries') ? Object.keys(kraftYaml.libraries) : []; + const libs = rawLibs.map((lib) => { + const libIndex = kraftLibs.indexOf(lib.package); if (libIndex !== -1) { kraftLibs.splice(libIndex, 1); } return this.toLib( - lib, + { + meta: { + name: lib.package + }, + data: lib + }, libIndex !== -1 ? - this.getKraftVersion(kraftYaml.libraries[lib.meta.name]) : - '', + this.getKraftVersion(kraftYaml.libraries[lib.package]) : + lib.latest, libIndex !== -1 ? true : false ); }); @@ -159,7 +199,7 @@ export class ExternalLibrariesProvider implements TreeDataProvider { lib, this.getKraftVersion(kraftYaml.libraries[lib]), true, - this.isDirectory(lib), + this.isAvailableLocally(lib, this.getKraftVersion(kraftYaml.libraries[lib])), '', TreeItemCollapsibleState.None, this.projectPath, @@ -169,18 +209,17 @@ export class ExternalLibrariesProvider implements TreeDataProvider { private getLibs(): Library[] { const libs = this.listLibs() - .map((lib: { meta: { name: any; }, data: { dists: {} } }) => - this.toLib(lib, '', false)) + .map((lib: { format: string, latest: string, package: string, type: string }) => + this.toLib({ meta: { name: lib.package }, data: lib }, '', false)) .sort(this.compareLibs); return libs; } - private listLibs(): [{ meta: { name: any; }, data: { dists: {} } }] { - const jsonLibs = execSync('kraft list -l -j', { env: this.kraftEnv }) + private listLibs(): [{ format: string, latest: string, package: string, type: string }] { + const jsonLibs = execSync('kraft pkg list -L -o=json', { env: this.kraftEnv }) .toString(); - - return JSON.parse(jsonLibs).libraries; + return JSON.parse(jsonLibs); } private getKraftVersion(lib: any): string { @@ -205,7 +244,7 @@ export class ExternalLibrariesProvider implements TreeDataProvider { } private toLib( - lib: { meta: { name: any; }, data: {} }, + lib: { meta: { name: any; }, data: { format: string, latest: string, package: string, type: string } }, kraftVersion: string, isInKraftYaml: boolean ): Library { @@ -213,7 +252,7 @@ export class ExternalLibrariesProvider implements TreeDataProvider { lib.meta.name, kraftVersion, isInKraftYaml, - this.isDirectory(lib.meta.name), + this.isAvailableLocally(lib.meta.name, kraftVersion), lib.data, TreeItemCollapsibleState.Collapsed, this.projectPath, @@ -221,16 +260,28 @@ export class ExternalLibrariesProvider implements TreeDataProvider { ); }; - private isDirectory(libName: string): boolean { - if (!this._ukWorkdir) { - return false; + private isAvailableLocally(libName: string, kraftVersion: string): boolean { + let fileExist = false; + + let sourcesFiles = readdirSync(this._sourcesDir) + sourcesFiles.forEach((element: string) => { + if (element.includes(libName) && element.includes(kraftVersion)) { + fileExist = true + } + }) + if (fileExist) { + return true } - const libPath = libName === 'unikraft' ? - join(this._ukWorkdir, libName) : - join(this._ukWorkdir, 'libs', libName); + const libYamlPath = join(this._manifestsDir, "libs", `${libName}.yaml`) + if (existsSync(libYamlPath)) { + const libyaml = yaml.load(readFileSync(libYamlPath)) + if (existsSync(libyaml.origin)) { + fileExist = true + } + } - return existsSync(libPath) && lstatSync(libPath).isDirectory(); + return fileExist; } private compareLibs(lib1: Library, lib2: Library): number { @@ -243,15 +294,23 @@ export class ExternalLibrariesProvider implements TreeDataProvider { private getLibVersions(lib: string): string[] { const libDetails = execSync( - `kraft list show -j ${lib}`, - {env: this.kraftEnv} - ).toString(); - const dists = JSON.parse(libDetails)[0].data.dists; - - return Object.keys(dists).map(dist => - Object.keys(dists[dist].data.versions) - .map(version => `${dist}-${version}`)) - .flat(); + `kraft pkg show -o=json ${lib}`, + { env: this.kraftEnv } + ).toString(); + const jsonLibDetails = JSON.parse(libDetails); + let channelVersions: string[] = jsonLibDetails.channels.map((channel: + { Name: string, Default: boolean, Latest: string, Manifest: string, Resource: string, Sha256: string } + ) => + channel["Name"] + ).filter((str: string) => str !== '') + + let versions: string[] = jsonLibDetails.versions ? + jsonLibDetails.versions.map( + (dist: { Version: string, Resource: string, Sha256: string, Type: string, Unikraft: string }) => + dist["Version"] + ).filter((str: string) => str !== '') : [] + + return channelVersions.concat(versions) } } @@ -261,7 +320,7 @@ export class Library extends TreeItem { public readonly name: string, private _kraftVersion: string, private _isInKraftYaml: boolean, - private readonly isDir: boolean, + private readonly isAvailable: boolean, public readonly data: any, public readonly collapsibleState: TreeItemCollapsibleState, private readonly projectPath: string | undefined, @@ -299,19 +358,44 @@ export class Library extends TreeItem { } public isPresent(): boolean { - return this._isInKraftYaml || this.isDir; + return this._isInKraftYaml || this.isAvailable; + } + + private removeCore( + kraftChannel: OutputChannel, + kraftStatusBarItem: StatusBarItem + ) { + if (!this.projectPath) { + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "No workspace." + ) + return + } + + let kraftYamlPath = getKraftYamlPath(this.projectPath) + if (!kraftYamlPath) { + return + } + let kraftYaml = getKraftYaml(this.projectPath) + kraftYaml["unikraft"] = undefined + writeFileSync(kraftYamlPath, YAML.stringify(kraftYaml)) + if (existsSync(join(this.projectPath, '.unikraft', 'unikraft'))) { + rmdirSync(join(this.projectPath, '.unikraft', 'unikraft'), { recursive: true }) + } } private getIconName(): string { - if (this._isInKraftYaml && this.isDir) { + if (this._isInKraftYaml && this.isAvailable) { return 'lib_present.svg'; } if (this._isInKraftYaml) { - return 'lib_no_dir.svg'; + return 'kraft_no_lib.svg'; } - if (this.isDir) { + if (this.isAvailable) { return 'lib_no_kraft.svg'; } @@ -323,23 +407,56 @@ export class Library extends TreeItem { kraftStatusBarItem: StatusBarItem, purge?: boolean ) { + kraftChannel.show(true); if (!this.projectPath) { + showErrorMessage(kraftChannel, kraftStatusBarItem, "No workspace found.") return; } - kraftStatusBarItem.text = 'Removing library...'; - kraftChannel.appendLine(`Removing library ${this.name}...`); + showInfoMessage(kraftChannel, kraftStatusBarItem, + `Removing library ${this.name}...` + ) + const commands = [] - const command = new Command( - `kraft lib remove ${purge ? '-P' : ''} ${this.name}`, - { cwd: this.projectPath, env: this.kraftEnv }, - `Removed ${this.name} from the project.`, - refreshViews - ); + if (this._isInKraftYaml) { + if (this.name == "unikraft") { + removeCore(kraftChannel, kraftStatusBarItem, this.projectPath); + } else { + commands.push(new Command( + `kraft pkg remove ${this.name}`, + { cwd: this.projectPath, env: this.kraftEnv }, + `Removed ${this.name}:${this._kraftVersion} from the project directory.`, + refreshViews + )) + } + } else if (!purge) { + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "Could not remove package as it is not used by the project." + ); + return; + } - command.execute(kraftChannel, kraftStatusBarItem); + if (this.isAvailable && purge) { + commands.push(new Command( + `kraft pkg prune ${this.name}:${this._kraftVersion}`, + { cwd: this.projectPath, env: this.kraftEnv }, + `Pruned ${this.name}:${this._kraftVersion} from the system.`, + refreshViews + )) + } else if (purge) { + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "Could not purge package as it is not available on the host machine." + ); + } - kraftStatusBarItem.text = 'Done removing library.'; - kraftChannel.appendLine(`Done removing library ${this.name}.`); + if (commands.length == 1) { + commands[0].execute(kraftChannel, kraftStatusBarItem); + } else if (commands.length > 1) { + commands[0].execute(kraftChannel, kraftStatusBarItem, commands.slice(1)); + } } } diff --git a/src/UnikraftExtension.ts b/src/UnikraftExtension.ts index a8ad8bf..e47b69c 100644 --- a/src/UnikraftExtension.ts +++ b/src/UnikraftExtension.ts @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause */ import * as vscode from 'vscode'; -import * as utils from './commands/utils'; +import { getProjectPath, getSourcesDir, getManifestsDir, showErrorMessage } from './commands/utils'; import { reloadConfig, reloadIncludes } from './language/c'; import { setupPythonSupport } from './language/python'; import { ExternalLibrariesProvider, Library } from './ExternalLibrariesProvider'; @@ -13,25 +13,31 @@ import { kraftUpdate } from './commands/update'; import { execSync } from 'child_process'; import { env } from 'process'; -import * as path from 'path'; -import * as os from 'os'; -import * as fs from 'fs'; +import { basename, join, win32 } from 'path'; +import { existsSync, readFileSync, rmSync } from 'fs'; -export class UnikraftExtension { +const commandExistsSync = require('command-exists').sync; - constructor(private context: vscode.ExtensionContext) {} +export class UnikraftExtension { + constructor(private context: vscode.ExtensionContext) { } - private kraftChannel = vscode.window.createOutputChannel(' Log (Unikraft)'); - private kraftStatusBarItem = vscode.window.createStatusBarItem( + private kraftChannel = vscode.window.createOutputChannel(' Log (Unikraft)'); + private kraftStatusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, 100 ); private externalLibrariesProvider = new ExternalLibrariesProvider( - utils.getProjectPath(), - utils.getUkWorkdir() + getProjectPath(), + getSourcesDir(), + getManifestsDir() ); - async activate() { + async activate() { + this.kraftChannel.show(true) + await this.setupExtension(); + } + + private postSetup() { const externalLibrariesTreeView = vscode.window.registerTreeDataProvider( 'externalLibraries', this.externalLibrariesProvider @@ -40,29 +46,40 @@ export class UnikraftExtension { this.context.subscriptions.push(externalLibrariesTreeView); this.context.subscriptions.push(this.kraftStatusBarItem); this.kraftStatusBarItem.show(); - - await this.setupExtension(); - this.registerCommands(); - + + vscode.window.onDidCloseTerminal(t => { if (t.exitStatus) { + if (t.name === 'Kraft setup') { + this.kraftChannel.appendLine('Installed kraft.'); + this.kraftStatusBarItem.text = 'Installed kraft.'; + this.kraftChannel.appendLine('Executing "kraft pkg update"...'); + this.kraftChannel.appendLine(execSync( + 'kraft pkg update', + { env: env } + ).toString() + ); + this.kraftChannel.appendLine('Executed "kraft pkg update".'); + this.initExtension() + } + if (t.name === 'kraft run') { this.kraftStatusBarItem.text = 'Done running project.'; } else if (t.name === 'kraft menuconfig') { this.kraftStatusBarItem.text = 'Done configuring project.'; const errFile = '/tmp/err_kraft_configure'; - if (fs.existsSync(errFile)) { - vscode.window.showErrorMessage(fs.readFileSync(errFile).toString()); + if (existsSync(errFile)) { + vscode.window.showErrorMessage(readFileSync(errFile).toString()); - fs.rmSync(errFile); + rmSync(errFile); } } - + if (!t.exitStatus.code) { return; } - + this.kraftChannel.appendLine( `${t.name} exit code: ${t.exitStatus.code}` ); @@ -70,18 +87,21 @@ export class UnikraftExtension { }); vscode.workspace.onDidSaveTextDocument((document: vscode.TextDocument) => { - if (path.basename(document.fileName) === 'kraft.yaml') { - const projectPath = utils.getProjectPath(); + if (basename(document.fileName) === 'kraft.yaml') { + const projectPath = getProjectPath(); setupPythonSupport(projectPath); reloadIncludes(projectPath); reloadConfig(projectPath); } - if (path.basename(document.fileName) === '.config') { - reloadConfig(utils.getProjectPath()); + if (basename(document.fileName) === '.config') { + reloadConfig(getProjectPath()); } }); + } + private initExtension() { + this.registerCommands(); this.kraftStatusBarItem.text = 'Unikraft'; vscode.window.showInformationMessage( 'Congratulations, your extension "Unikraft" is now active!' @@ -89,52 +109,47 @@ export class UnikraftExtension { } private async setupExtension() { - var githubToken = utils.getGithubToken(); - - if (githubToken === '') { - this.kraftStatusBarItem.text = 'Waiting for the Github Token...'; - githubToken = await utils.updateGithubToken(this.kraftChannel); - } - - if (utils.getUkWorkdir() === '') { - utils.updateUkWorkdir(path.join(os.homedir(), '.unikraft')); - } - - if (!fs.existsSync(path.join(os.homedir(), '.kraftrc'))) { - this.installKraft(githubToken); + if (!commandExistsSync('kraft')) { + vscode.window.showInformationMessage('Do you want to install Kraftkit ?', "Install", "Cancel") + .then((result) => { + if (result == "Install") { + this.installKraft(); + this.postSetup() + } else { + showErrorMessage(this.kraftChannel, + this.kraftStatusBarItem, + "Kraftkit is not installed on the system." + ) + } + }); + } else { + this.initExtension(); + this.postSetup() } } - private installKraft(githubToken: string) { + private installKraft() { const terminal = vscode.window.createTerminal(`Kraft setup`); this.kraftStatusBarItem.text = 'Installing kraft...'; - - this.kraftChannel.appendLine('Installing dependencies...'); - terminal.sendText('sudo apt-get install -y --no-install-recommends \ - build-essential libncurses-dev libyaml-dev flex git wget bison \ - unzip uuid-runtime'); - this.kraftChannel.appendLine('Installed dependencies.'); - this.kraftChannel.appendLine('Installing kraft...'); - this.kraftChannel.appendLine( - execSync( - 'pip install git+https://github.com/unikraft/kraft.git', - { env: env } - ).toString() - ); - this.kraftChannel.appendLine('Installed kraft.'); - this.kraftChannel.appendLine('Executing "kraft list update"...'); - this.kraftChannel.appendLine(execSync( - 'kraft list update', - { - env: Object.assign( - process.env, - { 'UK_KRAFT_GITHUB_TOKEN': githubToken }) - } - ).toString() - ); - this.kraftChannel.appendLine('Executed "kraft list update".'); + terminal.sendText(`sudo apt-get install -y --no-install-recommends build-essential \ + libncurses-dev \ + libyaml-dev \ + flex \ + wget \ + socat \ + bison \ + unzip \ + uuid-runtime \ + python3 \ + python3-setuptools \ + python3-pip \ + qemu-kvm \ + qemu-system-x86 \ + qemu-system-arm \ + sgabios \ + curl && curl --proto '=https' --tlsv1.2 -sSf https://get.kraftkit.sh | sh && exit`); } private registerCommands() { @@ -142,52 +157,44 @@ export class UnikraftExtension { 'unikraft.initialize', async () => { kraftInitialize(this.kraftChannel, this.kraftStatusBarItem); - this.externalLibrariesProvider.ukWorkdir = utils.getUkWorkdir(); - }); + }); const configureCommand = vscode.commands.registerCommand( 'unikraft.configure', async () => kraftConfigure( - this.kraftChannel, - this.kraftStatusBarItem, - this.context - ) + this.kraftChannel, + this.kraftStatusBarItem) ); const buildCommand = vscode.commands.registerCommand( 'unikraft.build', - async () => kraftBuild(this.kraftChannel,this.kraftStatusBarItem) + async () => kraftBuild(this.kraftChannel, this.kraftStatusBarItem) ); const runCommand = vscode.commands.registerCommand( 'unikraft.run', async () => kraftRun( this.kraftChannel, this.kraftStatusBarItem, - this.context ) ); const updateCommand = vscode.commands.registerCommand( 'unikraft.update', async () => kraftUpdate(this.kraftChannel, this.kraftStatusBarItem) ); - const editTokenCommand = vscode.commands.registerCommand( - 'unikraft.editToken', - async () => utils.updateGithubToken(this.kraftChannel) - ); const addLibraryCommand = vscode.commands.registerCommand( 'externalLibraries.addLibrary', () => this.externalLibrariesProvider.addLibrary( - this.kraftChannel, - this.kraftStatusBarItem - ) + this.kraftChannel, + this.kraftStatusBarItem + ) ); const removeLibraryCommand = vscode.commands.registerCommand( 'externalLibraries.removeLibrary', - (node: Library) => + (node: Library) => node.removeLibrary(this.kraftChannel, this.kraftStatusBarItem) ); const purgeLibraryCommand = vscode.commands.registerCommand( 'externalLibraries.purgeLibrary', - (node: Library) => + (node: Library) => node.removeLibrary(this.kraftChannel, this.kraftStatusBarItem, true) ); const refreshLibraryCommand = vscode.commands.registerCommand( @@ -202,7 +209,6 @@ export class UnikraftExtension { this.context.subscriptions.push(buildCommand); this.context.subscriptions.push(runCommand); this.context.subscriptions.push(updateCommand); - this.context.subscriptions.push(editTokenCommand); this.context.subscriptions.push(addLibraryCommand); this.context.subscriptions.push(removeLibraryCommand); this.context.subscriptions.push(purgeLibraryCommand); diff --git a/src/commands/build.ts b/src/commands/build.ts index f32fc57..f73b98c 100644 --- a/src/commands/build.ts +++ b/src/commands/build.ts @@ -1,35 +1,104 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -import { OutputChannel, StatusBarItem } from 'vscode'; +import { OutputChannel, StatusBarItem, window } from 'vscode'; import { Command } from './Command'; -import { getProjectPath, getUkWorkdir } from './utils'; +import { getProjectPath, getDefaultFileNames, showErrorMessage, getSourcesDir, getManifestsDir, getKraftYaml, showInfoMessage } from './utils'; +import { join } from 'path'; +import { existsSync, readFileSync } from 'fs'; + +const yaml = require('js-yaml'); export async function kraftBuild( kraftChannel: OutputChannel, - kraftStatusBarItem: StatusBarItem + kraftStatusBarItem: StatusBarItem, ): Promise { + kraftChannel.show(true) const projectPath = getProjectPath(); if (!projectPath) { kraftChannel.appendLine('No workspace.'); + showErrorMessage(kraftChannel, kraftStatusBarItem, 'Build error: No workspace.'); return; } + const type = await window.showQuickPick( + [ + 'Build using interactive CLI', + 'Build from Kraftfile' + ], + { placeHolder: 'Configuration type' } + ); + + if (type === 'Build from Kraftfile') { + buildFromYaml(kraftChannel, kraftStatusBarItem, projectPath); + } else { + configureInteractively(projectPath); + } +} + +async function buildFromYaml( + kraftChannel: OutputChannel, + kraftStatusBarItem: StatusBarItem, + projectPath: string +) { + const kraftYaml = getKraftYaml(projectPath); + if (kraftYaml.targets == undefined || kraftYaml.targets.length == 0) { + showErrorMessage(kraftChannel, kraftStatusBarItem, 'Build error: No target found in Kraftfile.'); + return; + } + const targets = kraftYaml.targets.map((target: { architecture: any; platform: any; }) => + `${target.platform}-${target.architecture}`); + const target = await window.showQuickPick( + targets, + { placeHolder: 'Choose the target' } + ); + if (!target) { + showErrorMessage(kraftChannel, kraftStatusBarItem, 'Build error: No matching target.'); + return; + } + + const splitTarget = target.split('-'); + + let sourcesDir = getSourcesDir(); + let manifestsDir = getManifestsDir(); const command = new Command( - 'kraft build --no-progress', + `kraft build -p ${splitTarget[0]} -m ${splitTarget[1]}`, { cwd: projectPath, - env: Object.assign(process.env, { 'UK_WORKDIR': getUkWorkdir() }), - + env: Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': sourcesDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }), }, 'Built project.' ); - kraftStatusBarItem.text = 'Building project...'; + showInfoMessage(kraftChannel, kraftStatusBarItem, + "Building project..." + ) try { command.execute(kraftChannel, kraftStatusBarItem); } catch (error) { - kraftStatusBarItem.text = '[Error] Build project'; - kraftChannel.appendLine(`[Error] Build project ${error}.`); + showErrorMessage(kraftChannel, kraftStatusBarItem, + `[Error] Build project ${error}.` + ) } } + +async function configureInteractively(projectPath: string) { + let sourcesDir = getSourcesDir(); + let manifestsDir = getManifestsDir(); + let terminal = window.createTerminal({ + name: "kraft build", + cwd: projectPath, + hideFromUser: false, + env: Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': sourcesDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }) + }); + terminal.show(); + terminal.sendText('kraft build 2> /tmp/err_kraft_build'); +} diff --git a/src/commands/configure.ts b/src/commands/configure.ts index 162b8e0..70edda5 100644 --- a/src/commands/configure.ts +++ b/src/commands/configure.ts @@ -1,93 +1,42 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -import { ExtensionContext, OutputChannel, StatusBarItem, window } from 'vscode'; -import { existsSync, readFileSync } from 'fs'; -import { join } from 'path'; -import { getProjectPath, getUkWorkdir } from './utils'; -import { Command } from './Command'; - -const yaml = require('js-yaml'); +import { OutputChannel, StatusBarItem, window } from 'vscode'; +import { getProjectPath, showErrorMessage, getSourcesDir, getManifestsDir, showInfoMessage } from './utils'; export async function kraftConfigure( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem, - context: ExtensionContext ) { + kraftChannel.show(true); // TODO: automatically update kraft.yaml syntax using a kraft command const projectPath = getProjectPath(); + let sourceDir = getSourcesDir() + let manifestsDir = getManifestsDir() if (!projectPath) { - kraftChannel.appendLine('No workspace.'); - return; - } - - const type = await window.showQuickPick( - ['from kraft.yaml', 'interactive'], - { placeHolder: 'Configuration type' } - ); - if (!type) { + showErrorMessage(kraftChannel, kraftStatusBarItem, 'Configure error: No workspace.') return; } - kraftStatusBarItem.text = 'Configuring project...'; + showInfoMessage(kraftChannel, kraftStatusBarItem, + "Configuring project..." + ) try { - if (type === 'from kraft.yaml') { - configureFromYaml( - kraftChannel, - kraftStatusBarItem, - projectPath - ); - } else if (type === 'interactive') { - configureInteractively(context); - } + let terminal = window.createTerminal({ + name: "kraft menu", + cwd: projectPath, + hideFromUser: false, + env: Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': sourceDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }) + }); + terminal.show(); + terminal.sendText('kraft menu 2> /tmp/err_kraft_configure'); } catch (error) { - kraftStatusBarItem.text = '[Error] Configure project'; - kraftChannel.appendLine(`[Error] Configure project ${error}.`); + showErrorMessage(kraftChannel, kraftStatusBarItem, + `[Error] Configure project ${error}.` + ) } } - -async function configureFromYaml( - kraftChannel: OutputChannel, - kraftStatusBarItem: StatusBarItem, - projectPath: string -) { - const kraftYamlPath = join(projectPath, 'kraft.yaml'); - if (!existsSync(kraftYamlPath)) { - kraftChannel.appendLine('No kraft.yaml'); - return; - } - - const kraftYaml = yaml.load(readFileSync(kraftYamlPath, 'utf-8')); - const target = await window.showQuickPick( - kraftYaml.targets.map((target: { architecture: any; platform: any; }) => - `${target.platform}-${target.architecture}`), - { placeHolder: 'Choose the target' } - ); - if (!target) { - return; - } - - const splitTarget = target.split('-'); - - const command = new Command( - `kraft configure -F -p ${splitTarget[0]} -m ${splitTarget[1]}`, - { - cwd: projectPath, - env: Object.assign(process.env, { 'UK_WORKDIR': getUkWorkdir() }) - }, - 'Configured project.' - ); - - command.execute(kraftChannel, kraftStatusBarItem); -} - -async function configureInteractively(context: ExtensionContext) { - let terminal = window.createTerminal({ - name: "kraft menuconfig", - hideFromUser: false, - shellPath: context.asAbsolutePath(join('src', - 'scripts', - 'configure.sh')), - }); - terminal.show(); -} diff --git a/src/commands/initialize.ts b/src/commands/initialize.ts index 248cee7..f76231e 100644 --- a/src/commands/initialize.ts +++ b/src/commands/initialize.ts @@ -1,44 +1,52 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -import { ConfigurationTarget, OutputChannel, StatusBarItem, window } from 'vscode'; +import { OutputChannel, StatusBarItem, window } from 'vscode'; import { join } from 'path'; import { execSync } from 'child_process'; -import { getProjectPath, refreshViews, updateUkWorkdir } from './utils'; +import { getProjectPath, getSourcesDir, getManifestsDir, refreshViews, getDefaultFileNames, showErrorMessage, getKraftYaml, getKraftYamlPath, showInfoMessage } from './utils'; import { Command } from './Command'; -import { homedir } from 'os'; import { setupLangSupport } from '../language/language'; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; +import { homedir } from 'os'; + +const YAML = require('yaml') export async function kraftInitialize( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem ) { + kraftChannel.show(true); const projectPath = getProjectPath(); if (!projectPath) { kraftChannel.appendLine('No workspace.'); return; } + // Deleted 'application' option from the below quickPick as command `kraft init` + // is not available in `Kraftkit`, Once command is available in `Kraftkit`. + // Please add in below quickPick. const type = await window.showQuickPick( - ['application', 'library', 'core'], - { placeHolder: 'application, library or core', } + ['library'], + { placeHolder: 'library', } ); if (!type) { return; } - kraftStatusBarItem.text = 'Initializing project...'; + showInfoMessage(kraftChannel, kraftStatusBarItem, + "Initializing project..." + ) try { if (type === 'library') { initializeLibrary(projectPath, kraftChannel, kraftStatusBarItem); } else if (type === 'application') { initializeApplication(projectPath, kraftChannel, kraftStatusBarItem); - } else if (type === 'core') { - initializeCore(projectPath, kraftChannel, kraftStatusBarItem); } } catch (error) { - kraftStatusBarItem.text = '[Error] Initialize project'; - kraftChannel.appendLine(`[Error] Initialize project ${error}.`); + showErrorMessage(kraftChannel, kraftStatusBarItem, + `[Error] Initialize project ${error}.` + ) } } @@ -47,69 +55,94 @@ async function initializeApplication( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem, ) { - const ukWorkdir = await chooseUkWorkdir(projectPath); - if (!ukWorkdir) { - return; - } - - const options = { - cwd: projectPath, - env: Object.assign(process.env, { 'UK_WORKDIR': ukWorkdir }) - }; - const commands = [new Command( - 'kraft list pull unikraft@staging', - options, - 'Pulled unikraft.' - )]; - - const template = await window.showQuickPick( - ['Use existing template', 'Blank application'] - ); - if (!template) { - return; - } - - if (template === 'Use existing template') { - var apps; - try { - apps = getApps(ukWorkdir); - } catch (error) { - kraftChannel.appendLine('Error: Cannot list application templates'); - return; - } - - const appTemplate = await window.showQuickPick( - apps, - { placeHolder: 'Choose the application template' } - ); - if (!appTemplate) { - return; - } - - commands.push(new Command( - `kraft init -F -M -t ${appTemplate}`, - options, - `Initialized ${appTemplate} application.`, - () => { - refreshViews(); - updateUkWorkdir(ukWorkdir, ConfigurationTarget.Workspace); - setupLangSupport(projectPath); - } - )); - } else { - commands.push(new Command( - `kraft init -F -M`, - options, - `Initialized blank application.`, - () => { - refreshViews(); - updateUkWorkdir(ukWorkdir, ConfigurationTarget.Workspace); - setupLangSupport(join(projectPath)); - } - )); - } - - commands[0].execute(kraftChannel, kraftStatusBarItem, commands.slice(1)); + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "Creating application template is not possible as command `kraft init` is not available in the `kraftkit`." + ) + + // Uncomment below code once `kraft init` is available in `kraftkit`. + + // const initWorkdir = await chooseInitWorkdir(); + // if (!initWorkdir) { + // return; + // } + + // let appsPath + // if (initWorkdir.endsWith('.unikraft')) { + // appsPath = join(initWorkdir, 'apps'); + // } else { + // appsPath = join(initWorkdir, 'sources'); + // } + + // let sourcesDir = getSourcesDir(); + // let manifestsDir = getManifestsDir(); + // let kraftEnv = Object.assign(process.env, { + // 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + // 'KRAFTKIT_PATHS_SOURCES': sourcesDir, + // 'KRAFTKIT_NO_CHECK_UPDATES': true + // }) + // const commands = [new Command( + // 'kraft pkg pull unikraft@staging', + // { cwd: projectPath, env: kraftEnv }, + // 'Pulled unikraft.' + // )]; + + // const template = await window.showQuickPick( + // ['Use existing template', 'Blank application'] + // ); + // if (!template) { + // return; + // } + + // if (template === 'Use existing template') { + // var apps; + // try { + // apps = getApps(ukPackWorkdir); + // if (apps.length == 0) { + // kraftChannel.appendLine('Not found any application template'); + // return + // } + // } catch (error) { + // kraftChannel.appendLine('Error: Cannot list application templates'); + // return; + // } + + // const appTemplate = await window.showQuickPick( + // apps, + // { placeHolder: 'Choose the application template' } + // ); + // if (!appTemplate) { + // return; + // } + + + // commands.push(new Command( + // `kraft init -F -M -t ${appTemplate}`, + // {cwd: appsPath, env: kraftEnv}, + // `Initialized ${appTemplate} application.`, + // () => { + // refreshViews(); + // updateUkPackWorkdir(ukPackWorkdir, ConfigurationTarget.Workspace); + // setupLangSupport(projectPath); + // } + // )); + + // } else { + + // commands.push(new Command( + // `kraft init -F -M`, + // {cwd: appsPath, env: kraftEnv}, + // `Initialized blank application.`, + // () => { + // refreshViews(); + // updateUkPackWorkdir(ukPackWorkdir, ConfigurationTarget.Workspace); + // setupLangSupport(join(projectPath)); + // } + // )); + // } + + // commands[0].execute(kraftChannel, kraftStatusBarItem, commands.slice(1)); return; } @@ -119,16 +152,43 @@ async function initializeLibrary( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem ) { - const ukWorkdir = await chooseUkWorkdir(projectPath); - if (!ukWorkdir) { + const initWorkdir = await chooseInitWorkdir(); + if (!initWorkdir) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + `No path specified.` + ); return; } - const libsPath = join(ukWorkdir, 'libs'); + let libsPath = initWorkdir + let isProjectPathUnikraft = false + if (initWorkdir.includes(join(projectPath, '.unikraft'))) { + libsPath = join(initWorkdir, 'libs'); + isProjectPathUnikraft = true; + } - const kraftEnv = Object.assign(process.env, { 'UK_WORKDIR': ukWorkdir }); - const commands = [new Command( - 'kraft list pull unikraft@staging', + if (!isProjectPathUnikraft && !existsSync(libsPath)) { + mkdirSync(libsPath, { recursive: true }); + window.showInformationMessage(`Created directory ${libsPath}`); + } + + if (!isProjectPathUnikraft && !existsSync(libsPath)) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + `Cound not create directory ${libsPath}.` + ); + return + } + + let sourcesDir = getSourcesDir(); + let manifestsDir = getManifestsDir(); + const kraftEnv = Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': sourcesDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }); + + const commands = [new Command( + 'kraft pkg pull unikraft:staging', { cwd: projectPath, env: kraftEnv }, 'Pulled unikraft.' )]; @@ -168,90 +228,81 @@ async function initializeLibrary( return; } + // This command creates a new library and package the created library. commands.push(new Command( - `kraft lib init --no-prompt` - + ` --author-name "${authorName}"` - + ` --author-email "${authorEmail}"` - + ` --version ${libVersion}` - + ` --origin ${libOrigin}` - + ` ${libName}`, + `kraft lib create --no-prompt --soft-pack` + + ` --author-name "${authorName}"` + + ` --author-email "${authorEmail}"` + + ` --version ${libVersion}` + + ` --origin ${libOrigin}` + + ` --project-name ${libName}`, { cwd: libsPath, env: kraftEnv }, `Initialized ${libName} library.` )); - commands.push(new Command( - `kraft list add ${join(libsPath, libName)}`, - { env: kraftEnv }, - `Added library to kraft.` - )); - - commands.push(new Command( - `kraft init -F -M`, - { cwd: projectPath, kraftEnv }, - 'Initialized blank application.' - )); - - commands.push(new Command( - `kraft lib add ${libName}@staging`, - { cwd: projectPath, env: kraftEnv }, - `Added library ${libName} to project.`, - () => { - refreshViews(); - updateUkWorkdir(ukWorkdir, ConfigurationTarget.Workspace); - setupLangSupport(join(projectPath)); + if (isProjectPathUnikraft) { + // When creating library at $PWD/.unikraft/ to the project then + // library is initialized at the location `$PWD/.unikraft/libs/` + // therefore no need to add the custom created library to the project + // with the command `kraft pkg add` + // Just Updating Kraftfile will work fine. + let kraftYamlPath = getKraftYamlPath(projectPath); + if (!kraftYamlPath) { + return; } - )); - + let kraftYaml = getKraftYaml(projectPath); + if (kraftYaml["libraries"] == undefined) { + kraftYaml["libraries"] = {}; + } + kraftYaml["libraries"][libName] = { + "version": "default" + }; + writeFileSync(kraftYamlPath, YAML.stringify(kraftYaml)); + } else { + commands.push(new Command( + `kraft pkg add ${libName}`, + { cwd: projectPath, env: kraftEnv }, + `Added library ${libName} to the project.`, + () => { + refreshViews(); + setupLangSupport(join(projectPath)); + } + )); + } commands[0].execute(kraftChannel, kraftStatusBarItem, commands.slice(1)); - window.showInformationMessage('Initialized new library.'); + showInfoMessage(kraftChannel, kraftStatusBarItem, + `Initialized new library at the location ${libsPath}.` + ) } -async function initializeCore( - projectPath: string, - kraftChannel: OutputChannel, - kraftStatusBarItem: StatusBarItem -) { - const command = new Command( - 'kraft list pull unikraft@staging', +function getApps(ukPackWorkdir: string): string[] { + const jsonApps = execSync( + 'kraft pkg list --apps -o=json', { - cwd: projectPath, - env: Object.assign(process.env, {'UK_WORKDIR': projectPath}) - }, - 'Initialized new core project.', - () => { - refreshViews(); - updateUkWorkdir(projectPath, ConfigurationTarget.Workspace); - setupLangSupport(projectPath); + env: Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': join(ukPackWorkdir, 'manifests'), + 'KRAFTKIT_PATHS_SOURCES': join(ukPackWorkdir, 'sources'), + 'KRAFTKIT_NO_CHECK_UPDATES': true + }) } - ); - - command.execute(kraftChannel, kraftStatusBarItem); -} + ).toString(); -function getApps(ukWorkdir: string): string[] { - const jsonApps = execSync( - 'kraft list -a -j', - {env: Object.assign(process.env, {'UK_WORKDIR': ukWorkdir})} - ).toString(); + if (jsonApps.trim().toLowerCase() == "null") { + window.showErrorMessage("Not found any existing application.") + return [] + } return JSON.parse(jsonApps) - .applications - .map((app: { meta: { name: any; }; }) => app.meta.name) + .map((app: { format: string, latest: string, package: string, type: string }) => app.package) .sort(); } -async function chooseUkWorkdir(projectPath: string): Promise { - const ukWorkdirLocation = await window.showQuickPick( - ['Use local', 'Use global'], - { placeHolder: 'Choose UK_WORKDIR location' } - ); - if (!ukWorkdirLocation) { - return; - } - - if (ukWorkdirLocation === 'Use local') - return join(projectPath, '.unikraft'); +async function chooseInitWorkdir(): Promise { + let path = window.showInputBox({ + placeHolder: `Insert path where to initialize library`, + value: homedir() + }); - return join(homedir(), '.unikraft'); + return path; } diff --git a/src/commands/run.ts b/src/commands/run.ts index 97d4f4e..ffe4334 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -1,141 +1,136 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -import { ExtensionContext, OutputChannel, StatusBarItem, window, workspace } from 'vscode'; +import { OutputChannel, StatusBarItem, window, workspace } from 'vscode'; import { existsSync, readFileSync } from 'fs'; import { basename, join } from 'path'; -import { getProjectPath, getUkWorkdir } from './utils'; -import * as net from 'net'; +import { getProjectPath, getSourcesDir, getManifestsDir, getDefaultFileNames, showErrorMessage, getKraftYaml, showInfoMessage } from './utils'; const yaml = require('js-yaml'); export async function kraftRun( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem, - context: ExtensionContext ) { + kraftChannel.show(true); const projectPath = getProjectPath(); if (!projectPath) { - kraftChannel.appendLine('No workspace.'); + showErrorMessage(kraftChannel, kraftStatusBarItem, 'Run error: no workspace.'); return; } - const target = await getTarget(kraftChannel, projectPath); - if (!target) { - return; - } + const target = await getTarget(kraftChannel, kraftStatusBarItem, projectPath); + if (!target) { + return; + } const splitTarget = target.split('-'); - const bridgeName = workspace.getConfiguration() - .get('unikraft.bridge_name', 'virbr0'); - var runArgs = `-p ${splitTarget[0]} -m ${splitTarget[1]}`; + var runArgs = `--plat ${splitTarget[0]} -m ${splitTarget[1]}`; + + const symbolic = workspace.getConfiguration().get('unikraft.symbolic', false); + if (symbolic) { + runArgs += ' --symbolic'; + } - const debug = workspace.getConfiguration().get('unikraft.debug', false); - if (debug) { + const disableAccel = workspace.getConfiguration().get('unikraft.disableAccel', false); + if (disableAccel) { + runArgs += ' -W'; + } + + const detach = workspace.getConfiguration().get('unikraft.detach', false); + if (detach) { runArgs += ' -d'; } - const paused = workspace.getConfiguration().get('unikraft.paused', false); - if (paused) { - runArgs += ' -P'; + const remove = workspace.getConfiguration().get('unikraft.remove', false); + if (remove) { + runArgs += ' --rm'; } - const gdb = workspace.getConfiguration().get('unikraft.gdb', false); - if (gdb) { - runArgs += ' -g '; - runArgs += workspace.getConfiguration().get('unikraft.gdb_port', 4123); + const ip = workspace.getConfiguration().get('unikraft.ip', ''); + if (ip !== '') { + runArgs += ' --ip ' + ip; } - const ip = workspace.getConfiguration().get('unikraft.ip4', '172.44.0.2'); - const gateway_ip = workspace.getConfiguration() - .get('unikraft.gateway_ip4', '172.44.0.1'); - const netmask = workspace.getConfiguration() - .get('unikraft.netmask4', '255.255.255.0'); - - const bridged = workspace.getConfiguration().get('unikraft.bridged', false); - if (bridged) { - if (!net.isIPv4(ip)) { - window.showErrorMessage(`Invalid ip address ${ip}.`); - return; - } - - if (!net.isIPv4(gateway_ip)) { - window.showErrorMessage(`Invalid gateway_ip address ${gateway_ip}.`); - return; - } - - if (!net.isIPv4(netmask)) { - window.showErrorMessage(`Invalid netmask ${netmask}.`); - return; - } + const network = workspace.getConfiguration().get('unikraft.network', ''); + if (network !== '') { + runArgs += ' --network ' + network; } - kraftStatusBarItem.text = 'Running project...'; + const memory = workspace.getConfiguration().get('unikraft.memory', ''); + if (memory !== '') { + runArgs += ' -M ' + memory; + } - const create_bridge = workspace.getConfiguration() - .get('unikraft.create_bridge', false); + const ports = workspace.getConfiguration().get('unikraft.ports', []); + if (ports.length > 0) { + runArgs += ' --port'; + ports.forEach(element => { + runArgs += " " + element; + }); + } + showInfoMessage(kraftChannel, kraftStatusBarItem, + "Running project..." + ) try { + let sourcesDir = getSourcesDir(); + let manifestsDir = getManifestsDir(); const terminal = window.createTerminal({ name: "kraft run", cwd: projectPath, hideFromUser: false, - shellPath: context.asAbsolutePath(join('src', 'scripts', 'run.sh')), - shellArgs: - create_bridge ? [runArgs, bridgeName, gateway_ip, netmask, ip, '1'] : - bridged ? [runArgs, bridgeName, gateway_ip, netmask, ip] : - [runArgs], - env: Object.assign(process.env, { 'UK_WORKDIR': getUkWorkdir() }) + env: Object.assign(process.env, { + 'KRAFTKIT_PATHS_MANIFESTS': manifestsDir, + 'KRAFTKIT_PATHS_SOURCES': sourcesDir, + 'KRAFTKIT_NO_CHECK_UPDATES': true + }) }); terminal.show(); + terminal.sendText(`kraft run ${runArgs}`); } catch (error) { - kraftStatusBarItem.text = '[Error] Run project'; - kraftChannel.appendLine(`[Error] Run project ${error}.`); + showErrorMessage(kraftChannel, kraftStatusBarItem, + `[Error] Run project ${error}.` + ) } } -async function getName( - kraftChannel: OutputChannel, - projectPath: string -): Promise { - const kraftYamlPath = join(projectPath, 'kraft.yaml'); - if (!existsSync(kraftYamlPath)) { - kraftChannel.appendLine('No kraft.yaml'); - return; - } - - const kraftYaml = yaml.load(readFileSync(kraftYamlPath, 'utf-8')); - - return kraftYaml.name; -} - async function getTarget( - kraftChannel: OutputChannel, - projectPath: string + kraftChannel: OutputChannel, + kraftStatusBarItem: StatusBarItem, + projectPath: string ): Promise { - const kraftYamlPath = join(projectPath, 'kraft.yaml'); - if (!existsSync(kraftYamlPath)) { - kraftChannel.appendLine('No kraft.yaml'); - return; - } - - const kraftYaml = yaml.load(readFileSync(kraftYamlPath, 'utf-8')); - const targets = kraftYaml.targets + const kraftYaml = getKraftYaml(projectPath); + if (kraftYaml.targets == undefined || kraftYaml.targets.length == 0) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + 'Run error: no target found in Kraftfile' + ); + return; + } + const targets: string[] = kraftYaml.targets .map((target: { architecture: any; platform: any; }) => `${target.platform}-${target.architecture}`) .filter((target: string) => existsSync(join( projectPath, + '.unikraft', 'build', `${basename(projectPath)}_${target}` ) - ) + ) + ); + + if (targets.length == 0) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + 'Run error: No matching builts found.' + ); + return; + } + + const target = await window.showQuickPick( + targets, + { placeHolder: 'Choose the target' } ); - const target = await window.showQuickPick( - targets, - { placeHolder: 'Choose the target' } - ); - return target; } diff --git a/src/commands/update.ts b/src/commands/update.ts index 4401f7d..7cad084 100644 --- a/src/commands/update.ts +++ b/src/commands/update.ts @@ -2,23 +2,25 @@ import { OutputChannel, StatusBarItem } from 'vscode'; import { Command } from './Command'; -import { getGithubToken } from './utils'; +import { showInfoMessage } from './utils'; export async function kraftUpdate( kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem ) { + kraftChannel.show(true); const command = new Command( - `kraft list update`, + `kraft pkg update`, { env: Object.assign( - process.env, - { 'UK_KRAFT_GITHUB_TOKEN': getGithubToken() }) + process.env) }, - 'Finished running kraft list update.' + 'Finished running kraft pkg update.' ); - kraftStatusBarItem.text = 'kraft list update...'; + showInfoMessage(kraftChannel, kraftStatusBarItem, + "kraft pkg update..." + ) command.execute(kraftChannel, kraftStatusBarItem); } diff --git a/src/commands/utils.ts b/src/commands/utils.ts index b24268f..712e810 100644 --- a/src/commands/utils.ts +++ b/src/commands/utils.ts @@ -1,54 +1,150 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -import { ConfigurationTarget, OutputChannel, commands, window, workspace } from 'vscode'; +import { OutputChannel, StatusBarItem, commands, workspace, window } from 'vscode'; +import { join } from 'path'; +import { homedir, } from 'os'; +import { env } from 'process' +import { readFileSync, existsSync, writeFileSync, rmdirSync } from 'fs'; +const yaml = require('js-yaml'); +const YAML = require('yaml') export function getProjectPath(): string | undefined { return (workspace.workspaceFolders && (workspace.workspaceFolders.length > 0)) - ? workspace.workspaceFolders[0].uri.fsPath : undefined; + ? workspace.workspaceFolders[0].uri.fsPath : undefined; } -export function getUkWorkdir(): string { - return workspace.getConfiguration() - .get('unikraft.ukWorkdir', ''); +export function getDefaultFileNames() { + return [ + "kraft.yaml", + "kraft.yml", + "Kraftfile.yml", + "Kraftfile.yaml", + "Kraftfile", + ] } -export async function updateUkWorkdir( - ukWorkdir: string, - scope=ConfigurationTarget.Global -) { - await workspace.getConfiguration().update( - 'unikraft.ukWorkdir', - ukWorkdir, - scope - ); +export function getSourcesDir(): string { + let sourcesDir: string = workspace.getConfiguration() + .get('unikraft.sources', ''); + if (sourcesDir === '') { + sourcesDir = env.KRAFTKIT_PATHS_SOURCES ? env.KRAFTKIT_PATHS_SOURCES : '' + } + if (sourcesDir === '') { + sourcesDir = getKraftkitConfigYAML().paths.sources + } + return sourcesDir; } -export function getGithubToken(): string { - return workspace.getConfiguration().get('unikraft.githubToken', ''); +export function getManifestsDir(): string { + let manifestDir: string = workspace.getConfiguration() + .get('unikraft.manifests', ''); + if (manifestDir === '') { + manifestDir = env.KRAFTKIT_PATHS_MANIFESTS ? env.KRAFTKIT_PATHS_MANIFESTS : ''; + } + if (manifestDir === '') { + manifestDir = getKraftkitConfigYAML().paths.manifests; + } + return manifestDir; } -export async function updateGithubToken(kraftChannel: OutputChannel) -: Promise { - var githubToken; - - while (!githubToken) { - githubToken = await window.showInputBox({ - placeHolder: `Insert your Gihub token`, - }); +export function getKraftYamlPath(projectPath: string): string | undefined { + let kraftYamlPath = ""; + getDefaultFileNames().forEach(element => { + let temPath = join(projectPath, element) + if (existsSync(temPath)) { + kraftYamlPath = temPath + } + }); + if (kraftYamlPath == "") { + return undefined } + return kraftYamlPath; +} - await workspace.getConfiguration().update( - 'unikraft.githubToken', - githubToken, - ConfigurationTarget.Global - ); +export function getKraftYaml(projectPath: string): any { + let kraftYamlPath = getKraftYamlPath(projectPath) - kraftChannel.appendLine('Edited the Github token.'); + if (!kraftYamlPath) { + return {} + } - return githubToken; + return yaml.load(readFileSync(kraftYamlPath, 'utf-8')); +} + +export function getKraftkitConfigYAML(): { + paths: { + sources: string, + manifests: string + } +} { + return yaml.load(readFileSync(join(homedir(), '.config/kraftkit/config.yaml'), 'utf-8')) } export function refreshViews() { commands.executeCommand('externalLibraries.refreshEntry'); } + +export function removeCoreProjectDir( + kraftChannel: OutputChannel, + kraftStatusBarItem: StatusBarItem, + projectPath: string +) { + if (existsSync(join(projectPath, '.unikraft', 'unikraft'))) { + rmdirSync(join(projectPath, '.unikraft', 'unikraft'), { recursive: true }); + showInfoMessage(kraftChannel, kraftStatusBarItem, + "Unikraft core has been removed from the project successfully." + ) + } else { + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "unikraft core is not present in the project" + ); + } +} + +export function removeCore( + kraftChannel: OutputChannel, + kraftStatusBarItem: StatusBarItem, + projectPath: string +) { + if (!projectPath) { + showErrorMessage( + kraftChannel, + kraftStatusBarItem, + "No workspace." + ); + return; + } + + let kraftYamlPath = getKraftYamlPath(projectPath); + if (!kraftYamlPath) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + "Kraftfile not found." + ); + return; + } + let kraftYaml = getKraftYaml(projectPath); + if (!kraftYaml["unikraft"]) { + showErrorMessage(kraftChannel, kraftStatusBarItem, + "Unikraft core is already not present in the project." + ) + } else { + kraftYaml["unikraft"] = undefined; + } + writeFileSync(kraftYamlPath, YAML.stringify(kraftYaml)); + removeCoreProjectDir(kraftChannel, kraftStatusBarItem, projectPath); +} + +export function showInfoMessage(kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem, msg: string) { + kraftStatusBarItem.text = msg; + kraftChannel.appendLine(msg); + // window.showInformationMessage(msg); +} + +export function showErrorMessage(kraftChannel: OutputChannel, kraftStatusBarItem: StatusBarItem, msg: string) { + kraftStatusBarItem.text = msg; + kraftChannel.appendLine(msg); + window.showErrorMessage(msg); +} diff --git a/src/language/c.ts b/src/language/c.ts index 28b8f9b..c560225 100644 --- a/src/language/c.ts +++ b/src/language/c.ts @@ -9,13 +9,18 @@ import { existsSync, readFileSync } from "fs"; const yaml = require('js-yaml'); export async function reloadIncludes(projectPath?: string) { - var includeFiles = getAllFiles(join(utils.getUkWorkdir(), 'unikraft')); + if (!projectPath) { + return; + } + + const projectUnikraft = join(projectPath, '.unikraft') + var includeFiles = getAllFiles(join(projectUnikraft, 'unikraft')); if (projectPath) { const libPaths = getLibFiles( projectPath, - join(utils.getUkWorkdir(), 'libs' - )); + join(projectUnikraft, 'libs') + ); libPaths.forEach(lib => includeFiles = includeFiles.concat(getAllFiles(lib))); } @@ -71,20 +76,27 @@ export async function setupCSupport(projectPath?: string) { } function getKraftYamlConfig(projectPath: string): string[] { + let kraftYamlPath = ""; + utils.getDefaultFileNames().forEach(element => { + let temPath = join(projectPath, element) + if (existsSync(temPath)) { + kraftYamlPath = temPath + } + }); const kraftYaml = yaml.load( - readFileSync(join(projectPath, 'kraft.yaml'), 'utf-8')); + readFileSync(kraftYamlPath, 'utf-8')); - const ukConfig = Object.keys(kraftYaml).includes('unikraft') - && Object.keys(kraftYaml.unikraft).includes('kconfig') ? + const ukConfig = Object.keys(kraftYaml).includes('unikraft') + && Object.keys(kraftYaml.unikraft).includes('kconfig') ? kraftYaml.unikraft.kconfig : []; const kraftLibs = Object.keys(kraftYaml).includes('libraries') ? Object.keys(kraftYaml.libraries).flatMap(lib => - Object.keys(kraftYaml.libraries[lib]).includes('kconfig') ? - kraftYaml.libraries[lib].kconfig : - []) : - []; + Object.keys(kraftYaml.libraries[lib]).includes('kconfig') ? + kraftYaml.libraries[lib].kconfig : + []) : + []; return kraftLibs.concat(ukConfig); } diff --git a/src/language/utils.ts b/src/language/utils.ts index f564de1..049b68b 100644 --- a/src/language/utils.ts +++ b/src/language/utils.ts @@ -1,7 +1,9 @@ /* SPDX-License-Identifier: BSD-3-Clause */ import { join } from 'path'; -import { readdirSync, readFileSync, statSync } from "fs"; +import { existsSync, readdirSync, readFileSync, statSync } from "fs"; +import * as utils from './../commands/utils'; + const yaml = require('js-yaml'); @@ -11,8 +13,15 @@ export function getLibFiles(projectPath: string, libsPath: string): string[] { } export function getKraftYamlLibs(projectPath: string): string[] { + let kraftYamlPath = ""; + utils.getDefaultFileNames().forEach(element => { + let temPath = join(projectPath, element) + if (existsSync(temPath)) { + kraftYamlPath = temPath + } + }); const kraftYaml = yaml.load( - readFileSync(join(projectPath, 'kraft.yaml'), 'utf-8')); + readFileSync(join(kraftYamlPath), 'utf-8')); const kraftLibs = Object.keys(kraftYaml).includes('libraries') ? Object.keys(kraftYaml.libraries) : []; diff --git a/src/scripts/configure.sh b/src/scripts/configure.sh deleted file mode 100644 index 84e5084..0000000 --- a/src/scripts/configure.sh +++ /dev/null @@ -1 +0,0 @@ -kraft menuconfig 2> /tmp/err_kraft_configure diff --git a/src/scripts/run.sh b/src/scripts/run.sh deleted file mode 100644 index 24ba987..0000000 --- a/src/scripts/run.sh +++ /dev/null @@ -1,26 +0,0 @@ -if [ $# -eq 6 ]; then - echo "Setup bridge $2" - sudo brctl addbr $2 - sudo ip a a $3/$4 dev $2 - sudo ip l set dev $2 up -fi - -if [ $# -eq 1 ]; then - echo "Executing kraft run $1" - kraft run $1 -fi - -if [ $# -ne 1 ]; then - echo "Executing kraft run $1 -b $2 \"netdev.ipv4_addr=$5 netdev.ipv4_gw_addr=$3 netdev.ipv4_subnet_mask=$4 -- \"" - kraft run $1 -b $2 "netdev.ipv4_addr=$5 netdev.ipv4_gw_addr=$3 netdev.ipv4_subnet_mask=$4 -- " -fi - -echo "Done executing kraft run" - -if [ $# -eq 6 ]; then - echo "Cleanup bridge $2" - sudo ip l set dev $2 down - sudo brctl delbr $2 -fi - -sleep 20