88
99from typing import List
1010
11- from pydantic import BaseModel , validator , StrictStr , StrictInt , Extra
11+ from pydantic import BaseModel , validator , StrictStr , StrictInt , Extra , PrivateAttr
1212
1313
1414class Impact (str , Enum ):
@@ -82,7 +82,7 @@ class CircuitImpact(BaseModel, extra=Extra.forbid):
8282 # Optional Attributes
8383 impact : Impact = Impact .OUTAGE
8484
85- # pylint: disable=no-self-argument,no-self-use
85+ # pylint: disable=no-self-argument
8686 @validator ("impact" )
8787 def validate_impact_type (cls , value ):
8888 """Validate Impact type."""
@@ -91,27 +91,42 @@ def validate_impact_type(cls, value):
9191 return value
9292
9393
94+ class Metadata (BaseModel ):
95+ """Metadata class to provide context about the Maintenance object."""
96+
97+ provider : StrictStr
98+ processor : StrictStr
99+ parsers : List [StrictStr ]
100+ generated_by_llm : bool = False
101+
102+
94103class Maintenance (BaseModel , extra = Extra .forbid ):
95104 """Maintenance class.
96105
97106 Mandatory attributes:
98107 provider: identifies the provider of the service that is the subject of the maintenance notification
99108 account: identifies an account associated with the service that is the subject of the maintenance notification
100109 maintenance_id: contains text that uniquely identifies the maintenance that is the subject of the notification
101- circuits: list of circuits affected by the maintenance notification and their specific impact
110+ circuits: list of circuits affected by the maintenance notification and their specific impact. Note this can be
111+ an empty list for notifications with a CANCELLED status if the provider does not populate the circuit list.
112+ status: defines the overall status or confirmation for the maintenance
102113 start: timestamp that defines the start date of the maintenance in GMT
103114 end: timestamp that defines the end date of the maintenance in GMT
104115 stamp: timestamp that defines the update date of the maintenance in GMT
105116 organizer: defines the contact information included in the original notification
106117
107118 Optional attributes:
108- status: defines the overall status or confirmation for the maintenance
109119 summary: description of the maintenace notification
110120 uid: specific unique identifier for each notification
111121 sequence: sequence number - initially zero - to serialize updates in case they are received or processed out of
112122 order
113123
114124 Example:
125+ >>> metadata = Metadata(
126+ ... processor="SimpleProcessor",
127+ ... provider="genericprovider",
128+ ... parsers=["EmailDateParser"]
129+ ... )
115130 >>> Maintenance(
116131 ... account="12345000",
117132 ... end=1533712380,
@@ -125,26 +140,33 @@ class Maintenance(BaseModel, extra=Extra.forbid):
125140 ... status="COMPLETED",
126141 ... summary="This is a maintenance notification",
127142 ... uid="1111",
143+ ... _metadata=metadata,
128144 ... )
129- Maintenance(provider='A random NSP', account='12345000', maintenance_id='VNOC-1-99999999999', circuits=[CircuitImpact(circuit_id='123', impact=<Impact.NO_IMPACT: 'NO-IMPACT'>), CircuitImpact(circuit_id='456', impact=<Impact.OUTAGE: 'OUTAGE'>)], start=1533704400, end=1533712380, stamp=1533595768, organizer='[email protected] ', status=<Status.COMPLETED: 'COMPLETED'> , uid='1111', sequence=1, summary='This is a maintenance notification') 145+ Maintenance(provider='A random NSP', account='12345000', maintenance_id='VNOC-1-99999999999', status=<Status.COMPLETED: 'COMPLETED'>, circuits=[CircuitImpact(circuit_id='123', impact=<Impact.NO_IMPACT: 'NO-IMPACT'>), CircuitImpact(circuit_id='456', impact=<Impact.OUTAGE: 'OUTAGE'>)], start=1533704400, end=1533712380, stamp=1533595768, organizer='[email protected] ', uid='1111', sequence=1, summary='This is a maintenance notification') 130146 """
131147
132148 provider : StrictStr
133149 account : StrictStr
134150 maintenance_id : StrictStr
151+ status : Status
135152 circuits : List [CircuitImpact ]
136153 start : StrictInt
137154 end : StrictInt
138155 stamp : StrictInt
139156 organizer : StrictStr
140- status : Status
157+ _metadata : Metadata = PrivateAttr ()
141158
142159 # Non mandatory attributes
143160 uid : StrictStr = "0"
144161 sequence : StrictInt = 1
145162 summary : StrictStr = ""
146163
147- # pylint: disable=no-self-argument,no-self-use
164+ def __init__ (self , ** data ):
165+ """Initialize the Maintenance object."""
166+ self ._metadata = data .pop ("_metadata" )
167+ super ().__init__ (** data )
168+
169+ # pylint: disable=no-self-argument
148170 @validator ("status" )
149171 def validate_status_type (cls , value ):
150172 """Validate Status type."""
@@ -160,9 +182,9 @@ def validate_empty_strings(cls, value):
160182 return value
161183
162184 @validator ("circuits" )
163- def validate_empty_circuits (cls , value ):
164- """Validate emptry strings ."""
165- if len (value ) < 1 :
185+ def validate_empty_circuits (cls , value , values ):
186+ """Validate non-cancel notifications have a populated circuit list ."""
187+ if len (value ) < 1 and values [ "status" ] != "CANCELLED" :
166188 raise ValueError ("At least one circuit has to be included in the maintenance" )
167189 return value
168190
@@ -184,3 +206,8 @@ def slug(self) -> str:
184206 def to_json (self ) -> str :
185207 """Get JSON representation of the class object."""
186208 return json .dumps (self , default = lambda o : o .__dict__ , sort_keys = True , indent = 2 )
209+
210+ @property
211+ def metadata (self ):
212+ """Get Maintenance Metadata."""
213+ return self ._metadata
0 commit comments