aria.ops.object

  1from __future__ import annotations
  2
  3import copy
  4from typing import Any
  5from typing import List
  6from typing import Optional
  7from typing import Set
  8
  9from aria.ops.data import Metric
 10from aria.ops.data import Property
 11from aria.ops.event import Event
 12
 13#  Copyright 2022 VMware, Inc.
 14#  SPDX-License-Identifier: Apache-2.0
 15
 16
 17class Key:
 18    """Object's Key class, used for identifying Objects
 19
 20    Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers.
 21
 22    Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs.
 23    In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True
 24    (this is the default).
 25
 26    Two Objects with the same Key are not permitted in a :class:`Result`.
 27
 28    Objects must be created with the full key. Keys should not change after the Object has been created.
 29
 30    All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have
 31    'is_part_of_uniqueness' set to True.
 32    """
 33
 34    def __init__(
 35        self,
 36        adapter_kind: str,
 37        object_kind: str,
 38        name: str,
 39        identifiers: Optional[List[Identifier]] = None,
 40    ) -> None:
 41        """Initializes a Key, which uniquely identifies a vROps Object
 42
 43        :param adapter_kind: The Adapter Kind this Object is associated with.
 44        :param object_kind: The Object Kind (e.g., class) of this Object.
 45        :param name: A human-readable name for this Object. Should be unique if possible.
 46        :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than
 47            the name must be unique and is used for identification. All Objects with the same adapter kind and Object
 48            kind must have the same set of identifiers.
 49        """
 50        self.adapter_kind = adapter_kind
 51        self.object_kind = object_kind
 52        self.name = name
 53        if identifiers is None:
 54            identifiers = []
 55        self.identifiers = {identifier.key: identifier for identifier in identifiers}
 56
 57    def __repr__(self) -> str:
 58        return f"{self.adapter_kind}:{self.object_kind}:{self.identifiers}"
 59
 60    def __key(self) -> tuple:
 61        # Sort all identifiers by 'key' that are part of uniqueness
 62        unique_identifiers = sorted(
 63            filter(lambda id_: id_.is_part_of_uniqueness, self.identifiers.values()),
 64            key=lambda id_: id_.key,
 65        )
 66        if len(unique_identifiers) == 0:
 67            # If there are no identifiers, or if all identifiers are not part of uniqueness, the name is used as
 68            # uniquely identifying
 69            return self.adapter_kind, self.object_kind, self.name
 70        else:
 71            # Otherwise, if there is at least one identifier that is part of uniqueness, name is not used for
 72            # identification. Add each of the unique identifiers to the tuple, sorted by key
 73            return (self.adapter_kind, self.object_kind) + tuple(unique_identifiers)
 74
 75    def __eq__(self, other: Any) -> bool:
 76        if isinstance(other, Key):
 77            # TODO: raise exception if the object types are the same but identifier keys don't match?
 78            return self.__key() == other.__key()
 79        else:
 80            return False
 81
 82    def __hash__(self) -> int:
 83        return hash(self.__key())
 84
 85    def get_identifier(
 86        self, key: str, default_value: Optional[str] = None
 87    ) -> Optional[str]:
 88        """Return the value for the given identifier key
 89
 90        :param key: The identifier key
 91        :param default_value: An optional default value
 92        :return: The value associated with the identifier.
 93        If the value associated with the identifier is empty and 'default_value' is
 94        provided, returns 'default_value'.
 95        If the identifier does not exist, returns default_value if provided, else 'None'.
 96        """
 97        if self.identifiers.get(key):
 98            if self.identifiers[key].value or default_value is None:
 99                return self.identifiers[key].value
