Пример #1
0
    def get(self, subcloud_ref=None, qualifier=None):
        """Get details about subcloud.

        :param subcloud_ref: ID or name of subcloud
        """
        context = restcomm.extract_context_from_environ()

        if subcloud_ref is None:
            # List of subclouds requested
            subclouds = db_api.subcloud_get_all_with_status(context)
            result = dict()
            result['subclouds'] = []
            first_time = True
            subcloud_list = []
            subcloud_status_list = []

            # We get back a subcloud, subcloud_status pair for every
            # subcloud_status entry corresponding to a subcloud.  (Subcloud
            # info repeats)
            # Aggregate all the sync status for each of the
            # endpoints per subcloud into an overall sync status
            for subcloud, subcloud_status in subclouds:
                subcloud_dict = db_api.subcloud_db_model_to_dict(subcloud)
                subcloud_status_dict = db_api.subcloud_status_db_model_to_dict(
                    subcloud_status)
                subcloud_dict.update(subcloud_status_dict)

                if not first_time:
                    if subcloud_list[-1]['id'] == subcloud_dict['id']:
                        # We have a match for this subcloud id already,
                        # check if we have a same sync_status
                        if subcloud_list[-1][consts.SYNC_STATUS] != \
                                subcloud_dict[consts.SYNC_STATUS]:
                            subcloud_list[-1][consts.SYNC_STATUS] = \
                                consts.SYNC_STATUS_OUT_OF_SYNC

                        if subcloud_status:
                            subcloud_status_list.append(
                                db_api.
                                subcloud_endpoint_status_db_model_to_dict(  # noqa
                                    subcloud_status))
                        subcloud_list[-1][
                            consts.ENDPOINT_SYNC_STATUS] = subcloud_status_list

                    else:
                        subcloud_status_list = []
                        if subcloud_status:
                            subcloud_status_list.append(
                                db_api.
                                subcloud_endpoint_status_db_model_to_dict(  # noqa
                                    subcloud_status))

                        subcloud_list.append(subcloud_dict)
                else:
                    if subcloud_status:
                        subcloud_status_list.append(
                            db_api.subcloud_endpoint_status_db_model_to_dict(
                                subcloud_status))
                    subcloud_list.append(subcloud_dict)

                first_time = False

            for s in subcloud_list:
                result['subclouds'].append(s)

            return result
        else:
            # Single subcloud requested
            subcloud = None
            subcloud_dict = dict()
            subcloud_status_list = []
            endpoint_sync_dict = dict()

            if subcloud_ref.isdigit():
                # Look up subcloud as an ID
                try:
                    subcloud = db_api.subcloud_get(context, subcloud_ref)
                except exceptions.SubcloudNotFound:
                    pecan.abort(404, _('Subcloud not found'))
            else:
                # Look up subcloud by name
                try:
                    subcloud = db_api.subcloud_get_by_name(
                        context, subcloud_ref)
                except exceptions.SubcloudNameNotFound:
                    pecan.abort(404, _('Subcloud not found'))

            subcloud_id = subcloud.id

            if qualifier:
                # Configuration for this subcloud requested.
                # Encrypt before sending.
                if qualifier == 'config':
                    result = dict()
                    user_list = self._get_subcloud_users()

                    # Use a hash of the subcloud name + management subnet
                    # as the encryption key
                    hashstring = subcloud.name + subcloud.management_subnet
                    h = MD5.new()
                    h.update(hashstring)
                    encryption_key = h.hexdigest()
                    user_list_string = json.dumps(user_list)
                    user_list_encrypted = crypt.urlsafe_encrypt(
                        encryption_key, user_list_string)
                    result['users'] = user_list_encrypted
                    return result
                else:
                    pecan.abort(400, _('Invalid request'))
            else:
                # Data for this subcloud requested
                # Build up and append a dictionary of the endpoints
                # sync status to the result.
                for subcloud, subcloud_status in db_api. \
                        subcloud_get_with_status(context, subcloud_id):
                    subcloud_dict = db_api.subcloud_db_model_to_dict(subcloud)
                    # may be empty subcloud_status entry, account for this
                    if subcloud_status:
                        subcloud_status_list.append(
                            db_api.subcloud_endpoint_status_db_model_to_dict(
                                subcloud_status))
                endpoint_sync_dict = {
                    consts.ENDPOINT_SYNC_STATUS: subcloud_status_list
                }
                subcloud_dict.update(endpoint_sync_dict)

                return subcloud_dict
