Esempio n. 1
0
 def resolve_base(self, options):
     """resolve a base object from a set of '--typeid value' options."""
     connection = self.check_connection()
     path = {}
     for opt in options:
         if not opt.endswith('id'):
             continue
         typename = opt[2:-2]
         info = schema.type_info(typename)
         if info is None:
             self.error('unknown type: %s' % typename)
         path[info[3]] = (options[opt], info)
     base = connection.get(schema.API)
     info = schema.type_info(type(base))
     while path:
         links = connection.get_links(base)
         for link in links:
             if link in path:
                 break
         else:
             self.error('cannot find object in %s' % info[2])
         id, info = path.pop(link)
         base = self.get_object(info[0], id, base)
         if base is None:
             self.error('%s does not exist: %s' % (info[2], id))
     return base
Esempio n. 2
0
 def resolve_type(self, name):
     """return a rhev.schema.* mapping type for a type name."""
     info = schema.type_info(name)
     if info is None:
         plural = schema.plural(name)
         if plural is None:
             self.error('no such type: %s' % name)
         info = schema.type_info(name)
         assert info is not None
         return info[0]._SupersedingClass()
     return info[1]._SupersedingClass()
Esempio n. 3
0
 def show_help(self):
     """Show help for "update"."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     subst = {}
     if len(args) < 2:
         helptext = self.helptext0
         types = self.get_singular_types()
         subst['types'] = self.format_list(types)
     elif len(args) == 2:
         info = schema.type_info(args[0])
         if info is None:
             self.error('no such type: %s' % args[0])
         base = self.resolve_base(opts)
         obj = self.get_object(info[0], args[1], base=base)
         if obj is None:
             self.error('no such %s: %s' % (args[0], args[1]))
         methods = connection.get_methods(obj)
         if 'PUT' not in methods:
             self.error('type cannot be updated: %s' % args[0])
         helptext = self.helptext1
         subst['type'] = args[0]
         options = self.get_options(info[0], 'U')
         subst['options'] = self.format_list(options)
     statuses = self.get_statuses()
     subst['statuses'] = self.format_list(statuses)
     helptext = self.format_help(helptext, subst)
     stdout = self.context.terminal.stdout
     stdout.write(helptext)
Esempio n. 4
0
 def show_help(self):
     """Show help for "create"."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     stdout = self.context.terminal.stdout
     subst = {}
     if len(args) == 0:
         helptext = self.helptext0
         types = self.get_singular_types()
         subst['types'] = self.format_list(types)
     elif len(args) == 1:
         info = schema.type_info(args[0])
         if info is None:
             self.error('unknown type: %s' % args[0])
         base = self.resolve_base(opts)
         methods = connection.get_methods(info[1], base=base)
         if 'POST' not in methods:
             self.error('type cannot be created: %s' % args[0])
         helptext = self.helptext1
         subst['type'] = args[0]
         options = self.get_options(info[0], 'C')
         subst['options'] = self.format_list(options)
     statuses = self.get_statuses()
     subst['statuses'] = self.format_list(statuses)
     helptext = self.format_help(helptext, subst)
     stdout.write(helptext)
Esempio n. 5
0
 def _resolve_url(self, typ, base=None, id=None, search=None,
                  special=None, **query):
     """INTERNAL: resolve a relationship `name' under the URL `base'."""
     info = schema.type_info(typ)
     if info is None:
         raise TypeError, 'Unknown binding type: %s' % typ
     rel = info[3]
     if rel is None:
         raise TypeError, 'Can\'t resolve URLs for type: %s' % typ
     elif rel.startswith('/'):
         return self._join_path(self.entrypoint, rel)
     if base is None:
         base = self.api()
     if search:
         special = 'search'
     elif query:
         special = 'search'
         search = ' AND '.join([ '%s=%s' % (k, query[k]) for k in query ])
     if special:
         rel = '%s/%s' % (rel, special)
     for link in base.link:
         if link.rel == rel:
             url = link.href
             break
     else:
         reason = 'relationship %s not found under %s' % (rel, base.href)
         raise Error(reason)
     if id is not None:
         url = self._join_path(url, str(id))
     elif search is not None:
         url = url.replace('{query}', urlencode(search))
     return url