100            return default_value
101        return default_value
102
103    def get_json(self) -> dict:
104        """Get a JSON representation of this Key
105
106        Returns a JSON representation of this Key in the format required by vROps.
107
108        :return: A JSON representation of this Key
109        """
110        return {
111            "name": self.name,
112            "adapterKind": self.adapter_kind,
113            "objectKind": self.object_kind,
114            "identifiers": [
115                identifier.get_json() for identifier in self.identifiers.values()
116            ],
117        }
118
119
120class IdentifierUniquenessException(Exception):
121    """Exception when two Objects of the same type have the same identifier but the `is_part_of_uniqueness` attribute
122    does not match.
123    """
124
125    pass
126
127
128class Identifier:
129    """Represents a piece of data that identifies an Object."""
130
131    def __init__(
132        self, key: str, value: str, is_part_of_uniqueness: bool = True
133    ) -> None:
134        """Creates an identifier which is used as part of an Object's identification in a :class:`Key`
135
136        Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can
137        change over time without creating a new Object. This is primarily used for human-readable values that are useful
138        in identification purposes, but may change at times.
139
140        :param key: A key that determines which identifier the value corresponds to.
141        :param value: The value of the identifier.
142        :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process
143        """
144        self.key = key
145        self.value = value
146        self.is_part_of_uniqueness = is_part_of_uniqueness
147
148    def __repr__(self) -> str:
149        u = "*" if self.is_part_of_uniqueness else ""
150        return f"{self.key}{u}:{self.value}"
151
152    def __key(self) -> tuple:
153        if self.is_part_of_uniqueness:
154            # 'True' is included as the second tuple because otherwise we could get a collision between a key that has
155            # a value of 'False' and a key that is not a part of uniqueness
156            return self.key, True, self.value
157        return self.key, False
158
159    def __eq__(self, other: Any) -> bool:
160        if isinstance(other, Identifier):
161            if (
162                self.key == other.key
163                and self.is_part_of_uniqueness != other.is_part_of_uniqueness
164            ):
165                # TODO: is there a better way we can handle this case?
166                raise IdentifierUniquenessException(
167                    f"Identifier '{self.key}' has an inconsistent uniqueness attribute"
168                )
169            return self.__key() == other.__key()
170        return False
171
172    def __hash__(self) -> int:
173        return hash(self.__key())
174
175    def get_json(self) -> dict:
176        """Get a JSON representation of this Identifier
177
178        Returns a JSON representation of this Identifier in the format required by vROps.
179
180        :return: A JSON representation of this Identifier
181        """
182        return {
183            "key": self.key,
184            "value": self.value,
185            "isPartOfUniqueness": self.is_part_of_uniqueness,
186        }
187
188
189class Object:
190    """Represents an Object (resource) in vROps.
191
192    Contains :class:`Metric`, :class:`Property`, :class:`Event`, and relationships to other Objects. Each Object is
193    identified by a unique :class:`Key`.
194    """
195
196    def __init__(self, key: Key) -> None:
197        """Create a new Object with a given Key.
198
199        The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result`
200        class, which ensures that for a given key only one Object exists.
201
202        :param key: The :class:`Key` that uniquely identifies this Object
203        """
204        self._key: Key = key
205        self._metrics: List[Metric] = []
206        self._properties: List[Property] = []
207        self._events: Set[Event] = set()
208        self._parents: Set[Key] = set()
209        self._children: Set[Key] = set()
210        self._updated_children: bool = False
211
212    def get_key(self) -> Key:
213        """Get a copy of the Object's Key.
214
215        An object's Key cannot change after it has been created.
216
217        :return: A copy of the object's key
218        """
219        return copy.deepcopy(self._key)
220
221    def adapter_type(self) -> str:
222        """Get the adapter type of this object
223
224        :return: The adapter type of this object
225        """
226        return self._key.adapter_kind
227
228    def object_type(self) -> str:
229        """Get the type of this object
230
231        :return: The type of this object
232        """
233        return self._key.object_kind
234
235    def get_identifier_value(
236        self, identifier_key: str, default_value: Optional[str] = None
237    ) -> Optional[str]:
238        """Retrieve the value of a given identifier
239
240        :param identifier_key: Key of the identifier
241        :param default_value: An optional default value
242        :return: The value associated with the identifier.
243        If the value associated with the identifier is empty and 'default_value' is
244        provided, returns 'default_value'.
245        If the identifier does not exist, returns default_value if provided, else 'None'.
246        """
247        return self._key.get_identifier(identifier_key, default_value)
248
249    def add_metric(self, metric: Metric) -> None:
250        """Method that adds a single Metric data point to this Object
251
252        :param metric: A :class:`Metric` data point to add to this Object
253        :return: None
254        """
255        self._metrics.append(metric)
256
257    def add_metrics(self, metrics: List[Metric]) -> None:
258        """Method that adds a list of Metric data points to this Object
259
260        :param metrics: A list of :class:`Metric` data points to add to this Object
261        :return: None
262        """
263        for metric in metrics:
264            self.add_metric(metric)
265
266    def with_metric(self, *args: Any, **kwargs: Any) -> None:
267        """Method that handles creating a :class:`Metric` data point, and adding to this Object.
268
269        The signature matches :class:`Metric.__init__`.
270        :return: None
271        """
272        self.add_metric(Metric(*args, **kwargs))
273
274    def get_metric(self, key: str) -> List[Metric]:
275        """
276
277        :param key: Metric key of the metric to return.
278        :return: All metrics matching the given key.
279        """
280        return list(filter(lambda metric: metric.key == key, self._metrics))
281
282    def get_metric_values(self, key: str) -> List[float]:
283        """
284
285        :param key: Metric key of the metric to return.
286        :return: A list of the metric values in chronological order.
287        """
288        # find matching metrics
289        metrics = self.get_metric(key)
290
291        # sort metrics by timestamp from oldest  to newest
292        metrics.sort(key=lambda metric: metric.timestamp)  # type: ignore
293
294        return [m.value for m in metrics]
295
296    def get_last_metric_value(self, key: str) -> Optional[float]:
297        """
298
299        :param key: Metric key of the metric to return.
300        :return: The latest value of the metric or None if no metric exists with the given key.
301        """
302        metrics = self.get_metric_values(key)
303
304        if not metrics:
305            return None
306        else:
307            return metrics[-1]
308
309    def add_property(self, property_: Property) -> None:
310        """Method that adds a single Property value to this Object
311
312        :param property_: A :class:`Property` value to add to this Object
313        :return: None
314        """
315        self._properties.append(property_)
316
317    def add_properties(self, properties: List[Property]) -> None:
318        """Method that adds a list of Property values to this Object
319
320        :param properties: A list of :class:`Property` values to add to this Object
321        :return: None
322        """
323        for property_ in properties:
324            self.add_property(property_)
325
326    def with_property(self, *args: Any, **kwargs: Any) -> None:
327        """Method that handles creating a :class:`Property` value, and adding to this Object.
328
329        The signature matches :class:`Property.__init__`.
330        :return: None
331        """
332        self.add_property(Property(*args, **kwargs))
333
334    def get_property(self, key: str) -> List[Property]:
335        """
336
337        :param key: Property key of the property to return.
338        :return: All properties matching the given key
339        """
340        return list(filter(lambda property_: property_.key == key, self._properties))
341
342    def get_property_values(self, key: str) -> List[str]:
343        """
344
345        :param key: Property key of the property to return.
346        :return: A list of the property values in chronological order.
347        """
348        # find matching properties
349        properties = self.get_property(key)
350
351        # sort properties by timestamp from oldest  to newest
352        properties.sort(key=lambda property_: property_.timestamp)  # type: ignore
353
354        return [p.value for p in properties]
355
356    def get_last_property_value(self, key: str) -> Optional[str | float]:
357        """
358
359        :param key: Property key of the property to return.
360        :return: The latest value of the property or None if no property exists with the given key.
361        """
362        properties = self.get_property_values(key)
363
364        if not properties:
365            return None
366        else:
367            return properties[-1]
368
369    def add_event(self, event: Event) -> None:
370        """Method that adds a single Event to this Object
371
372        :param event: An :class:`Event` to add to this Object
373        :return: None
374        """
375        self._events.add(event)
376
377    def add_events(self, events: List[Event]) -> None:
378        """Method that adds a list of Events to this Object
379
380        :param events: A list of :class:`Event` to add to this Object
381        :return: None
382        """
383        for event in events:
384            self.add_event(event)
385
386    def with_event(self, *args: Any, **kwargs: Any) -> None:
387        """Method that handles creating an :class:`Event`, and adding to this Object.
388
389        The signature matches :class:`Event.__init__`.
390        :return: None
391        """
392        self.add_event(Event(*args, **kwargs))
393
394    def add_parent(self, parent: Object) -> None:
395        """Method that adds a parent Object to this Object.
396
397        This Object will also be added as a child to the parent.
398
399        Relationship cycles are not permitted.
400
401        :param parent: Parent :class:`Object`
402        :return: None
403        """
404        self._parents.add(parent._key)
405        parent._children.add(self._key)
406
407    def add_parents(self, parents: List[Object]) -> None:
408        """Method that adds a list of parent Objects to this Object.
409
410        This Object will also be added as a child to each of the parents.
411
412        Relationship cycles are not permitted.
413
414        :param parents: A list of parent :class:`Object`
415        :return: None
416        """
417        for parent in parents:
418            self.add_parent(parent)
419
420    def get_parents(self) -> Set[Key]:
421        """
422        :return: A set of all object keys that are parents of this object
423        """
424        return self._parents
425
426    def add_child(self, child: Object) -> None:
427        """Method that adds a child Object to this Object.
428
429        This Object will also be added as a parent to the child.
430
431        Relationship cycles are not permitted.
432
433        :param child: Child :class:`Object`
434        :return: None
435        """
436        self._updated_children = True
437        self._children.add(child._key)
438        child._parents.add(self._key)
439
440    def add_children(self, children: List[Object]) -> None:
441        """Method that adds a list of child Objects to this Object.
442
443        This Object will also be added as a parent to each of the children.
444
445        Relationship cycles are not permitted.
446
447        :param children: A list of child :class:`Object`
448        :return: None
449        """
450        # We want to set this even in the case where the list is empty
451        self._updated_children = True
452        for child in children:
453            self.add_child(child)
454
455    def get_children(self) -> Set[Key]:
456        """
457        :return: A set of all object keys that are children of this object
458        """
459        return self._children
460
461    def has_content(self) -> bool:
462        """
463        :return: True if the object contains any metrics, properties or events; False otherwise.
464        """
465        return bool(self._metrics) or bool(self._properties) or bool(self._events)
466
467    def get_json(self) -> dict:
468        """Get a JSON representation of this Object
469
470        Returns a JSON representation of this Object in the format required by vROps.
471
472        :return: A JSON representation of this Object
473        """
474        return {
475            "key": self._key.get_json(),
476            "metrics": [metric.get_json() for metric in self._metrics],
477            "properties": [prop.get_json() for prop in self._properties],
478            "events": [event.get_json() for event in self._events],
479        }
class Key:
 18class Key:
 19    """Object's Key class, used for identifying Objects
 20
 21    Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers.
 22
 23    Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs.
 24    In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True
 25    (this is the default).
 26
 27    Two Objects with the same Key are not permitted in a :class:`Result`.
 28
 29    Objects must be created with the full key. Keys should not change after the Object has been created.
 30
 31    All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have
 32    'is_part_of_uniqueness' set to True.
 33    """
 34
 35    def __init__(
 36        self,
 37        adapter_kind: str,
 38        object_kind: str,
 39        name: str,
 40        identifiers: Optional[List[Identifier]] = None,
 41    ) -> None:
 42        """Initializes a Key, which uniquely identifies a vROps Object
 43
 44        :param adapter_kind: The Adapter Kind this Object is associated with.
 45        :param object_kind: The Object Kind (e.g., class) of this Object.
 46        :param name: A human-readable name for this Object. Should be unique if possible.
 47        :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than
 48            the name must be unique and is used for identification. All Objects with the same adapter kind and Object
 49            kind must have the same set of identifiers.
 50        """
 51        self.adapter_kind = adapter_kind
 52        self.object_kind = object_kind
 53        self.name = name
 54        if identifiers is None:
 55            identifiers = []
 56        self.identifiers = {identifier.key: identifier for identifier in identifiers}
 57
 58    def __repr__(self) -> str:
 59        return f"{self.adapter_kind}:{self.object_kind}:{self.identifiers}"
 60
 61    def __key(self) -> tuple:
 62        # Sort all identifiers by 'key' that are part of uniqueness
 63        unique_identifiers = sorted(
 64            filter(lambda id_: id_.is_part_of_uniqueness, self.identifiers.values()),
 65            key=lambda id_: id_.key,
 66        )
 67        if len(unique_identifiers) == 0:
 68            # If there are no identifiers, or if all identifiers are not part of uniqueness, the name is used as
 69            # uniquely identifying
 70            return self.adapter_kind, self.object_kind, self.name
 71        else:
 72            # Otherwise, if there is at least one identifier that is part of uniqueness, name is not used for
 73            # identification. Add each of the unique identifiers to the tuple, sorted by key
 74            return (self.adapter_kind, self.object_kind) + tuple(unique_identifiers)
 75
 76    def __eq__(self, other: Any) -> bool:
 77        if isinstance(other, Key):
 78            # TODO: raise exception if the object types are the same but identifier keys don't match?
 79            return self.__key() == other.__key()
 80        else:
 81            return False
 82
 83    def __hash__(self) -> int:
 84        return hash(self.__key())
 85
 86    def get_identifier(
 87        self, key: str, default_value: Optional[str] = None
 88    ) -> Optional[str]:
 89        """Return the value for the given identifier key
 90
 91        :param key: The identifier key
 92        :param default_value: An optional default value
 93        :return: The value associated with the identifier.
 94        If the value associated with the identifier is empty and 'default_value' is
 95        provided, returns 'default_value'.
 96        If the identifier does not exist, returns default_value if provided, else 'None'.
 97        """
 98        if self.identifiers.get(key):
 99            if self.identifiers[key].value or default_value is None:
