示例#1
0
  def request(self, software_release, software_type, partition_reference,
              shared=False, partition_parameter_kw=None, filter_kw=None,
              state=None):
    if partition_parameter_kw is None:
      partition_parameter_kw = {}
    elif not isinstance(partition_parameter_kw, dict):
      raise ValueError("Unexpected type of partition_parameter_kw '%s'" %
                       partition_parameter_kw)

    if filter_kw is None:
      filter_kw = {}
    elif not isinstance(filter_kw, dict):
      raise ValueError("Unexpected type of filter_kw '%s'" %
                       filter_kw)

    # Let enforce a default software type
    if software_type is None:
      software_type = DEFAULT_SOFTWARE_TYPE

    request_dict = {
        'computer_id': self._computer_id,
        'computer_partition_id': self._partition_id,
        'software_release': software_release,
        'software_type': software_type,
        'partition_reference': partition_reference,
        'shared_xml': xml_marshaller.dumps(shared),
        'partition_parameter_xml': xml_marshaller.dumps(
                                        partition_parameter_kw),
        'filter_xml': xml_marshaller.dumps(filter_kw),
        'state': xml_marshaller.dumps(state),
    }
    return self._requestComputerPartition(request_dict)
示例#2
0
 def request(self, software_release, partition_reference,
     partition_parameter_kw=None, software_type=None, filter_kw=None,
     state=None, shared=False):
   if partition_parameter_kw is None:
     partition_parameter_kw = {}
   if filter_kw is None:
     filter_kw = {}
   request_dict = {
       'software_release': software_release,
       'partition_reference': partition_reference,
       'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw),
       'filter_xml': xml_marshaller.dumps(filter_kw),
       'state': xml_marshaller.dumps(state),
       'shared_xml': xml_marshaller.dumps(shared),
     }
   if software_type is not None:
     request_dict['software_type'] = software_type
   try:
     self._connection_helper.POST('/requestComputerPartition', request_dict)
   except ResourceNotReady:
     return ComputerPartition(request_dict=request_dict)
   else:
     xml = self._connection_helper.response.read()
     software_instance = xml_marshaller.loads(xml)
     return ComputerPartition(
       software_instance.slap_computer_id.encode('UTF-8'),
       software_instance.slap_computer_partition_id.encode('UTF-8'))
示例#3
0
  def request(self, software_release, software_type, partition_reference,
              shared=False, partition_parameter_kw=None, filter_kw=None,
              state=None):
    if partition_parameter_kw is None:
      partition_parameter_kw = {}
    elif not isinstance(partition_parameter_kw, dict):
      raise ValueError("Unexpected type of partition_parameter_kw '%s'" % \
                       partition_parameter_kw)

    if filter_kw is None:
      filter_kw = {}
    elif not isinstance(filter_kw, dict):
      raise ValueError("Unexpected type of filter_kw '%s'" % \
                       filter_kw)

    # Let enforce a default software type
    if software_type is None:
      software_type = DEFAULT_SOFTWARE_TYPE

    request_dict = { 'computer_id': self._computer_id,
        'computer_partition_id': self._partition_id,
        'software_release': software_release,
        'software_type': software_type,
        'partition_reference': partition_reference,
        'shared_xml': xml_marshaller.dumps(shared),
        'partition_parameter_xml': xml_marshaller.dumps(
                                        partition_parameter_kw),
        'filter_xml': xml_marshaller.dumps(filter_kw),
        'state': xml_marshaller.dumps(state),
      }
    try:
      self._connection_helper.POST('/requestComputerPartition', request_dict)
    except ResourceNotReady:
      return ComputerPartition(
        request_dict=request_dict,
        connection_helper=self._connection_helper,
      )
    else:
      xml = self._connection_helper.response.read()
      software_instance = xml_marshaller.loads(xml)
      computer_partition = ComputerPartition(
        software_instance.slap_computer_id.encode('UTF-8'),
        software_instance.slap_computer_partition_id.encode('UTF-8'),
        connection_helper=self._connection_helper,
      )
      if shared:
        computer_partition._synced = True
        computer_partition._connection_dict = getattr(software_instance,
          '_connection_dict', None)
        computer_partition._parameter_dict = getattr(software_instance,
          '_parameter_dict', None)
      return computer_partition
