コード例 #1
0
    def delete(self, subcloud_ref):
        """Delete a subcloud.

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

        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

        try:
            # Ask dcmanager-manager to delete the subcloud.
            # It will do all the real work...
            return self.rpc_client.delete_subcloud(context, subcloud_id)
        except RemoteError as e:
            pecan.abort(422, e.value)
        except Exception as e:
            LOG.exception(e)
            pecan.abort(500, _('Unable to delete subcloud'))
コード例 #2
0
    def patch(self, subcloud_ref=None):
        """Update a subcloud.

        :param subcloud_ref: ID or name of subcloud to update
        """

        context = restcomm.extract_context_from_environ()
        subcloud = None

        if subcloud_ref is None:
            pecan.abort(400, _('Subcloud ID required'))

        payload = eval(request.body)
        if not payload:
            pecan.abort(400, _('Body required'))

        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

        management_state = payload.get('management-state')
        description = payload.get('description')
        location = payload.get('location')

        if not (management_state or description or location):
            pecan.abort(400, _('nothing to update'))

        # Syntax checking
        if management_state and \
                management_state not in [consts.MANAGEMENT_UNMANAGED,
                                         consts.MANAGEMENT_MANAGED]:
            pecan.abort(400, _('Invalid management-state'))

        try:
            # Inform dcmanager-manager that subcloud has been updated.
            # It will do all the real work...
            subcloud = self.rpc_client.update_subcloud(
                context,
                subcloud_id,
                management_state=management_state,
                description=description,
                location=location)
            return subcloud
        except RemoteError as e:
            pecan.abort(422, e.value)
        except Exception as e:
            # additional exceptions.
            LOG.exception(e)
            pecan.abort(500, _('Unable to update subcloud'))
コード例 #3
0
    def get(self, subcloud_ref=None):
        """Get details about software update options.

        :param subcloud: name or id of subcloud (optional)
        """
        context = restcomm.extract_context_from_environ()

        if subcloud_ref is None:
            # List of all subcloud options requested.
            # Prepend the all clouds default options to the result.

            result = dict()
            result['sw-update-options'] = list()

            default_sw_update_opts_dict = utils.get_sw_update_opts(context)

            result['sw-update-options'].append(default_sw_update_opts_dict)

            subclouds = db_api.sw_update_opts_get_all_plus_subcloud_info(
                context)

            for subcloud, sw_update_opts in subclouds:
                if sw_update_opts:
                    result['sw-update-options'].append(
                        db_api.sw_update_opts_w_name_db_model_to_dict(
                            sw_update_opts, subcloud.name))

            return result

        elif subcloud_ref == consts.DEFAULT_REGION_NAME:
            # Default options requested, guaranteed to succeed

            return utils.get_sw_update_opts(context)

        else:
            # Specific subcloud options requested

            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'))

            try:
                return utils.get_sw_update_opts(context,
                                                subcloud_id=subcloud.id)
            except Exception as e:
                pecan.abort(404, _('%s') % e)
コード例 #4
0
    def delete(self, subcloud_ref):
        """Delete the software update options."""

        context = restcomm.extract_context_from_environ()

        if subcloud_ref == consts.DEFAULT_REGION_NAME:
            # Delete defaults.
            # Note by deleting these, the next get will repopulate with
            # the global constants.

            try:
                db_api.sw_update_opts_default_destroy(context)
            except Exception:
                return
        else:

            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'))

            # Delete the subcloud specific options
            if db_api.sw_update_opts_get(context, subcloud.id):
                db_api.sw_update_opts_destroy(context, subcloud.id)
            else:
                pecan.abort(404, _('Subcloud patch options not found'))
コード例 #5
0
    def post(self, subcloud_ref=None, qualifier=None):
        """Create a new subcloud.

        :param subcloud_ref: ID of or name subcloud (only used when generating
                             config)
        :param qualifier: if 'config', returns the config INI file for the
                          subcloud
        """

        context = restcomm.extract_context_from_environ()

        if subcloud_ref is None:
            payload = eval(request.body)
            if not payload:
                pecan.abort(400, _('Body required'))
            name = payload.get('name')
            if not name:
                pecan.abort(400, _('name required'))
            management_subnet = payload.get('management-subnet')
            if not management_subnet:
                pecan.abort(400, _('management-subnet required'))
            management_start_ip = payload.get('management-start-ip')
            if not management_start_ip:
                pecan.abort(400, _('management-start-ip required'))
            management_end_ip = payload.get('management-end-ip')
            if not management_end_ip:
                pecan.abort(400, _('management-end-ip required'))
            management_gateway_ip = payload.get('management-gateway-ip')
            if not management_gateway_ip:
                pecan.abort(400, _('management-gateway-ip required'))
            systemcontroller_gateway_ip = \
                payload.get('systemcontroller-gateway-ip')
            if not systemcontroller_gateway_ip:
                pecan.abort(400, _('systemcontroller-gateway-ip required'))

            self._validate_subcloud_config(context, name, management_subnet,
                                           management_start_ip,
                                           management_end_ip,
                                           management_gateway_ip,
                                           systemcontroller_gateway_ip)

            try:
                # Ask dcmanager-manager to add the subcloud.
                # It will do all the real work...
                return self.rpc_client.add_subcloud(context, payload)
            except RemoteError as e:
                pecan.abort(422, e.value)
            except Exception as e:
                LOG.exception(e)
                pecan.abort(500, _('Unable to create subcloud'))
        elif qualifier:
            if qualifier == 'config':
                subcloud = None

                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'))

                payload = dict()
                if request.body:
                    payload = eval(request.body)
                config_file = self._create_subcloud_config_file(
                    context, subcloud, payload)
                result = dict()
                result['config'] = config_file
                return result
            else:
                pecan.abort(400, _('Invalid request'))
        else:
            pecan.abort(400, _('Invalid request'))
コード例 #6
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
コード例 #7
0
    def post(self, subcloud_ref=None):
        """Update or create sw update options.

        :param subcloud: name or id of subcloud (optional)
        """

        # Note creating or updating subcloud specific options require
        # setting all options.

        context = restcomm.extract_context_from_environ()

        payload = eval(request.body)
        if not payload:
            pecan.abort(400, _('Body required'))

        if subcloud_ref == consts.DEFAULT_REGION_NAME:

            # update default options
            subcloud_name = consts.SW_UPDATE_DEFAULT_TITLE

            if db_api.sw_update_opts_default_get(context):
                # entry already in db, update it.
                try:
                    sw_update_opts_ref = db_api.sw_update_opts_default_update(
                        context, payload['storage-apply-type'],
                        payload['compute-apply-type'],
                        payload['max-parallel-computes'],
                        payload['alarm-restriction-type'],
                        payload['default-instance-action'])
                except Exception as e:
                    LOG.exception(e)
                    raise e
            else:
                # no entry in db, create one.
                try:
                    sw_update_opts_ref = db_api.sw_update_opts_default_create(
                        context, payload['storage-apply-type'],
                        payload['compute-apply-type'],
                        payload['max-parallel-computes'],
                        payload['alarm-restriction-type'],
                        payload['default-instance-action'])
                except Exception as e:
                    LOG.exception(e)
                    raise e
        else:
            # update subcloud options

            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'))

                subcloud_name = subcloud.name

            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_name = subcloud_ref

            sw_update_opts = db_api.sw_update_opts_get(context, subcloud.id)

            if sw_update_opts is None:
                sw_update_opts_ref = db_api.sw_update_opts_create(
                    context, subcloud.id, payload['storage-apply-type'],
                    payload['compute-apply-type'],
                    payload['max-parallel-computes'],
                    payload['alarm-restriction-type'],
                    payload['default-instance-action'])

            else:
                # a row is present in table, update
                sw_update_opts_ref = db_api.sw_update_opts_update(
                    context, subcloud.id, payload['storage-apply-type'],
                    payload['compute-apply-type'],
                    payload['max-parallel-computes'],
                    payload['alarm-restriction-type'],
                    payload['default-instance-action'])

        return db_api.sw_update_opts_w_name_db_model_to_dict(
            sw_update_opts_ref, subcloud_name)
コード例 #8
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
コード例 #9
0
    def update_subcloud_endpoint_status(
            self,
            context,
            subcloud_name=None,
            endpoint_type=None,
            sync_status=consts.SYNC_STATUS_OUT_OF_SYNC,
            alarmable=True):
        """Update subcloud endpoint status

        :param context: request context object
        :param subcloud_name: name of subcloud to update
        :param endpoint_type: endpoint type to update
        :param sync_status: sync status to set
        """

        subcloud = None

        if subcloud_name:
            try:
                subcloud = db_api.subcloud_get_by_name(context, subcloud_name)
            except Exception as e:
                LOG.exception(e)
                raise e

            # Only allow updating the sync status if managed and online.
            # This means if a subcloud is going offline or unmanaged, then
            # the sync status update must be done first.
            if (((subcloud.availability_status == consts.AVAILABILITY_ONLINE)
                 and (subcloud.management_state == consts.MANAGEMENT_MANAGED))
                    or (sync_status != consts.SYNC_STATUS_IN_SYNC)):

                # update a single subcloud
                try:
                    self._update_endpoint_status_for_subcloud(
                        context, subcloud.id, endpoint_type, sync_status,
                        alarmable)
                except Exception as e:
                    LOG.exception(e)
                    raise e
            else:
                LOG.info("Ignoring unmanaged/offline subcloud sync_status "
                         "update for subcloud:%s endpoint:%s sync:%s" %
                         (subcloud_name, endpoint_type, sync_status))

        else:
            # update all subclouds
            for subcloud in db_api.subcloud_get_all(context):
                if (((subcloud.availability_status
                      == consts.AVAILABILITY_ONLINE) and
                     (subcloud.management_state == consts.MANAGEMENT_MANAGED))
                        or (sync_status != consts.SYNC_STATUS_IN_SYNC)):

                    try:
                        self._update_endpoint_status_for_subcloud(
                            context, subcloud.id, endpoint_type, sync_status,
                            alarmable)
                    except Exception as e:
                        LOG.exception(e)
                        raise e
                else:
                    LOG.info("Ignoring unmanaged/offline subcloud sync_status "
                             "update for subcloud:%s endpoint:%s sync:%s" %
                             (subcloud.name, endpoint_type, sync_status))
コード例 #10
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.
            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