100                return self.identifiers[key].value
101            return default_value
102        return default_value
103
104    def get_json(self) -> dict:
105        """Get a JSON representation of this Key
106
107        Returns a JSON representation of this Key in the format required by vROps.
108
109        :return: A JSON representation of this Key
110        """
111        return {
112            "name": self.name,
113            "adapterKind": self.adapter_kind,
114            "objectKind": self.object_kind,
115            "identifiers": [
116                identifier.get_json() for identifier in self.identifiers.values()
117            ],
118        }

Object's Key class, used for identifying Objects

Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers.

Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs. In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True (this is the default).

Two Objects with the same Key are not permitted in a Result.

Objects must be created with the full key. Keys should not change after the Object has been created.

All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have 'is_part_of_uniqueness' set to True.

Key( adapter_kind: str, object_kind: str, name: str, identifiers: Optional[List[aria.ops.object.Identifier]] = None)
35    def __init__(
36        self,
37        adapter_kind: str,
38        object_kind: str,
39        name: str,
40        identifiers: Optional[List[Identifier]] = None,
41    ) -> None:
42        """Initializes a Key, which uniquely identifies a vROps Object
43
44        :param adapter_kind: The Adapter Kind this Object is associated with.
45        :param object_kind: The Object Kind (e.g., class) of this Object.
46        :param name: A human-readable name for this Object. Should be unique if possible.
47        :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than
48            the name must be unique and is used for identification. All Objects with the same adapter kind and Object
49            kind must have the same set of identifiers.
50        """
51        self.adapter_kind = adapter_kind
52        self.object_kind = object_kind
53        self.name = name
54        if identifiers is None:
55            identifiers = []
56        self.identifiers = {identifier.key: identifier for identifier in identifiers}