Esempio n. 6
0
 def get_attributes(self, typ, prefix=''):
     """Return a list of valid attributes for a type."""
     attrs = []
     for elem in typ._ElementMap:
         name = elem.localName()
         if name in ('actions', 'link', 'fault'):
             continue
         prop = getattr(typ, name)
         if not isinstance(prop, property):
             continue
         subtype = schema.subtype(prop)
         if issubclass(subtype, schema.ComplexType):
             info = schema.type_info(subtype)
             if info is None:
                 attrs += self.get_attributes(subtype, prefix + name + '.')
             elif info[3]:
                 attrs.append('%s%s.id' % (prefix, name))
                 attrs.append('%s%s.name' % (prefix, name))
         elif issubclass(subtype, schema.SimpleType):
             attrs.append('%s%s' % (prefix, name))
     for attr in typ._AttributeMap:
         if not prefix and attr in ('id', 'href'):
             continue
         name = attr.localName()
         attrs.append('%s%s' % (prefix, name))
     return attrs
Esempio n. 7
0
 def _format_collection(self, collection):
     context = self.context
     settings = context.settings
     stdout = context.terminal.stdout
     info = schema.type_info(type(collection))
     rel = info[2]
     fields = self._get_fields(rel)
     fields = self._filter_fields(fields, info[0])
     # Calculate the width of each column
     if stdout.isatty() and not settings['wide']:
         widths = [ len(f) for f in fields ]
         for resource in collection:
             for i in range(len(fields)):
                 value = self._get_value(resource, fields[i])
                 widths[i] = max(widths[i], len(value))
         total = sum(widths) + 2*len(fields)
         # Now downsize if it doesn't fit
         if total > context.terminal.width:
             fraction = 1.0 * context.terminal.width / total
             fwidths = [0] * len(fields)
             # Pass 1: round down to nearest integer
             for i in range(len(fields)):
                 fwidths[i] = widths[i] * fraction
                 widths[i] = int(fwidths[i])
             # Pass 2: allocate fractional leftovers to columns
             available = context.terminal.width - 2*len(fields) - sum(widths)
             remainders = [ (fwidths[i] - widths[i], i)
                            for i in range(len(fields)) ]
             remainders.sort(reverse=True)
             for i in range(min(len(fields), available)):
                 widths[remainders[i][1]] += 1
         formats = ['%%-%d.%ds' % (w, w) for w in widths ]
     else:
         widths = [ sys.maxint ] * len(fields)
         formats = [ '%s' ] * len(fields)
     if settings['header']:
         # Header
         for i in range(len(fields)):
             stdout.write(formats[i] % fields[i])
             if i != len(fields)-1:
                 stdout.write('  ')
         stdout.write('\n')
         # Horizontal line
         for i in range(len(fields)):
             stdout.write('-' * widths[i])
             if i != len(fields)-1:
                 stdout.write('  ')
         stdout.write('\n')
     # Data elements
     for resource in collection:
         values = [ self._get_value(resource, field) for field in fields ]
         while sum([len(v) for v in values]) > 0:
             for i in range(len(fields)):
                 stdout.write(formats[i] % values[i])
                 values[i] = values[i][widths[i]:]
                 if i != len(fields)-1:
                     stdout.write('  ')
             stdout.write('\n')
     stdout.write('\n')
Esempio n. 8
0
 def resolve_singular_type(self, name):
     """return a singular type only."""
     plural = schema.plural(name)
     if plural is None:
         self.error('no such type: %s' % name)
     info = schema.type_info(plural)
     assert info is not None
     return info[0]._SupersedingClass()