示例#4
0
 def setConnectionDict(self, connection_dict, slave_reference=None):
   if self.getConnectionParameterDict() != connection_dict:
     self._connection_helper.POST('/setComputerPartitionConnectionXml', {
         'computer_id': self._computer_id,
         'computer_partition_id': self._partition_id,
         'connection_xml': xml_marshaller.dumps(connection_dict),
         'slave_reference': slave_reference})
示例#5
0
  def setConnectionDict(self, connection_dict, slave_reference=None):
    if self.getConnectionParameterDict() == connection_dict:
      return

    if slave_reference is not None:
      # check the connection parameters from the slave

      # Should we check existence?
      slave_parameter_list = self.getInstanceParameter("slave_instance_list")
      slave_connection_dict = {}
      for slave_parameter_dict in slave_parameter_list:
        if slave_parameter_dict.get("slave_reference") == slave_reference:
          connection_parameter_hash = slave_parameter_dict.get("connection-parameter-hash", None)
          break

      # Skip as nothing changed for the slave
      if connection_parameter_hash is not None and \
        connection_parameter_hash == hashlib.sha256(str(connection_dict)).hexdigest():
        return

    self._connection_helper.POST('setComputerPartitionConnectionXml', data={
          'computer_id': self._computer_id,
          'computer_partition_id': self._partition_id,
          'connection_xml': xml_marshaller.dumps(connection_dict),
          'slave_reference': slave_reference})
示例#6
0
 def setComputerPartitionRelatedInstanceList(self, instance_reference_list):
   self._connection_helper.POST('updateComputerPartitionRelatedInstanceList',
       data={
         'computer_id': self._computer_id,
         'computer_partition_id': self._partition_id,
         'instance_reference_xml': xml_marshaller.dumps(instance_reference_list)
         }
       )
示例#7
0
 def request(self, software_release, partition_reference,
     partition_parameter_kw=None, software_type=None, filter_kw=None,
     state=None, shared=False):
   if partition_parameter_kw is None:
     partition_parameter_kw = {}
   if filter_kw is None:
     filter_kw = {}
   request_dict = {
       'software_release': software_release,
       'partition_reference': partition_reference,
       'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw),
       'filter_xml': xml_marshaller.dumps(filter_kw),
       # XXX Cedric: Why state and shared are marshalled? First is a string
       #             And second is a boolean.
       'state': xml_marshaller.dumps(state),
       'shared_xml': xml_marshaller.dumps(shared),
     }
   if software_type is not None:
     request_dict['software_type'] = software_type
   else:
     # Let's enforce a default software type
     request_dict['software_type'] = DEFAULT_SOFTWARE_TYPE
   try:
     self._connection_helper.POST('/requestComputerPartition', request_dict)
   except ResourceNotReady:
     return ComputerPartition(
       request_dict=request_dict,
       connection_helper=self._connection_helper,
     )
   else:
     xml = self._connection_helper.response.read()
     software_instance = xml_marshaller.loads(xml)
     computer_partition = ComputerPartition(
       software_instance.slap_computer_id.encode('UTF-8'),
       software_instance.slap_computer_partition_id.encode('UTF-8'),
       connection_helper=self._connection_helper,
     )
     if shared:
       computer_partition._synced = True
       computer_partition._connection_dict = software_instance._connection_dict
       computer_partition._parameter_dict = software_instance._parameter_dict
     return computer_partition
 def stepDirectRequestComputerPartitionHttpRequestTimeoutResponseWithoutState(self,
   sequence, **kw):
   request_dict = { 'computer_id': sequence['computer_reference'] ,
       'computer_partition_id': sequence['computer_partition_reference'],
       'software_release': sequence['software_release_uri'],
       'software_type': sequence.get('requested_software_type',
         'requested_software_type'),
       'partition_reference': sequence.get('requested_reference',
         'requested_reference'),
       'shared_xml': xml_marshaller.dumps(kw.get("shared", False)),
       'partition_parameter_xml': xml_marshaller.dumps({}),
       'filter_xml': xml_marshaller.dumps({}),
       #'state': Note: State is omitted
     }
   scheme, netloc, path, query, fragment = urlparse.urlsplit(self.server_url)
   connection = httplib.HTTPConnection(host=netloc)
   connection.request("POST", path + '/requestComputerPartition',
       urllib.urlencode(request_dict),
       {'Content-type': "application/x-www-form-urlencoded"})
   response = connection.getresponse()
   self.assertEqual(httplib.REQUEST_TIMEOUT, response.status)
