[Erp5-report] r34991 rafael - in /erp5/trunk/utils/erp5.recipe.kvm: ./ src/ src/erp5/ src/e...
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed May 5 05:17:51 CEST 2010
Author: rafael
Date: Wed May 5 05:17:50 2010
New Revision: 34991
URL: http://svn.erp5.org?rev=34991&view=rev
Log:
Added a recipe to handle a KVM setup (Work in Progress).
Added:
erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt (with props)
erp5/trunk/utils/erp5.recipe.kvm/README.txt (with props)
erp5/trunk/utils/erp5.recipe.kvm/setup.py
erp5/trunk/utils/erp5.recipe.kvm/src/
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/__init__.py
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/__init__.py
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/__init__.py
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/kvm.py
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/run.py
erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/ssh.py
Added: erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,8 @@
+Changelog
+=========
+
+1.0 (2010-05-04)
+----------------
+
+- Initial Release
+ [Rafael Monnerat]
Propchange: erp5/trunk/utils/erp5.recipe.kvm/CHANGES.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: erp5/trunk/utils/erp5.recipe.kvm/README.txt
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/README.txt?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/README.txt (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/README.txt [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,14 @@
+Introduction
+============
+
+XXX Introductions
+
+Example
+=======
+
+XXX Example
+
+Options
+=======
+
+XXX Description
Propchange: erp5/trunk/utils/erp5.recipe.kvm/README.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: erp5/trunk/utils/erp5.recipe.kvm/setup.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/setup.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/setup.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/setup.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,32 @@
+from setuptools import setup, find_packages
+
+name = "erp5.recipe.kvm"
+version = '1.0'
+
+def read(name):
+ return open(name).read()
+
+long_description=( read('README.txt')
+ + '\n' +
+ read('CHANGES.txt')
+ )
+
+setup(
+ name = name,
+ version = version,
+ author = "Rafael Monnerat",
+ author_email = "rafael at nexedi.com",
+ description = "ZC Buildout recipe for create a kvm setup for a image",
+ long_description=long_description,
+ license = "ZPL 2.1",
+ keywords = "buildout kvm",
+ classifiers=[
+ "License :: OSI Approved :: Zope Public License",
+ "Framework :: Buildout",
+ ],
+ packages = find_packages('src'),
+ package_dir = {'': 'src'},
+ install_requires = ['zc.recipe.egg', 'paramiko', 'setuptools'],
+ namespace_packages = ['erp5', 'erp5.recipe'],
+ entry_points = {'zc.buildout': ['default = %s:Recipe' % name]},
+ )
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/__init__.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/__init__.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/__init__.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/__init__.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/__init__.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/__init__.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/__init__.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/__init__.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/__init__.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/__init__.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/__init__.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/__init__.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,140 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved.
+# Copyright (c) 2006-2008 Zope Corporation and Contributors.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import os
+import logging
+
+#import zc.buildout
+import zc.buildout.easy_install
+import zc.buildout.download
+import zc.recipe.egg
+
+class Recipe(object):
+
+ def __init__(self, buildout, name, options):
+ self.buildout, self.options, self.name = buildout, options, name
+ self.logger=logging.getLogger(self.name)
+ self.egg = zc.recipe.egg.Egg(buildout, options['recipe'], options)
+
+
+ options.setdefault('location',os.path.join(
+ buildout['buildout']['parts-directory'],
+ self.name,
+ ))
+
+ options.setdefault('kvm_bin_directory',
+ buildout['buildout']['bin-directory'])
+
+ options.setdefault("url", '')
+ options.setdefault("md5sum", '')
+ options.setdefault("gzip", 'true')
+ options.setdefault("gzip_md5", '')
+
+ # XXX Informations to connect to instance
+ # this should be used to create the commands to
+ # Manipulate it.
+ options.setdefault("ssh_port", "") # XXX
+ options.setdefault("ssh_hostname", "") # XXX
+ options.setdefault("ssh_key_path", "") # XXX
+ options.setdefault("ssh_user", "") # XXX
+
+ def install(self):
+ options = self.options
+ location = options['location']
+ if not os.path.exists(location):
+ os.mkdir(location)
+ download_file, is_temp = self.download()
+ image = self.copy(download_file)
+ ssh_port = options.get("ssh_port")
+ ssh_hostname = options.get("ssh_hostname")
+ ssh_key_path = options.get("ssh_key_path")
+ ssh_user = options.get("ssh_user")
+ md5_image = self.options.get("md5_image", None)
+ assert zc.buildout.download.check_md5sum(image, md5_image) == True
+
+ requirements, ws = self.egg.working_set(['erp5.recipe.kvm'])
+ script_name = "%s-sendfile" % self.name
+ scripts = zc.buildout.easy_install.scripts(
+ [(script_name,'erp5.recipe.kvm.ssh', 'put')],
+ ws, options['executable'], options.get("kvm_bin_directory"),
+ arguments = ("\n '%s', '%s',"
+ "\n '%s', '%s', "
+ "\n sys.argv[1], sys.argv[2]" % (ssh_user, ssh_hostname,
+ ssh_port, ssh_key_path)))
+
+ script_name = "%s-getfile" % self.name
+ scripts = zc.buildout.easy_install.scripts(
+ [(script_name,'erp5.recipe.kvm.ssh', 'get')],
+ ws, options['executable'], options.get("kvm_bin_directory"),
+ arguments = ("\n '%s', '%s',"
+ "\n '%s', '%s', "
+ "\n sys.argv[1], sys.argv[2]" % (ssh_user, ssh_hostname,
+ ssh_port, ssh_key_path)))
+
+ script_name = "%s-runscript" % self.name
+ scripts = zc.buildout.easy_install.scripts(
+ [(script_name,'erp5.recipe.kvm.ssh', 'run')],
+ ws, options['executable'], options.get("kvm_bin_directory"),
+ arguments = ("\n '%s', '%s',"
+ "\n '%s', '%s', "
+ "\n sys.argv[1]" % (ssh_user, ssh_hostname,
+ ssh_port, ssh_key_path)))
+
+ script_name = "%s-ctl" % self.name
+ scripts = zc.buildout.easy_install.scripts(
+ [(script_name,'erp5.recipe.kvm.kvm', 'ctl')],
+ ws, options['executable'], options.get("kvm_bin_directory"),
+ arguments = ("\n '%s', '%s', "
+ "\n '%s.pid' , '%s', "
+ "\n sys.argv[1:]" % (image, ssh_port,
+ self.name, self.name)))
+ return location
+
+ def download(self):
+ """Download image file
+ """
+ url = self.options['url']
+ namespace = self.options['recipe']
+ download = zc.buildout.download.Download(self.buildout['buildout'],
+ namespace=namespace,
+ logger=self.logger)
+ return download(url, self.options.get("md5_download", None))
+
+ def copy(self, download_file):
+ """ Copy downloaded file to a appropriate place
+ """
+ image = os.path.join(self.options['location'], self.name)
+
+ if os.path.exists(image):
+ self.logger.info("Image (%s) already exists... "
+ "skipping uncompress." % image)
+ return image
+
+ if self.options["gzip"].lower() == "true":
+ self._gzip(download_file, image)
+ return image
+
+ os.copy(download_file, image)
+ return image
+
+ def _gzip(self, download_file, image):
+ """ Uncompress image into in case it is compressed
+ """
+ # XXX USE Subprocess.
+ code = os.system('gunzip -cd %s > %s' % (download_file,
+ image))
+ assert code == 0
+
+ update = install
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/kvm.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/kvm.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/kvm.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/kvm.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,62 @@
+import subprocess
+import os
+import signal
+
+BASE_COMMAND = "kvm -snapshot -net nic,model=ne2k_pci -redir tcp:%s::22 -k fr -net user,hostname=mdv2010 -m 1024 -hda %s -daemonize -nographic -pidfile %s $@"
+
+class Kvm:
+ def __init__(self, image, port, pid_file, hostname):
+ """ Handle the KVM command for a certain image, and
+ start ssh in a certain port.
+
+ image: Image Path
+ """
+ self.image = image
+ self.ssh_port = port
+ self.kvm_pid_file = ""
+ self.kvm_hostname = ""
+
+ def start(self):
+ """ Start Kvm in background."""
+ subprocess.call(BASE_COMMAND % ( self.ssh_port,
+ self.image,
+ self.kvm_pid_file))
+
+ def stop(self):
+ """ Stop Kvm in the server """
+ try:
+ pid = int(open(self.kvm_pid_file, 'r').read().strip())
+ except:
+ pid = None
+ print "Can't read child pidfile %s!" % self.kvm_pid_file
+ return
+ # XXX SIGKILL is too brutal?
+ os.kill(pid, signal.SIGKILL)
+
+ def status(self):
+ """ Check Kvm status """
+ try:
+ pid = int(open(self.kvm_pid_file, 'r').read().strip())
+ except:
+ pid = None
+ print "Can't read child pidfile %s!" % self.kvm_pid_file
+ return False
+ try:
+ os.kill(pid , 0)
+ except OSError, err:
+ return False
+ return True
+
+ def restart(self):
+ self.stop()
+ self.start()
+
+def ctl(image, port, pid_file, hostname, command):
+ """ Control KVM Command
+ """
+ handler = Kvm(image, port, pid_file, hostname)
+ command = getattr(handler, command, None)
+ if command is not None:
+ return command()
+
+ return "ERROR!"
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/run.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/run.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/run.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/run.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,16 @@
+from ssh import ssh
+import sys
+
+def run(script_path):
+ """ Copy a script and Run it into KVM environment
+ """
+ handler = ssh()
+ handler.put(script_path, some_remote_place)
+ # We could do in some assincron way.
+ output = handler.run("python %s " % script_path)
+ return output
+
+def main():
+ # Use opt parser instead?
+ script_list = sys.argv[1:]
+
Added: erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/ssh.py
URL: http://svn.erp5.org/erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/ssh.py?rev=34991&view=auto
==============================================================================
--- erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/ssh.py (added)
+++ erp5/trunk/utils/erp5.recipe.kvm/src/erp5/recipe/kvm/ssh.py [utf8] Wed May 5 05:17:50 2010
@@ -1,0 +1,105 @@
+
+import paramiko
+from paramiko.ssh_exception import SSHException
+import os
+
+CHANNEL_RECV = 8000
+
+class connection(object):
+ """Holds an SSH connection to a remote SSH server.
+ """
+ def __init__(self, username, host, port, key_path):
+ self.username = username
+ self.host = host
+ self.port = port
+ self.transport = None
+ self.sftp = None
+ if os.path.exists(key_path):
+ self.key_path = key_path
+ else:
+ raise ValueError, 'key_path does not exist: %s' % key_path
+
+ def connect(self):
+ """ Connect and instantiate transport and sftp.
+ """
+ self.transport = paramiko.Transport((self.host, int(self.port)))
+ rsa_key = paramiko.RSAKey.from_private_key_file(self.key_path)
+ try:
+ self.transport.connect(username=self.username,
+ pkey=rsa_key)
+ except SSHException, e:
+ self.transport.close()
+ raise SSHException(str(e))
+ else:
+ self.sftp = paramiko.SFTPClient.from_transport(self.transport)
+
+ def close(self):
+ """Close the sftp and transport connection.
+ """
+ self.sftp.close()
+ self.transport.close()
+
+ def test(self):
+ """ Test connect to a remote server.
+ """
+ try:
+ try:
+ self.connect()
+ return True
+ except SSHException, e:
+ return False
+ finally:
+ self.close()
+
+ def get(self, remote_path, local_path):
+ """ Get a remote file and transfer for local file
+ """
+ try:
+ self.connect()
+ self.sftp.get(remote_path, local_path)
+ finally:
+ self.close()
+
+ def put(self, remote_path, local_path):
+ """ Send a local file to a remote path
+ """
+ try:
+ self.connect()
+ self.sftp.put(local_path, remote_path)
+ finally:
+ self.close()
+
+ def run(self, command):
+ """ Run a command in remote server
+ """
+ response = ""
+ try:
+ self.connect()
+ channel = self.transport.open_channel(kind='session')
+ channel.exec_command(command + " 2>&1")
+ if (channel.recv_ready):
+ response += channel.recv(CHANNEL_RECV)
+ finally:
+ self.close()
+ return response
+
+def put(username, host, port, key_path, remote_path, local_path):
+ """ Send file using paramiko
+ """
+ handler = connection(username, host, port, key_path)
+ handler.put(remote_path, local_path)
+ return True
+
+def run(username, host, port, key_path, command):
+ """ Connect into a remote instance and run a script
+ """
+ handler = connection(username, host, port, key_path)
+ handler.run(command)
+ return True
+
+def get(username, host, port, key_path, remote_path, local_path):
+ """ Get file by ssh
+ """
+ handler = connection(username, host, port, key_path)
+ handler.get(remote_path, local_path)
+ return True
More information about the Erp5-report
mailing list