Initializes a Key, which uniquely identifies a vROps Object

Parameters
  • adapter_kind: The Adapter Kind this Object is associated with.
  • object_kind: The Object Kind (e.g., class) of this Object.
  • name: A human-readable name for this Object. Should be unique if possible.
  • identifiers: A list of Identifier that uniquely identify the Object. If none are present than the name must be unique and is used for identification. All Objects with the same adapter kind and Object kind must have the same set of identifiers.
def get_identifier(self, key: str, default_value: Optional[str] = None) -> Optional[str]:
 86    def get_identifier(
 87        self, key: str, default_value: Optional[str] = None
 88    ) -> Optional[str]:
 89        """Return the value for the given identifier key
 90
 91        :param key: The identifier key
 92        :param default_value: An optional default value
 93        :return: The value associated with the identifier.
 94        If the value associated with the identifier is empty and 'default_value' is
 95        provided, returns 'default_value'.
 96        If the identifier does not exist, returns default_value if provided, else 'None'.
 97        """
 98        if self.identifiers.get(key):
 99            if self.identifiers[key].value or default_value is None:
100                return self.identifiers[key].value
101            return default_value
102        return default_value

Return the value for the given identifier key

Parameters
  • key: The identifier key
  • default_value: An optional default value
Returns

The value associated with the identifier. If the value associated with the identifier is empty and 'default_value' is provided, returns 'default_value'. If the identifier does not exist, returns default_value if provided, else 'None'.

def get_json(self) -> dict:
104    def get_json(self) -> dict:
105        """Get a JSON representation of this Key
106
107        Returns a JSON representation of this Key in the format required by vROps.
108
109        :return: A JSON representation of this Key
110        """
111        return {
112            "name": self.name,
113            "adapterKind": self.adapter_kind,
114            "objectKind": self.object_kind,
115            "identifiers": [
116                identifier.get_json() for identifier in self.identifiers.values()
117            ],
118        }

Get a JSON representation of this Key

Returns a JSON representation of this Key in the format required by vROps.

Returns

A JSON representation of this Key

class IdentifierUniquenessException(builtins.Exception):
121class IdentifierUniquenessException(Exception):
122    """Exception when two Objects of the same type have the same identifier but the `is_part_of_uniqueness` attribute
123    does not match.
124    """
125
126    pass

Exception when two Objects of the same type have the same identifier but the is_part_of_uniqueness attribute does not match.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
add_note
class Identifier:
129class Identifier:
130    """Represents a piece of data that identifies an Object."""
131
132    def __init__(
133        self, key: str, value: str, is_part_of_uniqueness: bool = True
134    ) -> None:
135        """Creates an identifier which is used as part of an Object's identification in a :class:`Key`
136
137        Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can
138        change over time without creating a new Object. This is primarily used for human-readable values that are useful
139        in identification purposes, but may change at times.
140
141        :param key: A key that determines which identifier the value corresponds to.
142        :param value: The value of the identifier.
143        :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process
144        """
145        self.key = key
146        self.value = value
147        self.is_part_of_uniqueness = is_part_of_uniqueness
148
149    def __repr__(self) -> str:
150        u = "*" if self.is_part_of_uniqueness else ""
151        return f"{self.key}{u}:{self.value}"
152
153    def __key(self) -> tuple:
154        if self.is_part_of_uniqueness:
155            # 'True' is included as the second tuple because otherwise we could get a collision between a key that has
156            # a value of 'False' and a key that is not a part of uniqueness
157            return self.key, True, self.value
158        return self.key, False
159
160    def __eq__(self, other: Any) -> bool:
161        if isinstance(other, Identifier):
162            if (
163                self.key == other.key
164                and self.is_part_of_uniqueness != other.is_part_of_uniqueness
165            ):
166                # TODO: is there a better way we can handle this case?
167                raise IdentifierUniquenessException(
168                    f"Identifier '{self.key}' has an inconsistent uniqueness attribute"
169                )
170            return self.__key() == other.__key()
171        return False
172
173    def __hash__(self) -> int:
174        return hash(self.__key())
175
176    def get_json(self) -> dict:
177        """Get a JSON representation of this Identifier
178
179        Returns a JSON representation of this Identifier in the format required by vROps.
180
181        :return: A JSON representation of this Identifier
182        """
183        return {
184            "key": self.key,
185            "value": self.value,
186            "isPartOfUniqueness": self.is_part_of_uniqueness,
187        }