示例#9
0
def forwardRequestToExternalMaster(master_url, request_form):
  """
  Forward instance request to external SlapOS Master.
  """
  master_entry = app.config.get('multimaster').get(master_url, {})
  key_file = master_entry.get('key')
  cert_file = master_entry.get('cert')
  if master_url.startswith('https') and (not key_file or not cert_file):
    app.logger.warning('External master %s configuration did not specify key or certificate.' % master_url)
    abort(404)
  if master_url.startswith('https') and not master_url.startswith('https') and (key_file or cert_file):
    app.logger.warning('External master %s configurqtion specifies key or certificate but is using plain http.' % master_url)
    abort(404)

  slap = slapos.slap.slap()
  if key_file:
    slap.initializeConnection(master_url, key_file=key_file, cert_file=cert_file)
  else:
    slap.initializeConnection(master_url)

  partition_reference = request_form['partition_reference'].encode()
  # Store in database
  execute_db('forwarded_partition_request', 'INSERT OR REPLACE INTO %s values(:partition_reference, :master_url)',
             {'partition_reference':partition_reference, 'master_url': master_url})

  new_request_form = request_form.copy()
  filter_kw = loads(new_request_form['filter_xml'].encode())
  filter_kw['source_instance_id'] = partition_reference
  new_request_form['filter_xml'] = dumps(filter_kw)

  xml = slap._connection_helper.POST('/requestComputerPartition', data=new_request_form)
  if type(xml) is unicode:
    xml = str(xml)
    xml.encode('utf-8')
  partition = loads(xml)

  # XXX move to other end
  partition._master_url = master_url

  return dumps(partition)
示例#10
0
  def dump(self, path_to_xml):
    """
    Dump the computer object to an xml file via xml_marshaller.

    Args:
      path_to_xml: String, path to the file to load.
      users: List of User, list of user needed to be add to the dump
          (even if they are not related to any tap interface).
    """

    computer_dict = _getDict(self)
    output_file = open(path_to_xml,'w')
    output_file.write(xml_marshaller.dumps(computer_dict))
    output_file.close()
示例#11
0
 def request(self, software_release, partition_reference,
             partition_parameter_kw=None, software_type=None,
             filter_kw=None, state=None, shared=False):
   if partition_parameter_kw is None:
     partition_parameter_kw = {}
   if filter_kw is None:
     filter_kw = {}
   request_dict = {
       'software_release': software_release,
       'partition_reference': partition_reference,
       'partition_parameter_xml': xml_marshaller.dumps(partition_parameter_kw),
       'filter_xml': xml_marshaller.dumps(filter_kw),
       # XXX Cedric: Why state and shared are marshalled? First is a string
       #             And second is a boolean.
       'state': xml_marshaller.dumps(state),
       'shared_xml': xml_marshaller.dumps(shared),
   }
   if software_type is not None:
     request_dict['software_type'] = software_type
   else:
     # Let's enforce a default software type
     request_dict['software_type'] = DEFAULT_SOFTWARE_TYPE
   return self._requestComputerPartition(request_dict)