Пример #2
0
    def update_subcloud(self,
                        context,
                        subcloud_id,
                        management_state=None,
                        description=None,
                        location=None):
        """Update subcloud and notify orchestrators.

        :param context: request context object
        :param subcloud_id: id of subcloud to update
        :param management_state: new management state
        :param description: new description
        :param location: new location
        """

        LOG.info("Updating subcloud %s." % subcloud_id)

        # Get the subcloud details from the database
        subcloud = db_api.subcloud_get(context, subcloud_id)

        # Semantic checking
        if management_state:
            if management_state == consts.MANAGEMENT_UNMANAGED:
                if subcloud.management_state == consts.MANAGEMENT_UNMANAGED:
                    LOG.warning("Subcloud %s already unmanaged" % subcloud_id)
                    raise exceptions.BadRequest(
                        resource='subcloud',
                        msg='Subcloud is already unmanaged')
            elif management_state == consts.MANAGEMENT_MANAGED:
                if subcloud.management_state == consts.MANAGEMENT_MANAGED:
                    LOG.warning("Subcloud %s already managed" % subcloud_id)
                    raise exceptions.BadRequest(
                        resource='subcloud', msg='Subcloud is already managed')
                if subcloud.availability_status != \
                        consts.AVAILABILITY_ONLINE:
                    LOG.warning("Subcloud %s is not online" % subcloud_id)
                    raise exceptions.SubcloudNotOnline()
            else:
                LOG.error("Invalid management_state %s" % management_state)
                raise exceptions.InternalError()

        subcloud = db_api.subcloud_update(context,
                                          subcloud_id,
                                          management_state=management_state,
                                          description=description,
                                          location=location)

        # Inform orchestrators that subcloud has been updated
        if management_state:

            try:
                # Inform orchestrator of state change
                self.dcorch_rpc_client.update_subcloud_states(
                    context, subcloud.name, management_state,
                    subcloud.availability_status)

                LOG.info('Notifying dcorch, subcloud:%s management: %s, '
                         'availability:%s' % (subcloud.name, management_state,
                                              subcloud.availability_status))

            except Exception as e:
                LOG.exception(e)
                LOG.warn('Problem informing dcorch of subcloud '
                         'state change, subcloud: %s' % subcloud.name)

            if management_state == consts.MANAGEMENT_UNMANAGED:

                # set all endpoint statuses to unknown
                self.update_subcloud_endpoint_status(
                    context,
                    subcloud_name=subcloud.name,
                    endpoint_type=None,
                    sync_status=consts.SYNC_STATUS_UNKNOWN)

        return db_api.subcloud_db_model_to_dict(subcloud)
