Exemplo n.º 1
0
    def __get_vm(self, *, playbook_path: str, inventory_path: str,
                 vm_name: str, unit_id: str):
        """
        Invoke ansible playbook to get a provisioned VM
        :param playbook_path: playbook location
        :param inventory_path: inventory location
        :param vm_name: VM Name
        :param unit_id: Unit Id
        :return: OK result
        """
        ansible_helper = AnsibleHelper(inventory_path=inventory_path,
                                       logger=self.get_logger())
        vm_name = f"{unit_id}-{vm_name}"

        extra_vars = {
            AmConstants.VM_PROV_OP: AmConstants.VM_PROV_OP_GET,
            AmConstants.VM_NAME: vm_name
        }
        ansible_helper.set_extra_vars(extra_vars=extra_vars)

        self.get_logger().info(
            f"Executing playbook {playbook_path} to get VM extra_vars: {extra_vars}"
        )
        ansible_helper.run_playbook(playbook_path=playbook_path)
        return ansible_helper.get_result_callback().get_json_result_ok()
Exemplo n.º 2
0
    def __cleanup(self, *, sliver: NetworkServiceSliver, unit_id: str, raise_exception: bool = False):
        if sliver.get_labels() is None or sliver.get_labels().local_name is None:
            # truncate service_name length to no greater than 53 (36+1+16)
            sliver_name = sliver.get_name()[:16] if len(sliver.get_name()) > 16 else sliver.get_name()
            service_name = f'{sliver_name}-{unit_id}'
        else:
            service_name = sliver.get_labels().local_name
        resource_type = str(sliver.get_type())
        service_type = resource_type.lower()
        if service_type == 'fabnetv4' or service_type == 'fabnetv6':
            service_type = 'l3rt'
        elif service_type == 'portmirror':
            service_type = 'port-mirror'
        data = {
            "tailf-ncs:services": {
                f'{service_type}:{service_type}': [{
                    "name": f'{service_name}',
                    "__state": "absent"
                }]
            }
        }
        extra_vars = {
            "service_name": service_name,
            "service_type": service_type,
            "service_action": "delete",
            "data": data
        }
        try:
            playbook_path = self.get_config()[AmConstants.PLAYBOOK_SECTION][AmConstants.PB_LOCATION]
            inventory_path = self.get_config()[AmConstants.PLAYBOOK_SECTION][AmConstants.PB_INVENTORY]
            playbook = self.get_config()[AmConstants.PLAYBOOK_SECTION][resource_type]
            if playbook is None or inventory_path is None or playbook_path is None:
                raise NetHandlerException(f"Missing config parameters playbook: {playbook} "
                                          f"playbook_path: {playbook_path} inventory_path: {inventory_path}")
            playbook_path_full = f"{playbook_path}/{playbook}"
            ansible_helper = AnsibleHelper(inventory_path=inventory_path, logger=self.get_logger())
            ansible_helper.set_extra_vars(extra_vars=extra_vars)
            self.get_logger().debug(f"Executing playbook {playbook_path_full} to delete Network Service")
            ansible_helper.run_playbook(playbook_path=playbook_path_full)
            ansible_callback = ansible_helper.get_result_callback()
            unreachable = ansible_callback.get_json_result_unreachable()
            if unreachable:
                raise NetHandlerException(f'network service {service_name} was not cleaned up due to connection error')
            failed = ansible_callback.get_json_result_failed()
            if failed:
                ansible_callback.dump_all_failed(logger=self.get_logger())
                raise NetHandlerException(f'network service {service_name} was not cleaned up due to config error')
            ok = ansible_callback.get_json_result_ok()
            if ok:
                if not ok['changed']:
                    self.get_logger().info(f'network service {service_name} was cleaned up ok but without change')

        except Exception as e:
            self.get_logger().error(f"Exception occurred in cleanup {e}")
            self.get_logger().error(traceback.format_exc())
            if raise_exception:
                raise e
Exemplo n.º 3
0
    def __delete_vm(self, *, playbook_path: str, inventory_path: str,
                    vm_name: str, unit_id: str) -> bool:
        """
        Invoke ansible playbook to remove a provisioned VM
        :param playbook_path: playbook location
        :param inventory_path: inventory location
        :param vm_name: VM Name
        :param unit_id: Unit Id
        :return: True or False representing success/failure
        """
        ansible_helper = AnsibleHelper(inventory_path=inventory_path,
                                       logger=self.get_logger())
        vm_name = f"{unit_id}-{vm_name}"

        extra_vars = {
            AmConstants.VM_PROV_OP: AmConstants.VM_PROV_OP_DELETE,
            AmConstants.VM_NAME: vm_name
        }
        ansible_helper.set_extra_vars(extra_vars=extra_vars)

        self.get_logger().info(
            f"Executing playbook {playbook_path} to delete VM extra_vars: {extra_vars}"
        )
        ansible_helper.run_playbook(playbook_path=playbook_path)
        return True