Esempio n. 9
0
 def show_help(self):
     """Show help for the action command."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     stdout = self.context.terminal.stdout
     subst = {}
     if len(args) < 2:
         helptext = self.helptext0
         types = self.get_singular_types()
         subst['types'] = self.format_list(types)
     elif len(args) == 2:
         helptext = self.helptext1
         info = schema.type_info(args[0])
         if info is None:
             self.error('no such type: %s' % args[0])
         subst['type'] = args[0]
         subst['id'] = args[1]
         base = self.resolve_base(opts)
         obj = self.get_object(info[0], args[1], base)
         if obj is None:
             self.error('no such %s: %s' % (args[0], args[1]))
         actions = connection.get_actions(obj)
         subst['actions'] = self.format_list(actions)
     elif len(args) == 3:
         helptext = self.helptext1
         info = schema.type_info(args[0])
         if info is None:
             self.error('no such type: %s' % args[0])
         subst['type'] = args[0]
         subst['id'] = args[1]
         subst['action'] = args[2]
         base = self.resolve_base(self.options)
         obj = self.get_object(info[0], args[1], base)
         if obj is None:
             self.error('no such %s: %s' % (args[0], args[1]))
         actions = connection.get_actions(obj)
         if args[2] not in actions:
             self.error('no such action: %s' % args[2])
         scope = '%s:%s' % (info[0].__name__, args[2])
         options = self.get_options(schema.Action, 'C', scope=scope)
         subst['options'] = self.format_list(options, bullet='')
     statuses = self.get_statuses()
     subst['statuses'] = self.format_list(statuses)
     helptext = self.format_help(helptext, subst)
     stdout.write(helptext)
Esempio n. 10
0
 def _get_types(self, plural):
     """INTERNAL: return a list of types."""
     connection = self.check_connection()
     links = connection.get_links(connection.api())
     types = [ schema.type_info(link) for link in links ]
     ix = 2 + int(plural)
     types = [ info[ix] for info in types if info and info[ix] ]
     return types
Esempio n. 11
0
 def _format_collection(self, collection, scope=None):
     context = self.context
     settings = context.settings
     stdout = context.terminal.stdout
     info = schema.type_info(type(collection))
     fields = self._get_fields(info[0], "L", scope)
     # Calculate the width of each column
     if stdout.isatty() and not settings["wide"]:
         widths = [len(f.name) for f in fields]
         for resource in collection:
             for i in range(len(fields)):
                 value = fields[i].get(resource, self.context)
                 widths[i] = max(widths[i], len(value))
         total = sum(widths) + 2 * len(fields)
         # Now downsize if it doesn't fit
         if total > context.terminal.width:
             fraction = 1.0 * context.terminal.width / total
             fwidths = [0] * len(fields)
             # Pass 1: round down to nearest integer
             for i in range(len(fields)):
                 fwidths[i] = widths[i] * fraction
                 widths[i] = int(fwidths[i])
             # Pass 2: allocate fractional leftovers to columns
             available = context.terminal.width - 2 * len(fields) - sum(widths)
             remainders = [(fwidths[i] - widths[i], i) for i in range(len(fields))]
             remainders.sort(reverse=True)
             for i in range(min(len(fields), available)):
                 widths[remainders[i][1]] += 1
         formats = ["%%-%d.%ds" % (w, w) for w in widths]
     else:
         widths = [sys.maxint] * len(fields)
         formats = ["%s"] * len(fields)
     if settings["header"]:
         # Header
         for i in range(len(fields)):
             stdout.write(formats[i] % fields[i].name)
             if i != len(fields) - 1:
                 stdout.write("  ")
         stdout.write("\n")
         # Horizontal line
         for i in range(len(fields)):
             stdout.write("-" * widths[i])
             if i != len(fields) - 1:
                 stdout.write("  ")
         stdout.write("\n")
     # Data elements
     for resource in collection:
         values = [field.get(resource, self.context) for field in fields]
         while sum([len(v) for v in values]) > 0:
             for i in range(len(fields)):
                 stdout.write(formats[i] % values[i])
                 values[i] = values[i][widths[i] :]
                 if i != len(fields) - 1:
                     stdout.write("  ")
             stdout.write("\n")
     stdout.write("\n")
Esempio n. 12
0
 def execute(self):
     """Execute "list"."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     info = schema.type_info(args[0])
     if info is None:
         self.error("no such type: %s" % args[0])
     base = self.resolve_base(opts)
     search = " ".join(self.arguments[1:])
     result = connection.getall(info[0], base=base, search=search)
     self.context.formatter.format(self.context, result)
Esempio n. 13
0
 def _get_fields(self, typ, flag, scope=None):
     info = schema.type_info(typ)
     assert info is not None
     override = self.context.settings.get("fields.%s" % info[2])
     if override is None:
         override = self.context.settings.get("fields")
     if override is None:
         fields = metadata.get_fields(typ, flag, scope)
     else:
         override = override.split(",")
         fields = metadata.get_fields(typ, "")
         fields = filter(lambda f: f.name in override, fields)
     return fields
Esempio n. 14
0
 def _fixup_object(self, obj):
     """INTERNAL: fixup a mapping object."""
     # Here we put stuff that we'd like to become part of the API itself.
     if isinstance(obj, schema.API):
         obj.href = self.entrypoint
     if hasattr(obj, 'link'):
         for link in obj.link:
             info = schema.type_info(link.rel, base=obj)
             if info:
                 link.type = info[0].__name__
     if hasattr(obj, 'actions') and hasattr(obj.actions, 'link'):
         for link in obj.actions.link:
             link.type = 'Action'
     return obj