Represents a piece of data that identifies an Object.

Identifier(key: str, value: str, is_part_of_uniqueness: bool = True)
132    def __init__(
133        self, key: str, value: str, is_part_of_uniqueness: bool = True
134    ) -> None:
135        """Creates an identifier which is used as part of an Object's identification in a :class:`Key`
136
137        Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can
138        change over time without creating a new Object. This is primarily used for human-readable values that are useful
139        in identification purposes, but may change at times.
140
141        :param key: A key that determines which identifier the value corresponds to.
142        :param value: The value of the identifier.
143        :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process
144        """
145        self.key = key
146        self.value = value
147        self.is_part_of_uniqueness = is_part_of_uniqueness

Creates an identifier which is used as part of an Object's identification in a Key

Represents a piece of data that identifies an Object. If is_part_of_uniqueness is False, this data can change over time without creating a new Object. This is primarily used for human-readable values that are useful in identification purposes, but may change at times.

Parameters
  • key: A key that determines which identifier the value corresponds to.
  • value: The value of the identifier.
  • is_part_of_uniqueness: Determines if this key/value pair is used in the identification process
def get_json(self) -> dict:
176    def get_json(self) -> dict:
177        """Get a JSON representation of this Identifier
178
179        Returns a JSON representation of this Identifier in the format required by vROps.
180
181        :return: A JSON representation of this Identifier
182        """
183        return {
184            "key": self.key,
185            "value": self.value,
186            "isPartOfUniqueness": self.is_part_of_uniqueness,
187        }

Get a JSON representation of this Identifier

Returns a JSON representation of this Identifier in the format required by vROps.

Returns

A JSON representation of this Identifier