Exemplo n.º 4
0
    def __post_boot_config(self, *, mgmt_ip: str, user: str):
        """
        Perform post boot configuration, install required software
        :param mgmt_ip Management IP to access the VM
        :param user Default Linux user to use for SSH/Ansible
        """
        try:

            # Grab the playbook location
            playbook_location = self.get_config()[
                AmConstants.PLAYBOOK_SECTION][AmConstants.PB_LOCATION]

            # Grab the playbook name
            playbook = self.get_config()[AmConstants.PLAYBOOK_SECTION][
                AmConstants.PB_POST_BOOT_CONFIG]

            # Construct the playbook path
            playbook_path = f"{playbook_location}/{playbook}"

            # Construct ansible helper
            ansible_helper = AnsibleHelper(inventory_path=None,
                                           logger=self.get_logger(),
                                           sources=f"{mgmt_ip},")

            # Set the variables
            extra_vars = {
                AmConstants.VM_NAME: mgmt_ip,
                AmConstants.IMAGE: user
            }

            ansible_helper.set_extra_vars(extra_vars=extra_vars)

            # Grab the SSH Key
            admin_ssh_key = self.get_config()[AmConstants.PLAYBOOK_SECTION][
                AmConstants.ADMIN_SSH_KEY]

            # Invoke the playbook
            self.get_logger().info(
                f"Executing playbook {playbook_path} to do post boot config extra_vars: "
                f"{extra_vars}")
            ansible_helper.run_playbook(playbook_path=playbook_path,
                                        user=user,
                                        private_key_file=admin_ssh_key)
        except Exception as e:
            self.get_logger().error(f"Exception : {e}")
            self.get_logger().error(traceback.format_exc())
Exemplo n.º 5
0
    def create(self, unit: ConfigToken) -> Tuple[dict, ConfigToken]:
        """
        Create a Network Service
        :param unit: unit representing an NSO Network Service
        :return: tuple of result status and the unit
        """
        result = {Constants.PROPERTY_TARGET_NAME: Constants.TARGET_CREATE,
                  Constants.PROPERTY_TARGET_RESULT_CODE: Constants.RESULT_CODE_OK,
                  Constants.PROPERTY_ACTION_SEQUENCE_NUMBER: 0}
        sliver = None

        try:
            self.get_logger().info(f"Create invoked for unit: {unit}")
            sliver = unit.get_sliver()
            unit_id = str(unit.get_reservation_id())
            if sliver is None:
                raise NetHandlerException(f"Unit # {unit} has no assigned slivers")

            unit_properties = unit.get_properties()  # use: TBD

            resource_type = str(sliver.get_type())

            playbook_path = self.get_config()[AmConstants.PLAYBOOK_SECTION][AmConstants.PB_LOCATION]
            inventory_path = self.get_config()[AmConstants.PLAYBOOK_SECTION][AmConstants.PB_INVENTORY]

            playbook = self.get_config()[AmConstants.PLAYBOOK_SECTION][resource_type]
            if playbook is None or inventory_path is None or playbook_path is None:
                raise NetHandlerException(f"Missing config parameters playbook: {playbook} "
                                          f"playbook_path: {playbook_path} inventory_path: {inventory_path}")
            playbook_path_full = f"{playbook_path}/{playbook}"

            if sliver.get_labels() is None or sliver.get_labels().local_name is None:
                # truncate service_name length to no greater than 53 (36+1+16)
                sliver_name = sliver.get_name()[:16] if len(sliver.get_name()) > 16 else sliver.get_name()
                service_name = f'{sliver_name}-{unit_id}'
            else:
                service_name = sliver.get_labels().local_name
            service_type = resource_type.lower()
            if service_type == 'l2bridge':
                service_data = self.__l2bridge_create_data(sliver, service_name)
            elif service_type == 'l2ptp':
                service_data = self.__l2ptp_create_data(sliver, service_name)
            elif service_type == 'l2sts':
                service_data = self.__l2sts_create_data(sliver, service_name)
            elif service_type == 'fabnetv4':
                service_data = self.__fabnetv4_create_data(sliver, service_name)
                service_type = 'l3rt'
            elif service_type == 'fabnetv6':
                service_data = self.__fabnetv6_create_data(sliver, service_name)
                service_type = 'l3rt'
            elif service_type == 'portmirror':
                service_data = self.__portmirror_create_data(sliver, service_name)
                service_type = 'port-mirror'
            else:
                raise NetHandlerException(f'unrecognized network service type "{service_type}"')
            data = {
                "tailf-ncs:services": {
                    f'{service_type}:{service_type}': [service_data]
                }
            }
            extra_vars = {
                "service_name": service_name,
                "service_type": service_type,
                "service_action": "create",
                "data": data
            }
            print(json.dumps(extra_vars))
            ansible_helper = AnsibleHelper(inventory_path=inventory_path, logger=self.get_logger())
            ansible_helper.set_extra_vars(extra_vars=extra_vars)
            self.get_logger().debug(f"Executing playbook {playbook_path_full} to create Network Service")
            ansible_helper.run_playbook(playbook_path=playbook_path_full)
            ansible_callback = ansible_helper.get_result_callback()
            unreachable = ansible_callback.get_json_result_unreachable()
            if unreachable:
                raise NetHandlerException(f'network service {service_name} was not committed due to connection error')
            failed = ansible_callback.get_json_result_failed()
            if failed:
                ansible_callback.dump_all_failed(logger=self.get_logger())
                raise NetHandlerException(f'network service {service_name} was not committed due to config error')
            ok = ansible_callback.get_json_result_ok()
            if ok:
                if not ok['changed']:
                    self.get_logger().info(f'network service {service_name} was committed ok but without change')

        except Exception as e:
            # Delete VM in case of failure
            if sliver is not None and unit_id is not None:
                self.__cleanup(sliver=sliver, unit_id=unit_id)
            result = {Constants.PROPERTY_TARGET_NAME: Constants.TARGET_CREATE,
                      Constants.PROPERTY_TARGET_RESULT_CODE: Constants.RESULT_CODE_EXCEPTION,
                      Constants.PROPERTY_ACTION_SEQUENCE_NUMBER: 0,
                      Constants.PROPERTY_EXCEPTION_MESSAGE: e}
            self.get_logger().error(e)
            self.get_logger().error(traceback.format_exc())
        finally:
            self.get_logger().info(f"Create completed")
        return result, unit
