예제 #1
0
    def disk_format_gpt(self, host_uuid, idisk_dict, is_cinder_device):
        disk_node = idisk_dict.get('device_path')

        utils.disk_wipe(disk_node)
        utils.execute('parted', disk_node, 'mklabel', 'gpt')

        if is_cinder_device:
            LOG.debug("Removing .node_cinder_lvm_config_complete_file")
            try:
                os.remove(constants.NODE_CINDER_LVM_CONFIG_COMPLETE_FILE)
            except OSError:
                LOG.error(".node_cinder_lvm_config_complete_file not present.")
                pass

        # On SX ensure wipe succeeds before DB is updated.
        # Flag file is used to mark wiping in progress.
        try:
            os.remove(constants.DISK_WIPE_IN_PROGRESS_FLAG)
        except OSError:
            # it's ok if file is not present.
            pass

        # We need to send the updated info about the host disks back to
        # the conductor.
        idisk_update = self.idisk_get()
        ctxt = context.get_admin_context()
        rpcapi = conductor_rpcapi.ConductorAPI(
            topic=conductor_rpcapi.MANAGER_TOPIC)
        rpcapi.idisk_update_by_ihost(ctxt,
                                     host_uuid,
                                     idisk_update)
예제 #2
0
    def _test_rpcapi(self, method, rpc_method, **kwargs):
        ctxt = context.get_admin_context()
        rpcapi = conductor_rpcapi.ConductorAPI(topic='fake-topic')

        default_rpc_api_version = '1.0'
        expected_retval = 'hello world' if method == 'call' else None
        expected_version = kwargs.pop('version', default_rpc_api_version)
        expected_msg = rpcapi.make_msg(method, **kwargs)

        expected_msg['version'] = expected_version

        expected_topic = 'fake-topic'

        self.fake_args = None
        self.fake_kwargs = None

        def _fake_rpc_method(*args, **kwargs):
            self.fake_args = args
            self.fake_kwargs = kwargs
            if expected_retval:
                return expected_retval

        with mock.patch.object(rpc, rpc_method) as mock_method:
            mock_method.side_effect = _fake_rpc_method
            retval = getattr(rpcapi, method)(ctxt, **kwargs)
            self.assertEqual(retval, expected_retval)
            expected_args = [ctxt, expected_topic, expected_msg]
            for arg, expected_arg in zip(self.fake_args, expected_args):
                self.assertEqual(arg, expected_arg)
예제 #3
0
    def fpga_pci_update(self, context):
        """Collect FPGA PCI data for this host.

        We know that the PCI address of the N3000 can change the first time
        We reset it after boot, so we need to gather the new PCI device
        information and send it to sysinv-conductor.

        This needs to exactly mirror what sysinv-agent does as far as PCI
        updates.  We could potentially modify sysinv-agent to do the PCI
        updates when triggered by an RPC cast, but we don't need to rescan
        all PCI devices, just the N3000 devices.

        :param:   context: an admin context
        :returns: nothing
        """

        LOG.info("Updating N3000 PCI info.")
        pci_device_list = get_n3000_pci_info()

        rpcapi = conductor_rpcapi.ConductorAPI(
            topic=conductor_rpcapi.MANAGER_TOPIC)

        host_uuid = self.host_uuid
        try:
            if pci_device_list:
                LOG.info("reporting N3000 PCI devices for host %s: %s" %
                         (host_uuid, pci_device_list))
                rpcapi.pci_device_update_by_host(context,
                                                 host_uuid,
                                                 pci_device_list,
                                                 cleanup_stale=True)
        except Exception:
            LOG.exception("Exception updating n3000 PCI devices, "
                          "this will likely cause problems.")
            pass