class Object:
190class Object:
191    """Represents an Object (resource) in vROps.
192
193    Contains :class:`Metric`, :class:`Property`, :class:`Event`, and relationships to other Objects. Each Object is
194    identified by a unique :class:`Key`.
195    """
196
197    def __init__(self, key: Key) -> None:
198        """Create a new Object with a given Key.
199
200        The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result`
201        class, which ensures that for a given key only one Object exists.
202
203        :param key: The :class:`Key` that uniquely identifies this Object
204        """
205        self._key: Key = key
206        self._metrics: List[Metric] = []
207        self._properties: List[Property] = []
208        self._events: Set[Event] = set()
209        self._parents: Set[Key] = set()
210        self._children: Set[Key] = set()
211        self._updated_children: bool = False
212
213    def get_key(self) -> Key:
214        """Get a copy of the Object's Key.
215
216        An object's Key cannot change after it has been created.
217
218        :return: A copy of the object's key
219        """
220        return copy.deepcopy(self._key)
221
222    def adapter_type(self) -> str:
223        """Get the adapter type of this object
224
225        :return: The adapter type of this object
226        """
227        return self._key.adapter_kind
228
229    def object_type(self) -> str:
230        """Get the type of this object
231
232        :return: The type of this object
233        """
234        return self._key.object_kind
235
236    def get_identifier_value(
237        self, identifier_key: str, default_value: Optional[str] = None
238    ) -> Optional[str]:
239        """Retrieve the value of a given identifier
240
241        :param identifier_key: Key of the identifier
242        :param default_value: An optional default value
243        :return: The value associated with the identifier.
244        If the value associated with the identifier is empty and 'default_value' is
245        provided, returns 'default_value'.
246        If the identifier does not exist, returns default_value if provided, else 'None'.
247        """
248        return self._key.get_identifier(identifier_key, default_value)
249
250    def add_metric(self, metric: Metric) -> None:
251        """Method that adds a single Metric data point to this Object
252
253        :param metric: A :class:`Metric` data point to add to this Object
254        :return: None
255        """
256        self._metrics.append(metric)
257
258    def add_metrics(self, metrics: List[Metric]) -> None:
259        """Method that adds a list of Metric data points to this Object
260
261        :param metrics: A list of :class:`Metric` data points to add to this Object
262        :return: None
263        """
264        for metric in metrics:
265            self.add_metric(metric)
266
267    def with_metric(self, *args: Any, **kwargs: Any) -> None:
268        """Method that handles creating a :class:`Metric` data point, and adding to this Object.
269
270        The signature matches :class:`Metric.__init__`.
271        :return: None
272        """
273        self.add_metric(Metric(*args, **kwargs))
274
275    def get_metric(self, key: str) -> List[Metric]:
276        """
277
278        :param key: Metric key of the metric to return.
279        :return: All metrics matching the given key.
280        """
281        return list(filter(lambda metric: metric.key == key, self._metrics))
282
283    def get_metric_values(self, key: str) -> List[float]:
284        """
285
286        :param key: Metric key of the metric to return.
287        :return: A list of the metric values in chronological order.
288        """
289        # find matching metrics
290        metrics = self.get_metric(key)
291
292        # sort metrics by timestamp from oldest  to newest
293        metrics.sort(key=lambda metric: metric.timestamp)  # type: ignore
294
295        return [m.value for m in metrics]
296
297    def get_last_metric_value(self, key: str) -> Optional[float]:
298        """
299
300        :param key: Metric key of the metric to return.
301        :return: The latest value of the metric or None if no metric exists with the given key.
302        """
303        metrics = self.get_metric_values(key)
304
305        if not metrics:
306            return None
307        else:
308            return metrics[-1]
309
310    def add_property(self, property_: Property) -> None:
311        """Method that adds a single Property value to this Object
312
313        :param property_: A :class:`Property` value to add to this Object
314        :return: None
315        """
316        self._properties.append(property_)
317
318    def add_properties(self, properties: List[Property]) -> None:
319        """Method that adds a list of Property values to this Object
320
321        :param properties: A list of :class:`Property` values to add to this Object
322        :return: None
323        """
324        for property_ in properties:
325            self.add_property(property_)
326
327    def with_property(self, *args: Any, **kwargs: Any) -> None:
328        """Method that handles creating a :class:`Property` value, and adding to this Object.
329
330        The signature matches :class:`Property.__init__`.
331        :return: None
332        """
333        self.add_property(Property(*args, **kwargs))
334
335    def get_property(self, key: str) -> List[Property]:
336        """
337
338        :param key: Property key of the property to return.
339        :return: All properties matching the given key
340        """
341        return list(filter(lambda property_: property_.key == key, self._properties))
342
343    def get_property_values(self, key: str) -> List[str]:
344        """
345
346        :param key: Property key of the property to return.
347        :return: A list of the property values in chronological order.
348        """
349        # find matching properties
350        properties = self.get_property(key)
351
352        # sort properties by timestamp from oldest  to newest
353        properties.sort(key=lambda property_: property_.timestamp)  # type: ignore
354
355        return [p.value for p in properties]
356
357    def get_last_property_value(self, key: str) -> Optional[str | float]:
358        """
359
360        :param key: Property key of the property to return.
361        :return: The latest value of the property or None if no property exists with the given key.
362        """
363        properties = self.get_property_values(key)
364
365        if not properties:
366            return None
367        else:
368            return properties[-1]
369
370    def add_event(self, event: Event) -> None:
371        """Method that adds a single Event to this Object
372
373        :param event: An :class:`Event` to add to this Object
374        :return: None
375        """
376        self._events.add(event)
377
378    def add_events(self, events: List[Event]) -> None:
379        """Method that adds a list of Events to this Object
380
381        :param events: A list of :class:`Event` to add to this Object
382        :return: None
383        """
384        for event in events:
385            self.add_event(event)
386
387    def with_event(self, *args: Any, **kwargs: Any) -> None:
388        """Method that handles creating an :class:`Event`, and adding to this Object.
389
390        The signature matches :class:`Event.__init__`.
391        :return: None
392        """
393        self.add_event(Event(*args, **kwargs))
394
395    def add_parent(self, parent: Object) -> None:
396        """Method that adds a parent Object to this Object.
397
398        This Object will also be added as a child to the parent.
399
400        Relationship cycles are not permitted.
401
402        :param parent: Parent :class:`Object`
403        :return: None
404        """
405        self._parents.add(parent._key)
406        parent._children.add(self._key)
407
408    def add_parents(self, parents: List[Object]) -> None:
409        """Method that adds a list of parent Objects to this Object.
410
411        This Object will also be added as a child to each of the parents.
412
413        Relationship cycles are not permitted.
414
415        :param parents: A list of parent :class:`Object`
416        :return: None
417        """
418        for parent in parents:
419            self.add_parent(parent)
420
421    def get_parents(self) -> Set[Key]:
422        """
423        :return: A set of all object keys that are parents of this object
424        """
425        return self._parents
426
427    def add_child(self, child: Object) -> None:
428        """Method that adds a child Object to this Object.
429
430        This Object will also be added as a parent to the child.
431
432        Relationship cycles are not permitted.
433
434        :param child: Child :class:`Object`
435        :return: None
436        """
437        self._updated_children = True
438        self._children.add(child._key)
439        child._parents.add(self._key)
440
441    def add_children(self, children: List[Object]) -> None:
442        """Method that adds a list of child Objects to this Object.
443
444        This Object will also be added as a parent to each of the children.
445
446        Relationship cycles are not permitted.
447
448        :param children: A list of child :class:`Object`
449        :return: None
450        """
451        # We want to set this even in the case where the list is empty
452        self._updated_children = True
453        for child in children:
454            self.add_child(child)
455
456    def get_children(self) -> Set[Key]:
457        """
458        :return: A set of all object keys that are children of this object
459        """
460        return self._children
461
462    def has_content(self) -> bool:
463        """
464        :return: True if the object contains any metrics, properties or events; False otherwise.
465        """
466        return bool(self._metrics) or bool(self._properties) or bool(self._events)
467
468    def get_json(self) -> dict:
469        """Get a JSON representation of this Object
470
471        Returns a JSON representation of this Object in the format required by vROps.
472
473        :return: A JSON representation of this Object
474        """
475        return {
476            "key": self._key.get_json(),
477            "metrics": [metric.get_json() for metric in self._metrics],
478            "properties": [prop.get_json() for prop in self._properties],
479            "events": [event.get_json() for event in self._events],
480        }

Represents an Object (resource) in vROps.

Contains Metric, Property, Event, and relationships to other Objects. Each Object is identified by a unique Key.

Object(key: aria.ops.object.Key)
197    def __init__(self, key: Key) -> None:
198        """Create a new Object with a given Key.
199
200        The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result`
201        class, which ensures that for a given key only one Object exists.
202
203        :param key: The :class:`Key` that uniquely identifies this Object
204        """
205        self._key: Key = key
206        self._metrics: List[Metric] = []
207        self._properties: List[Property] = []
208        self._events: Set[Event] = set()
209        self._parents: Set[Key] = set()
210        self._children: Set[Key] = set()
211        self._updated_children: bool = False

Create a new Object with a given Key.

The preferred way to create a new Object is to call the Result.object method on the Result class, which ensures that for a given key only one Object exists.

Parameters
  • key: The Key that uniquely identifies this Object
def get_key(self) -> aria.ops.object.Key:
213    def get_key(self) -> Key:
214        """Get a copy of the Object's Key.
215
216        An object's Key cannot change after it has been created.
217
218        :return: A copy of the object's key
219        """
220        return copy.deepcopy(self._key)

Get a copy of the Object's Key.

An object's Key cannot change after it has been created.

Returns

A copy of the object's key

def adapter_type(self) -> str:
222    def adapter_type(self) -> str:
223        """Get the adapter type of this object
224
225        :return: The adapter type of this object
226        """
227        return self._key.adapter_kind

