Ejemplo n.º 1
0
  def parse(cls, data, from_user=True):

    def validate_dependencies(contrs):
      contrs = {c.id: c for c in contrs}
      parents = {}
      for c in contrs.values():
        nonexist = list(filter(lambda c: c not in contrs, c.dependencies))
        if nonexist:
          return 422, None, "Dependencies '%s' do not exist in this appliance" % nonexist
      parents.setdefault(c.id, set()).update(c.dependencies)
      for c, p in parents.items():
        cycles = ['%s<->%s' % (c, pp)
                  for pp in filter(lambda x: c in parents.get(x, set()), p)]
        if cycles:
          return 422, None, "Cycle(s) found: %s" % cycles
      return 200, 'Dependencies are valid', None

    if not isinstance(data, dict):
      return 422, None, "Failed to parse appliance request format: %s"%type(data)
    missing = Appliance.REQUIRED - data.keys()
    if missing:
      return 400, None, "Missing required field(s) of appliance: %s"%missing
    fields = {}
    # instantiate container objects
    containers, contr_ids = [], set()
    for c in data.pop('containers', []):
      if c['id'] in contr_ids:
        return 400, None, "Duplicate container id: %s"%c['id']
      if from_user:
        for unwanted_f in ('appliance', ):
          c.pop(unwanted_f, None)
      status, contr, err = Container.parse(dict(**c, appliance=data['id']), from_user)
      if status != 200:
        return status, None, err
      containers.append(contr)
      contr_ids.add(contr.id)
    addresses = set()
    for c in containers:
      if c.cmd:
        addresses.update(get_short_ids(c.cmd))
      for arg in c.args:
        addresses.update(get_short_ids(arg))
      for v in c.env.values():
        addresses.update(get_short_ids(v))
    undefined = list(addresses - contr_ids)
    if undefined:
      return 400, None, "Undefined container(s): %s"%undefined
    status, msg, err = validate_dependencies(containers)
    if status != 200:
      return status, None, err
    fields.update(containers=containers)

    # instantiate data persistence object
    if 'data_persistence' in data:
      status, dp, err = DataPersistence.parse(dict(**data.pop('data_persistence', {}),
                                                   appliance=data['id']), from_user)
      if status != 200:
        return status, None, err
      fields.update(data_persistence=dp)

    # instantiate scheduler object
    if 'scheduler' in data:
      status, scheduler, err = Scheduler.parse(data.pop('scheduler', {}), from_user)
      if status != 200:
        return status, None, err
      fields.update(scheduler=scheduler)

    return 200, Appliance(**fields, **data), None