rift/mano/utils/__init.py__
rift/mano/utils/compare_desc.py
rift/mano/utils/juju_api.py
+ rift/mano/utils/short_name.py
COMPONENT ${PKG_LONG_NAME}
PYTHON3_ONLY
)
--- /dev/null
+#!/usr/bin/python
+
+#
+# Copyright 2017 RIFT.IO Inc
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Author: Aniruddha Atale
+
+import hashlib
+import basehash
+
+
+class StringShortner(object):
+ FOLDS = 3
+ STRING_LEN=9
+ def __init__(self, string = None):
+ self._string = string
+
+ @property
+ def string(self):
+ return self._string
+
+ @string.setter
+ def string(self, string):
+ self._string = string
+
+ @property
+ def short_string(self):
+ if self._string:
+ return StringShortner._get_short_string(self._string)
+ else:
+ return str()
+
+ @staticmethod
+ def _fold_hex_series(series):
+ length = len(series)
+ result = list()
+ for i in range(int(length/2)):
+ result.append(series[i] ^ series[(length - 1) - i])
+
+ if length % 2:
+ result.append(series[int(length/2) + 1])
+
+ return result
+
+ @staticmethod
+ def _num_from_hex_series(series):
+ result = 0
+ for i in range(len(series)):
+ result = result * 256
+ result += series[i]
+ return result
+
+ @staticmethod
+ def _get_short_string(string):
+ sha = hashlib.sha384(string.encode())
+ digest = sha.digest()
+ for i in range(StringShortner.FOLDS):
+ digest = StringShortner._fold_hex_series(digest)
+
+ number = StringShortner._num_from_hex_series(digest)
+ base62 = basehash.base62(length=StringShortner.STRING_LEN)
+ return base62.hash(number)
type string;
}
+ leaf unique-short-name {
+ description "Short Unique name of the VDU
+ This will be of the format NSR name-ShortnedString-VDUname
+ NSR name and VDU name shall be constrained to 10 characters";
+ rwpb:field-inline "true";
+ rwpb:field-string-max 64;
+ type string;
+ }
+
leaf vdu-id-ref {
type leafref {
path "../../vnfd/vdu/id";
}
"""
kwargs = dict()
+ metadata = dict()
+
+ if vdu_params.has_field('node_id'):
+ metadata['rift_node_id'] = vdu_params.node_id
+ kwargs['metadata'] = metadata
+
if vdu_params.has_field('vdu_init') and vdu_params.vdu_init.has_field('userdata'):
kwargs['userdata'] = vdu_params.vdu_init.userdata
else:
else:
kwargs['config_drive'] = False
- if vdu_params.supplemental_boot_data.has_field('custom_meta_data'):
- metadata = dict()
- for cm in vdu_params.supplemental_boot_data.custom_meta_data:
- metadata[cm] = cm.value
- kwargs['metadata'] = metadata
+ try:
+ # Rift model only
+ if vdu_params.supplemental_boot_data.has_field('custom_meta_data'):
+ metadata = dict()
+ for cm in vdu_params.supplemental_boot_data.custom_meta_data:
+ metadata[cm.name] = cm.value
+ kwargs['metadata'] = metadata
+ except Exception as e:
+ pass
return kwargs
else:
return str()
+ def _parse_vdu_boot_config_data(self, vm_info):
+ """
+ Parses VDU supplemental boot data
+ Arguments:
+ vm_info : A dictionary returned by novaclient library listing VM attributes
+
+ Returns:
+ List of RwcalYang.VDUInfoParams_SupplementalBootData()
+ """
+ supplemental_boot_data = None
+ node_id = None
+ if 'config_drive' in vm_info:
+ supplemental_boot_data = RwcalYang.VDUInfoParams_SupplementalBootData()
+ supplemental_boot_data.boot_data_drive = vm_info['config_drive']
+ # Look for any metadata
+ if 'metadata' not in vm_info:
+ return node_id, supplemental_boot_data
+ if supplemental_boot_data is None:
+ supplemental_boot_data = RwcalYang.VDUInfoParams_SupplementalBootData()
+ for key, value in vm_info['metadata'].items():
+ if key == 'rift_node_id':
+ node_id = value
+ else:
+ try:
+ # rift only
+ cm = supplemental_boot_data.custom_meta_data.add()
+ cm.name = key
+ cm.value = str(value)
+ except Exception as e:
+ pass
+ return node_id, supplemental_boot_data
+
def _parse_vdu_volume_info(self, vm_info):
"""
Get VDU server group information
ha = vdu.host_aggregate.add()
ha.from_dict(aggr.as_dict())
+ vdu.node_id, vdu.supplemental_boot_data = self._parse_vdu_boot_config_data(vm_info)
+
cp_list = self._parse_vdu_cp_info(vdu.vdu_id)
for cp in cp_list:
vdu.connection_points.append(cp)
from gi.repository import RwcalYang
from gi.repository.RwTypes import RwStatus
-from rift.rwcal.openstack.openstack_drv import KeystoneDriver, NovaDriver, KeystoneDriverV3, KeystoneDriverV2
+#from rift.rwcal.openstack.openstack_drv import KeystoneDriver, NovaDriver, KeystoneDriverV3, KeystoneDriverV2
logger = logging.getLogger('rwcal-openstack')
# Important information about openstack installation. This needs to be manually verified
#
openstack_info = {
- 'username' : 'pluto',
- 'password' : 'mypasswd',
- 'auth_url' : 'http://10.66.4.17:5000/v3/',
- 'project_name' : 'demo',
+ 'username' : 'xxxxxx',
+ 'password' : 'xxxxxx',
+ 'auth_url' : 'http://10.66.4.102:5000/v2.0/',
+ 'project_name' : 'xxxxxx',
'mgmt_network' : 'private',
'reserved_flavor' : 'm1.medium',
'reserved_image' : 'Fedora-x86_64-20-20131211.1-sda-ping.qcow2',
rc = self.cal.do_delete_flavor(self._acct, flavor_id)
self.assertEqual(rc, RwStatus.SUCCESS)
+ '''
@unittest.skip("Skipping test_expiry_token")
def test_expiry_token(self):
"""
except Exception:
auth_exp = True
self.assertFalse(auth_exp)
+ '''
@unittest.skip("Skipping test_vm_operations")
def test_vm_operations(self):
vdu.name = "cal.vdu"
vdu.node_id = OpenStackTest.NodeID
vdu.image_id = self._image.id
+ vdu.vm_flavor.memory_mb = 512
+ vdu.vm_flavor.vcpu_count = 1
+ vdu.vm_flavor.storage_gb = 4
vdu.flavor_id = self._flavor.id
vdu.vdu_init.userdata = PING_USERDATA
vdu.allocate_public_address = True
- meta1 = vdu.supplemental_boot_data.custom_meta_data.add()
- meta1.name = "EMS_IP"
- meta1.data_type = "STRING"
- meta1.value = "10.5.6.6"
- #meta2 = vdu.supplemental_boot_data.custom_meta_data.add()
- #meta2.name = "Cluster_data"
- #meta2.data_type = "JSON"
- #meta2.value = '''{ "cluster_id": "12" , "vnfc_id": "112" }'''
+ try:
+ meta1 = vdu.supplemental_boot_data.custom_meta_data.add()
+ meta1.name = "EMS_IP"
+ meta1.data_type = "STRING"
+ meta1.value = "10.5.6.6"
+ #meta2 = vdu.supplemental_boot_data.custom_meta_data.add()
+ #meta2.name = "Cluster_data"
+ #meta2.data_type = "JSON"
+ #meta2.value = '''{ "cluster_id": "12" , "vnfc_id": "112" }'''
+ except Exception as e:
+ pass
#vdu.supplemental_boot_data.boot_data_drive = True
customfile1 = vdu.supplemental_boot_data.config_file.add()
customfile1.source = "abcdef124"
return vdu
- @unittest.skip("Skipping test_create_delete_virtual_link_and_vdu")
+ #@unittest.skip("Skipping test_create_delete_virtual_link_and_vdu")
def test_create_delete_virtual_link_and_vdu(self):
"""
Test to create VDU
"""
vdu = RwcalYang.VDUInitParams()
vdu.name = "cal_vdu"
- vdu.flavor_id = self._flavor.id
+ vdu.vm_flavor.memory_mb = 512
+ vdu.vm_flavor.vcpu_count = 1
+ vdu.vm_flavor.storage_gb = 4
vdu.allocate_public_address = True
ctr = 0
for vl in vlink_list:
vol0.name = "vda"
vol0.image = openstack_info['reserved_image']
vol0.size = 10
- vol0.boot_priority = 0
+ try:
+ vol0.boot_priority = 0
+ except Exception as e:
+ pass
vol0.device_type = "disk"
- meta1 = vol0.custom_meta_data.add()
- meta1.name = "fs_type"
- meta1.data_type = "STRING"
- meta1.value = "ext4"
+ try:
+ meta1 = vol0.custom_meta_data.add()
+ meta1.name = "fs_type"
+ meta1.data_type = "STRING"
+ meta1.value = "ext4"
+ except Exception as e:
+ pass
return vdu
- #@unittest.skip("Skipping test_create_vol_vdu")
+ @unittest.skip("Skipping test_create_vol_vdu")
def test_create_vol_vdu(self):
"""
Test to create VDU with mgmt port using Volumes
# Fetch the VNFD associated with this VNF
placement_groups = self.get_placement_groups(vnfd_msg, const_vnfd)
self._log.info("Cloud Account for VNF %d is %s",const_vnfd.member_vnf_index,cloud_account_name)
- self._log.info("Launching VNF: %s (Member Index: %s) in NSD plancement Groups: %s",
+ self._log.info("Launching VNF: %s (Member Index: %s) in NSD plancement Groups: %s, restart mode self.restart_mode %s",
vnfd_msg.name,
const_vnfd.member_vnf_index,
- [ group.name for group in placement_groups])
+ [ group.name for group in placement_groups],
+ self.restart_mode)
vnfr = yield from VirtualNetworkFunctionRecord.create_record(self._dts,
self._log,
self._loop,
self._log.error(msg)
raise NetworkServiceRecordError(msg)
- self._log.info("Create NetworkServiceRecord nsr id %s from nsd_id %s",
+ self._log.info("Create NetworkServiceRecord nsr id %s from nsd_id %s, restart mode %s",
nsr_msg.id,
- nsr_msg.nsd.id)
+ nsr_msg.nsd.id,
+ restart_mode)
nsm_plugin = self._ro_plugin_selector.ro_plugin
sdn_account_name = self._cloud_account_handler.get_cloud_account_sdn_name(nsr_msg.cloud_account)
@asyncio.coroutine
def reallocate_virtual_network(self, event_id, cloud_account_name, request, resource):
- self._log.info("Received network resource allocation request with event-id: %s", event_id)
+ self._log.info("Received network resource reallocation request with event-id: %s", event_id)
resource = yield from self.core.reallocate_virtual_resource(event_id, cloud_account_name, request, 'network', resource)
return resource
@asyncio.coroutine
def reallocate_virtual_compute(self, event_id, cloud_account_name, request, resource):
- self._log.info("Received compute resource allocation request "
+ self._log.info("Received compute resource reallocation request "
"(cloud account: %s) with event-id: %s",
cloud_account_name, event_id)
resource = yield from self.core.reallocate_virtual_resource(
import rift.package.cloud_init
import rift.package.script
import rift.mano.dts as mano_dts
+import rift.mano.utils.short_name as mano_short_name
class VMResourceError(Exception):
loop,
vdud,
vnfr,
+ nsr_config,
mgmt_intf,
mgmt_network,
cloud_account_name,
self._loop = loop
self._vdud = vdud
self._vnfr = vnfr
+ self._nsr_config = nsr_config
self._mgmt_intf = mgmt_intf
self._cloud_account_name = cloud_account_name
self._vnfd_package_store = vnfd_package_store
""" Return this VDUR's name """
return self._name
+ # Truncated name confirming to RFC 1123
+ @property
+ def unique_short_name(self):
+ """ Return this VDUR's unique short name """
+ # Impose these restrictions on Unique name
+ # Max 64
+ # - Max 10 of NSR name (remove all specialcharacters, only numbers and alphabets)
+ # - 6 chars of shortened name
+ # - Max 10 of VDU name (remove all specialcharacters, only numbers and alphabets)
+ #
+ def _restrict_tag(input_str):
+ # Exclude all characters except a-zA-Z0-9
+ outstr = re.sub('[^a-zA-Z0-9]', '', input_str)
+ # Take max of 10 chars
+ return outstr[-10:]
+
+ # Use NSR name for part1
+ part1 = _restrict_tag(self._nsr_config.name)
+ # Get unique short string (6 chars)
+ part2 = mano_short_name.StringShortner(self._name)
+ # Use VDU ID for part3
+ part3 = _restrict_tag(self._vdud.id)
+ shortstr = part1 + "-" + part2.short_string + "-" + part3
+ return shortstr
+
@property
def cloud_account_name(self):
""" Cloud account this VDU should be created in """
"hypervisor_epa",
"host_epa",
"volumes",
- "name"]
+ ]
vdu_copy_dict = {k: v for k, v in
self._vdud.as_dict().items() if k in vdu_fields}
vdur_dict = {"id": self._vdur_id,
"vdu_id_ref": self._vdud.id,
"operational_status": self.operational_status,
"operational_status_details": self._state_failed_reason,
+ "name": self.name,
+ "unique_short_name": self.unique_short_name
}
+
if self.vm_resp is not None:
vdur_dict.update({"vim_id": self.vm_resp.vdu_id,
"flavor_id": self.vm_resp.flavor_id
vdu_copy_dict = {k: v for k, v in self._vdud.as_dict().items() if k in vdu_fields}
vm_create_msg_dict = {
- "name": self.name,
+ "name": self.unique_short_name, # Truncated name confirming to RFC 1123
+ "node_id": self.name, # Rift assigned Id
}
if self.image_name is not None:
return None
@asyncio.coroutine
- def get_vdu_placement_groups(self, vdu):
+ def get_vdu_placement_groups(self, vdu, nsr_config):
placement_groups = []
### Step-1: Get VNF level placement groups
for group in self._vnfr_msg.placement_groups_info:
#group_info.from_dict(group.as_dict())
placement_groups.append(group)
- ### Step-2: Get NSR config. This is required for resolving placement_groups cloud constructs
- nsr_config = yield from self.get_nsr_config()
-
- ### Step-3: Get VDU level placement groups
+ ### Step-2: Get VDU level placement groups
for group in self.vnfd.placement_groups:
for member_vdu in group.member_vdus:
if member_vdu.member_vdu_ref == vdu.id:
self._log.info("Creating VDU's for vnfd id: %s", self.vnfd_id)
+
+ # Get NSR config - Needed for placement groups and to derive VDU short-name
+ nsr_config = yield from self.get_nsr_config()
+
for vdu in self._rw_vnfd.vdu:
self._log.debug("Creating vdu: %s", vdu)
vdur_id = get_vdur_id(vdu)
- placement_groups = yield from self.get_vdu_placement_groups(vdu)
- self._log.info("Launching VDU: %s from VNFD :%s (Member Index: %s) with Placement Groups: %s",
+
+ placement_groups = yield from self.get_vdu_placement_groups(vdu, nsr_config)
+ self._log.info("Launching VDU: %s from VNFD :%s (Member Index: %s) with Placement Groups: %s, Existing vdur_id %s",
vdu.name,
self.vnf_name,
self.member_vnf_index,
- [ group.name for group in placement_groups])
+ [ group.name for group in placement_groups],
+ vdur_id)
vdur = VirtualDeploymentUnitRecord(
dts=self._dts,
loop=self._loop,
vdud=vdu,
vnfr=vnfr,
+ nsr_config=nsr_config,
mgmt_intf=self.has_mgmt_interface(vdu),
mgmt_network=self._mgmt_network,
cloud_account_name=self.cloud_account_name,
# instantiate VLs
- self._log.debug("VNFR-ID %s: Instantiate VLs", self._vnfr_id)
+ self._log.debug("VNFR-ID %s: Instantiate VLs, restart mode %s", self._vnfr_id, restart_mode)
try:
yield from self.instantiate_vls(xact, restart_mode)
except Exception as e:
self.set_state(VirtualNetworkFunctionRecordState.VM_INIT_PHASE)
# instantiate VDUs
- self._log.debug("VNFR-ID %s: Create VDUs", self._vnfr_id)
+ self._log.debug("VNFR-ID %s: Create VDUs, restart mode %s", self._vnfr_id, restart_mode)
yield from self.create_vdus(self, restart_mode)
try:
set_if_not_none('name', vdur._vdud.name)
set_if_not_none('mgmt.ip', vdur.vm_management_ip)
+ # The below can be used for hostname
+ set_if_not_none('vdur_name', vdur.unique_short_name)
def update(self, vdur):
"""Update the VDUR information in the datastore
set_or_delete('name', vdur._vdud.name)
set_or_delete('mgmt.ip', vdur.vm_management_ip)
+ # The below can be used for hostname
+ set_or_delete('vdur_name', vdur.unique_short_name)
def remove(self, vdur_id):
"""Remove all of the data associated with specified VDUR