示例#12
0
  def request(self, software_release, software_type, partition_reference,
              shared=False, partition_parameter_kw=None, filter_kw=None,
              state=None):
    if partition_parameter_kw is None:
      partition_parameter_kw = {}
    elif not isinstance(partition_parameter_kw, dict):
      raise ValueError("Unexpected type of partition_parameter_kw '%s'" % \
                       partition_parameter_kw)

    if filter_kw is None:
      filter_kw = {}
    elif not isinstance(filter_kw, dict):
      raise ValueError("Unexpected type of filter_kw '%s'" % \
                       filter_kw)

    request_dict = { 'computer_id': self._computer_id,
        'computer_partition_id': self._partition_id,
        'software_release': software_release,
        'software_type': software_type,
        'partition_reference': partition_reference,
        'shared_xml': xml_marshaller.dumps(shared),
        'partition_parameter_xml': xml_marshaller.dumps(
                                        partition_parameter_kw),
        'filter_xml': xml_marshaller.dumps(filter_kw),
        'state': xml_marshaller.dumps(state),
      }
    try:
      self._connection_helper.POST('/requestComputerPartition', request_dict)
    except ResourceNotReady:
      return ComputerPartition(request_dict=request_dict)
    else:
      xml = self._connection_helper.response.read()
      software_instance = xml_marshaller.loads(xml)
      return ComputerPartition(
        software_instance.slap_computer_id.encode('UTF-8'),
        software_instance.slap_computer_partition_id.encode('UTF-8'))
示例#13
0
  def send(self, config):
    """
    Send a marshalled dictionary of the computer object serialized via_getDict.
    """

    slap_instance = slap.slap()
    connection_dict = {}
    if config.key_file and config.cert_file:
      connection_dict.update(
        key_file=config.key_file,
        cert_file=config.cert_file)
    slap_instance.initializeConnection(config.master_url,
      **connection_dict)
    slap_computer = slap_instance.registerComputer(self.reference)
    if config.dry_run:
      return
    return slap_computer.updateConfiguration(
        xml_marshaller.dumps(_getDict(self)))
示例#14
0
  def __init__(self, config, process_group_pid_set=None):
    self.config = config
    # By erasing everything, we make sure that we are able to "update"
    # existing profiles. This is quite dirty way to do updates...
    if os.path.exists(config['proxy_database']):
      os.unlink(config['proxy_database'])
    proxy = subprocess.Popen([config['slapproxy_binary'],
      config['slapos_config']], close_fds=True, preexec_fn=os.setsid)
    process_group_pid_set.add(proxy.pid)
    # XXX: dirty, giving some time for proxy to being able to accept
    # connections
    time.sleep(10)
    slap = slapos.slap.slap()
    slap.initializeConnection(config['master_url'])
    # register software profile
    self.software_profile = config['custom_profile_path']
    slap.registerSupply().supply(
        self.software_profile,
        computer_guid=config['computer_id'])
    computer = slap.registerComputer(config['computer_id'])
    # create partition and configure computer
    partition_reference = config['partition_reference']
    partition_path = os.path.join(config['instance_root'], partition_reference)
    if not os.path.exists(partition_path):
      os.mkdir(partition_path)
      os.chmod(partition_path, 0750)
    computer.updateConfiguration(xml_marshaller.dumps({
 'address': config['ipv4_address'],
 'instance_root': config['instance_root'],
 'netmask': '255.255.255.255',
 'partition_list': [{'address_list': [{'addr': config['ipv4_address'],
                                       'netmask': '255.255.255.255'},
                                      {'addr': config['ipv6_address'],
                                       'netmask': 'ffff:ffff:ffff::'},
                      ],
                     'path': partition_path,
                     'reference': partition_reference,
                     'tap': {'name': partition_reference},
                     }
                    ],
 'reference': config['computer_id'],
 'software_root': config['software_root']}))
