softwaretype.py 5.99 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 96
      # ... Except for backward compatibility. Then use "default".
      if software_type in ['RootSoftwareType']:
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 119 120
      if isinstance(value, str):
        buildout.set('slap-parameter', parameter, value)
      else:
        buildout.set('slap-parameter', parameter, json.dumps(value))
121 122

    buildout.add_section('slap-network-information')
123
    buildout.set('slap-network-information', 'local-ipv4',
124
                 self.getLocalIPv4Address())
125
    buildout.set('slap-network-information', 'global-ipv6',
126
                 self.getGlobalIPv6Address())
127
    buildout.set('slap-network-information', 'network-interface',
128
                 self.getNetworkInterface())
129 130 131 132 133 134

    # 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)
135 136
    # XXX: Needed for lxc. Use non standard API
    buildout.set('slap-connection', 'requested', self.computer_partition._requested_state)
137 138 139 140

    work_directory = os.path.abspath(self.buildout['buildout'][
      'directory'])
    buildout_filename = os.path.join(work_directory,
141
                                     'buildout-%s.cfg' % self.name)
142 143 144 145 146 147 148 149 150 151 152 153 154 155
    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