Exemplo n.º 6
0
    def configure_network_interface(self,
                                    *,
                                    mgmt_ip: str,
                                    user: str,
                                    resource_type: str,
                                    mac_address: str,
                                    ipv4_address: str = None,
                                    ipv6_address: str = None,
                                    vlan: str = None):
        """
        Configure Network Interface inside the VM
        :param mgmt_ip Management IP to access the VM
        :param user Default Linux user to use for SSH/Ansible
        :param resource_type Type of NIC card (SharedNIC or SmartNIC)
        :param mac_address Mac address used to identify the interface
        :param ipv4_address IPV4 address to assign
        :param ipv6_address IPV6 address to assign
        :param vlan Vlan tag in case of tagged interface
        """
        try:
            if ipv6_address is None and ipv4_address is None:
                return False

            # Grab the playbook location
            playbook_location = self.get_config()[
                AmConstants.PLAYBOOK_SECTION][AmConstants.PB_LOCATION]

            # Grab the playbook name
            playbook = self.get_config()[AmConstants.PLAYBOOK_SECTION][
                AmConstants.PB_NW_CONFIG]

            # Construct the playbook path
            playbook_path = f"{playbook_location}/{playbook}"

            # Construct ansible helper
            ansible_helper = AnsibleHelper(inventory_path=None,
                                           logger=self.get_logger(),
                                           sources=f"{mgmt_ip},")

            # Set the variables
            extra_vars = {
                AmConstants.VM_NAME: mgmt_ip,
                AmConstants.MAC: mac_address.lower(),
                AmConstants.IMAGE: user
            }

            if ipv4_address is not None:
                extra_vars[AmConstants.IPV4_ADDRESS] = ipv4_address
            if ipv6_address is not None:
                extra_vars[AmConstants.IPV6_ADDRESS] = ipv6_address
            if vlan is not None and resource_type != ComponentType.SharedNIC.name:
                extra_vars[AmConstants.VLAN] = vlan

            ansible_helper.set_extra_vars(extra_vars=extra_vars)

            # Grab the SSH Key
            admin_ssh_key = self.get_config()[AmConstants.PLAYBOOK_SECTION][
                AmConstants.ADMIN_SSH_KEY]

            # Invoke the playbook
            self.get_logger().info(
                f"Executing playbook {playbook_path} to configure interface extra_vars: "
                f"{extra_vars}")
            ansible_helper.run_playbook(playbook_path=playbook_path,
                                        user=user,
                                        private_key_file=admin_ssh_key)
        except Exception as e:
            self.get_logger().error(f"Exception : {e}")
            self.get_logger().error(traceback.format_exc())
