mirror of
https://github.com/clearlinux/python-lkvm.git
synced 2026-06-15 18:15:48 +00:00
+107
@@ -0,0 +1,107 @@
|
||||
|
||||
# Created by https://www.gitignore.io/api/python,emacs,vim
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
|
||||
### Emacs ###
|
||||
# -*- mode: gitignore; -*-
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
|
||||
# Org-mode
|
||||
.org-id-locations
|
||||
*_archive
|
||||
|
||||
# flymake-mode
|
||||
*_flymake.*
|
||||
|
||||
# eshell files
|
||||
/eshell/history
|
||||
/eshell/lastdir
|
||||
|
||||
# elpa packages
|
||||
/elpa/
|
||||
|
||||
# reftex files
|
||||
*.rel
|
||||
|
||||
# AUCTeX auto folder
|
||||
/auto/
|
||||
|
||||
# cask packages
|
||||
.cask/
|
||||
|
||||
|
||||
### Vim ###
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
*.un~
|
||||
Session.vim
|
||||
.netrwhist
|
||||
*~
|
||||
@@ -0,0 +1,4 @@
|
||||
Munoz, Obed N <obed.n.munoz@intel.com>
|
||||
Simental Magana, Marcos <marcos.simental.magana@intel.com>
|
||||
Victor Morales <victor.morales@intel.com>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
CHANGES
|
||||
=======
|
||||
|
||||
* Fix Readme
|
||||
* Add license
|
||||
* Add python logging support
|
||||
* Implement function to get more information about the instances
|
||||
* Implement sandbox method
|
||||
* Implement setup method
|
||||
* Fix identation code
|
||||
* Add example into documentation
|
||||
* Send process to background (the hard way)
|
||||
* Change background process validation
|
||||
* Fix import module (for real)
|
||||
* Fix import lkvm module
|
||||
* Ignore build/ dir
|
||||
* Add setup.py install capability
|
||||
* Add the implementation of balloon method
|
||||
* Change root_helper to string variable
|
||||
* Add root helper property
|
||||
* Add draft is_support function
|
||||
* Add the implementation of stat method
|
||||
* Add the implementation of resume method
|
||||
* Add the implementation of pause method
|
||||
* Add the implementation of stop method
|
||||
* Add the implemention of run method
|
||||
* Add list_instance method implementation
|
||||
* Change name to list_instances
|
||||
* Initial structure
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
Summary
|
||||
===========
|
||||
|
||||
**python-lkvm** is a python wrapper for lkvm command line which exposes its
|
||||
methods through a simple API. This allows other python applications to manage
|
||||
instances.
|
||||
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
As most of python modules, *python-lkvm* can be installed via setuptools: ::
|
||||
|
||||
$ python setup.py install
|
||||
|
||||
Once this module is installed, it can be used their method creating a client
|
||||
instance, for example, for listing existing instances: ::
|
||||
|
||||
import lkvm
|
||||
|
||||
client = lkvm.Client()
|
||||
|
||||
for ins in client.list_instances():
|
||||
print ins.name, ins.state
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2015 Intel Corporation
|
||||
#
|
||||
# Author: Munoz, Obed N <obed.n.munoz@intel.com>
|
||||
# Author: Simental Magana, Marcos <marcos.simental.magana@intel.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
#
|
||||
# Copyright (c) 2015 Intel Corporation
|
||||
#
|
||||
# Author: Morales, Victor <victor.morales@intel.com>
|
||||
# Author: Munoz, Obed N <obed.n.munoz@intel.com>
|
||||
# Author: Simental Magana, Marcos <marcos.simental.magana@intel.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import psutil
|
||||
import six
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
LKVM_PATH='/usr/bin/lkvm'
|
||||
|
||||
logging.basicConfig(format='%(message)s', level=logging.INFO)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
class LKVMException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class LKVMInstance(object):
|
||||
pass
|
||||
|
||||
|
||||
class Client(object):
|
||||
|
||||
def __init__(self):
|
||||
self._root_helper = None
|
||||
|
||||
@property
|
||||
def root_helper(self):
|
||||
return self._root_helper
|
||||
|
||||
@root_helper.setter
|
||||
def root_helper(self, value):
|
||||
self._root_helper = value
|
||||
|
||||
def _get_instance_info(self, pid):
|
||||
if isinstance(pid, six.string_types):
|
||||
pid = int(pid)
|
||||
try:
|
||||
args = psutil.Process(pid).cmdline[2:]
|
||||
except NoSuchProcess:
|
||||
raise LKVMException("PID %s not found" % pid)
|
||||
props = {args[i][2:]: args[i+1] for i in range(0, len(args), 2)}
|
||||
LOG.debug('Properties found : ' + str(props))
|
||||
|
||||
return type('LKVMInstance', (object,), props)
|
||||
|
||||
def _execute(self, cmd, *args, **kwargs):
|
||||
"""Helper method to shell out and execute a command through subprocess.
|
||||
|
||||
:param cmd: Command
|
||||
:type cmd: string
|
||||
:param args: Arguments
|
||||
:type args: string
|
||||
|
||||
"""
|
||||
|
||||
if hasattr(os, 'geteuid') and os.geteuid() != 0 and not self._root_helper:
|
||||
return
|
||||
|
||||
command = [LKVM_PATH]
|
||||
if self._root_helper:
|
||||
command = [self._root_helper] + command
|
||||
command.append(cmd)
|
||||
command.extend(*args)
|
||||
|
||||
command = [str(c) for c in command]
|
||||
|
||||
LOG.debug('Executing command : %s ', command)
|
||||
if kwargs.get('background'):
|
||||
command.insert(0, 'nohup')
|
||||
command = ' '.join(command) + ' >/dev/null 2>&1'
|
||||
subprocess.Popen(command, shell=True)
|
||||
else:
|
||||
_PIPE = subprocess.PIPE
|
||||
obj = subprocess.Popen(command,
|
||||
stdin=_PIPE,
|
||||
stdout=_PIPE,
|
||||
stderr=_PIPE)
|
||||
try:
|
||||
result = obj.communicate()
|
||||
obj.stdin.close()
|
||||
except OSError as err:
|
||||
if isinstance(err, ProcessExecutionError):
|
||||
err_msg = ('{e[description]}\ncommand: {e[cmd]}\n'
|
||||
'exit code: {e[exit_code]}\nstdout: {e[stdout]}\n'
|
||||
'stderr: {e[stderr]}').format(e=err)
|
||||
raise LKVMException(err_msg)
|
||||
if result[1]:
|
||||
raise LKVMException(result[1])
|
||||
|
||||
return result[0]
|
||||
|
||||
def run(self, cpus, mem, shmem, console, kernel, params,
|
||||
network, name=None, disk=None, balloon=False,
|
||||
vnc=False, gtk=False, sdl=False, rng=False,
|
||||
plan9=False, dev=None, tty=None, sandbox=None,
|
||||
hugetlbs=None, initrd=None, firmware=None,
|
||||
no_dhcp=False):
|
||||
"""Start the virtual machine
|
||||
|
||||
:param name: Name of the guest
|
||||
:type name: string
|
||||
:param cpus: Number of CPUs
|
||||
:type cpus: integer
|
||||
:param mem: Virtual machine memory size in MiB.
|
||||
:type mem: integer
|
||||
:param shmem: Share host shmem with guest via pci device
|
||||
:type shmem: string
|
||||
:param disk: Disk image or rootfs directory
|
||||
:type disk: string
|
||||
:param balloon: Enable virtio balloon
|
||||
:type balloon: boolean
|
||||
:param vnc: Enable VNC framebuffer
|
||||
:type vnc: boolean
|
||||
:param gtk: Enable GTK framebuffer
|
||||
:type gtk: boolean
|
||||
:param sdl: Enable SDL framebuffer
|
||||
:type sdl: boolean
|
||||
:param rng: Enable virtio Random Number Generator
|
||||
:type rng: boolean
|
||||
:param plan9: Enable virtio 9p to share files between host and guest
|
||||
:type plan9: boolean
|
||||
:param console: Console to use
|
||||
:type console: string
|
||||
:param dev: KVM device file
|
||||
:type dev: string
|
||||
:param tty: Remap guest TTY into a pty on the host
|
||||
:type tty: string
|
||||
:param sandbox: Run this script when booting into custom rootfs
|
||||
:type sandbox: string
|
||||
:param hugetlbfs: Hugetlbfs path
|
||||
:type hugetlbfs: string
|
||||
:param kernel: Kernel to boot in virtual machine
|
||||
:type kernel: string
|
||||
:param initrd: Initial RAM disk image
|
||||
:type initrd: integer
|
||||
:param params: Kernel command line arguments
|
||||
:type params: string
|
||||
:param firmware: Firmware image to boot in virtual machine
|
||||
:type firmware: string
|
||||
:param network: Create a new guest NIC
|
||||
:type network: string
|
||||
:param no_dhcp: Disable kernel DHCP in rootfs mode
|
||||
:type no_dhcp: boolean
|
||||
|
||||
"""
|
||||
|
||||
_params = []
|
||||
|
||||
# Basic options
|
||||
|
||||
|
||||
_params.extend(['--cpus', cpus,
|
||||
'--mem', mem,
|
||||
'--shmem', shmem])
|
||||
|
||||
if name:
|
||||
_params.extend(['--name', name])
|
||||
if console in ['serial', 'virtio', 'hv']:
|
||||
_params.extend(['--console', console])
|
||||
if balloon:
|
||||
_params.append('--balloon')
|
||||
if vnc:
|
||||
_params.append('--vnc')
|
||||
if gtk:
|
||||
_params.append('--gtk')
|
||||
if sdl:
|
||||
_params.append('--sdl')
|
||||
if rng:
|
||||
_params.append('--rng')
|
||||
if plan9:
|
||||
_params.append('--9p')
|
||||
if disk:
|
||||
_params.extend(['--disk', disk])
|
||||
if dev:
|
||||
_params.extend(['--dev', dev])
|
||||
if tty:
|
||||
_params.extend(['--tty', tty])
|
||||
if sandbox:
|
||||
_params.extend(['--sandbox', sandbox])
|
||||
if hugetlbs:
|
||||
_params.extend(['--hugetlbs', hugetlbs])
|
||||
|
||||
# Kernel options
|
||||
|
||||
_params.extend(['--kernel', kernel,
|
||||
'--params', '"%s"' % params])
|
||||
|
||||
if initrd:
|
||||
_params.extend(['--initrd', initrd])
|
||||
if firmware:
|
||||
_params.extend(['--firmware', firmware])
|
||||
|
||||
# Networking options
|
||||
|
||||
_params.extend(['--network', network])
|
||||
|
||||
if no_dhcp:
|
||||
_params.append('--no-dhcp')
|
||||
|
||||
self._execute('run', _params, background=True)
|
||||
|
||||
def setup(self, name):
|
||||
"""
|
||||
Setup a new virtual machine
|
||||
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
|
||||
"""
|
||||
params = ['--name', name]
|
||||
|
||||
return self._execute('setup', params)
|
||||
|
||||
def pause(self, all=False, name=None):
|
||||
"""Pause the virtual machine
|
||||
|
||||
:param all: Pause all instances
|
||||
:type all: boolean
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
|
||||
"""
|
||||
params = []
|
||||
if all:
|
||||
params.append('--all')
|
||||
elif name:
|
||||
params.extend(['--name', name])
|
||||
else:
|
||||
return
|
||||
|
||||
self._execute('pause', params)
|
||||
|
||||
def resume(self, all=False, name=None):
|
||||
"""Resume the virtual machine
|
||||
|
||||
:param all: Resume all instances
|
||||
:type all: boolean
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
|
||||
"""
|
||||
params = []
|
||||
if all:
|
||||
params.append('--all')
|
||||
elif name:
|
||||
params.extend(['--name', name])
|
||||
else:
|
||||
return
|
||||
|
||||
self._execute('resume', params)
|
||||
|
||||
def list_instances(self, run=True, rootfs=True):
|
||||
"""Print a list of running instances on the host.
|
||||
|
||||
:param run: List running instances
|
||||
:type cmd: boolean
|
||||
:param rootfs: List rootfs instances
|
||||
:type args: boolean
|
||||
|
||||
"""
|
||||
params = []
|
||||
if run:
|
||||
params.append('--run')
|
||||
if rootfs:
|
||||
params.append('--rootfs')
|
||||
|
||||
output = self._execute('list', params)
|
||||
|
||||
instances = []
|
||||
if output:
|
||||
results = output.split('\n')
|
||||
if len(results) > 2 :
|
||||
for result in results[2:-1]:
|
||||
ins = result.split()
|
||||
instance = self._get_instance_info(ins[0])
|
||||
instance.pid = ins[0]
|
||||
instance.name = ins[1]
|
||||
instance.state = ins[2]
|
||||
instances.append(instance)
|
||||
|
||||
return instances
|
||||
|
||||
def balloon(self, name, amount, balloon_options):
|
||||
"""Inflate or deflate the virtio balloon
|
||||
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
:param amount: Amount to inflate/deflate (in MB)
|
||||
:type amount: integer
|
||||
:param ballon_options:
|
||||
|
||||
"""
|
||||
params = ['name', name]
|
||||
if balloon_options == 'inflate':
|
||||
params.extend(['--inflate', amount])
|
||||
elif balloon_options == 'deflate':
|
||||
params.extend(['--deflate', amount])
|
||||
|
||||
self._execute('balloon', params)
|
||||
|
||||
def stop(self, all=False, name=None):
|
||||
"""Stop a running instance
|
||||
|
||||
:param all: Stop all instances
|
||||
:type all: boolean
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
|
||||
"""
|
||||
params = []
|
||||
if all:
|
||||
params.append('--all')
|
||||
elif name:
|
||||
params.extend(['--name', name])
|
||||
else:
|
||||
return
|
||||
|
||||
self._execute('stop', params)
|
||||
|
||||
def stat(self, memory=True, all=False, name=None):
|
||||
"""Print statistics about a running instance
|
||||
|
||||
:param memory: Display memory statistics
|
||||
:type memory: boolean
|
||||
:param all: All instances
|
||||
:type all: boolean
|
||||
:param name: Instance name
|
||||
:type name: string
|
||||
|
||||
"""
|
||||
return # This method is not supported by lkvm client
|
||||
|
||||
params = ['--memory']
|
||||
if all:
|
||||
params.append('--all')
|
||||
elif name:
|
||||
params.extend(['--name', name])
|
||||
else:
|
||||
return
|
||||
|
||||
output = self._execute('stat', params)
|
||||
|
||||
instances = []
|
||||
if len(output) > 1:
|
||||
if len(results) > 2 :
|
||||
for result in results[2:-1]:
|
||||
ins = result.split()
|
||||
instance = KVMInstance(ins[0], ins[1], ins[2])
|
||||
instances.append(instance)
|
||||
|
||||
return instances
|
||||
|
||||
def sandbox(self, cpus, mem, shmem, console, kernel, params,
|
||||
network, name=None, disk=None, balloon=False,
|
||||
vnc=False, gtk=False, sdl=False, rng=False,
|
||||
plan9=False, dev=None, tty=None, sandbox=None,
|
||||
hugetlbs=None, initrd=None, firmware=None,
|
||||
no_dhcp=False):
|
||||
"""Run a command in a sandboxed guest
|
||||
|
||||
:param name: Name of the guest
|
||||
:type name: string
|
||||
:param cpus: Number of CPUs
|
||||
:type cpus: integer
|
||||
:param mem: Virtual machine memory size in MiB.
|
||||
:type mem: integer
|
||||
:param shmem: Share host shmem with guest via pci device
|
||||
:type shmem: string
|
||||
:param disk: Disk image or rootfs directory
|
||||
:type disk: string
|
||||
:param balloon: Enable virtio balloon
|
||||
:type balloon: boolean
|
||||
:param vnc: Enable VNC framebuffer
|
||||
:type vnc: boolean
|
||||
:param gtk: Enable GTK framebuffer
|
||||
:type gtk: boolean
|
||||
:param sdl: Enable SDL framebuffer
|
||||
:type sdl: boolean
|
||||
:param rng: Enable virtio Random Number Generator
|
||||
:type rng: boolean
|
||||
:param plan9: Enable virtio 9p to share files between host and guest
|
||||
:type plan9: boolean
|
||||
:param console: Console to use
|
||||
:type console: string
|
||||
:param dev: KVM device file
|
||||
:type dev: string
|
||||
:param tty: Remap guest TTY into a pty on the host
|
||||
:type tty: string
|
||||
:param sandbox: Run this script when booting into custom rootfs
|
||||
:type sandbox: string
|
||||
:param hugetlbfs: Hugetlbfs path
|
||||
:type hugetlbfs: string
|
||||
:param kernel: Kernel to boot in virtual machine
|
||||
:type kernel: string
|
||||
:param initrd: Initial RAM disk image
|
||||
:type initrd: integer
|
||||
:param params: Kernel command line arguments
|
||||
:type params: string
|
||||
:param firmware: Firmware image to boot in virtual machine
|
||||
:type firmware: string
|
||||
:param network: Create a new guest NIC
|
||||
:type network: string
|
||||
:param no_dhcp: Disable kernel DHCP in rootfs mode
|
||||
:type no_dhcp: boolean
|
||||
|
||||
"""
|
||||
|
||||
_params = []
|
||||
|
||||
# Basic options
|
||||
|
||||
|
||||
_params.extend(['--cpus', cpus,
|
||||
'--mem', mem,
|
||||
'--shmem', shmem])
|
||||
|
||||
if name:
|
||||
_params.extend(['--name', name])
|
||||
if console in ['serial', 'virtio', 'hv']:
|
||||
_params.extend(['--console', console])
|
||||
if balloon:
|
||||
_params.append('--balloon')
|
||||
if vnc:
|
||||
_params.append('--vnc')
|
||||
if gtk:
|
||||
_params.append('--gtk')
|
||||
if sdl:
|
||||
_params.append('--sdl')
|
||||
if rng:
|
||||
_params.append('--rng')
|
||||
if plan9:
|
||||
_params.append('--9p')
|
||||
if disk:
|
||||
_params.extend(['--disk', disk])
|
||||
if dev:
|
||||
_params.extend(['--dev', dev])
|
||||
if tty:
|
||||
_params.extend(['--tty', tty])
|
||||
if sandbox:
|
||||
_params.extend(['--sandbox', sandbox])
|
||||
if hugetlbs:
|
||||
_params.extend(['--hugetlbs', hugetlbs])
|
||||
|
||||
# Kernel options
|
||||
|
||||
_params.extend(['--kernel', kernel,
|
||||
'--params', '"%s"' % params])
|
||||
|
||||
if initrd:
|
||||
_params.extend(['--initrd', initrd])
|
||||
if firmware:
|
||||
_params.extend(['--firmware', firmware])
|
||||
|
||||
# Networking options
|
||||
|
||||
_params.extend(['--network', network])
|
||||
|
||||
if no_dhcp:
|
||||
_params.append('--no-dhcp')
|
||||
|
||||
self._execute('sandbox', _params, background=True)
|
||||
|
||||
def is_supported(self):
|
||||
return os.path.isfile(LKVM_PATH)
|
||||
@@ -0,0 +1,4 @@
|
||||
pbr>=1.8
|
||||
psutil==3.3.0
|
||||
six==1.10.0
|
||||
wheel==0.24.0
|
||||
@@ -0,0 +1,17 @@
|
||||
[metadata]
|
||||
name = python-lkvm
|
||||
summary = Library for lkvm
|
||||
description-file =
|
||||
README.rst
|
||||
author = Obed N Munoz
|
||||
author-email = obed.n.munoz@intel.com
|
||||
home-page =
|
||||
classifier =
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.3
|
||||
@@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) 2015 Intel Corporation
|
||||
#
|
||||
# Author: Munoz, Obed N <obed.n.munoz@intel.com>
|
||||
# Author: Simental Magana, Marcos <marcos.simental.magana@intel.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr>=1.8'],
|
||||
pbr=True,
|
||||
packages=[''],
|
||||
package_dir={'': 'python_lkvm'})
|
||||
Reference in New Issue
Block a user