7d095c1ee9b1724be7a6013b3f031b25b31058ae
1 # Copyright 2016 RIFT.io Inc
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from copy
import deepcopy
22 from rift
.mano
.yang_translator
.common
.exception
import ValidationError
23 from rift
.mano
.yang_translator
.common
.utils
import _
24 from rift
.mano
.yang_translator
.rwmano
.syntax
.tosca_resource \
27 import rift
.package
.image
29 TARGET_CLASS_NAME
= 'YangVdu'
32 class YangVdu(ToscaResource
):
33 '''Class for RIFT.io YANG VDU descriptor translation to TOSCA type.'''
37 OTHER_KEYS
= (VM_FLAVOR
, CLOUD_INIT
, IMAGE
, IMAGE_CHKSUM
,
38 VNFD_CP_REF
, CP_TYPE
, CLOUD_INIT_FILE
,) = \
39 ('vm_flavor', 'cloud_init', 'image', 'image_checksum',
40 'vnfd_connection_point_ref', 'cp_type', 'cloud_init_file',)
42 TOSCA_MISC_KEYS
= (VIRT_LINK
, VIRT_BIND
, VDU_INTF_NAME
,
44 ('virtualLink', 'virtualBinding', 'vdu_intf_name',
48 'vcpu_count': 'num_cpus',
49 'memory_mb': 'mem_size',
50 'storage_gb': 'disk_size',
64 super(YangVdu
, self
).__init
__(log
,
73 self
.cloud_init_file
= None
75 def process_vdu(self
):
76 self
.log
.debug(_("Process VDU desc {0}: {1}").format(self
.name
,
79 vdu_dic
= deepcopy(self
.yang
)
82 fields
= [self
.ID
, self
.COUNT
, self
.CLOUD_INIT
,
83 self
.IMAGE
, self
.IMAGE_CHKSUM
, self
.CLOUD_INIT_FILE
,]
86 vdu
[key
] = vdu_dic
.pop(key
)
88 self
.id = vdu
[self
.ID
]
90 if self
.VM_FLAVOR
in vdu_dic
:
92 for key
, value
in vdu_dic
.pop(self
.VM_FLAVOR
).items():
93 vdu
[self
.HOST
][self
.VM_FLAVOR_MAP
[key
]] = "{}{}". \
94 format(value
, self
.VM_SIZE_UNITS_MAP
[key
])
96 if self
.EXT_INTF
in vdu_dic
:
97 for ext_intf
in vdu_dic
.pop(self
.EXT_INTF
):
99 cp
[self
.NAME
] = ext_intf
.pop(self
.VNFD_CP_REF
)
100 cp
[self
.VDU_INTF_NAME
] = ext_intf
.pop(self
.NAME
)
101 cp
[self
.VDU_INTF_TYPE
] = ext_intf
[self
.VIRT_INTF
][self
.TYPE_Y
]
102 self
.log
.debug(_("{0}, External interface {1}: {2}").
103 format(self
, cp
, ext_intf
))
104 self
.ext_cp
.append(cp
)
106 self
.remove_ignored_fields(vdu_dic
)
108 self
.log
.warn(_("{0}, Did not process the following in "
110 format(self
, vdu_dic
))
112 self
.log
.debug(_("{0} VDU: {1}").format(self
, vdu
))
115 def get_cp(self
, name
):
116 for cp
in self
.ext_cp
:
117 if cp
[self
.NAME
] == name
:
121 def has_cp(self
, name
):
122 if self
.get_cp(name
):
126 def set_cp_type(self
, name
, cp_type
):
127 for idx
, cp
in enumerate(self
.ext_cp
):
128 if cp
[self
.NAME
] == name
:
129 cp
[self
.CP_TYPE
] = cp_type
130 self
.ext_cp
[idx
] = cp
131 self
.log
.debug(_("{0}, Updated CP: {1}").
132 format(self
, self
.ext_cp
[idx
]))
135 err_msg
= (_("{0}, Did not find connection point {1}").
137 self
.log
.error(err_msg
)
138 raise ValidationError(message
=err_msg
)
140 def set_vld(self
, name
, vld_name
):
141 cp
= self
.get_cp(name
)
143 cp
[self
.VLD
] = vld_name
145 err_msg
= (_("{0}, Did not find connection point {1}").
147 self
.log
.error(err_msg
)
148 raise ValidationError(message
=err_msg
)
150 def get_name(self
, vnf_name
):
151 # Create a unique name incase multiple VNFs use same
153 return "{}_{}".format(vnf_name
, self
.name
)
155 def generate_tosca_type(self
, tosca
):
156 self
.log
.debug(_("{0} Generate tosa types").
159 # Add custom artifact type
160 if self
.ARTIFACT_TYPES
not in tosca
:
161 tosca
[self
.ARTIFACT_TYPES
] = {}
162 if self
.T_ARTF_QCOW2
not in tosca
[self
.ARTIFACT_TYPES
]:
163 tosca
[self
.ARTIFACT_TYPES
][self
.T_ARTF_QCOW2
] = {
164 self
.DERIVED_FROM
: 'tosca.artifacts.Deployment.Image.VM.QCOW2',
166 {self
.TYPE
: self
.STRING
,
167 self
.REQUIRED
: self
.NO
},
170 if self
.T_VDU1
not in tosca
[self
.NODE_TYPES
]:
171 tosca
[self
.NODE_TYPES
][self
.T_VDU1
] = {
172 self
.DERIVED_FROM
: 'tosca.nodes.nfv.VDU',
175 {self
.TYPE
: self
.INTEGER
,
178 {self
.TYPE
: self
.STRING
,
179 self
.REQUIRED
: self
.NO
,},
180 self
.CLOUD_INIT_FILE
:
181 {self
.TYPE
: self
.STRING
,
182 self
.REQUIRED
: self
.NO
,},
186 self
.TYPE
: 'tosca.capabilities.nfv.VirtualLinkable'
192 if self
.T_CP1
not in tosca
[self
.NODE_TYPES
]:
193 tosca
[self
.NODE_TYPES
][self
.T_CP1
] = {
194 self
.DERIVED_FROM
: 'tosca.nodes.nfv.CP',
197 {self
.TYPE
: self
.STRING
,
198 self
.DESC
: 'Name of the connection point'},
200 {self
.TYPE
: self
.STRING
,
201 self
.DESC
: 'Type of the connection point'},
203 {self
.TYPE
: self
.STRING
,
204 self
.DESC
: 'Name of the interface on VDU'},
206 {self
.TYPE
: self
.STRING
,
207 self
.DESC
: 'Type of the interface on VDU'},
213 def generate_vdu_template(self
, tosca
, vnf_name
):
214 self
.log
.debug(_("{0} Generate tosca template for {2}").
215 format(self
, tosca
, vnf_name
))
217 name
= self
.get_name(vnf_name
)
220 node
[self
.TYPE
] = self
.T_VDU1
222 if self
.HOST
in self
.props
:
223 node
[self
.CAPABILITIES
] = {
224 self
.HOST
: {self
.PROPERTIES
: self
.props
.pop(self
.HOST
)}
227 self
.log
.warn(_("{0}, Does not have host requirements defined").
230 if self
.IMAGE
in self
.props
:
231 img_name
= "{}_{}_vm_image".format(vnf_name
, self
.name
)
232 image
= "../{}/{}".format(self
.IMAGE_DIR
, self
.props
.pop(self
.IMAGE
))
234 node
[self
.ARTIFACTS
] = {img_name
: {
236 self
.TYPE
: self
.T_ARTF_QCOW2
,
238 if self
.IMAGE_CHKSUM
in self
.props
:
239 node
[self
.ARTIFACTS
][img_name
][self
.IMAGE_CHKSUM
] = \
240 self
.props
.pop(self
.IMAGE_CHKSUM
)
241 node
[self
.INTERFACES
] = {'Standard': {
245 # Add cloud init script if available
246 if self
.CLOUD_INIT_FILE
in self
.props
:
247 self
.cloud_init_file
= self
.props
[self
.CLOUD_INIT_FILE
]
250 self
.props
.pop(self
.ID
)
251 node
[self
.PROPERTIES
] = self
.props
253 self
.log
.debug(_("{0}, VDU node: {1}").format(self
, node
))
254 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][name
] = node
256 # Generate the connection point templates
257 for cp
in self
.ext_cp
:
258 cpt
= {self
.TYPE
: self
.T_CP1
}
260 cpt
[self
.REQUIREMENTS
] = []
261 cpt
[self
.REQUIREMENTS
].append({self
.VIRT_BIND
: {
262 self
.NODE
: self
.get_name(vnf_name
)
265 vld
= cp
.pop(self
.VLD
)
266 cpt
[self
.REQUIREMENTS
].append({self
.VIRT_LINK
: {
270 cpt
[self
.PROPERTIES
] = cp
271 cp_name
= cp
[self
.NAME
].replace('/', '_')
273 self
.log
.debug(_("{0}, CP node {1}: {2}").
274 format(self
, cp_name
, cpt
))
275 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][cp_name
] = cpt
279 def get_supporting_files(self
):
282 if self
.image
is not None:
283 image_name
= os
.path
.basename(self
.image
)
287 self
.NAME
: image_name
,
288 self
.DEST
: "{}/{}".format(self
.IMAGE_DIR
, image_name
),
291 if self
.cloud_init_file
is not None:
293 self
.TYPE
: 'cloud_init',
294 self
.NAME
: self
.cloud_init_file
,
295 self
.DEST
: "{}/{}".format(self
.CLOUD_INIT
, self
.cloud_init_file
)
298 self
.log
.debug(_("Supporting files for {} : {}").format(self
, files
))
300 shutil
.rmtree(out_dir
)