Exemplo n.º 7
0
    def __attach_detach_pci(self,
                            *,
                            playbook_path: str,
                            inventory_path: str,
                            host: str,
                            instance_name: str,
                            device_name: str,
                            component: ComponentSliver,
                            user: str = None,
                            mgmt_ip: str = None,
                            attach: bool = True):
        """
        Invoke ansible playbook to attach/detach a PCI device to a provisioned VM
        :param playbook_path: playbook location
        :param inventory_path: inventory location
        :param host: host
        :param instance_name: Instance Name
        :param device_name: Device Name
        :param component: Component Sliver
        :param mgmt_ip: Management IP of the VM to which the component is attached
        :param attach: True for attach and False for detach
        :return:
        """
        self.get_logger().debug("__attach_detach_pci IN")
        try:
            pci_device_list = None
            mac = None
            if component.get_type() == ComponentType.SharedNIC:
                for ns in component.network_service_info.network_services.values(
                ):
                    if ns.interface_info is None or ns.interface_info.interfaces is None:
                        continue

                    for ifs in ns.interface_info.interfaces.values():
                        mac = ifs.label_allocations.mac
            if isinstance(component.label_allocations.bdf, str):
                pci_device_list = [component.label_allocations.bdf]
            else:
                pci_device_list = component.label_allocations.bdf

            worker_node = host

            extra_vars = {
                AmConstants.WORKER_NODE_NAME: worker_node,
                AmConstants.PCI_PROV_DEVICE: device_name
            }
            if attach:
                extra_vars[
                    AmConstants.PCI_OPERATION] = AmConstants.PCI_PROV_ATTACH
            else:
                extra_vars[
                    AmConstants.PCI_OPERATION] = AmConstants.PCI_PROV_DETACH

            self.get_logger().info(
                f"Device List Size: {len(pci_device_list)} List: {pci_device_list}"
            )
            index = 0
            for device in pci_device_list:
                ansible_helper = AnsibleHelper(inventory_path=inventory_path,
                                               logger=self.get_logger())
                ansible_helper.set_extra_vars(extra_vars=extra_vars)

                device_char_arr = self.__extract_device_addr_octets(
                    device_address=device)
                ansible_helper.add_vars(host=worker_node,
                                        var_name=AmConstants.KVM_GUEST_NAME,
                                        value=instance_name)
                ansible_helper.add_vars(host=worker_node,
                                        var_name=AmConstants.PCI_DOMAIN,
                                        value=device_char_arr[0])
                ansible_helper.add_vars(host=worker_node,
                                        var_name=AmConstants.PCI_BUS,
                                        value=device_char_arr[1])
                ansible_helper.add_vars(host=worker_node,
                                        var_name=AmConstants.PCI_SLOT,
                                        value=device_char_arr[2])
                ansible_helper.add_vars(host=worker_node,
                                        var_name=AmConstants.PCI_FUNCTION,
                                        value=device_char_arr[3])

                if mac is not None:
                    ansible_helper.add_vars(host=worker_node,
                                            var_name=AmConstants.MAC,
                                            value=mac)

                self.get_logger().info(
                    f"Executing playbook {playbook_path} to attach({attach})/detach({not attach}) "
                    f"PCI device ({device}) extra_vars: {extra_vars}")

                ansible_helper.run_playbook(playbook_path=playbook_path)

            # Configure the Network Interface card
            if attach:
                self.configure_nic(component=component,
                                   mgmt_ip=mgmt_ip,
                                   user=user)
        finally:
            self.get_logger().debug("__attach_detach_pci OUT")
