console.py 7.12 KB
Newer Older
1
# -*- coding: utf-8 -*-
Łukasz Nowak's avatar
Łukasz Nowak committed
2 3
##############################################################################
#
4 5
# Copyright (c) 2010, 2011, 2012 Vifib SARL and Contributors.
# All Rights Reserved.
Łukasz Nowak's avatar
Łukasz Nowak committed
6 7 8 9 10
#
# 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
11
# guarantees and support are strongly advised to contract a Free Software
Łukasz Nowak's avatar
Łukasz Nowak committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
# 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.
#
##############################################################################

30
import slapos.slap.slap
31
from slapos.slap import ResourceNotReady
32 33

import sys
34
import os
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
from optparse import OptionParser, Option
import ConfigParser

class Parser(OptionParser):
  """
  Parse all arguments.
  """
  def __init__(self, usage=None, version=None):
    """
    Initialize all options possibles.
    """
    OptionParser.__init__(self, usage=usage, version=version,
                          option_list=[
        Option("-u", "--master_url",
               default=None,
               action="store",
               help="Url of SlapOS Master to use."),
        Option("-k", "--key_file",
              action="store",
              help="SSL Authorisation key file."),
        Option("-c", "--cert_file",
            action="store",
            help="SSL Authorisation certificate file.")
    ])

  def check_args(self):
    """
    Check arguments
    """
    (options, args) = self.parse_args()
65 66
    if len(args) == 0:
      self.error("Incorrect number of arguments")
67 68
    elif not os.path.isfile(args[0]):
      self.error("%s: Not found or not a regular file." % args[0])
69

70
    return options, args
71

72 73 74 75 76 77 78 79 80 81 82
class RequestParser(Parser):
  def check_args(self):
    """
    Check arguments
    """
    (options, args) = Parser.check_args(self)
    if len(args) < 3:
      self.error("Incorrect number of arguments")

    return options, args

83 84 85 86 87 88 89 90 91 92 93 94 95
class Config:
  def setConfig(self, option_dict, configuration_file_path):
    """
    Set options given by parameters.
    """
    # Set options parameters
    for option, value in option_dict.__dict__.items():
      setattr(self, option, value)

    # Load configuration file
    configuration_parser = ConfigParser.SafeConfigParser()
    configuration_parser.read(configuration_file_path)
    # Merges the arguments and configuration
96 97 98 99 100 101 102
    try:
      configuration_dict = dict(configuration_parser.items("slapconsole"))
    except ConfigParser.NoSectionError:
      pass
    else:
      for key in configuration_dict:
        if not getattr(self, key, None):
103
          setattr(self, key, configuration_dict[key])
104 105
    configuration_dict = dict(configuration_parser.items('slapos'))
    master_url = configuration_dict.get('master_url', None)
106 107 108 109 110 111
    if not master_url:
      raise ValueError("No option 'master_url'")
    elif master_url.startswith('https') and \
         not getattr(self, 'key_file', None) and \
         not getattr(self, 'cert_file', None):
      raise ValueError("No option 'key_file' and/or 'cert_file'")
112 113
    else:
      setattr(self, 'master_url', master_url)
114 115

def init(config):
116
  """Initialize Slap instance, connect to server and create
117
  aliases to common software releases"""
118
  slap = slapos.slap.slap()
119
  slap.initializeConnection(config.master_url,
120
      key_file=config.key_file, cert_file=config.cert_file)
121
  local = globals().copy()
122
  local['slap'] = slap
123
  # Create aliases as global variables
124 125 126 127
  try:
    alias = config.alias.split('\n')
  except AttributeError:
    alias = []
128
  software_list = []
129 130 131
  for software in alias:
    if software is not '':
      name, url = software.split(' ')
132
      software_list.append(name)
133
      local[name] = url
134
  # Create global variable too see available aliases
135
  local['software_list'] = software_list
136
  # Create global shortcut functions to request instance and software
137 138 139 140 141
  # XXX-Cedric : can we change given parameters to something like
  # *args, **kwargs, but without the bad parts, in order to be generic?
  def shorthandRequest(software_release, partition_reference,
      partition_parameter_kw=None, software_type=None, filter_kw=None,
      state=None):
142
    return slap.registerOpenOrder().request(software_release, partition_reference,
143
      partition_parameter_kw, software_type, filter_kw, state)
144 145
  def shorthandSupply(software_release, computer_guid=None, state='available'):
    return slap.registerSupply().supply(software_release, computer_guid, state)
146 147 148
  local['request'] = shorthandRequest
  local['supply'] = shorthandSupply

149 150 151 152 153
  return local

def request():
  """Ran when invoking slapos-request"""
  # Parse arguments
154 155
  usage = """usage: %s [options] CONFIGURATION_FILE SOFTWARE_INSTANCE INSTANCE_REFERENCE
slapos-request allows you to request slapos instances.""" % sys.argv[0]
156
  config = Config()
157
  options, arguments = RequestParser(usage=usage).check_args()
158
  config.setConfig(options, arguments[0])
159

160
  local = init(config)
161

162
  # Request instance
163
  # XXX-Cedric : support things like :
164 165 166 167 168 169 170
  # --instance-type std --configuration-size 23 --computer-region europe/france
  # XXX-Cedric : add support for xml_parameter
  software_url = arguments[1]
  partition_reference = arguments[2]
  print("Requesting %s..." % software_url)
  if software_url in local:
    software_url = local[software_url]
171 172 173 174 175 176
  try:
    partition = local['slap'].registerOpenOrder().request(software_url,
        partition_reference)
    print("Instance requested.\nState is : %s.\nYou can "
        "rerun to get up-to-date informations." % (
        partition.getState()))
177
    # XXX-Cedric : provide a way for user to fetch parameter, url, object, etc
178 179 180 181
  except ResourceNotReady:
    print("Instance requested. Master is provisionning it. Please rerun in a "
    "couple of minutes to get connection informations")
    exit(2)
182 183 184 185

def run():
  """Ran when invoking slapconsole"""
  # Parse arguments
186
  usage = """usage: %s [options] CONFIGURATION_FILE
187 188 189 190 191 192 193 194 195 196
slapconsole allows you interact with slap API. You can play with the global
"slap" object and with the global "request" method.

examples :
  >>> # Request instance
  >>> request(kvm, "myuniquekvm")
  >>> # Request software installation on owned computer
  >>> supply(kvm, "mycomputer")
  >>> # Fetch instance informations on already launched instance
  >>> request(kvm, "myuniquekvm").getConnectionParameter("url")""" % sys.argv[0]
197 198
  config = Config()
  config.setConfig(*Parser(usage=usage).check_args())
199

200 201
  local = init(config)
  __import__("code").interact(banner="", local=local)