3 # Copyright 2016-2017 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
23 gi
.require_version('NsdBaseYang', '1.0')
24 gi
.require_version('ProjectNsdYang', '1.0')
25 gi
.require_version('NsrYang', '1.0')
26 from gi
.repository
import (
28 ProjectNsdYang
as NsdYang
,
33 class ScalingGroupIndexExists(Exception):
37 class ScaleGroupTrigger(Enum
):
38 """ Trigger for scaling config """
45 class ScaleGroupState(Enum
):
46 """ Scaling group state """
52 class ScalingGroup(object):
53 """ This represents a configured NSR scaling group """
54 def __init__(self
, log
, group_msg
):
55 """ Create a ScalingGroup instance
57 This class is responsible for representing a configured scaling group
58 which is present within an NSR.
60 :param log: A logger instance
61 :param group_msg: A NSD scaling group pb message
64 self
._group
_msg
= group_msg
69 return "ScalingGroup(%s)" % self
.name
73 """ Name of the scaling group """
74 return self
._group
_msg
.name
78 """ State of the scaling group """
79 state
= ScaleGroupState
.RUNNING
80 for instance
in self
._instances
.values():
81 if instance
.operational_status
in ["init", "vnf_init_phase"]:
82 self
._log
.debug("Scaling instance %s in scaling-out state: %s",
83 instance
, instance
.operational_status
)
84 state
= ScaleGroupState
.SCALING_OUT
86 elif instance
.operational_status
in ["terminate", "vnf_terminate_phase"]:
87 self
._log
.debug("Scaling instance %s in scaling-in state: %s",
88 instance
, instance
.operational_status
)
89 state
= ScaleGroupState
.SCALING_IN
94 def vnf_index_count_map(self
):
95 """ The mapping of member_vnf_index_ref to count"""
96 return {mbr
.member_vnf_index_ref
: mbr
.count
for mbr
in self
._group
_msg
.vnfd_member
}
100 """ Return the scale group PB message """
101 return self
._group
_msg
104 def min_instance_count(self
):
105 """ Minimum (and default) number of instance of the scaling group """
106 return self
._group
_msg
.min_instance_count
109 def max_instance_count(self
):
110 """ Maximum number of instance of the scaling group """
111 return self
._group
_msg
.max_instance_count
113 def create_record_msg(self
):
114 """ Returns a NSR Scaling group record """
115 msg
= NsrYang
.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ScalingGroupRecord(
116 scaling_group_name_ref
=self
.name
,
119 for instance
in self
.instances
:
120 msg
.instance
.append(instance
.create_record_msg())
126 return self
._instances
.values()
128 def get_instance(self
, instance_id
):
129 """ Get a scaling group instance
131 :param instance_id: The instance's instance_id
133 return self
._instances
[instance_id
]
135 def create_instance(self
, instance_id
, is_default
=False):
136 """ Create a scaling group instance
138 :param instance_id: The new instance's instance_id
140 self
._log
.debug("Creating %s instance instance_id %s ", self
, instance_id
)
142 if instance_id
in self
._instances
:
143 raise ScalingGroupIndexExists("%s instance_id %s already exists" % (self
, instance_id
))
145 instance
= ScalingGroupInstance(
147 group_name
=self
.name
,
148 instance_id
=instance_id
,
149 is_default
=is_default
,
152 self
._instances
[instance_id
] = instance
156 def delete_instance(self
, instance_id
):
157 self
._log
.debug("Deleting %s instance instance_id %s ", self
, instance_id
)
158 del self
._instances
[instance_id
]
160 def trigger_map(self
, trigger
):
162 NsdBaseYang
.ScalingTrigger
.PRE_SCALE_IN
: 'pre_scale_in',
163 NsdBaseYang
.ScalingTrigger
.POST_SCALE_IN
: 'post_scale_in',
164 NsdBaseYang
.ScalingTrigger
.PRE_SCALE_OUT
: 'pre_scale_out',
165 NsdBaseYang
.ScalingTrigger
.POST_SCALE_OUT
: 'post_scale_out',
169 return trig_map
[trigger
]
170 except Exception as e
:
171 self
._log
.error("Unknown scaling group trigger passed: {}".format(trigger
))
172 self
._log
.exception(e
)
174 def trigger_config(self
, trigger
):
175 """ Get the config action for the trigger """
176 self
._log
.debug("Trigger config {}: {}".format(trigger
, self
._group
_msg
))
177 trig
= self
.trigger_map(trigger
)
181 for config
in self
._group
_msg
.scaling_config_action
:
182 if trig
== config
.trigger
:
186 class ScalingGroupInstance(object):
187 """ This class represents a configured NSR Scaling Group instance"""
189 valid_status_list
= (
194 "vnf_terminate_phase",
199 valid_config_status_list
= (
205 def __init__(self
, log
, group_name
, instance_id
, is_default
=False):
207 self
._group
_name
= group_name
208 self
._instance
_id
= instance_id
209 self
._is
_default
= is_default
213 self
._create
_time
= int(time
.time())
214 self
._op
_status
= "init"
215 self
._config
_status
= "configuring"
216 self
._config
_err
_msg
= None
219 return "ScalingGroupInstance(%s #%s)" % (self
._group
_name
, self
.instance_id
)
222 def operational_status(self
):
223 return self
._op
_status
225 @operational_status.setter
226 def operational_status(self
, op_status
):
227 if op_status
not in ScalingGroupInstance
.valid_status_list
:
228 raise ValueError("Invalid scaling group instance status: %s", op_status
)
230 self
._op
_status
= op_status
233 def config_status(self
):
234 return self
._config
_status
236 @config_status.setter
237 def config_status(self
, status
):
238 if status
not in ScalingGroupInstance
.valid_config_status_list
:
239 raise ValueError("%s, invalid status: %s",
242 self
._config
_status
= status
245 def config_err_msg(self
):
246 return self
._config
_err
_msg
248 @config_err_msg.setter
249 def config_err_msg(self
, msg
):
250 if self
.config_err_msg
is not None:
251 self
._log
.info("%s, overwriting previous config error msg '%s' with '%s'",
252 self
, self
.config_err_msg
, msg
)
254 self
._config
_err
_msg
= msg
257 def instance_id(self
):
258 return self
._instance
_id
261 def is_default(self
):
262 return self
._is
_default
266 """ Return all VirtualNetworkFunctionRecord's that have been added"""
267 return self
._vnfrs
.values()
269 def create_record_msg(self
):
270 msg
= NsrYang
.YangData_RwProject_Project_NsInstanceOpdata_Nsr_ScalingGroupRecord_Instance(
271 instance_id
=self
._instance
_id
,
272 create_time
=self
._create
_time
,
273 op_status
=self
._op
_status
,
274 config_status
=self
._config
_status
,
275 error_msg
=self
._config
_err
_msg
,
276 is_default
=self
._is
_default
279 for vnfr
in self
.vnfrs
:
280 msg
.vnfrs
.append(vnfr
.id)
284 def add_vnfr(self
, vnfr
):
285 """ Add a VirtualNetworkFunctionRecord"""
286 self
._log
.debug("Added %s to %s", vnfr
, self
)
287 self
._vnfrs
[vnfr
.id] = vnfr