示例#15
0
def requestComputerPartition():
  parsed_request_dict = parseRequestComputerPartitionForm(request.form)

  # Is it a slave instance?
  slave = loads(request.form.get('shared_xml', EMPTY_DICT_XML).encode())

  # Check first if instance is already allocated
  if slave:
    # XXX: change schema to include a simple "partition_reference" which
    # is name of the instance. Then, no need to do complex search here.
    slave_reference = parsed_request_dict['partition_id'] + '_' + parsed_request_dict['partition_reference']
    requested_computer_id = parsed_request_dict['filter_kw'].get('computer_guid', app.config['computer_id'])
    matching_partition = getAllocatedSlaveInstance(slave_reference, requested_computer_id)
  else:
    matching_partition = getAllocatedInstance(parsed_request_dict['partition_reference'])

  if matching_partition:
    # Then the instance is already allocated, just update it
    # XXX: split request and request slave into different update/allocate functions and simplify.
    # By default, ALWAYS request instance on default computer
    parsed_request_dict['filter_kw'].setdefault('computer_guid', app.config['computer_id'])
    if slave:
      software_instance = requestSlave(**parsed_request_dict)
    else:
      software_instance = requestNotSlave(**parsed_request_dict)
  else:
    # Instance is not yet allocated: try to do it.
    external_master_url = isRequestToBeForwardedToExternalMaster(parsed_request_dict)
    if external_master_url:
      return forwardRequestToExternalMaster(external_master_url, request.form)
    # XXX add support for automatic deployment on specific node depending on available SR and partitions on each Node.
    # Note: It only deploys on default node if SLA not specified
    # XXX: split request and request slave into different update/allocate functions and simplify.

    # By default, ALWAYS request instance on default computer
    parsed_request_dict['filter_kw'].setdefault('computer_guid', app.config['computer_id'])
    if slave:
      software_instance = requestSlave(**parsed_request_dict)
    else:
      software_instance = requestNotSlave(**parsed_request_dict)

  return dumps(software_instance)
示例#16
0
  def send(self, config):
    """
    Send a marshalled dictionary of the computer object serialized via_getDict.
    """

    slap_instance = slap.slap()
    connection_dict = {}
    if config.key_file and config.cert_file:
      connection_dict.update(
        key_file=config.key_file,
        cert_file=config.cert_file)
    slap_instance.initializeConnection(config.master_url,
      **connection_dict)
    slap_computer = slap_instance.registerComputer(self.reference)
    if config.dry_run:
      return
    try:
      slap_computer.updateConfiguration(xml_marshaller.dumps(_getDict(self)))
    except slap.NotFoundError as error:
      raise slap.NotFoundError("%s\nERROR : This SlapOS node is not recognised by "
          "SlapOS Master. Please make sure computer_id of slapos.cfg looks "
          "like 'COMP-123' and is correct.\nError is : 404 Not Found." % error)
    return