Get the adapter type of this object

Returns

The adapter type of this object

def object_type(self) -> str:
229    def object_type(self) -> str:
230        """Get the type of this object
231
232        :return: The type of this object
233        """
234        return self._key.object_kind

Get the type of this object

Returns

The type of this object

def get_identifier_value( self, identifier_key: str, default_value: Optional[str] = None) -> Optional[str]:
236    def get_identifier_value(
237        self, identifier_key: str, default_value: Optional[str] = None
238    ) -> Optional[str]:
239        """Retrieve the value of a given identifier
240
241        :param identifier_key: Key of the identifier
242        :param default_value: An optional default value
243        :return: The value associated with the identifier.
244        If the value associated with the identifier is empty and 'default_value' is
245        provided, returns 'default_value'.
246        If the identifier does not exist, returns default_value if provided, else 'None'.
247        """
248        return self._key.get_identifier(identifier_key, default_value)

Retrieve the value of a given identifier

Parameters
  • identifier_key: Key of the identifier
  • default_value: An optional default value
Returns

The value associated with the identifier. If the value associated with the identifier is empty and 'default_value' is provided, returns 'default_value'. If the identifier does not exist, returns default_value if provided, else 'None'.

def add_metric(self, metric: aria.ops.data.Metric) -> None:
250    def add_metric(self, metric: Metric) -> None:
251        """Method that adds a single Metric data point to this Object
252
253        :param metric: A :class:`Metric` data point to add to this Object
254        :return: None
255        """
256        self._metrics.append(metric)

Method that adds a single Metric data point to this Object

Parameters
  • metric: A Metric data point to add to this Object
Returns

None

def add_metrics(self, metrics: List[aria.ops.data.Metric]) -> None:
258    def add_metrics(self, metrics: List[Metric]) -> None:
259        """Method that adds a list of Metric data points to this Object
260
261        :param metrics: A list of :class:`Metric` data points to add to this Object
262        :return: None
263        """
264        for metric in metrics:
265            self.add_metric(metric)

Method that adds a list of Metric data points to this Object

Parameters
  • metrics: A list of Metric data points to add to this Object
Returns

None

def with_metric(self, *args: Any, **kwargs: Any) -> None:
267    def with_metric(self, *args: Any, **kwargs: Any) -> None:
268        """Method that handles creating a :class:`Metric` data point, and adding to this Object.
269
270        The signature matches :class:`Metric.__init__`.
271        :return: None
272        """
273        self.add_metric(Metric(*args, **kwargs))

Method that handles creating a Metric data point, and adding to this Object.

The signature matches Metric.__init__.

Returns

None

def get_metric(self, key: str) -> List[aria.ops.data.Metric]:
275    def get_metric(self, key: str) -> List[Metric]:
276        """
277
278        :param key: Metric key of the metric to return.
279        :return: All metrics matching the given key.
280        """
281        return list(filter(lambda metric: metric.key == key, self._metrics))
Parameters
  • key: Metric key of the metric to return.
Returns

All metrics matching the given key.

def get_metric_values(self, key: str) -> List[float]:
283    def get_metric_values(self, key: str) -> List[float]:
284        """
285
286        :param key: Metric key of the metric to return.
287        :return: A list of the metric values in chronological order.
288        """
289        # find matching metrics
290        metrics = self.get_metric(key)
291
292        # sort metrics by timestamp from oldest  to newest
293        metrics.sort(key=lambda metric: metric.timestamp)  # type: ignore
294
295        return [m.value for m in metrics]
Parameters
  • key: Metric key of the metric to return.
Returns

A list of the metric values in chronological order.

def get_last_metric_value(self, key: str) -> Optional[float]:
297    def get_last_metric_value(self, key: str) -> Optional[float]:
298        """
299
300        :param key: Metric key of the metric to return.
301        :return: The latest value of the metric or None if no metric exists with the given key.
302        """
303        metrics = self.get_metric_values(key)
304
305        if not metrics:
306            return None
307        else:
308            return metrics[-1]
Parameters
  • key: Metric key of the metric to return.
Returns

The latest value of the metric or None if no metric exists with the given key.

def add_property(self, property_: aria.ops.data.Property) -> None:
310    def add_property(self, property_: Property) -> None:
311        """Method that adds a single Property value to this Object
312
313        :param property_: A :class:`Property` value to add to this Object
314        :return: None
315        """
316        self._properties.append(property_)

Method that adds a single Property value to this Object

Parameters
  • property_: A Property value to add to this Object
Returns

None

def add_properties(self, properties: List[aria.ops.data.Property]) -> None:
318    def add_properties(self, properties: List[Property]) -> None:
319        """Method that adds a list of Property values to this Object
320
321        :param properties: A list of :class:`Property` values to add to this Object
322        :return: None
323        """
324        for property_ in properties:
325            self.add_property(property_)

Method that adds a list of Property values to this Object

Parameters
  • properties: A list of Property values to add to this Object
Returns

None

def with_property(self, *args: Any, **kwargs: Any) -> None:
327    def with_property(self, *args: Any, **kwargs: Any) -> None:
328        """Method that handles creating a :class:`Property` value, and adding to this Object.
329
330        The signature matches :class:`Property.__init__`.
331        :return: None
332        """
333        self.add_property(Property(*args, **kwargs))

Method that handles creating a Property value, and adding to this Object.

The signature matches Property.__init__.

Returns

None

def get_property(self, key: str) -> List[aria.ops.data.Property]:
335    def get_property(self, key: str) -> List[Property]:
336        """
337
338        :param key: Property key of the property to return.
339        :return: All properties matching the given key
340        """
341        return list(filter(lambda property_: property_.key == key, self._properties))
Parameters
  • key: Property key of the property to return.
Returns

All properties matching the given key