Esempio n. 15
0
 def _resolve_url(self, typ, base=None, id=None, search=None,
                  special=None, **query):
     """INTERNAL: resolve a relationship `name' under the URL `base'."""
     info = schema.type_info(typ)
     if info is None:
         raise TypeError, 'Unknown binding type: %s' % typ
     rel = info[2]
     if rel is None:
         raise TypeError, 'Can\'t resolve URLs for type: %s' % typ
     elif rel.startswith('/'):
         return self._join_path(self.entrypoint, rel)
     if base is not None:
         if hasattr(base, 'href'):
             base = base.href
         else:
             base = self._resolve_url(type(base))
     else:
         base = self.entrypoint
     if search:
         special = 'search'
     elif query:
         special = 'search'
         search = ' AND '.join([ '%s=%s' % (k, query[k]) for k in query ])
     if special:
         rel = '%s/%s' % (rel, special)
     if base not in self._cache:
         response = self._make_request('GET', base)
         if response.status != http.OK:
             raise self._create_exception(response)
         parsed = self._parse_xml(response)
         self._cache[base] = parsed
     else:
         parsed = self._cache[base]
     for link in parsed.link:
         if link.rel == rel:
             url = link.href
             break
     else:
         reason = 'relationship %s not found under %s' % (rel, base)
         raise Error(reason)
     if id is not None:
         url = self._join_path(url, str(id))
     elif search is not None:
         url = url.replace('{query}', urlencode(search))
     return url
Esempio n. 16
0
 def execute(self):
     """Execute "delete"."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     base = self.resolve_base(opts)
     info = schema.type_info(args[0], base=base)
     if info is None:
         self.error('no such type: %s' % args[0])
     for link in base.link:
         if link.rel == info[3]:
             break
     else:
         self.error('type does not exist here: %s' % args[0])
     obj = self.get_object(info[0], args[1], base)
     if obj is None:
         self.error('object does not exist')
     result = connection.delete(obj)
     self.context.formatter.format(self.context, result)
Esempio n. 17
0
 def execute(self):
     """Execute the "create" command."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     stdout = self.context.terminal.stdout
     base = self.resolve_base(opts)
     info = schema.type_info(args[0], base=base)
     if info is None:
         self.error('no such type: %s' % args[0])
     for link in base.link:
         if link.rel == info[3]:
             break
     else:
         self.error('type cannot be created here: %s' % args[0])
     obj = self.read_object()
     if obj is None:
         obj = self.create_object(info[0], opts)
     connection.create(obj, base=base)
Esempio n. 18
0
 def execute(self):
     """Execute the "update" command."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     base = self.resolve_base(opts)
     info = schema.type_info(args[0], base=base)
     if info is None:
         self.error('no such type: %s' % args[0])
     for link in base.link:
         if link.rel == info[3]:
             break
     else:
         self.error('type does not exist here: %s' % args[0])
     obj = self.get_object(info[0], args[1], base)
     if obj is None:
         self.error('object does not exist')
     # Trac issue #179: don't set fields that already exist
     obj = schema.href(obj)
     self.update_object(obj, self.options)
     connection.update(obj)
Esempio n. 19
0
 def get_object(self, typ, id, base=None):
     """Return an object by id or name."""
     self.check_connection()
     connection = self.context.connection
     # Try by id
     try:
         obj = connection.get(typ, id=id, base=base)
     except rhev.Error:
         obj = None  # work around RHEV issue #120
     if obj is not None:
         return obj
     # Try by name: either search, or filter
     info = schema.type_info(typ)
     if base is None:
         base = connection.get(schema.API)
     links = connection.get_links(base)
     rel = '%s/search' % info[3]
     if rel in links:
         obj = connection.get(typ, name=id, base=base)
     else:
         obj = connection.get(typ, base=base, filter={'name': id})
     return obj
Esempio n. 20
0
 def execute(self):
     """Execute the action command."""
     args = self.arguments
     opts = self.options
     connection = self.check_connection()
     base = self.resolve_base(opts)
     info = schema.type_info(args[0], base=base)
     if info is None:
         self.error('no such type: %s' % args[0])
     for link in base.link:
         if link.rel == info[3]:
             break
     else:
         self.error('type does not exist here: %s' % args[0])
     obj = self.get_object(info[0], args[1], base)
     if obj is None:
         self.error('object does not exist: %s/%s', (args[0], args[1]))
     scope = '%s:%s' % (info[0].__name__, args[2])
     action = self.create_object(schema.Action, opts, scope=scope)
     try:
         result = connection.action(obj, args[2], action)
     except rhev.Error, e:
         self.error(str(e))
Esempio n. 21
0
 def resolve_plural_type(self, name):
     """resolve a plural type only."""
     info = schema.type_info(name)
     if info is None:
         self.error('no such type: %s' % name)
     return info[1]._SupersedingClass()