Skip to content

Commit

Permalink
Merge pull request #83 from AdaptiveScale/lxdui-2.0
Browse files Browse the repository at this point in the history
Lxdui 2.0
  • Loading branch information
ailegion authored Apr 6, 2018
2 parents ee0198f + 865fe73 commit ed15784
Show file tree
Hide file tree
Showing 118 changed files with 6,205 additions and 2,378 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.idea/*
conf/lxdui.conf
*.pyc
venv
lxdui.egg-info
build
dist/
LXDUI.egg-info
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
recursive-include lxdui/app_metadata *
recursive-include lxdui/helpers *
recursive-include lxdui/conf *
recursive-include lxdui/static *
recursive-include lxdui/templates *
recursive-include conf *.conf
recursive-include logs *
recursive-include app/ui/static *
recursive-include app/ui/templates *
69 changes: 25 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,26 @@ LXDUI is a Python Flask application that leverages LXD's Python client library,
## Installation

### Prerequisites
The following are the prerequisites required to run LDXUI (supported only on Ubuntu 14 & 16):
- **Python 2.7** (lxdui has not been tested with python3).
- **pip** and some additional modules.
The following are the prerequisites required to run LDXUI (supported only on 16):
- **Python 3.5** (lxdui does not support python2.7 anymore).
- **pip3** and some additional modules.

To install **pip** run:

`sudo apt-get install libfontconfig libffi-dev libssl-dev build-essential python-dev python-pip python-virtualenv -y`
`sudo apt-get install -y python3-pip`

Install the following (required for development)

`sudo apt-get install build-essential libssl-dev libffi-dev python-dev`

- Your must have **LXD 2.3 or higher** already installed.
# Depreciation Notice #
```
The LXD team has deprecated the PPA repos, so if you want to use version 1.0
of LXDUI you'll have to install LXD and LXC from the official backports in the
Ubuntu archive. More information on this is available here:
https://insights.ubuntu.com/2017/11/20/lxd-weekly-status-24-lxd-2-20
Version 2.0 of LXDUI, which is a complete rewrite, is under active development
to fully support the latest snap version of LXD, and once it is released 1.0 will
be deprecated as well. The recommendtion is to wait for the next release
scheduled for the end of March, 2018.
```
If you are on Xenial you can install LXD and LXC via `apt install -t xenial-backports lxd lxd-client`
More on backports here: https://help.ubuntu.com/community/UbuntuBackports
- Your must have **LXD 2.4.4 or higher** already installed.

The following commands will install the latest stable version of LXC/LXD .

- `sudo apt-get install software-properties-common -y`
- `sudo apt-get update -y`
- `sudo apt install -t xenial-backports lxd lxd-client`
- `sudo apt-get update`
- `sudo apt-get install snap`
- `sudo snap install lxd`

**NOTE**:

Expand All @@ -57,21 +47,19 @@ The following are the prerequisites required to run LDXUI (supported only on Ubu
`git clone https://github.com/AdaptiveScale/lxdui.git`

### 2) Install from source
Go into to the `lxdui` directory and execute `sudo python setup.py install`
Go into to the `lxdui` directory and execute `sudo python3 setup.py install`


### 3) Run the app
Run the command to start the server: `sudo lxdui`

**NOTE:**
- `lxdui` requires privileged execution (**sudo**)
- To see the available customizable arguments type: `sudo lxdui -h`
- To start the server as a background process type: `sudo lxdui &`
Run the command to configure the server `lui init`
Run the command to start the server: `lui start`

- To start the server as a background process type: `lui start &`

**Issues you might run into during installation**
> - **ImportError: No module named build_py**.
> - This is a **pip** error, and is easily fixed by re-running the same install command again.
> - This is a **pip** error, adn is easily fixed by re-running the same install command again.
> - **ImportError: No module named connection**
> - **pip** fails to install the correct **urllib3** module according to the required version of the dependencies.
> - `pip show urllib3` might deceive you showing you that the right version is already installed.
Expand All @@ -82,25 +70,18 @@ Run the command to start the server: `sudo lxdui`
> - `git clone --branch 1.8 git://github.com/shazow/urllib3.git`
> - `cd urllib3 && sudo python setup.py install`
## Default configuration
The configuration file `config.json` found within the **conf** directory gets copied to the python's packages designated directory as is, upon each installation.
To change the credentials to be used for authenticatication there are 2 alternatives:
- Permanently via `/conf/config.json` located in python's package directory for `lxdui`
- Temporarily via the **-c** application argument where you specify authentication credentials via the `username`:`password` pattern.
## Install via PIP
Instructions will be made available soon.

## Helpful Info</h1>

- To start the server on a different port with custom authentication credentials use the following command:
- `sudo lxdui -c admin:secret -p 5555 &`
- To stop `lxdui`, find the **process id** using the `ps` command and issue the kill command on that process:
- `ps -ef | grep lxdui`
- To stop `lui`, find the **process id** using the `ps` command and issue the kill command on that process:
- `ps -ef | grep lui`
```
example output:

root 32488 1062 0 10:46 pts/0 00:00:00 sudo lxdui -c admin:secret -p 5555
root 32489 32488 0 10:46 pts/0 00:00:00 /usr/bin/python /usr/local/bin/lxdui -c admin:secret -p 5555
root 32488 1062 0 10:46 pts/0 00:00:00 lui start
root 32489 32488 0 10:46 pts/0 00:00:00 /usr/bin/python3 /usr/local/bin/lui
```
- `sudo kill 32489`

Expand Down
File renamed without changes.
65 changes: 65 additions & 0 deletions app/__metadata__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
APP_NAME = 'LXDUI'
APP_CLI_CMD = 'lui'
VERSION = '2.0-beta'
GIT_URL = 'https://github.com/AdaptiveScale/lxdui.git'
LXD_URL = 'http://localhost:8443'
LICENSE = 'Apache 2.0'
AUTHOR = 'AdaptiveScale, Inc.'
AUTHOR_URL = 'http://www.adaptivescale.com'
AUTHOR_EMAIL = '[email protected]'
KEYWORDS = 'lxc lxc-containers lxd'

'''
The following section is for the default configuration
that will be written to the lxdui.conf file if the file
does not already exist.
'''
AUTO_LOAD_CONFIG = True
DEFAULT_CONFIG_FORMAT = 'ini'
__default_config__ = """
[LXDUI]
lxdui.port = 15151
lxdui.token.expiration = 1200
lxdui.admin.user = admin
lxdui.conf.dir = {{app_root}}/conf
lxdui.conf.file = ${lxdui.conf.dir}/lxdui.conf
lxdui.auth.conf = ${lxdui.conf.dir}/auth.conf
lxdui.ssl.cert = ${lxdui.conf.dir}/client.crt
lxdui.ssl.key = ${lxdui.conf.dir}/client.key
lxdui.log.dir = {{app_root}}/logs
lxdui.log.file = ${lxdui.log.dir}/lxdui.log
#lxdui.log.rotate = true
#lxdui.log.max = 10M
#lxdui.log.keep.generations = 5
lxdui.profiles = ${lxdui.conf.dir}/profiles
lxdui.zfs.pool.name = lxdpool
lxdui.app.alias = LXDUI
lxdui.cli = lui
[LXDUI_CERT]
lxdui.cert.country = US
lxdui.cert.state = Texas
lxdui.cert.locale = Dallas
lxdui.cert.org = AdaptiveScale, Inc.
lxdui.cert.ou = OU=AdaptiveScale, DN=com
[LXD]
lxd.bridge.enabled = true
lxd.bridge.name = lxdbr0
lxd.dns.conf.file =
lxd.dns.domain = lxd
lxd.ipv4.addr = 10.5.5.1
lxd.ipv4.netmask = 255.255.255.0
lxd.ipv4.network = 10.5.5.0/24
lxd.ipv4.dhcp.range = 253
lxd.ipv4.dhcp.max = 10.5.5.2,10.5.5.254
lxd.ipv4.nat = true
lxd.ipv6.addr = 2001:470:b368:4242::1
lxd.ipv6.mask = 255.255.255.0
lxd.ipv6.network = 2001:470:b368:4242::/64
lxd.ipv6.nat = false
lxd.ipv6.proxy = false
"""

File renamed without changes.
File renamed without changes.
161 changes: 161 additions & 0 deletions app/api/controllers/container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
from flask import Blueprint, request
from flask_jwt import jwt_required
from app.api.schemas.container_schema import doValidate, doValidateCloneMove, doValidateImageExport

from app.api.models.LXCContainer import LXCContainer
from app.api.models.LXDModule import LXDModule
from app.api.utils import response

container_api = Blueprint('container_api', __name__)

@container_api.route('/')
@jwt_required()
def containers():
client = LXDModule()
result = []
containers = client.listContainers()
for container in containers:
c = LXCContainer({'name': container.get('name')})
result.append(c.info())
return response.reply(result)


@container_api.route('/<string:name>')
@jwt_required()
def getContainer(name):
try:
container = LXCContainer({'name': name})
return response.replySuccess(container.info())
except ValueError as e:
return response.replyFailed(message=e.__str__())



@container_api.route('/', methods=['POST'])
@jwt_required()
def createContainer():
input = request.get_json(silent=True)
validation = doValidate(input)
if validation:
return response.reply(message=validation.message, status=403)

input = [input] if not isinstance(input, list) else input

try:
result = []
for container in input:
client = LXCContainer(container)
result.append(client.create())
return response.reply(result)
except ValueError as ex:
return response.reply(message=ex.__str__(), status=403)

@container_api.route('/', methods=['PUT'])
@jwt_required()
def updateContainer():
input = request.get_json(silent=True)
validation = doValidate(input)
if validation:
return response.reply(message=validation.message, status=403)

try:
client = LXCContainer(input)
return response.reply(client.update())
except ValueError as ex:
return response.reply(message=ex.__str__(), status=403)


@container_api.route('/<string:name>', methods=['DELETE'])
@jwt_required()
def deleteContainer(name):
input = request.get_json(silent=True)
force = False if input == None else input.get('force')
try:
container = LXCContainer({'name': name})
container.delete(force)
return response.reply(None)
except ValueError as ex:
return response.replyFailed(message=ex.__str__())


@container_api.route('/start/<string:name>', methods=['PUT'])
@jwt_required()
def startContainer(name):
try:
container = LXCContainer({'name': name})
container.start()
return response.replySuccess(container.info())
except ValueError as e:
return response.replyFailed(message=e.__str__())


@container_api.route('/stop/<string:name>', methods=['PUT'])
@jwt_required()
def stopContainer(name):
try:
container = LXCContainer({'name': name})
ephemeral = container.info()['ephemeral']
container.stop()
if ephemeral:
return response.replySuccess(data={}, message='success')
return response.replySuccess(container.info())
except ValueError as e:
return response.replyFailed(message=e.__str__())


@container_api.route('/restart/<string:name>', methods=['PUT'])
@jwt_required()
def restartContainer(name):
try:
container = LXCContainer({'name': name})
container.restart()
return response.replySuccess(container.info())
except ValueError as e:
return response.replyFailed(message=e.__str__())

@container_api.route('/clone/<string:name>', methods=['POST'])
@jwt_required()
def cloneContainer(name):
input = request.get_json(silent=True)
validation = doValidateCloneMove(input)
if validation:
return response.reply(message=validation.message, status=403)

input['name'] = name
try:
container = LXCContainer(input)
return response.replySuccess(container.clone())
except ValueError as e:
return response.replyFailed(message=e.__str__())

@container_api.route('/move/<string:name>', methods=['POST'])
@jwt_required()
def moveContainer(name):
input = request.get_json(silent=True)
validation = doValidateCloneMove(input)
if validation:
return response.reply(message=validation.message, status=403)

input['name'] = name
try:
container = LXCContainer(input)
return response.replySuccess(container.move())
except ValueError as e:
return response.replyFailed(message=e.__str__())


@container_api.route('/export/<string:name>', methods=['POST'])
@jwt_required()
def exportContainer(name):
input = request.get_json(silent=True)
validation = doValidateImageExport(input)
if validation:
return response.reply(message=validation.message, status=403)

force = False if input.get('force') == None else input.get('force')
input['name'] = name
try:
container = LXCContainer(input)
return response.replySuccess(container.export(force))
except ValueError as e:
return response.replyFailed(message=e.__str__())
Loading

0 comments on commit ed15784

Please sign in to comment.