def get_property_values(self, key: str) -> List[str]:
343    def get_property_values(self, key: str) -> List[str]:
344        """
345
346        :param key: Property key of the property to return.
347        :return: A list of the property values in chronological order.
348        """
349        # find matching properties
350        properties = self.get_property(key)
351
352        # sort properties by timestamp from oldest  to newest
353        properties.sort(key=lambda property_: property_.timestamp)  # type: ignore
354
355        return [p.value for p in properties]
Parameters
  • key: Property key of the property to return.
Returns

A list of the property values in chronological order.

def get_last_property_value(self, key: str) -> Union[str, float, NoneType]:
357    def get_last_property_value(self, key: str) -> Optional[str | float]:
358        """
359
360        :param key: Property key of the property to return.
361        :return: The latest value of the property or None if no property exists with the given key.
362        """
363        properties = self.get_property_values(key)
364
365        if not properties:
366            return None
367        else:
368            return properties[-1]
Parameters
  • key: Property key of the property to return.
Returns

The latest value of the property or None if no property exists with the given key.

def add_event(self, event: aria.ops.event.Event) -> None:
370    def add_event(self, event: Event) -> None:
371        """Method that adds a single Event to this Object
372
373        :param event: An :class:`Event` to add to this Object
374        :return: None
375        """
376        self._events.add(event)

Method that adds a single Event to this Object

Parameters
  • event: An Event to add to this Object
Returns

None

def add_events(self, events: List[aria.ops.event.Event]) -> None:
378    def add_events(self, events: List[Event]) -> None:
379        """Method that adds a list of Events to this Object
380
381        :param events: A list of :class:`Event` to add to this Object
382        :return: None
383        """
384        for event in events:
385            self.add_event(event)

Method that adds a list of Events to this Object

Parameters
  • events: A list of Event to add to this Object
Returns

None

def with_event(self, *args: Any, **kwargs: Any) -> None:
387    def with_event(self, *args: Any, **kwargs: Any) -> None:
388        """Method that handles creating an :class:`Event`, and adding to this Object.
389
390        The signature matches :class:`Event.__init__`.
391        :return: None
392        """
393        self.add_event(Event(*args, **kwargs))

Method that handles creating an Event, and adding to this Object.

The signature matches Event.__init__.

Returns

None

def add_parent(self, parent: aria.ops.object.Object) -> None:
395    def add_parent(self, parent: Object) -> None:
396        """Method that adds a parent Object to this Object.
397
398        This Object will also be added as a child to the parent.
399
400        Relationship cycles are not permitted.
401
402        :param parent: Parent :class:`Object`
403        :return: None
404        """
405        self._parents.add(parent._key)
406        parent._children.add(self._key)

Method that adds a parent Object to this Object.

This Object will also be added as a child to the parent.

Relationship cycles are not permitted.

Parameters
Returns

None

def add_parents(self, parents: List[aria.ops.object.Object]) -> None:
408    def add_parents(self, parents: List[Object]) -> None:
409        """Method that adds a list of parent Objects to this Object.
410
411        This Object will also be added as a child to each of the parents.
412
413        Relationship cycles are not permitted.
414
415        :param parents: A list of parent :class:`Object`
416        :return: None
417        """
418        for parent in parents:
419            self.add_parent(parent)

Method that adds a list of parent Objects to this Object.

This Object will also be added as a child to each of the parents.

Relationship cycles are not permitted.

Parameters
  • parents: A list of parent Object
Returns

None

def get_parents(self) -> Set[aria.ops.object.Key]:
421    def get_parents(self) -> Set[Key]:
422        """
423        :return: A set of all object keys that are parents of this object
424        """
425        return self._parents
Returns

A set of all object keys that are parents of this object

def add_child(self, child: aria.ops.object.Object) -> None:
427    def add_child(self, child: Object) -> None:
428        """Method that adds a child Object to this Object.
429
430        This Object will also be added as a parent to the child.
431
432        Relationship cycles are not permitted.
433
434        :param child: Child :class:`Object`
435        :return: None
436        """
437        self._updated_children = True
438        self._children.add(child._key)
439        child._parents.add(self._key)

Method that adds a child Object to this Object.

This Object will also be added as a parent to the child.

Relationship cycles are not permitted.

Parameters
Returns

None

def add_children(self, children: List[aria.ops.object.Object]) -> None:
441    def add_children(self, children: List[Object]) -> None:
442        """Method that adds a list of child Objects to this Object.
443
444        This Object will also be added as a parent to each of the children.
445
446        Relationship cycles are not permitted.
447
448        :param children: A list of child :class:`Object`
449        :return: None
450        """
451        # We want to set this even in the case where the list is empty
452        self._updated_children = True
453        for child in children:
454            self.add_child(child)

Method that adds a list of child Objects to this Object.

This Object will also be added as a parent to each of the children.

Relationship cycles are not permitted.

Parameters
  • children: A list of child Object
Returns

None

def get_children(self) -> Set[aria.ops.object.Key]:
456    def get_children(self) -> Set[Key]:
457        """
458        :return: A set of all object keys that are children of this object
459        """
460        return self._children
Returns

A set of all object keys that are children of this object

def has_content(self) -> bool:
462    def has_content(self) -> bool:
463        """
464        :return: True if the object contains any metrics, properties or events; False otherwise.
465        """
466        return bool(self._metrics) or bool(self._properties) or bool(self._events)
Returns

True if the object contains any metrics, properties or events; False otherwise.

def get_json(self) -> dict:
468    def get_json(self) -> dict:
469        """Get a JSON representation of this Object
470
471        Returns a JSON representation of this Object in the format required by vROps.
472
473        :return: A JSON representation of this Object
474        """
475        return {
476            "key": self._key.get_json(),
477            "metrics": [metric.get_json() for metric in self._metrics],
478            "properties": [prop.get_json() for prop in self._properties],
479            "events": [event.get_json() for event in self._events],
480        }

Get a JSON representation of this Object

Returns a JSON representation of this Object in the format required by vROps.

Returns

A JSON representation of this Object