Пример #3
0
    def add_subcloud(self, context, payload):
        """Add subcloud and notify orchestrators.

        :param context: request context object
        :param name: name of subcloud to add
        :param payload: subcloud configuration
        """
        LOG.info("Adding subcloud %s." % payload['name'])

        try:
            subcloud = db_api.subcloud_get_by_name(context, payload['name'])
        except exceptions.SubcloudNameNotFound:
            pass
        else:
            raise exceptions.BadRequest(
                resource='subcloud',
                msg='Subcloud with that name already exists')

        # Subcloud is added with software version that matches system
        # controller.
        software_version = SW_VERSION
        try:
            subcloud = db_api.subcloud_create(
                context, payload['name'], payload.get('description'),
                payload.get('location'), software_version,
                payload['management-subnet'], payload['management-gateway-ip'],
                payload['management-start-ip'], payload['management-end-ip'],
                payload['systemcontroller-gateway-ip'])
        except Exception as e:
            LOG.exception(e)
            raise e

        # Populate the subcloud status table with all endpoints
        for endpoint in dcorch_consts.ENDPOINT_TYPES_LIST:
            db_api.subcloud_status_create(context, subcloud.id, endpoint)

        try:
            # Create a new route to this subcloud on the management interface
            # on both controllers.
            m_ks_client = KeystoneClient()
            subcloud_subnet = netaddr.IPNetwork(payload['management-subnet'])
            session = m_ks_client.endpoint_cache.get_session_from_token(
                context.auth_token, context.project)
            sysinv_client = SysinvClient(consts.DEFAULT_REGION_NAME, session)
            controllers = sysinv_client.get_controller_hosts()
            for controller in controllers:
                management_interface = sysinv_client.get_management_interface(
                    controller.hostname)
                if management_interface is not None:
                    sysinv_client.create_route(
                        management_interface.uuid, str(subcloud_subnet.ip),
                        subcloud_subnet.prefixlen,
                        payload['systemcontroller-gateway-ip'], 1)

            # Create identity endpoints to this subcloud on the
            # management-start-ip of the subcloud which will be allocated
            # as the floating Management IP of the Subcloud if the
            # Address Pool is not shared. Incase the endpoint entry
            # is incorrect, or the management IP of the subcloud is changed
            # in the future, it will not go managed or will show up as
            # out of sync. To fix this use Openstack endpoint commands
            # on the SystemController to change the subcloud endpoint
            ks_service_id = None
            for service in m_ks_client.services_list:
                if service.type == dcorch_consts.ENDPOINT_TYPE_IDENTITY:
                    ks_service_id = service.id
                    break
            else:
                raise exceptions.BadRequest(
                    resource='subcloud',
                    msg='No Identity service found on SystemController')

            identity_endpoint_ip = payload['management-start-ip']

            if netaddr.IPAddress(identity_endpoint_ip).version == 6:
                identity_endpoint_url = \
                    "http://[{}]:5000/v3".format(identity_endpoint_ip)
            else:
                identity_endpoint_url = \
                    "http://{}:5000/v3".format(identity_endpoint_ip)

            for iface in ['internal', 'admin']:
                m_ks_client.keystone_client.endpoints.create(
                    ks_service_id,
                    identity_endpoint_url,
                    interface=iface,
                    region=subcloud.name)

            # Inform orchestrator that subcloud has been added
            self.dcorch_rpc_client.add_subcloud(context, subcloud.name,
                                                subcloud.software_version)

            # Regenerate the addn_hosts_dc file
            self._create_addn_hosts_dc(context)

            return db_api.subcloud_db_model_to_dict(subcloud)

        except Exception as e:
            LOG.exception(e)
            # If we failed to create the subcloud, clean up anything we may
            # have done.
            self._delete_subcloud_routes(context, subcloud)
            db_api.subcloud_destroy(context, subcloud.id)
            raise e
    def add_subcloud(self, context, payload):
        """Add subcloud and notify orchestrators.

        :param context: request context object
        :param name: name of subcloud to add
        :param payload: subcloud configuration
        """
        LOG.info("Adding subcloud %s." % payload['name'])

        try:
            subcloud = db_api.subcloud_get_by_name(context, payload['name'])
        except exceptions.SubcloudNameNotFound:
            pass
        else:
            raise exceptions.BadRequest(
                resource='subcloud',
                msg='Subcloud with that name already exists')

        # Subcloud is added with software version that matches system
        # controller.
        software_version = SW_VERSION
        try:
            subcloud = db_api.subcloud_create(
                context, payload['name'], payload.get('description'),
                payload.get('location'), software_version,
                payload['management-subnet'], payload['management-gateway-ip'],
                payload['management-start-ip'], payload['management-end-ip'],
                payload['systemcontroller-gateway-ip'])
        except Exception as e:
            LOG.exception(e)
            raise e

        # Populate the subcloud status table with all endpoints
        for endpoint in dcorch_consts.ENDPOINT_TYPES_LIST:
            db_api.subcloud_status_create(context, subcloud.id, endpoint)

        try:
            # Create a new route to this subcloud on the management interface
            # on both controllers.
            subcloud_subnet = netaddr.IPNetwork(payload['management-subnet'])
            session = endpoint_cache.EndpointCache().get_session_from_token(
                context.auth_token, context.project)
            sysinv_client = SysinvClient(consts.DEFAULT_REGION_NAME, session)
            controllers = sysinv_client.get_controller_hosts()
            for controller in controllers:
                management_interface = sysinv_client.get_management_interface(
                    controller.hostname)
                if management_interface is not None:
                    sysinv_client.create_route(
                        management_interface.uuid, str(subcloud_subnet.ip),
                        subcloud_subnet.prefixlen,
                        payload['systemcontroller-gateway-ip'], 1)

            # Inform orchestrator that subcloud has been added
            self.dcorch_rpc_client.add_subcloud(context, subcloud.name,
                                                subcloud.software_version)

            # Regenerate the addn_hosts_dc file
            self._create_addn_hosts_dc(context)

            return db_api.subcloud_db_model_to_dict(subcloud)

        except Exception as e:
            LOG.exception(e)
            # If we failed to create the subcloud, clean up anything we may
            # have done.
            self._delete_subcloud_routes(context, subcloud)
            db_api.subcloud_destroy(context, subcloud.id)
            raise e