Exemplo n.º 8
0
    def __attach_fip(self, *, playbook_path: str, inventory_path: str,
                     vm_name: str, unit_id: str) -> str:
        """
        Invoke ansible playbook to attach a floating IP to a provisioned VM
        :param playbook_path: playbook location
        :param inventory_path: inventory location
        :param host: host
        :param vm_name: VM Name
        :param unit_id: Unit Id
        :return: floating ip assigned to the VM
        """
        try:
            self.process_lock.acquire()
            vmname = f"{unit_id}-{vm_name}"
            ansible_helper = AnsibleHelper(inventory_path=inventory_path,
                                           logger=self.get_logger())
            extra_vars = {
                AmConstants.VM_PROV_OP: AmConstants.VM_PROV_OP_ATTACH_FIP,
                AmConstants.VM_NAME: vmname
            }
            ansible_helper.set_extra_vars(extra_vars=extra_vars)

            self.get_logger().info(
                f"Executing playbook {playbook_path} to attach FIP extra_vars: {extra_vars}"
            )
            ansible_helper.run_playbook(playbook_path=playbook_path)

            ok = ansible_helper.get_result_callback().get_json_result_ok()

            if self.test_mode:
                floating_ip = ok[AmConstants.ANSIBLE_FACTS][
                    AmConstants.FLOATING_IP]
                floating_ip = json.loads(floating_ip)
                return floating_ip[AmConstants.FLOATING_IP_ADDRESS]

            floating_ip = ok[AmConstants.FLOATING_IP]
            result = None
            if floating_ip is None:
                self.get_logger().info(
                    "Floating IP returned by attach was null, trying to get via get_vm"
                )
                ok = self.__get_vm(playbook_path=playbook_path,
                                   inventory_path=inventory_path,
                                   vm_name=vm_name,
                                   unit_id=unit_id)
                self.get_logger().info(f"Info returned by __get_vm: {ok}")
                servers = ok[AmConstants.OS_SERVERS]
                self.get_logger().debug(f"Servers: {servers}")
                if servers is not None and len(servers) == 1:
                    result = servers[0][AmConstants.SERVER_ACCESS_IPV4]
                    if result is None:
                        result = servers[0][AmConstants.SERVER_ACCESS_IPV6]
                else:
                    self.get_logger().error(
                        f"No server found for {unit_id}-{vm_name}")
            else:
                result = floating_ip[AmConstants.FLOATING_IP_ADDRESS]

            if result is None:
                raise VmHandlerException(
                    f"Unable to get the Floating IP for {unit_id}-{vm_name}")

            self.get_logger().info(
                f"Returning FIP {result} for {unit_id}-{vm_name}")
            return str(result)
        finally:
            self.process_lock.release()
Exemplo n.º 9
0
    def __create_vm(self,
                    *,
                    playbook_path: str,
                    inventory_path: str,
                    vm_name: str,
                    worker_node: str,
                    image: str,
                    flavor: str,
                    unit_id: str,
                    ssh_key: str,
                    init_script: str = None) -> dict:
        """
        Invoke ansible playbook to provision a VM
        :param playbook_path: playbook location
        :param inventory_path: inventory location
        :param vm_name: VM Name
        :param worker_node: worker_node
        :param image: Image
        :param flavor: Flavor
        :param unit_id: Unit Id
        :param ssh_key: ssh_key
        :param init_script: Init Script
        :return: dictionary containing created instance details
        """
        ansible_helper = AnsibleHelper(inventory_path=inventory_path,
                                       logger=self.get_logger())
        vm_name_combined = f"{unit_id}-{vm_name}"

        avail_zone = f"nova:{worker_node}"

        default_user = self.__get_default_user(image=image)

        if init_script is None:
            init_script = ""

        extra_vars = {
            AmConstants.VM_PROV_OP: AmConstants.VM_PROV_OP_CREATE,
            AmConstants.EC2_AVAILABILITY_ZONE: avail_zone,
            AmConstants.VM_NAME: vm_name_combined,
            AmConstants.FLAVOR: flavor,
            AmConstants.IMAGE: image,
            AmConstants.HOSTNAME: vm_name,
            AmConstants.SSH_KEY: ssh_key,
            AmConstants.DEFAULT_USER: default_user,
            AmConstants.INIT_SCRIPT: init_script
        }
        ansible_helper.set_extra_vars(extra_vars=extra_vars)

        self.get_logger().info(
            f"Executing playbook {playbook_path} to create VM extra_vars: {extra_vars}"
        )
        ansible_helper.run_playbook(playbook_path=playbook_path)
        ok = ansible_helper.get_result_callback().get_json_result_ok()

        server = ok.get(AmConstants.SERVER, None)
        # Added this code for enabling test suite
        if server is None:
            server = ok[AmConstants.ANSIBLE_FACTS][AmConstants.SERVER]
            server = json.loads(server)

        result = {
            AmConstants.SERVER_VM_STATE:
            str(server[AmConstants.SERVER_VM_STATE]),
            AmConstants.SERVER_INSTANCE_NAME:
            str(server[AmConstants.SERVER_INSTANCE_NAME]),
            AmConstants.SERVER_ACCESS_IPV4:
            str(server[AmConstants.SERVER_ACCESS_IPV4])
        }
        if server[AmConstants.SERVER_ACCESS_IPV6] is not None:
            result[AmConstants.SERVER_ACCESS_IPV6] = str(
                server[AmConstants.SERVER_ACCESS_IPV6])
        self.get_logger().debug(f"Returning properties {result}")

        return result