[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