示例#17
0
def run(args):
  config = args[0]
  for k,v in config['environment'].iteritems():
    os.environ[k] = v
  proxy = None
  slapgrid = None
  supervisord_pid_file = os.path.join(config['instance_root'], 'var', 'run',
        'supervisord.pid')
  if os.path.exists(config['proxy_database']):
    os.unlink(config['proxy_database'])
  try:
    proxy = subprocess.Popen([config['slapproxy_binary'],
      config['slapos_config']], close_fds=True, preexec_fn=os.setsid)
    process_group_pid_list.append(proxy.pid)
    slap = slapos.slap.slap()
    slap.initializeConnection(config['master_url'])
    while True:
      try:
        slap.registerSupply().supply(config['profile_url'],
          computer_guid=config['computer_id'])
      except socket.error:
        time.sleep(1)
        pass
      else:
        break
    while True:
      slapgrid = subprocess.Popen([config['slapgrid_software_binary'], '-vc',
        config['slapos_config']], close_fds=True, preexec_fn=os.setsid)
      process_group_pid_list.append(slapgrid.pid)
      slapgrid.wait()
      if slapgrid.returncode == 0:
        print 'Software installed properly'
        break
      print 'Problem with software installation, trying again'
      time.sleep(600)
    computer = slap.registerComputer(config['computer_id'])
    partition_reference = config['partition_reference']
    partition_path = os.path.join(config['instance_root'], partition_reference)
    if not os.path.exists(partition_path):
      os.mkdir(partition_path)
      os.chmod(partition_path, 0750)
    computer.updateConfiguration(xml_marshaller.dumps({
 'address': config['ipv4_address'],
 'instance_root': config['instance_root'],
 'netmask': '255.255.255.255',
 'partition_list': [{'address_list': [{'addr': config['ipv4_address'],
                                       'netmask': '255.255.255.255'},
                                      {'addr': config['ipv6_address'],
                                       'netmask': 'ffff:ffff:ffff::'},
                      ],
                     'path': partition_path,
                     'reference': partition_reference,
                     'tap': {'name': partition_reference},
                     }
                    ],
 'reference': config['computer_id'],
 'software_root': config['software_root']}))
    slap.registerOpenOrder().request(config['profile_url'],
        partition_reference='testing partition',
        partition_parameter_kw=config['instance_dict'])
    slapgrid = subprocess.Popen([config['slapgrid_partition_binary'], '-vc',
      config['slapos_config']], close_fds=True, preexec_fn=os.setsid)
    slapgrid.wait()
    if slapgrid.returncode != 0:
      raise ValueError('Slapgrid instance failed')
    runUnitTest = os.path.join(partition_path, 'bin', 'runUnitTest')
    if not os.path.exists(runUnitTest):
      raise ValueError('No %r provided' % runUnitTest)
  except:
    try:
      if os.path.exists(supervisord_pid_file):
        os.kill(int(open(supervisord_pid_file).read().strip()), signal.SIGTERM)
    except:
      pass
    raise
  finally:
    # Nice way to kill *everything* generated by run process -- process
    # groups working only in POSIX compilant systems
    # Exceptions are swallowed during cleanup phase
    if proxy is not None:
      os.killpg(proxy.pid, signal.SIGTERM)
    if os.path.exists(config['proxy_database']):
      os.unlink(config['proxy_database'])
    if slapgrid is not None and slapgrid.returncode is None:
      os.killpg(slapgrid.pid, signal.SIGTERM)
  try:
    bot_env = os.environ.copy()
    bot_env['PATH'] = ':'.join([config['bin_directory']] +
        bot_env['PATH'].split(':'))
    for l in config['bot_environment'].split():
      k, v = l.split('=')
      bot_env[k] = v
    if subprocess.call([config['buildbot_binary'], 'create-slave', '-f',
      config['working_directory'], config['buildbot_host'],
      config['slave_name'], config['slave_password']]) != 0:
      raise ValueError('Buildbot call failed')
    process_command_list.append([config['buildbot_binary'], 'stop',
      config['working_directory']])
    if os.path.exists(os.path.join(config['working_directory'],
      'buildbot.tac.new')):
      tac = os.path.join(config['working_directory'], 'buildbot.tac')
      if os.path.exists(tac):
        os.unlink(tac)
      os.rename(os.path.join(config['working_directory'],
      'buildbot.tac.new'), tac)
    if subprocess.call([config['buildbot_binary'], 'start',
      config['working_directory']], env=bot_env) != 0:
      raise ValueError('Issue during starting buildbot')
    while True:
      time.sleep(3600)
  finally:
    try:
      subprocess.call([config['buildbot_binary'], 'stop',
      config['working_directory']])
    except:
      pass
    try:
      if os.path.exists(supervisord_pid_file):
        os.kill(int(open(supervisord_pid_file).read().strip()), signal.SIGTERM)
    except:
      pass
示例#18
0
import random
import string
from slapos.slap.slap import Computer, ComputerPartition, \
    SoftwareRelease, SoftwareInstance, NotFoundError
from slapos.proxy.db_version import DB_VERSION
import slapos.slap
from slapos.util import sqlite_connect

from flask import g, Flask, request, abort
import xml_marshaller
from xml_marshaller.xml_marshaller import loads
from xml_marshaller.xml_marshaller import dumps

app = Flask(__name__)

EMPTY_DICT_XML = dumps({})

class UnauthorizedError(Exception):
  pass


# cast everything to string, utf-8 encoded
def to_str(v):
  if isinstance(v, str):
    return v
  if not isinstance(v, unicode):
    v = unicode(v)
  return v.encode('utf-8')


def xml2dict(xml):