updated install docs to try and be more explicit, updated install tasks to allow forcing an install type override for unsupported OSs
This commit is contained in:
parent
0306f77147
commit
a3d2e6dfe3
2 changed files with 187 additions and 90 deletions
159
docs/install.md
159
docs/install.md
|
@ -1,29 +1,70 @@
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
* Table of Contents
|
* Table of Contents
|
||||||
{:toc}
|
{:toc}
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
CORE provides a script to help automate the installation of dependencies,
|
||||||
|
build and install, and either generate a CORE specific python virtual environment
|
||||||
|
or build and install a python wheel.
|
||||||
|
|
||||||
CORE provides a script to help automate installing all required software
|
### Tools Used
|
||||||
to build and run, including a python virtual environment to run it all in.
|
|
||||||
|
|
||||||
The following tools will be leveraged during installation:
|
The following tools will be leveraged during installation:
|
||||||
|
|
||||||
|Tool|Description|
|
|Tool|Description|
|
||||||
|---|---|
|
|---|---|
|
||||||
|[pip](https://pip.pypa.io/en/stable/)|used to install pipx|
|
|[pip](https://pip.pypa.io/en/stable/)|used to install pipx|
|
||||||
|[pipx](https://pipxproject.github.io/pipx/)|used to install standalone python tools (invoke, poetry)|
|
|[pipx](https://pipxproject.github.io/pipx/)|used to install standalone python tools (invoke, poetry)|
|
||||||
|[invoke](http://www.pyinvoke.org/)|used to run provided tasks (install, daemon, gui, tests, etc)|
|
|[invoke](http://www.pyinvoke.org/)|used to run provided tasks (install, uninstall, reinstall, etc)|
|
||||||
|[poetry](https://python-poetry.org/)|used to install the managed python virtual environment for running CORE|
|
|[poetry](https://python-poetry.org/)|used to install python virtual environment or building a python wheel|
|
||||||
|
|
||||||
## Required Hardware
|
### Files
|
||||||
|
The following is a list of files that would be installed after running the automated installation.
|
||||||
|
|
||||||
|
> **NOTE:** the default install prefix is /usr/local, but can be changed as noted below
|
||||||
|
|
||||||
|
* executable files
|
||||||
|
* <prefix>/bin/{core-daemon, core-gui, vcmd, vnoded, etc}
|
||||||
|
* tcl/tk gui files
|
||||||
|
* <prefix>/lib/core
|
||||||
|
* <prefix>/share/core/icons
|
||||||
|
* example imn files
|
||||||
|
* <prefix>/share/core/examples
|
||||||
|
* python files
|
||||||
|
* poetry virtual env
|
||||||
|
* `cd <repo>/daemon && poetry env info`
|
||||||
|
* ~/.cache/pypoetry/virtualenvs/
|
||||||
|
* local python install
|
||||||
|
* default install path for python3 installation of a wheel
|
||||||
|
* `python3 -c "import core; print(core.__file__)"`
|
||||||
|
* configuration files
|
||||||
|
* /etc/core/{core.conf, logging.conf}
|
||||||
|
* ospf mdr repository files
|
||||||
|
* <repo>/../ospf-mdr
|
||||||
|
* emane repository files
|
||||||
|
* <repo>/../emane
|
||||||
|
|
||||||
|
### Installed Executables
|
||||||
|
After the installation complete it will have installed the following scripts.
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
|---|---|
|
||||||
|
| core-cleanup | tool to help removed lingering core created containers, bridges, directories |
|
||||||
|
| core-cli | tool to query, open xml files, and send commands using gRPC |
|
||||||
|
| core-daemon | runs the backed core server providing TLV and gRPC APIs |
|
||||||
|
| core-gui | runs the legacy tcl/tk based GUI |
|
||||||
|
| core-imn-to-xml | tool to help automate converting a .imn file to .xml format |
|
||||||
|
| core-manage | tool to add, remove, or check for services, models, and node types |
|
||||||
|
| core-pygui | runs the new python/tk based GUI |
|
||||||
|
| core-python | provides a convenience for running the core python virtual environment |
|
||||||
|
| core-route-monitor | tool to help monitor traffic across nodes and feed that to SDT |
|
||||||
|
| core-service-update | tool to update automate modifying a legacy service to match current naming |
|
||||||
|
| coresendmsg | tool to send TLV API commands from command line |
|
||||||
|
|
||||||
|
### Required Hardware
|
||||||
Any computer capable of running Linux should be able to run CORE. Since the physical machine will be hosting numerous
|
Any computer capable of running Linux should be able to run CORE. Since the physical machine will be hosting numerous
|
||||||
containers, as a general rule you should select a machine having as much RAM and CPU resources as possible.
|
containers, as a general rule you should select a machine having as much RAM and CPU resources as possible.
|
||||||
|
|
||||||
## Supported Linux Distributions
|
### Supported Linux Distributions
|
||||||
|
|
||||||
Plan is to support recent Ubuntu and CentOS LTS releases.
|
Plan is to support recent Ubuntu and CentOS LTS releases.
|
||||||
|
|
||||||
Verified:
|
Verified:
|
||||||
|
@ -46,14 +87,14 @@ sudo yum install -y kernel-modules-extra
|
||||||
sudo modprobe sch_netem
|
sudo modprobe sch_netem
|
||||||
```
|
```
|
||||||
|
|
||||||
## Utility Requirements
|
### Utility Requirements
|
||||||
|
The following are known dependencies that will result in errors when not met.
|
||||||
|
|
||||||
* iproute2 4.5+ is a requirement for bridge related commands
|
* iproute2 4.5+ is a requirement for bridge related commands
|
||||||
* ebtables not backed by nftables
|
* ebtables not backed by nftables
|
||||||
|
|
||||||
## Upgrading
|
## Upgrading from Older Release
|
||||||
|
Please make sure to uninstall any previous installations of CORE cleanly
|
||||||
Please make sure to uninstall the previous installation of CORE cleanly
|
|
||||||
before proceeding to install.
|
before proceeding to install.
|
||||||
|
|
||||||
Previous install was built from source:
|
Previous install was built from source:
|
||||||
|
@ -72,92 +113,97 @@ sudo yum remove core
|
||||||
sudo apt remove core
|
sudo apt remove core
|
||||||
```
|
```
|
||||||
|
|
||||||
## Automated Installation
|
## Automated Install
|
||||||
|
The automated install will do the following:
|
||||||
> **NOTE:** installing globally can have issues with dependency conflicts etc
|
|
||||||
|
|
||||||
The automated install will install do the following:
|
|
||||||
* install base tools needed for installation
|
* install base tools needed for installation
|
||||||
* python3, pip, pipx, invoke, poetry
|
* python3, pip, pipx, invoke, poetry
|
||||||
* installs system dependencies for building core
|
* installs system dependencies for building core
|
||||||
* installs latest version of [OPSF MDR](https://github.com/USNavalResearchLaboratory/ospf-mdr)
|
* clone/build/install working version of [OPSF MDR](https://github.com/USNavalResearchLaboratory/ospf-mdr)
|
||||||
* installs core into poetry managed virtual environment or locally, if flag is passed
|
* installs core into poetry managed virtual environment or locally, if flag is passed
|
||||||
* installs scripts pointing to python interpreter being used
|
* installs scripts pointing pointing to appropriate python location based on install type
|
||||||
* installs systemd service, disabled by default
|
* installs systemd service pointing to appropriate python location based on install type
|
||||||
|
|
||||||
After installation has completed you should be able to run the various
|
After installation has completed you should be able to run `core-daemon` and `core-gui`.
|
||||||
CORE scripts for running core.
|
|
||||||
|
|
||||||
> **NOTE:** provide a prefix that will be found on path when running as sudo
|
> **NOTE:** installing locally comes with its own risks, it can result it potential
|
||||||
> if the default prefix is not valid
|
> dependency conflicts with system package manager installed python dependencies
|
||||||
|
|
||||||
|
> **NOTE:** provide a prefix that will be found on path when running as sudo,
|
||||||
|
> if the default prefix /usr/local will not be valid
|
||||||
|
|
||||||
|
`install.sh` will attempt to determine your OS by way of `/etc/os-release`, currently it supports
|
||||||
|
attempts to install OSs that are debian/redhat like (yum/apt).
|
||||||
```shell
|
```shell
|
||||||
# clone CORE repo
|
# clone CORE repo
|
||||||
git clone https://github.com/coreemu/core.git
|
git clone https://github.com/coreemu/core.git
|
||||||
cd core
|
cd core
|
||||||
|
|
||||||
# run install script
|
|
||||||
# script usage: install.sh [-v] [-d] [-l] [-p <prefix>]
|
# script usage: install.sh [-v] [-d] [-l] [-p <prefix>]
|
||||||
#
|
#
|
||||||
# -v enable verbose install
|
# -v enable verbose install
|
||||||
# -d enable developer install
|
# -d enable developer install
|
||||||
# -l enable local install, not compatible with developer install
|
# -l enable local install, not compatible with developer install
|
||||||
# -p install prefix, defaults to /usr/local
|
# -p install prefix, defaults to /usr/local
|
||||||
./install.sh
|
|
||||||
|
# install core to virtual environment
|
||||||
|
./install.sh -p <prefix>
|
||||||
|
|
||||||
|
# install core locally
|
||||||
|
./install.sh -p <prefix> -l
|
||||||
```
|
```
|
||||||
|
|
||||||
### Unsupported Linux Distribution
|
### Unsupported Linux Distribution
|
||||||
|
For unsupported OSs you could attempt to do the following to translate
|
||||||
|
an installation to your use case.
|
||||||
|
|
||||||
If you are on an unsupported distribution, you can look into the
|
* make sure you have python3.6+ with venv support
|
||||||
[install.sh](https://github.com/coreemu/core/blob/master/install.sh)
|
* make sure you have python3 invoke available to leverage `<repo>/tasks.py`
|
||||||
and
|
|
||||||
[tasks.py](https://github.com/coreemu/core/blob/master/tasks.py)
|
|
||||||
files to see the various commands ran to install CORE and translate them to
|
|
||||||
your use case, assuming it is possible.
|
|
||||||
|
|
||||||
If you get install down entirely, feel free to contribute and help others.
|
```shell
|
||||||
|
cd <repo>
|
||||||
|
|
||||||
## Installed Scripts
|
# Usage: inv[oke] [--core-opts] install [--options] [other tasks here ...]
|
||||||
|
#
|
||||||
|
# Docstring:
|
||||||
|
# install core, poetry, scripts, service, and ospf mdr
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -d, --dev install development mode
|
||||||
|
# -i STRING, --install-type=STRING
|
||||||
|
# -l, --local determines if core will install to local system, default is False
|
||||||
|
# -p STRING, --prefix=STRING prefix where scripts are installed, default is /usr/local
|
||||||
|
# -v, --verbose enable verbose
|
||||||
|
|
||||||
After the installation complete it will have installed the following scripts.
|
# install virtual environment
|
||||||
|
inv install -p <prefix>
|
||||||
|
|
||||||
| Name | Description |
|
# indstall locally
|
||||||
|---|---|
|
inv install -p <prefix> -l
|
||||||
| core-cleanup | tool to help removed lingering core created containers, bridges, directories |
|
|
||||||
| core-cli | tool to query, open xml files, and send commands using gRPC |
|
# this will print the commands that would be ran for a given installation
|
||||||
| core-daemon | runs the backed core server providing TLV and gRPC APIs |
|
# type without actually running them, they may help in being used as
|
||||||
| core-gui | runs the legacy tcl/tk based GUI |
|
# the basis for translating to your OS
|
||||||
| core-imn-to-xml | tool to help automate converting a .imn file to .xml format |
|
inv install --dry -v -p <prefix> -i <install type>
|
||||||
| core-manage | tool to add, remove, or check for services, models, and node types |
|
```
|
||||||
| core-pygui | runs the new python/tk based GUI |
|
|
||||||
| core-python | provides a convenience for running the core python virtual environment |
|
|
||||||
| core-route-monitor | tool to help monitor traffic across nodes and feed that to SDT |
|
|
||||||
| core-service-update | tool to update automate modifying a legacy service to match current naming |
|
|
||||||
| coresendmsg | tool to send TLV API commands from command line |
|
|
||||||
|
|
||||||
## Running User Scripts
|
## Running User Scripts
|
||||||
|
|
||||||
If you create your own python scripts to run CORE directly or using the gRPC/TLV
|
If you create your own python scripts to run CORE directly or using the gRPC/TLV
|
||||||
APIs you will need to make sure you are running them within context of the
|
APIs you will need to make sure you are running them within context of the
|
||||||
installed virtual environment. To help support this CORE provides the `core-python`
|
installed virtual environment. To help support this CORE provides the `core-python`
|
||||||
executable. This executable will allow you to enter CORE's python virtual
|
executable. This executable will allow you to enter CORE's python virtual
|
||||||
environment interpreter or to run a script within it.
|
environment interpreter or to run a script within it.
|
||||||
|
|
||||||
> **NOTE:** the following assumes CORE has been installed successfully
|
For installations installed to a virtual environment:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
core-python <script>
|
core-python <script>
|
||||||
```
|
```
|
||||||
|
|
||||||
If CORE was installed locally, then you can run scripts using the default python3
|
For local installations:
|
||||||
interpreter.
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
python3 <script>
|
python3 <script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installing EMANE
|
## Installing EMANE
|
||||||
|
|
||||||
> **NOTE:** installng emane for the virtual environment is known to work for 1.21+
|
> **NOTE:** installng emane for the virtual environment is known to work for 1.21+
|
||||||
> **NOTE:** automated install currently targets 1.25
|
> **NOTE:** automated install currently targets 1.25
|
||||||
|
|
||||||
|
@ -205,7 +251,6 @@ poetry run pip install <EMANE_REPO>/src/python
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using Invoke Tasks
|
## Using Invoke Tasks
|
||||||
|
|
||||||
The invoke tool installed by way of pipx provides conveniences for running
|
The invoke tool installed by way of pipx provides conveniences for running
|
||||||
CORE tasks to help ensure usage of the create python virtual environment.
|
CORE tasks to help ensure usage of the create python virtual environment.
|
||||||
|
|
||||||
|
|
92
tasks.py
92
tasks.py
|
@ -8,7 +8,7 @@ from contextlib import contextmanager
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
|
|
||||||
from invoke import task, Context
|
from invoke import task, Context
|
||||||
|
|
||||||
|
@ -16,6 +16,14 @@ DAEMON_DIR: str = "daemon"
|
||||||
DEFAULT_PREFIX: str = "/usr/local"
|
DEFAULT_PREFIX: str = "/usr/local"
|
||||||
EMANE_CHECKOUT: str = "v1.2.5"
|
EMANE_CHECKOUT: str = "v1.2.5"
|
||||||
OSPFMDR_CHECKOUT: str = "26fe5a4401a26760c553fcadfde5311199e89450"
|
OSPFMDR_CHECKOUT: str = "26fe5a4401a26760c553fcadfde5311199e89450"
|
||||||
|
REDHAT_LIKE = {
|
||||||
|
"redhat",
|
||||||
|
"fedora",
|
||||||
|
}
|
||||||
|
DEBIAN_LIKE = {
|
||||||
|
"ubuntu",
|
||||||
|
"debian",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Progress:
|
class Progress:
|
||||||
|
@ -55,11 +63,28 @@ class Progress:
|
||||||
class OsName(Enum):
|
class OsName(Enum):
|
||||||
UBUNTU = "ubuntu"
|
UBUNTU = "ubuntu"
|
||||||
CENTOS = "centos"
|
CENTOS = "centos"
|
||||||
|
UNKNOWN = "unknown"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, name: str) -> "OsName":
|
||||||
|
try:
|
||||||
|
return OsName(name)
|
||||||
|
except ValueError:
|
||||||
|
return OsName.UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
class OsLike(Enum):
|
class OsLike(Enum):
|
||||||
DEBIAN = "debian"
|
DEBIAN = "debian"
|
||||||
REDHAT = "rhel fedora"
|
REDHAT = "rhel"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, values: List[str]) -> Optional["OsLike"]:
|
||||||
|
for value in values:
|
||||||
|
if value in DEBIAN_LIKE:
|
||||||
|
return OsLike.DEBIAN
|
||||||
|
elif value in REDHAT_LIKE:
|
||||||
|
return OsLike.REDHAT
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class OsInfo:
|
class OsInfo:
|
||||||
|
@ -68,6 +93,22 @@ class OsInfo:
|
||||||
self.like: OsLike = like
|
self.like: OsLike = like
|
||||||
self.version: float = version
|
self.version: float = version
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, name: str, like: List[str], version: Optional[str]) -> "OsInfo":
|
||||||
|
os_name = OsName.get(name)
|
||||||
|
os_like = OsLike.get(like)
|
||||||
|
if not os_like:
|
||||||
|
like = " ".join(like)
|
||||||
|
print(f"unsupported os install type({like})")
|
||||||
|
sys.exit(1)
|
||||||
|
if version:
|
||||||
|
try:
|
||||||
|
version = float(version)
|
||||||
|
except ValueError:
|
||||||
|
print(f"os version is not a float: {version}")
|
||||||
|
sys.exit(1)
|
||||||
|
return OsInfo(os_name, os_like, version)
|
||||||
|
|
||||||
|
|
||||||
def get_python(c: Context, warn: bool = False) -> str:
|
def get_python(c: Context, warn: bool = False) -> str:
|
||||||
with c.cd(DAEMON_DIR):
|
with c.cd(DAEMON_DIR):
|
||||||
|
@ -85,7 +126,12 @@ def get_pytest(c: Context) -> str:
|
||||||
return os.path.join(venv, "bin", "pytest")
|
return os.path.join(venv, "bin", "pytest")
|
||||||
|
|
||||||
|
|
||||||
def get_os() -> OsInfo:
|
def get_os(install_type: Optional[str]) -> OsInfo:
|
||||||
|
if install_type:
|
||||||
|
name_value = OsName.UNKNOWN.value
|
||||||
|
like_value = install_type
|
||||||
|
version_value = None
|
||||||
|
else:
|
||||||
d = {}
|
d = {}
|
||||||
with open("/etc/os-release", "r") as f:
|
with open("/etc/os-release", "r") as f:
|
||||||
for line in f.readlines():
|
for line in f.readlines():
|
||||||
|
@ -97,16 +143,7 @@ def get_os() -> OsInfo:
|
||||||
name_value = d["ID"]
|
name_value = d["ID"]
|
||||||
like_value = d["ID_LIKE"]
|
like_value = d["ID_LIKE"]
|
||||||
version_value = d["VERSION_ID"]
|
version_value = d["VERSION_ID"]
|
||||||
try:
|
return OsInfo.get(name_value, like_value.split(), version_value)
|
||||||
name = OsName(name_value)
|
|
||||||
like = OsLike(like_value)
|
|
||||||
version = float(version_value)
|
|
||||||
except ValueError:
|
|
||||||
print(
|
|
||||||
f"unsupported os({name_value}) like({like_value}) version({version_value}"
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
return OsInfo(name, like, version)
|
|
||||||
|
|
||||||
|
|
||||||
def check_existing_core(c: Context, hide: bool) -> None:
|
def check_existing_core(c: Context, hide: bool) -> None:
|
||||||
|
@ -304,9 +341,13 @@ def install_scripts(c, local=False, verbose=False, prefix=DEFAULT_PREFIX):
|
||||||
"verbose": "enable verbose",
|
"verbose": "enable verbose",
|
||||||
"local": "determines if core will install to local system, default is False",
|
"local": "determines if core will install to local system, default is False",
|
||||||
"prefix": f"prefix where scripts are installed, default is {DEFAULT_PREFIX}",
|
"prefix": f"prefix where scripts are installed, default is {DEFAULT_PREFIX}",
|
||||||
|
"install-type": "used to force an install type, "
|
||||||
|
"can be one of the following (redhat, debian)",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
def install(c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX):
|
def install(
|
||||||
|
c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX, install_type=None
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
install core, poetry, scripts, service, and ospf mdr
|
install core, poetry, scripts, service, and ospf mdr
|
||||||
"""
|
"""
|
||||||
|
@ -315,7 +356,8 @@ def install(c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX):
|
||||||
c.run("sudo -v", hide=True)
|
c.run("sudo -v", hide=True)
|
||||||
p = Progress(verbose)
|
p = Progress(verbose)
|
||||||
hide = not verbose
|
hide = not verbose
|
||||||
os_info = get_os()
|
os_info = get_os(install_type)
|
||||||
|
if not c["run"]["dry"]:
|
||||||
with p.start("checking for old installations"):
|
with p.start("checking for old installations"):
|
||||||
check_existing_core(c, hide)
|
check_existing_core(c, hide)
|
||||||
with p.start("installing system dependencies"):
|
with p.start("installing system dependencies"):
|
||||||
|
@ -342,16 +384,18 @@ def install(c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX):
|
||||||
help={
|
help={
|
||||||
"verbose": "enable verbose",
|
"verbose": "enable verbose",
|
||||||
"local": "used determine if core is installed locally, default is False",
|
"local": "used determine if core is installed locally, default is False",
|
||||||
|
"install-type": "used to force an install type, "
|
||||||
|
"can be one of the following (redhat, debian)",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
def install_emane(c, verbose=False, local=False):
|
def install_emane(c, verbose=False, local=False, install_type=None):
|
||||||
"""
|
"""
|
||||||
install emane and the python bindings
|
install emane and the python bindings
|
||||||
"""
|
"""
|
||||||
c.run("sudo -v", hide=True)
|
c.run("sudo -v", hide=True)
|
||||||
p = Progress(verbose)
|
p = Progress(verbose)
|
||||||
hide = not verbose
|
hide = not verbose
|
||||||
os_info = get_os()
|
os_info = get_os(install_type)
|
||||||
with p.start("installing system dependencies"):
|
with p.start("installing system dependencies"):
|
||||||
if os_info.like == OsLike.DEBIAN:
|
if os_info.like == OsLike.DEBIAN:
|
||||||
c.run(
|
c.run(
|
||||||
|
@ -458,11 +502,19 @@ def uninstall(c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX):
|
||||||
"verbose": "enable verbose",
|
"verbose": "enable verbose",
|
||||||
"local": "determines if core will install to local system, default is False",
|
"local": "determines if core will install to local system, default is False",
|
||||||
"prefix": f"prefix where scripts are installed, default is {DEFAULT_PREFIX}",
|
"prefix": f"prefix where scripts are installed, default is {DEFAULT_PREFIX}",
|
||||||
"branch": "branch to install latest code from, default is current branch"
|
"branch": "branch to install latest code from, default is current branch",
|
||||||
|
"install-type": "used to force an install type, "
|
||||||
|
"can be one of the following (redhat, debian)",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
def reinstall(
|
def reinstall(
|
||||||
c, dev=False, verbose=False, local=False, prefix=DEFAULT_PREFIX, branch=None
|
c,
|
||||||
|
dev=False,
|
||||||
|
verbose=False,
|
||||||
|
local=False,
|
||||||
|
prefix=DEFAULT_PREFIX,
|
||||||
|
branch=None,
|
||||||
|
install_type=None
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
run the uninstall task, get latest from specified branch, and run install task
|
run the uninstall task, get latest from specified branch, and run install task
|
||||||
|
@ -479,7 +531,7 @@ def reinstall(
|
||||||
c.run("git pull", hide=hide)
|
c.run("git pull", hide=hide)
|
||||||
if not Path("tasks.py").exists():
|
if not Path("tasks.py").exists():
|
||||||
raise FileNotFoundError(f"missing tasks.py on branch: {branch}")
|
raise FileNotFoundError(f"missing tasks.py on branch: {branch}")
|
||||||
install(c, dev, verbose, local, prefix)
|
install(c, dev, verbose, local, prefix, install_type)
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
|
|
Loading…
Reference in a new issue