def __init__(self, *args, **kwargs): if 'virtual_mem_size' in kwargs and 'num_virtual_cpu' in kwargs and 'image' in kwargs: self.memory = kwargs['virtual_mem_size'] self.cpu = kwargs['num_virtual_cpu'] self.image = kwargs['image'] self.network_name = kwargs['network_name'] if 'network_name' in kwargs else None self.user_name = kwargs['user_name'] if 'user_name' in kwargs else None self.user_public_key = kwargs['user_public_key'] if 'user_public_key' in kwargs else None self.config_map_mount_path = kwargs['config_map_mount_path'] if 'config_map_mount_path' in kwargs else None self.command = kwargs['command'] if 'command' in kwargs else None self.replicas = kwargs['replicas'] if 'replicas' in kwargs else None self.labels = kwargs['labels'] if 'labels' in kwargs and isinstance(kwargs['labels'], dict) else None if 'ports' in kwargs and 'name_of_service' in kwargs: self.name_of_service = kwargs['name_of_service'] super().__init__(*args, **kwargs) self.etcd_client = EtcdClient() self.etcd_client.set_deploy_name(instance_name=self.instance_name, pod_name=None)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.etcd_client = EtcdClient() self.alarm = AlarmEvent() global is_running if not is_running: threading.Thread( target=self._get_replica_event, args=(self.app_v1.list_deployment_for_all_namespaces, self.deployment_status), daemon=True).start() threading.Thread(target=partial(self._get_pod_event), daemon=True).start() threading.Thread( target=self._get_replica_event, args= (self.kubevirt_api. list_virtual_machine_instance_replica_set_for_all_namespaces, self.virtual_machine_replica_set), daemon=True).start() threading.Thread(target=partial(self._get_virtual_machine_event), daemon=True).start() is_running = True
def __init__(self, package_id): self.package_id = package_id super().__init__(self.get_root_path()) self.etcd_client = EtcdClient()
class NSLifecycleManagementViewSet(viewsets.ModelViewSet): queryset = NsInstance.objects.all() serializer_class = NsInstanceSerializer monitor_vnf = MonitorVnf() etcd_client = EtcdClient() def create(self, request, **kwargs): ns_descriptors_info = NsdInfo.objects.filter( nsdId=request.data['nsdId']).last() vnf_pkg_ids = json.loads(ns_descriptors_info.vnfPkgIds) nsd_info_id = str(ns_descriptors_info.id) request.data['nsdInfoId'] = nsd_info_id request.data['nsInstanceName'] = request.data['nsName'] request.data['nsInstanceDescription'] = request.data['nsDescription'] request.data['nsdId'] = request.data['nsdId'] request.data['vnfInstance'] = get_vnf_instance(vnf_pkg_ids) request.data['_links'] = {'self': request.build_absolute_uri()} request.data['vnffgInfo'] = get_vnffg(nsd_info_id) return super().create(request) def get_success_headers(self, data): return {'Location': data['_links']['self']} def destroy(self, request, *args, **kwargs): instance = self.get_object() if not_instantiated != instance.nsState: raise APIException( detail='nsState is not {}'.format(not_instantiated), code=status.HTTP_409_CONFLICT) super().destroy(request) return Response(status=status.HTTP_204_NO_CONTENT) @action(detail=True, methods=['POST'], url_path='instantiate') def instantiate_ns(self, request, **kwargs): ns_instance = self.get_object() if not_instantiated != ns_instance.nsState: raise APIException( detail='Network Service Instance State have been {}'.format( not_instantiated), code=status.HTTP_409_CONFLICT) vnf_instance_list = list() vnf_instance_data = request.data.pop('vnfInstanceData') process_vnffg = None if ns_instance.NsInstance_VnffgInfo.last() is not None: process_vnffg = ProcessFPInstance(str(ns_instance.nsdInfoId)) for vnf_instance_info in vnf_instance_data: vnf_instance = ns_instance.NsInstance_VnfInstance.get( id=vnf_instance_info['vnfInstanceId']) vnf_instance.VnfInstance_instantiatedVnfInfo.vnfState = 'STARTED' vnf_instance.VnfInstance_instantiatedVnfInfo.save() create_network_service = \ CreateService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process_instance() vnf_instance_list.append(vnf_instance) if process_vnffg: process_vnffg.mapping_rsp(vnf_instance.vnfdId, vnf_instance.vnfInstanceName) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.instantiate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.instantiate, vnf_instances=vnf_instance_list, container_phase='Running', usage_state=in_use) ns_instance.nsState = instantiated ns_instance.save() return Response( status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='scale') def scale_ns(self, request, **kwargs): ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException( detail='Network Service instance State have been INSTANTIATE') if 'scaleType' not in request.data: raise APIException(detail='scaleType parameter is necessary') vnf_instance_list = list() if 'SCALE_VNF' == request.data['scaleType']: for scale_vnf_data in request.data['scaleVnfData']: vnf_instance = ns_instance.NsInstance_VnfInstance.get( id=scale_vnf_data['vnfInstanceId']) if 'SCALE_OUT' == scale_vnf_data['scaleVnfType']: if 'additionalParams' in scale_vnf_data['scaleByStepData']: additional_params = scale_vnf_data['scaleByStepData'][ 'additionalParams'] replicas = int( additional_params['replicas'] ) if 'replicas' in additional_params else None virtual_mem_size = additional_params[ 'virtual_mem_size'] if 'virtual_mem_size' in additional_params else None num_virtual_cpu = additional_params[ 'num_virtual_cpu'] if 'num_virtual_cpu' in additional_params else None create_network_service = CreateService( vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process_instance( replicas=replicas, virtual_mem_size=virtual_mem_size, num_virtual_cpu=num_virtual_cpu) vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, 'SCALE') self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.scale, vnf_instances=vnf_instance_list, container_phase='Running', ns_state=instantiated, usage_state=in_use) return Response( status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='update') def update_ns(self, request, **kwargs): ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException( detail='Network Service instance State have been INSTANTIATE') if 'updateType' not in request.data: raise APIException(detail='updateType parameter is necessary') vnf_instance_list = list() if request.data['updateType'] == 'ADD_VNF': if 'addVnfInstance' not in request.data and isinstance( request.data['addVnfInstance'], list): raise APIException( detail='Not found removeVnfInstanceId parameter') add_vnf_instance = request.data['addVnfInstance'] for vnf_instance_request in add_vnf_instance: if 'vnfInstanceId' not in vnf_instance_request: raise APIException(detail='Error parameter vnfInstanceId') # vnfInstanceId (nm -> vnfpkgid) vnf_info = get_vnf_instance( [vnf_instance_request['vnfInstanceId']]).pop(0) vnf_instance = create_vnf_instance(vnf_info) ns_instance.NsInstance_VnfInstance.add(vnf_instance) create_network_service = CreateService( vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process_instance() vnf_instance_list.append(vnf_instance) elif request.data['updateType'] == 'REMOVE_VNF': if 'removeVnfInstanceId' not in request.data: raise APIException( detail='Not found removeVnfInstanceId parameter') vnf_instance = ns_instance.NsInstance_VnfInstance.get( id=request.data['removeVnfInstanceId']) vnf_instance.delete() delete_network_service = DeleteService( vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) delete_network_service.process_instance() vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.update) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.update, vnf_instances=vnf_instance_list, container_phase='Running', ns_state=instantiated, usage_state=in_use) return Response( status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='terminate') def terminate_ns(self, request, **kwargs): ns_instance = self.get_object() if instantiated != ns_instance.nsState: raise APIException( detail='Network Service instance State have been {}'.format( instantiated), code=status.HTTP_409_CONFLICT) vnf_instance_list = list() process_vnffg = None if ns_instance.NsInstance_VnffgInfo.last() is not None: process_vnffg = ProcessFPInstance(str(ns_instance.nsdInfoId)) for vnf_instance in ns_instance.NsInstance_VnfInstance.all(): vnf_instance.VnfInstance_instantiatedVnfInfo.vnfState = 'STOPPED' vnf_instance.VnfInstance_instantiatedVnfInfo.save() delete_network_service = \ DeleteService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) delete_network_service.process_instance() self.etcd_client.set_deploy_name( instance_name=vnf_instance.vnfInstanceName.lower(), pod_name=None) self.etcd_client.release_pod_ip_address() vnf_instance_list.append(vnf_instance) if process_vnffg: process_vnffg.mapping_rsp(vnf_instance.vnfdId, vnf_instance.vnfInstanceName) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.terminate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.terminate, vnf_instances=vnf_instance_list, container_phase='Terminating', usage_state=not_in_use) ns_instance.nsState = not_instantiated ns_instance.save() if process_vnffg: process_vnffg.remove_vnffg() return Response( status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self})
class NSLifecycleManagementViewSet(viewsets.ModelViewSet): queryset = NsInstance.objects.all() serializer_class = NsInstanceSerializer monitor_vnf = MonitorVnf() etcd_client = EtcdClient() def create(self, request, **kwargs): ns_descriptors_info = NsdInfo.objects.filter(nsdId=request.data['nsdId']).last() vnf_pkg_ids = json.loads(ns_descriptors_info.vnfPkgIds) nsd_info_id = str(ns_descriptors_info.id) request.data['nsdInfoId'] = nsd_info_id request.data['nsInstanceName'] = request.data['nsName'] request.data['nsInstanceDescription'] = request.data['nsDescription'] request.data['nsdId'] = request.data['nsdId'] request.data['vnfInstance'] = get_vnf_Instance(vnf_pkg_ids) request.data['_links'] = {'self': request.build_absolute_uri()} request.data['vnffgInfo'] = get_vnffg(nsd_info_id) return super().create(request) def get_success_headers(self, data): return {'Location': data['_links']['self']} def destroy(self, request, *args, **kwargs): instance = self.get_object() if not_instantiated != instance.nsState: raise APIException(detail='nsState is not {}'.format(not_instantiated), code=status.HTTP_409_CONFLICT) super().destroy(request) return Response(status=status.HTTP_204_NO_CONTENT) @action(detail=True, methods=['POST'], url_path='instantiate') def instantiate_ns(self, request, **kwargs): ns_instance = self.get_object() if not_instantiated != ns_instance.nsState: raise APIException(detail='Network Service Instance State have been {}'.format(not_instantiated), code=status.HTTP_409_CONFLICT) vnf_instance_list = list() vnf_instance_data = request.data.pop('vnfInstanceData') process_vnffg = None if ns_instance.NsInstance_VnffgInfo.last() is not None: process_vnffg = ProcessFPInstance(str(ns_instance.nsdInfoId)) for vnf_instance_info in vnf_instance_data: vnf_instance = ns_instance.NsInstance_VnfInstance.get(id=vnf_instance_info['vnfInstanceId']) create_network_service = \ CreateService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process() vnf_instance_list.append(vnf_instance) if process_vnffg: process_vnffg.mapping_rsp(vnf_instance.vnfdId, vnf_instance.vnfInstanceName) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.instantiate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.instantiate, vnf_instances=vnf_instance_list, container_phase='Running', usage_state=in_use) ns_instance.nsState = instantiated ns_instance.save() return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='terminate') def terminate_ns(self, request, **kwargs): ns_instance = self.get_object() if instantiated != ns_instance.nsState: raise APIException(detail='Network Service instance State have been {}'.format(instantiated), code=status.HTTP_409_CONFLICT) vnf_instance_list = list() process_vnffg = None if ns_instance.NsInstance_VnffgInfo.last() is not None: process_vnffg = ProcessFPInstance(str(ns_instance.nsdInfoId)) for vnf_instance in ns_instance.NsInstance_VnfInstance.all(): delete_network_service = \ DeleteService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) delete_network_service.process() self.etcd_client.set_deploy_name(instance_name=vnf_instance.vnfInstanceName.lower(), pod_name=None) self.etcd_client.release_pod_ip_address() vnf_instance_list.append(vnf_instance) if process_vnffg: process_vnffg.mapping_rsp(vnf_instance.vnfdId, vnf_instance.vnfInstanceName) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.terminate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.terminate, vnf_instances=vnf_instance_list, container_phase='Terminating', usage_state=not_in_use) ns_instance.nsState = not_instantiated ns_instance.save() if process_vnffg: process_vnffg.remove_vnffg() return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self})
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.run_watch_event() self.etcd_client = EtcdClient()
class MonitorDeployment(BaseKubernetes): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # self.run_watch_event() self.etcd_client = EtcdClient() # def run_watch_event(self): # threading.Thread( # target=partial(self._get_deployment_event), # daemon=True # ).start() # # threading.Thread( # target=partial(self._get_pod_event), # daemon=True # ).start() def _get_pod_event(self, resource_version): if resource_version is None: stream = self.watch.stream(partial(self.core_v1.list_pod_for_all_namespaces), timeout_seconds=5) else: stream = self.watch.stream(partial(self.core_v1.list_pod_for_all_namespaces), resource_version=resource_version, timeout_seconds=5) for event in stream: _type = event['type'] _metadata = event['object']['metadata'] _status = event['object']['status'] if 'name' not in _metadata: continue _name = _metadata['name'] resource_version = _metadata['resourceVersion'] _phase = _status['phase'] if _type == 'MODIFIED' and 'deletionTimestamp' not in _metadata: if 'containerStatuses' in _status: container_status = _status['containerStatuses'] for status in container_status: if 'state' not in status: continue state = status['state'] if 'waiting' in state and \ 'CrashLoopBackOff' == state['waiting']['reason']: # alarm self.pod_crash_event(None, _name) else: self.pod_status[_name] = _phase elif _type == 'DELETED' and _name in list( self.pod_status) and 'deletionTimestamp' in _metadata: self.pod_crash_event(_name, None) else: self.pod_status[_name] = _phase return resource_version def pod_crash_event(self, instance_name, pod_name): if pod_name: self.pod_status.pop(pod_name) self.etcd_client.set_deploy_name(instance_name=instance_name, pod_name=pod_name) self.etcd_client.release_pod_ip_address() def _get_deployment_event(self, resource_version): if resource_version is None: stream = self.watch.stream(partial(self.app_v1.list_deployment_for_all_namespaces), timeout_seconds=5) else: stream = self.watch.stream(partial(self.app_v1.list_deployment_for_all_namespaces), resource_version=resource_version, timeout_seconds=5) for event in stream: _type = event['type'] if 'name' not in event['object']['metadata']: continue _name = event['object']['metadata']['name'] resource_version = event['object']['metadata']['resourceVersion'] replicas = event['object']['spec']['replicas'] if _type == 'DELETED' and _name in list(self.deployment_status): self.deployment_status.pop(_name) else: if _name not in list(self.deployment_status): self.deployment_status[_name] = {'replicas': replicas} return resource_version def watch_specific_deployment(self, container_instance_name, _status, events): _queue = queue.Queue() threading.Thread( target=partial(self._get_deploy_status, _queue=_queue, events=events), daemon=True ).start() threading.Thread( target=lambda q, deploy_names, status: q.put( self._check_specific_deployment_status( input_deployment_set=deploy_names, status=status)), args=(_queue, container_instance_name, _status), daemon=True ).start() def _check_specific_deployment_status(self, input_deployment_set, status): loop_count = -1 resource_version_deployment = None resource_version_pod = None while len(input_deployment_set) != 0: resource_version_deployment = self._get_deployment_event(resource_version_deployment) resource_version_pod = self._get_pod_event(resource_version_pod) if loop_count < 0: loop_count = len(input_deployment_set) - 1 all_deployment_key = list(self.deployment_status) input_specific_deployment = list(input_deployment_set)[loop_count] if status == 'Terminating': if input_specific_deployment not in all_deployment_key: input_deployment_set.remove(input_specific_deployment) else: if input_specific_deployment in all_deployment_key: pod_status_count = 0 for pod_name in list(self.pod_status): if input_specific_deployment in pod_name: if status == self.pod_status[pod_name]: pod_status_count += 1 if self.deployment_status[input_specific_deployment]['replicas'] == pod_status_count: input_deployment_set.remove(input_specific_deployment) loop_count = loop_count - 1 return True def _get_deploy_status(self, _queue, events): while _queue.empty(): pass print('success') [event() for event in events]
class MonitorDeployment(BaseKubernetes): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.etcd_client = EtcdClient() self.alarm = AlarmEvent() global is_running if not is_running: threading.Thread( target=self._get_replica_event, args=(self.app_v1.list_deployment_for_all_namespaces, self.deployment_status), daemon=True).start() threading.Thread(target=partial(self._get_pod_event), daemon=True).start() threading.Thread( target=self._get_replica_event, args= (self.kubevirt_api. list_virtual_machine_instance_replica_set_for_all_namespaces, self.virtual_machine_replica_set), daemon=True).start() threading.Thread(target=partial(self._get_virtual_machine_event), daemon=True).start() is_running = True def _get_replica_event(self, events, record: dict): while True: stream = self.watch.stream(partial(events), timeout_seconds=5) for event in stream: _type = event['type'] if 'name' not in event['object']['metadata']: continue _name = event['object']['metadata']['name'] replicas = event['object']['spec']['replicas'] if _name not in list(record): record[_name] = {'replicas': replicas} def _get_virtual_machine_event(self): while True: for vmi in self.kubevirt_api.list_virtual_machine_instance_for_all_namespaces( ).items: metadata = vmi.metadata name = metadata.name deletion_timestamp = metadata.deletion_timestamp status = vmi.status phase = status.phase if status.conditions: if 'Failed' == phase: if not deletion_timestamp: error_reason = None error_message = None type_record = list() for conditions in status.conditions: type_record.append(conditions.type) if conditions.type != 'LiveMigratable' and conditions.type != 'Ready': error_reason = conditions.reason error_message = conditions.message if 'Ready' not in type_record: self.alarm.create_alarm( name, error_reason, error_message, False) if name in list(self.virtual_machine_status): self.virtual_machine_status.pop(name) elif name in list(self.virtual_machine_status): self.virtual_machine_status.pop(name) elif phase == 'Running' and name: self.virtual_machine_status[name] = phase def _get_pod_event(self): while True: stream = self.watch.stream(partial( self.core_v1.list_pod_for_all_namespaces), timeout_seconds=5) for event in stream: _type = event['type'] _metadata = event['object']['metadata'] _status = event['object']['status'] if 'name' not in _metadata: continue _name = _metadata['name'] _phase = _status['phase'] if _phase == 'Running': self.pod_status[_name] = _phase if _type == 'MODIFIED' and 'deletionTimestamp' not in _metadata: if 'containerStatuses' in _status: container_status = _status['containerStatuses'] for status in container_status: if 'state' not in status: continue state = status['state'] if 'waiting' in state and \ 'CrashLoopBackOff' == state['waiting']['reason']: self.alarm.create_alarm( _name, state['waiting']['reason'], state['waiting']['message'], True) if _name in list(self.pod_status): self.pod_crash_event(None, _name) elif _type == 'DELETED' and _name in list( self.pod_status) and 'deletionTimestamp' in _metadata: self.pod_crash_event(_name, None) self.pod_status.pop(_name) def pod_crash_event(self, instance_name, pod_name): self.etcd_client.set_deploy_name(instance_name=instance_name, pod_name=pod_name) self.etcd_client.release_pod_ip_address() def watch_specific_deployment(self, container_instance_name, vm_instance_name, _status, events): _queue = queue.Queue() # check two event success_count = 2 threading.Thread(target=partial(self._get_deploy_status, _queue=_queue, events=events, success_count=success_count), daemon=True).start() threading.Thread(target=lambda q, deployment_names, status: q.put( self._check_status( input_set=deployment_names, status=status, isContainer=True)), args=(_queue, container_instance_name, _status), daemon=True).start() threading.Thread(target=lambda q, vm_names, status: q.put( self._check_status( input_set=vm_names, status=status, isContainer=False)), args=(_queue, vm_instance_name, _status), daemon=True).start() def _check_status(self, input_set, status, isContainer): loop_count = -1 while len(input_set) != 0: if isContainer: all_resource = self.deployment_status server_set = self.pod_status else: all_resource = self.virtual_machine_replica_set server_set = self.virtual_machine_status if loop_count < 0: loop_count = len(input_set) - 1 specific_input_resource = list(input_set)[loop_count] if specific_input_resource in list(all_resource): if status == 'Terminating': if not any(specific_input_resource in _ for _ in list(server_set)): input_set.remove(specific_input_resource) all_resource.pop(specific_input_resource) else: complete_count = 0 for name in list(server_set): if specific_input_resource in name: if status == server_set[name]: complete_count += 1 if all_resource[specific_input_resource][ 'replicas'] == complete_count: input_set.remove(specific_input_resource) loop_count -= 1 return True def _get_deploy_status(self, _queue, events, success_count): while success_count: success_status = _queue.get() if success_status: success_count -= 1 print('success') [event() for event in events]
class VirtualMachineInstance(KubernetesApi): serial = "ABCDFGHJIKLMNOPQRSTUVWXYZ1234567890" def __init__(self, *args, **kwargs): if 'virtual_mem_size' in kwargs and 'num_virtual_cpu' in kwargs and 'image' in kwargs: self.memory = kwargs['virtual_mem_size'] self.cpu = kwargs['num_virtual_cpu'] self.image = kwargs['image'] self.network_name = kwargs['network_name'] if 'network_name' in kwargs else None self.user_name = kwargs['user_name'] if 'user_name' in kwargs else None self.user_public_key = kwargs['user_public_key'] if 'user_public_key' in kwargs else None self.config_map_mount_path = kwargs['config_map_mount_path'] if 'config_map_mount_path' in kwargs else None self.command = kwargs['command'] if 'command' in kwargs else None self.replicas = kwargs['replicas'] if 'replicas' in kwargs else None self.labels = kwargs['labels'] if 'labels' in kwargs and isinstance(kwargs['labels'], dict) else None if 'ports' in kwargs and 'name_of_service' in kwargs: self.name_of_service = kwargs['name_of_service'] super().__init__(*args, **kwargs) self.etcd_client = EtcdClient() self.etcd_client.set_deploy_name(instance_name=self.instance_name, pod_name=None) def instance_specific_resource(self, **kwargs): virtual_machine_instance_match_label = { "app": self.name_of_service if self.name_of_service else self.instance_name} virtual_machine_instance_meta = self.kubevirt_client.K8sIoApimachineryPkgApisMetaV1ObjectMeta(labels=virtual_machine_instance_match_label) vmirs_spec = self.kubevirt_client.V1VirtualMachineInstanceReplicaSetSpec( replicas=self.replicas, selector=self.kubevirt_client.K8sIoApimachineryPkgApisMetaV1LabelSelector(match_labels=virtual_machine_instance_match_label), template=self.kubevirt_client.V1VirtualMachineInstanceTemplateSpec( spec=self._get_virtual_machine_instance_replica_set_spec(), metadata=virtual_machine_instance_meta)) vmirs = self.kubevirt_client.V1VirtualMachineInstanceReplicaSet( api_version="kubevirt.io/v1alpha3", kind="VirtualMachineInstanceReplicaSet", spec=vmirs_spec) vmirs.metadata = self.kubevirt_client.K8sIoApimachineryPkgApisMetaV1ObjectMeta( name=self.instance_name, labels=virtual_machine_instance_match_label, namespace=self.namespace) return vmirs def _get_virtual_machine_instance_replica_set_spec(self): if isinstance(self.cpu, int): self.cpu = str(self.cpu) resource = self.kubevirt_client.V1ResourceRequirements( requests={'memory': self.memory, 'cpu': self.cpu}) disks = list() disks.append(self.kubevirt_client.V1Disk( name='{}-{}'.format(self.instance_name, 'disk'), disk=self.kubevirt_client.V1DiskTarget(bus='virtio'))) disks.append(self.kubevirt_client.V1Disk( name='{}-{}'.format(self.instance_name, 'init'), disk=self.kubevirt_client.V1DiskTarget(bus='virtio'))) volumes = list() volumes.append(self.kubevirt_client.V1Volume( name='{}-{}'.format(self.instance_name, 'disk'), container_disk=self.kubevirt_client.V1ContainerDiskSource(image=self.image))) mount_script = str() if self.config_map_mount_path: for _ in self.config_map_mount_path: serial = self._get_serial() path = os.path.split(_.strip()) disk_name = path[1].lower() if "." not in path[1] else path[1].split(".")[0].lower() print(disk_name) disks.append(self.kubevirt_client.V1Disk( name=disk_name, serial=serial, disk=self.kubevirt_client.V1DiskTarget())) mount_script += self._mount_configmap(path=path[0], serial=serial) volumes.append(self.kubevirt_client.V1Volume( name=disk_name, config_map=self.kubevirt_client.V1ConfigMapVolumeSource(name=disk_name))) interface = list() interface.append(self.kubevirt_client.V1Interface( name='default', masquerade=self.kubevirt_client.V1InterfaceMasquerade())) networks = list() networks.append(self.kubevirt_client.V1Network(name='default', pod=self.kubevirt_client.V1PodNetwork())) if self.network_name.__len__() > 0: for idx, net_info in enumerate(self.network_name): if net_info['type'] == SR_IOV: interface.append(self.kubevirt_client.V1Interface( name='{}-{}'.format(self.instance_name, net_info['network_name']), sriov=self.kubevirt_client.V1InterfaceSRIOV())) elif net_info['type'] == OVS: interface.append(self.kubevirt_client.V1Interface( name='{}-{}'.format(self.instance_name, net_info['network_name']), bridge=self.kubevirt_client.V1InterfaceBridge())) networks.append( self.kubevirt_client.V1Network( name='{}-{}'.format(self.instance_name, net_info['network_name']), multus=self.kubevirt_client.V1MultusNetwork(network_name=net_info['network_name']))) # TODO ovs-cni can not setting interface name # ubuntu default interface name (enp2s0) interface_name_count = idx + 2 interface_name = 'enp{}s0'.format(interface_name_count) mount_script += self._multiple_interface(interface_name, net_info['ip_address']) # mount_script += self._multiple_interface(interface_name, self.etcd_client.get_vm_cidr()) interface_name_count += 1 mount_script += '/etc/init.d/networking restart\n' if self.command: for _ in self.command: mount_script += '{}\n'.format(_) volumes.append(self.kubevirt_client.V1Volume( name='{}-{}'.format(self.instance_name, 'init'), cloud_init_no_cloud=self.kubevirt_client.V1CloudInitNoCloudSource( user_data=self._get_user_data(mount_script)))) devices = self.kubevirt_client.V1Devices(disks=disks, interfaces=interface) domain = self.kubevirt_client.V1DomainSpec(resources=resource, devices=devices) virtual_machine_instance_spec = self.kubevirt_client.V1VirtualMachineInstanceSpec( networks=networks, volumes=volumes, domain=domain, termination_grace_period_seconds=0) return virtual_machine_instance_spec def patch_resource(self, **kwargs): # vmi.spec.template.spec.domain.resources.requests['memory'] = '512M' self.kubevirt_api.replace_namespaced_virtual_machine_instance_replica_set( name=self.instance_name, namespace=self.namespace, body=self.resource) # self._restart_vmis() def delete_resource(self, **kwargs): self.kubevirt_api.delete_namespaced_virtual_machine_instance_replica_set( namespace=self.namespace, name=self.instance_name, body=self.kubevirt_client.K8sIoApimachineryPkgApisMetaV1DeleteOptions()) def create_resource(self, **kwargs): body = self.resource namespace = self.namespace api_response = self.kubevirt_api.create_namespaced_virtual_machine_instance_replica_set(body, namespace) def read_resource(self, **kwargs): try: resource = self.kubevirt_api.read_namespaced_virtual_machine_instance_replica_set( name=self.instance_name, namespace=self.namespace) except self.kubevirt_client.api_client.ApiException as e: if e.status == 404: print("Exception when calling DefaultApi->read_namespaced_virtual_machine_instance_replica_set: %s\n" % e) return None raise return resource def _restart_vmis(self): self.kubevirt_api.restart(namespace=self.namespace, name=self.instance_name) def _get_serial(self): return ''.join(random.choice(self.serial) for _ in range(16)) def _get_user_data(self, mount_script): return ('#!/bin/bash\n' 'export NEW_USER={user_name}\n' 'export SSH_PUB_KEY="{user_public_key}"\n' 'sudo adduser -U -m $NEW_USER\n' 'echo "$NEW_USER:atomic" | chpasswd\n' 'sudo mkdir /home/$NEW_USER/.ssh\n' 'sudo echo "$SSH_PUB_KEY" > /home/$NEW_USER/.ssh/authorized_keys\n' 'sudo chown -R ${NEW_USER}: /home/$NEW_USER/.ssh\n' '{mount_script}' ).format(user_name=self.user_name, user_public_key=self.user_public_key, NEW_USER='******', mount_script=mount_script) def _multiple_interface(self, interface_name, cidr): return ('cat << EOF >> /etc/network/interfaces.d/50-cloud-init.cfg\n' 'auto {interface_name}\n' 'iface {interface_name} inet static\n' 'address {cidr} \n' 'EOF\n' ).format(interface_name=interface_name, cidr=cidr) def _mount_configmap(self, path, serial): return ('sudo mkdir {config_path}\n' 'sudo mount /dev/$(lsblk --nodeps -no name,serial | grep {serial} | cut -f1 -d " ") {config_path}\n' ).format(config_path=path, serial=serial)
class NSLifecycleManagementViewSet(viewsets.ModelViewSet): queryset = NsInstance.objects.all() serializer_class = NsInstanceSerializer monitor_vnf = MonitorVnf() etcd_client = EtcdClient() kafka_notification = KafkaNotification('ns_instance') def create(self, request, **kwargs): """ Create a NS instance resource. The POST method creates a new NS instance resource. """ if 'nsdId' not in request.data: raise APIException(detail='nsdId is not existing', code=status.HTTP_409_CONFLICT) if 'nsName' not in request.data: raise APIException(detail='nsName is not existing', code=status.HTTP_409_CONFLICT) if 'nsDescription' not in request.data: raise APIException(detail='nsDescription is not existing', code=status.HTTP_409_CONFLICT) ns_descriptors_info = NsdInfo.objects.filter(nsdId=request.data['nsdId']).last() if ns_descriptors_info is None: raise APIException(detail='nsdId is not existing', code=status.HTTP_409_CONFLICT) vnf_pkg_Ids = json.loads(ns_descriptors_info.vnfPkgIds) nsd_info_id = str(ns_descriptors_info.id) request.data['nsdInfoId'] = nsd_info_id request.data['nsInstanceName'] = request.data['nsName'] request.data['nsInstanceDescription'] = request.data['nsDescription'] request.data['nsdId'] = request.data['nsdId'] request.data['vnfInstance'] = get_vnf_instance(vnf_pkg_Ids) request.data['_links'] = {'self': request.build_absolute_uri()} return super().create(request) def get_success_headers(self, data): return {'Location': data['_links']['self']} def retrieve(self, request, *args, **kwargs): """ Read an individual NS instance resource. The GET method retrieves information about a NS instance by reading an individual NS instance resource. """ return super().retrieve(request) def update(self, request, *args, **kwargs): raise APIException(detail='Method Not Allowed', code=status.HTTP_405_METHOD_NOT_ALLOWED) def list(self, request, *args, **kwargs): """ Query multiple NS instances. Query NS Instances.\ The GET method queries information about multiple NS instances. \ This method shall support the URI query parameters, request and response data structures, \ and response codes, as specified in the Tables 6.4.2.3.2-1 and 6.4.2.3.2-2. """ return super().list(request) def destroy(self, request, *args, **kwargs): """ Delete NS instance resource. Delete NS Identifier This method deletes an individual NS instance resource. """ instance = self.get_object() if not_instantiated != instance.nsState: raise APIException(detail='nsState is not {}'.format(not_instantiated), code=status.HTTP_409_CONFLICT) super().destroy(request) self.kafka_notification.notify(kwargs['pk'], 'NS Instance({}) had been destroy'.format(kwargs['pk'])) return Response(status=status.HTTP_204_NO_CONTENT) @action(detail=True, methods=['POST'], url_path='instantiate') def instantiate_ns(self, request, **kwargs): """ Instantiate a NS. The POST method requests to instantiate a NS instance resource. """ ns_instance = self.get_object() if 'vnfInstanceData' not in request.data: raise APIException(detail='vnfInstanceData is not existing', code=status.HTTP_409_CONFLICT) vnf_instance_list = list() vnf_instance_data = request.data.pop('vnfInstanceData') for vnf_instance_info in vnf_instance_data: if 'vnfInstanceId' not in vnf_instance_info: raise APIException(detail='vnfInstanceId is not existing', code=status.HTTP_409_CONFLICT) vnf_instance = ns_instance.NsInstance_VnfInstance.get(id=vnf_instance_info['vnfInstanceId']) if vnf_instance is None: raise APIException(detail='vnf_instance is not existing', code=status.HTTP_409_CONFLICT) vnf_instance.VnfInstance_instantiatedVnfInfo.vnfState = 'STARTED' vnf_instance.VnfInstance_instantiatedVnfInfo.save() create_network_service = \ CreateService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) threading.Thread( target=partial(create_network_service.process_instance), daemon=True ).start() vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.instantiate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.instantiate, vnf_instances=vnf_instance_list, container_phase='Running', ns_state=instantiated, usage_state=in_use) ns_instance.nsState = instantiated ns_instance.save() return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='scale') def scale_ns(self, request, **kwargs): """ Scale a NS instance. The POST method requests to instantiate a NS instance resource. """ ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException(detail='Network Service instance State have been INSTANTIATE') if 'scaleType' not in request.data: raise APIException(detail='scaleType parameter is necessary') vnf_instance_list = list() if 'SCALE_VNF' == request.data['scaleType']: for scale_vnf_data in request.data['scaleVnfData']: vnf_instance = ns_instance.NsInstance_VnfInstance.get(id=scale_vnf_data['vnfInstanceId']) if 'SCALE_OUT' == scale_vnf_data['scaleVnfType']: if 'additionalParams' in scale_vnf_data['scaleByStepData']: additional_params = scale_vnf_data['scaleByStepData']['additionalParams'] replicas = int(additional_params['replicas']) if 'replicas' in additional_params else None virtual_mem_size = additional_params[ 'virtual_mem_size'] if 'virtual_mem_size' in additional_params else None num_virtual_cpu = additional_params[ 'num_virtual_cpu'] if 'num_virtual_cpu' in additional_params else None create_network_service = CreateService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process_instance( replicas=replicas, virtual_mem_size=virtual_mem_size, num_virtual_cpu=num_virtual_cpu) vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, 'SCALE') self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.scale, vnf_instances=vnf_instance_list, container_phase='Running', ns_state=instantiated, usage_state=in_use) return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) # TODO @action(detail=True, methods=['POST'], url_path='heal') def heal_ns(self, request, **kwargs): """ Heal a NS instance. The POST method requests to heal a NS instance resource. \ This method shall follow the provisions specified in the Tables 6.4.7.3.1-1 and 6.4.7.3.1-2 \ for URI query parameters, request and response data structures, and response codes. """ ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException(detail='Network Service instance State have been INSTANTIATE') return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='update') def update_ns(self, request, **kwargs): """ Updates a NS instance. Scale NS instance. The POST method requests to scale a NS instance resource. """ ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException(detail='Network Service instance State have been INSTANTIATE') if 'updateType' not in request.data: raise APIException(detail='updateType parameter is necessary') vnf_instance_list = list() if request.data['updateType'] == 'ADD_VNF': if 'addVnfInstance' not in request.data and isinstance(request.data['addVnfInstance'], list): raise APIException(detail='Not found removeVnfInstanceId parameter') add_vnf_instance = request.data['addVnfInstance'] for vnf_instance_request in add_vnf_instance: if 'vnfInstanceId' not in vnf_instance_request: raise APIException(detail='Error parameter vnfInstanceId') # vnfInstanceId (nm -> vnfpkgid) vnf_info = get_vnf_instance([vnf_instance_request['vnfInstanceId']]).pop(0) vnf_instance = create_vnf_instance(vnf_info) ns_instance.NsInstance_VnfInstance.add(vnf_instance) create_network_service = CreateService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) create_network_service.process_instance() vnf_instance_list.append(vnf_instance) elif request.data['updateType'] == 'REMOVE_VNF': if 'removeVnfInstanceId' not in request.data: raise APIException(detail='Not found removeVnfInstanceId parameter') vnf_instance = ns_instance.NsInstance_VnfInstance.get(id=request.data['removeVnfInstanceId']) vnf_instance.delete() delete_network_service = DeleteService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) delete_network_service.process_instance() vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.update) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.update, vnf_instances=vnf_instance_list, container_phase='Running', ns_state=instantiated, usage_state=in_use) return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self}) @action(detail=True, methods=['POST'], url_path='terminate') def terminate_ns(self, request, **kwargs): """ Terminate a NS instance. Terminate NS task. The POST method terminates a NS instance. \ This method can only be used with a NS instance in the INSTANTIATED state. \ Terminating a NS instance does not delete the NS instance identifier, \ but rather transitions the NS into the NOT_INSTANTIATED state. \ This method shall support the URI query parameters, request and response data structures, \ and response codes, as specified in the Tables 6.4.8.3.1-1 and 6.8.8.3.1-2. """ ns_instance = self.get_object() if 'INSTANTIATED' != ns_instance.nsState: raise APIException(detail='Network Service instance State have been INSTANTIATE', code=status.HTTP_409_CONFLICT) vnf_instance_list = list() for vnf_instance in ns_instance.NsInstance_VnfInstance.all(): vnf_instance.VnfInstance_instantiatedVnfInfo.vnfState = 'STOPPED' vnf_instance.VnfInstance_instantiatedVnfInfo.save() delete_network_service = DeleteService(vnf_instance.vnfPkgId, vnf_instance.vnfInstanceName) threading.Thread( target=partial(delete_network_service.process_instance), daemon=True ).start() self.etcd_client.set_deploy_name(instance_name=vnf_instance.vnfInstanceName.lower(), pod_name=None) self.etcd_client.release_pod_ip_address() vnf_instance_list.append(vnf_instance) set_ns_lcm_op_occ(ns_instance, request, vnf_instance_list, self.monitor_vnf.terminate) self.monitor_vnf.monitoring_vnf(kwargs['pk'], self.monitor_vnf.terminate, vnf_instances=vnf_instance_list, container_phase='Terminating', ns_state=not_instantiated, usage_state=not_in_use) ns_instance.nsState = not_instantiated ns_instance.save() return Response(status=status.HTTP_202_ACCEPTED, headers={'Location': ns_instance.NsInstance_links.link_self})