예제 #4
0
def local_registry_list(filename, included_apps, include_all_apps=False):
    """ Save the list of images present in the local registry
    to a file in yaml format.

    :param filename: name of the file to save to.
    :param include_apps: list of applications for which images are saved in yaml format.
    :param include_all_apps: if True then the list of apps images will include all apps
                             regardless of include_apps list.
    """

    ctxt = context.get_admin_context()
    rpcapi = conductor_rpcapi.ConductorAPI(
        topic=conductor_rpcapi.MANAGER_TOPIC)

    # Save local registry images tags
    image_name_tag_list = []
    temp_image_name_list = rpcapi.docker_registry_image_list(ctxt)
    if not temp_image_name_list:
        raise Exception("Image list could not be retrieved "
                        "from local registry")

    for temp_image_name in temp_image_name_list:
        image_name = temp_image_name.get('name', None)
        if image_name:
            temp_image_tags = rpcapi.docker_registry_image_tags(
                ctxt, image_name)

            for image_name_tag in temp_image_tags:
                image_tag = image_name_tag.get('tag', None)
                if image_tag:
                    image_name_tag_list.append("%s:%s" %
                                               (image_name, image_tag))

    # Retrieve the images used by apps that should be excluded from yaml file
    excluded_images = []
    if not include_all_apps:
        apps_images = rpcapi.docker_get_apps_images(ctxt).items()
        if not apps_images:
            raise Exception("Apps image list could not be retrieved")
        for app, images in apps_images:
            if included_apps is None or app not in included_apps:
                excluded_images.extend(images)

    # Exclude apps images
    image_name_tag_list = list(set(image_name_tag_list) - set(excluded_images))

    data = {}
    data.update({'images': image_name_tag_list})

    try:
        with open(filename, 'w') as outfile:
            yaml.safe_dump(data, outfile, default_flow_style=False)
    except Exception as e:
        LOG.error("Error with local_registry_list: %s", e)
        sys.exit(1)
def add_lease(mac, ip_address):
    """Called when a new lease is created."""

    ctxt = context.get_admin_context()
    rpcapi = conductor_rpcapi.ConductorAPI(
        topic=conductor_rpcapi.MANAGER_TOPIC)

    cid = None
    cid = os.getenv('DNSMASQ_CLIENT_ID')

    tags = None
    tags = os.getenv('DNSMASQ_TAGS')

    if tags is not None:
        # TODO: Maybe this shouldn't be synchronous - if this hangs, we could
        # cause dnsmasq to get stuck...
        rpcapi.handle_dhcp_lease(ctxt, tags, mac, ip_address, cid)
예제 #6
0
def send_notification(operation, success):
    if operation not in VALID_NOTIFICATION_VALUES:
        LOG.error("Invalid notification '{}'.".format(operation))
        sys.exit(2)
    ctx = context.get_admin_context()
    rpcapi = conductor_rpcapi.ConductorAPI(
        topic=conductor_rpcapi.MANAGER_TOPIC)
    ok, app = rpcapi.backup_restore_lifecycle_actions(ctx, operation, success)
    if not ok:
        if app is not None:
            LOG.error("Operation '{}' was aborted by '{}' appliction.".format(
                operation, app))
            sys.stderr.write(app)
            sys.exit(1)
        else:
            LOG.error(
                "Error while performing operation '{}'.".format(operation))
            sys.exit(2)
def old_lease(mac, ip_address):
    """Called when an old lease is recognized."""

    # This happens when a node is rebooted, but it can also happen if the
    # node was deleted and then rebooted, so we need to re-add in that case.

    ctxt = context.get_admin_context()
    rpcapi = conductor_rpcapi.ConductorAPI(
        topic=conductor_rpcapi.MANAGER_TOPIC)

    cid = None
    cid = os.getenv('DNSMASQ_CLIENT_ID')

    tags = None
    tags = os.getenv('DNSMASQ_TAGS')

    if tags is not None:
        # TODO: Maybe this shouldn't be synchronous - if this hangs, we could
        # cause dnsmasq to get stuck...
        rpcapi.handle_dhcp_lease(ctxt, tags, mac, ip_address, cid)
예제 #8
0
파일: manager.py 프로젝트: starlingx/config
    def fpga_pci_update(self, context):
        """Collect FPGA PCI data for this host.

        We know that the PCI address of the N3000 can change the first time
        We reset it after boot, so we need to gather the new PCI device
        information and send it to sysinv-conductor.

        This needs to exactly mirror what sysinv-agent does as far as PCI
        updates.  We could potentially modify sysinv-agent to do the PCI
        updates when triggered by an RPC cast, but we don't need to rescan
        all PCI devices, just the N3000 devices.

        :param:   context: an admin context
        :returns: nothing
        """

        LOG.info("Updating N3000 PCI info.")
        pci_device_list = get_n3000_pci_info()

        rpcapi = conductor_rpcapi.ConductorAPI(
            topic=conductor_rpcapi.MANAGER_TOPIC)

        host_uuid = self.host_uuid
        try:
            if pci_device_list:
                LOG.info("reporting N3000 PCI devices for host %s: %s" %
                         (host_uuid, pci_device_list))

                # Don't ask conductor to cleanup stale entries while worker
                # manifest is not complete. For N3000 device, it could get rid
                # of a valid entry with a different PCI address but restored
                # from previous database backup
                cleanup_stale = \
                    os.path.exists(tsc.VOLATILE_WORKER_CONFIG_COMPLETE)
                rpcapi.pci_device_update_by_host(context, host_uuid,
                                                 pci_device_list,
                                                 cleanup_stale)
        except Exception:
            LOG.exception("Exception updating n3000 PCI devices, "
                          "this will likely cause problems.")
            pass
