softwaretype.py 6.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

import os
import sys
import copy
from ConfigParser import ConfigParser
32
import json
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
import subprocess
import slapos.slap
import netaddr
import logging

import zc.buildout

class Recipe:

  def __init__(self, buildout, name, options):
    self.buildout = buildout
    self.options = options
    self.name = name
    self.logger = logging.getLogger(self.name)

  def _getIpAddress(self, test_method):
    """Internal helper method to fetch ip address"""
    if not 'ip_list' in self.parameter_dict:
      raise AttributeError
    for name, ip in self.parameter_dict['ip_list']:
      if test_method(ip):
        return ip
    raise AttributeError

  def getLocalIPv4Address(self):
    """Returns local IPv4 address available on partition"""
    # XXX: Lack checking for locality of address
    return self._getIpAddress(netaddr.valid_ipv4)

  def getGlobalIPv6Address(self):
    """Returns global IPv6 address available on partition"""
    # XXX: Lack checking for globality of address
    return self._getIpAddress(netaddr.valid_ipv6)

67 68 69 70 71 72 73 74 75
  def getNetworkInterface(self):
    """Returns the network interface available on partition"""
    if not 'ip_list' in self.parameter_dict:
      raise AttributeError
    for name, ip in self.parameter_dict['ip_list']:
      if name:
        return name
    raise AttributeError, "Not network interface found"

76 77 78 79 80 81 82 83 84 85 86 87 88 89
  def install(self):
    slap = slapos.slap.slap()
    slap_connection = self.buildout['slap_connection']
    computer_id = slap_connection['computer_id']
    computer_partition_id = slap_connection['partition_id']
    server_url = slap_connection['server_url']
    key_file = slap_connection.get('key_file')
    cert_file = slap_connection.get('cert_file')
    slap.initializeConnection(server_url, key_file, cert_file)
    self.computer_partition = slap.registerComputerPartition(
      computer_id,
      computer_partition_id)
    self.parameter_dict = self.computer_partition.getInstanceParameterDict()
    software_type = self.parameter_dict['slap_software_type']
Cédric de Saint Martin's avatar
Typo  
Cédric de Saint Martin committed
90 91
    self.logger.info('Deploying instance with software type %s' % \
        software_type)
92

93
    # Raise if request software_type does not exist ...
94
    if software_type not in self.options:
95
      # ... Except for backward compatibility. Then use "default".
96
      if software_type in ['RootSoftwareInstance']:
97 98
        software_type = 'default'
      else:
99 100
        raise zc.buildout.UserError("This software type (%s) isn't mapped." % \
            software_type)
101 102 103 104

    instance_file_path = self.options[software_type]

    if not os.path.exists(instance_file_path):
Łukasz Nowak's avatar
Łukasz Nowak committed
105 106
      raise zc.buildout.UserError("The specified buildout config file %r does "
                                  "not exist." % instance_file_path)
107 108 109 110 111

    buildout = ConfigParser()
    with open(instance_file_path) as instance_path:
      buildout.readfp(instance_path)

112
    buildout.set('buildout', 'installed', '.installed-%s.cfg' % self.name)
113

114 115
    if not buildout.has_section('slap-parameter'):
      buildout.add_section('slap-parameter')
116
    for parameter, value in self.parameter_dict.items():
117 118
      # All parameters evaluating to False are... False, and shouldn't
      # convey any information.
119
      # Here, all those parameters are simply ignored.
120 121 122 123 124
      if value:
        if isinstance(value, str):
          buildout.set('slap-parameter', parameter, value)
        else:
          buildout.set('slap-parameter', parameter, json.dumps(value))
125 126

    buildout.add_section('slap-network-information')
127
    buildout.set('slap-network-information', 'local-ipv4',
128
                 self.getLocalIPv4Address())
129
    buildout.set('slap-network-information', 'global-ipv6',
130
                 self.getGlobalIPv6Address())
131
    buildout.set('slap-network-information', 'network-interface',
132
                 self.getNetworkInterface())
133 134 135 136 137 138

    # Copy/paste slap_connection
    buildout.add_section('slap-connection')
    for key, value in self.buildout['slap_connection'].iteritems():
      # XXX: Waiting for SlapBaseRecipe to use dash instead of underscores
      buildout.set('slap-connection', key.replace('_', '-'), value)
139 140
    # XXX: Needed for lxc. Use non standard API
    buildout.set('slap-connection', 'requested', self.computer_partition._requested_state)
141 142 143 144

    work_directory = os.path.abspath(self.buildout['buildout'][
      'directory'])
    buildout_filename = os.path.join(work_directory,
145
                                     'buildout-%s.cfg' % self.name)
146 147 148 149 150 151 152 153 154 155 156 157 158 159
    with open(buildout_filename, 'w') as buildout_file:
      buildout.write(buildout_file)

    # XXX-Antoine: We gotta find a better way to do this. I tried to check
    # out how slapgrid-cp was running buildout. But it is worse than that.
    command_line_args = copy.copy(sys.argv) + ['-c', buildout_filename]

    self.logger.info("Invoking commandline : '%s'",
                     ' '.join(command_line_args))

    subprocess.check_call(command_line_args, cwd=work_directory,
                          env=os.environ.copy())
    return []
  update = install