예제 #9
0
    def report_fpga_inventory(self, context):
        """Collect FPGA data for this host.

        This method allows host FPGA data to be collected.

        :param:   context: an admin context
        :returns: nothing
        """

        host_uuid = self.host_uuid

        rpcapi = conductor_rpcapi.ConductorAPI(
            topic=conductor_rpcapi.MANAGER_TOPIC)

        fpgainfo_list = self.get_fpga_info()

        LOG.info("reporting FPGA inventory for host %s: %s" %
                 (host_uuid, fpgainfo_list))
        try:
            rpcapi.fpga_device_update_by_host(context, host_uuid, fpgainfo_list)
        except exception.SysinvException:
            LOG.exception("Exception updating fpga devices.")
            pass
예제 #10
0
 def before(self, state):
     state.request.rpcapi = rpcapi.ConductorAPI()
예제 #11
0
    def device_update_image(self, context, pci_addr, filename, transaction_id):
        """Write the device image to the device at the specified address.

        Transaction is the transaction ID as specified by sysinv-conductor.

        This must send back either success or failure to sysinv-conductor
        via an RPC cast.  The transaction ID is sent back to allow sysinv-conductor
        to locate the transaction in the DB.

        TODO: could get fancier with an image cache and delete based on LRU.
        """

        rpcapi = conductor_rpcapi.ConductorAPI(
                        topic=conductor_rpcapi.MANAGER_TOPIC)

        try:
            LOG.info("ensure device image cache exists")
            ensure_device_image_cache_exists()

            # Pull the image from the controller.
            LOG.info("fetch device image %s" % filename)
            # For now, we only need to support AIO nodes, so just copy the
            # file from where we know sysinv-conductor put it.
            local_path = fetch_device_image_local(filename)

            # TODO: when we need to support standalone workers, we'll need to
            # pull in the image file via HTTP.
            # local_path = fetch_device_image(filename)

            # TODO: check CSK used to sign image, ensure it hasn't been cancelled
            # TODO: check root key used to sign image, ensure it matches root key of hardware
            #       Note: may want to check these in the sysinv API too.

            try:
                LOG.info("setting transaction id %s as in progress" % transaction_id)
                rpcapi.device_update_image_status(
                    context, self.host_uuid, transaction_id,
                    dconstants.DEVICE_IMAGE_UPDATE_IN_PROGRESS)

                # Disable the watchdog service to prevent a reboot on things
                # like critical process death. We don't want to reboot while
                # flashing the FPGA.
                stop_watchdog()

                # Write the image to the specified PCI device.
                # TODO:  when we support more than just N3000, we'll need to
                # pick the appropriate low-level write function based on the
                # hardware type.
                LOG.info("writing device image %s to device %s" % (filename, pci_addr))
                write_device_image_n3000(filename, pci_addr)

                # If we get an exception trying to send the status update
                # there's not much we can do.
                try:
                    LOG.info("setting transaction id %s as complete" % transaction_id)
                    rpcapi.device_update_image_status(
                        context, self.host_uuid, transaction_id,
                        dconstants.DEVICE_IMAGE_UPDATE_COMPLETED)
                except Exception:
                    LOG.exception("Unable to send fpga update image status "
                                  "completion message for transaction %s."
                                  % transaction_id)
            finally:
                # Delete the image file.
                os.remove(local_path)
                # start the watchdog service again
                start_watchdog()

        except exception.SysinvException as exc:
            LOG.info("setting transaction id %s as failed" % transaction_id)
            rpcapi.device_update_image_status(context, self.host_uuid,
                                            transaction_id,
                                            dconstants.DEVICE_IMAGE_UPDATE_FAILED,
                                            exc.message)