Module cvpysdk.index_server

File for performing index server related operations on the commcell

IndexServers, IndexServer and _Roles are 3 classes defined in this file

IndexServers: Class for representing all the index servers associated with the commcell

IndexServer: Class for a instance of a single index server of the commcell

_Roles: Class for storing all the cloud role details

"IndexServerOSType" is the enum class used to represent os type of IS

IndexServers

__init__()                          --  initialize object of IndexServers class associated with
                                        the commcell

__str()                             --  returns all the index servers of the commcell

__repr__()                          --  returns the string to represent the instance

__len__()                           --  returns the number of index servers associated

_get_index_servers()                --  gets all the index server associated with the commcell

_response_not_success()             --  raise exception when response is not 200

_get_all_roles()                    --  creates an instance of _Roles class

has()                               --  returns whether the index server is present or not

get()                               --  returns a IndexServer object for given cloud name

create()                            --  creates a index server within the commcell

delete()                            --  deletes a index server associated with commcell

update_roles_data()                 --  fetches the cloud roles data from commcell

get_properties()                    --  returns a dict of data of index server for the given
                                        cloud name

refresh()                           --  refresh the index servers associated with commcell

prune_orphan_datasources()          --  Deletes all the orphan datasources

Indexservers Attributes

**all_index_servers**               --  returns the dictionary consisting of all the index
                                        servers associated with the commcell and there details

**roles_data**                      --  returns the list of cloud roles details

IndexServer

__init()__                          --  initializes the object with the specified commcell
                                        object, index server name and the cloud id

__repr__()                          --  returns the index server's name, the instance is
associated with

_get_cloud_id()                     --  gets the cloud id

_get_properties()                   --  gets all the properties of the index server

refresh()                           --  refresh all the properties of client

update_roles_data()                 --  fetches the cloud roles data from commcell

modify()                            --  to modify the index server node details

change_plan()                       --  changes the plan of a given index server

update_role()                       --  to update the roles assigned to cloud

delete_docs_from_core()             --  Deletes the docs from the given core name on index server depending
                                        on the select dict passed

hard_commit                         --  do hard commit on specified index server solr core

get_health_indicators()             --  get health indicators for index server node by client name

get_all_cores                       --  gets all the cores in index server

_create_solr_query()                --  Create solr search query based on inputs provided

execute_solr_query()                --  Creates solr url based on input and executes it on solr on given core

get_index_node()                    --  returns an Index server node object for given node name

get_os_info()                       --  returns the OS type for the Index server

get_plan_info()                     --  Returns the plan information of the index server

__form_field_query()                --  returns the query with the key and value passed

Indexserver Attributes

**properties**                      --  returns the properties of this index server

**roles_data**                      --  returns all the available cloud roles data

**host_name**                       --  returns the host name for the index server

**internal_cloud_name**             --  returns the internal cloud name

**client_name**                     --  returns the client name for index server

**server_url**                      --  returns the content indexing server url

**type**                            --  returns the type of the index server

**base_port**                       --  returns the base port of this index server

**client_id**                       --  returns the client id for this index server

**roles**                           --  returns the array of roles installed
                                        with the index server within the commcell

**cloud_id**                        --  returns the cloud id of the index server

**server_type**                     --  returns the server type of the index server

**engine_name**                     --  returns the engine name that is index server name

**index_server_client_id**          --  returns the index server client id

**role_display_name**               --  display name of roles

**is_cloud**                        --  returns boolean True if the Index server is cloud else returns False

**node_count**                      --  returns the number of Index server nodes

**os_info**                         --  returns the OS type for the Index server

**plan_name**                       --  Returns the plan name associated with index server

IndexNode

__init__()                          --  initializes the class with commcell object
                                        Index server cloud id and Node client name

refresh()                           --  refreshes the attributes

modify()                            --  to modify the index server node details

Indexnode Attributes

**node_name**                       --  returns Index server node client name

**node_id**                         --  returns Index server node client id

**solr_port**                       --  returns port number Solr is running on the                                            Index server node

**solr_url**                        --  returns Solr URL for Index server node

**roles**                           --  returns the array of roles installed
                                        with the index server within the commcell

**index_location**                  --  returns Index directory for the Index server Node

**jvm_memory**                      --  returns Solr JVM memory for the Index server Node

_Roles

__init__()                          --  initializes the class with commcell object

refresh()                           --  refreshes the attributes

_get_all_roles()                    --  fetches the cloud roles data from commcell

get_role_id()                       --  returns role id for given role name

update_roles_data()                 --  fetches the cloud roles data from commcell

_Roles Attributes

**roles_data**                      --  returns the list of details of all cloud roles
Expand source code Browse git
# --------------------------------------------------------------------------
# Copyright Commvault Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# --------------------------------------------------------------------------

"""File for performing index server related operations on the commcell

IndexServers, IndexServer and _Roles are 3 classes defined in this file

IndexServers:   Class for representing all the index servers associated with the commcell

IndexServer:    Class for a instance of a single index server of the commcell

_Roles:         Class for storing all the cloud role details

"IndexServerOSType" is the enum class used to represent os type of IS

IndexServers
============

    __init__()                          --  initialize object of IndexServers class associated with
                                            the commcell

    __str()                             --  returns all the index servers of the commcell

    __repr__()                          --  returns the string to represent the instance

    __len__()                           --  returns the number of index servers associated

    _get_index_servers()                --  gets all the index server associated with the commcell

    _response_not_success()             --  raise exception when response is not 200

    _get_all_roles()                    --  creates an instance of _Roles class

    has()                               --  returns whether the index server is present or not

    get()                               --  returns a IndexServer object for given cloud name

    create()                            --  creates a index server within the commcell

    delete()                            --  deletes a index server associated with commcell

    update_roles_data()                 --  fetches the cloud roles data from commcell

    get_properties()                    --  returns a dict of data of index server for the given
                                            cloud name

    refresh()                           --  refresh the index servers associated with commcell

    prune_orphan_datasources()          --  Deletes all the orphan datasources

IndexServers Attributes
-----------------------

    **all_index_servers**               --  returns the dictionary consisting of all the index
                                            servers associated with the commcell and there details

    **roles_data**                      --  returns the list of cloud roles details


IndexServer
===========

    __init()__                          --  initializes the object with the specified commcell
                                            object, index server name and the cloud id

    __repr__()                          --  returns the index server's name, the instance is
    associated with

    _get_cloud_id()                     --  gets the cloud id

    _get_properties()                   --  gets all the properties of the index server

    refresh()                           --  refresh all the properties of client

    update_roles_data()                 --  fetches the cloud roles data from commcell

    modify()                            --  to modify the index server node details

    change_plan()                       --  changes the plan of a given index server

    update_role()                       --  to update the roles assigned to cloud

    delete_docs_from_core()             --  Deletes the docs from the given core name on index server depending
                                            on the select dict passed

    hard_commit                         --  do hard commit on specified index server solr core

    get_health_indicators()             --  get health indicators for index server node by client name

    get_all_cores                       --  gets all the cores in index server

    _create_solr_query()                --  Create solr search query based on inputs provided

    execute_solr_query()                --  Creates solr url based on input and executes it on solr on given core

    get_index_node()                    --  returns an Index server node object for given node name

    get_os_info()                       --  returns the OS type for the Index server

    get_plan_info()                     --  Returns the plan information of the index server

    __form_field_query()                --  returns the query with the key and value passed

IndexServer Attributes
----------------------

    **properties**                      --  returns the properties of this index server

    **roles_data**                      --  returns all the available cloud roles data

    **host_name**                       --  returns the host name for the index server

    **internal_cloud_name**             --  returns the internal cloud name

    **client_name**                     --  returns the client name for index server

    **server_url**                      --  returns the content indexing server url

    **type**                            --  returns the type of the index server

    **base_port**                       --  returns the base port of this index server

    **client_id**                       --  returns the client id for this index server

    **roles**                           --  returns the array of roles installed
                                            with the index server within the commcell

    **cloud_id**                        --  returns the cloud id of the index server

    **server_type**                     --  returns the server type of the index server

    **engine_name**                     --  returns the engine name that is index server name

    **index_server_client_id**          --  returns the index server client id

    **role_display_name**               --  display name of roles

    **is_cloud**                        --  returns boolean True if the Index server is cloud else returns False

    **node_count**                      --  returns the number of Index server nodes

    **os_info**                         --  returns the OS type for the Index server

    **plan_name**                       --  Returns the plan name associated with index server


IndexNode
=========

    __init__()                          --  initializes the class with commcell object
                                            Index server cloud id and Node client name

    refresh()                           --  refreshes the attributes

    modify()                            --  to modify the index server node details

IndexNode Attributes
--------------------

    **node_name**                       --  returns Index server node client name

    **node_id**                         --  returns Index server node client id

    **solr_port**                       --  returns port number Solr is running on the\
                                            Index server node

    **solr_url**                        --  returns Solr URL for Index server node

    **roles**                           --  returns the array of roles installed
                                            with the index server within the commcell

    **index_location**                  --  returns Index directory for the Index server Node

    **jvm_memory**                      --  returns Solr JVM memory for the Index server Node

_Roles
======

    __init__()                          --  initializes the class with commcell object

    refresh()                           --  refreshes the attributes

    _get_all_roles()                    --  fetches the cloud roles data from commcell

    get_role_id()                       --  returns role id for given role name

    update_roles_data()                 --  fetches the cloud roles data from commcell

_Roles Attributes
-----------------

    **roles_data**                      --  returns the list of details of all cloud roles
    """
import json

import http.client as httplib
from copy import deepcopy
import enum
from .exception import SDKException
from .datacube.constants import IndexServerConstants


class IndexServers(object):
    """Class for representing all the index servers associated with the commcell."""

    def __init__(self, commcell_object):
        """Initialize object of the IndexServers class.

            Args:
                commcell_object (object)  --  instance of the Commcell class

            Returns:
                object - instance of the IndexServers class
        """
        self._commcell_object = commcell_object
        self._cvpysdk_object = commcell_object._cvpysdk_object
        self._services = commcell_object._services
        self._update_response_ = commcell_object._update_response_
        self._all_index_servers = None
        self._roles_obj = None
        self.refresh()

    def __str__(self):
        """Representation string consisting of all index servers of the commcell.

                Returns:
                    str - string of all the index servers with different roles associated
                    with the commcell
        """
        representation_string = '{:^5}\t{:^20}\n\n'.format('S. No.', 'IS Name')
        index = 1
        for index_server in self._all_index_servers:
            representation_string += '{:^5}\t{:^20}\n'.format(
                index, index_server['engineName'])
            index += 1
        return representation_string

    def __repr__(self):
        """Representation string for the instance of the IndexServers class."""
        return "IndexServers class instance for Commcell: '{0}'".format(
            self._commcell_object.commserv_name
        )

    def __len__(self):
        """Returns the number of the index servers associated with the commcell"""
        return len(self._all_index_servers)

    def _response_not_success(self, response):
        """Helper method to raise exception when response is not 200 (ok)

                Raises:
                    SDKException:
                        Response was not success
        """
        raise SDKException(
            'Response',
            '101',
            self._update_response_(
                response.text))

    def _get_index_servers(self):
        """Method to retrieve all the index server available on commcell.

            Raises:
                SDKException:
                    Failed to get the list of analytics engines

                    Response was not success
        """
        flag, response = self._cvpysdk_object.make_request(
            'GET', self._services['GET_ALL_INDEX_SERVERS'])
        if flag:
            if response.json() and 'listOfCIServer' in response.json():
                for item in response.json()['listOfCIServer']:
                    if item['cloudID'] in self._all_index_servers:
                        # Add only unique roles to list
                        if item['version'] not in self._all_index_servers[item['cloudID']]['version']:
                            self._all_index_servers[item['cloudID']]['version'].append(item['version'])
                        # check whether we have populated node details earlier. if not, add it to
                        # exisitng respective fields
                        if item['clientName'] not in self._all_index_servers[item['cloudID']]['clientName']:

                            self._all_index_servers[item['cloudID']]['clientId'].append(item['clientId'])
                            self._all_index_servers[item['cloudID']]['clientName'].append(item['clientName'])
                            self._all_index_servers[item['cloudID']]['hostName'].append(item['hostName'])
                            self._all_index_servers[item['cloudID']]['cIServerURL'].append(item['cIServerURL'])
                            self._all_index_servers[item['cloudID']]['basePort'].append(item['basePort'])

                    else:
                        item['version'] = [item['version']]
                        item['clientId'] = [item['clientId']]
                        item['clientName'] = [item['clientName']]
                        item['hostName'] = [item['hostName']]
                        item['cIServerURL'] = [item['cIServerURL']]
                        item['basePort'] = [item['basePort']]
                        self._all_index_servers[item['cloudID']] = item
            else:
                self._all_index_servers = {}
        else:
            self._response_not_success(response)

    def _get_all_roles(self):
        """Creates an instance of _Roles class and adds it to the IndexServer class"""
        self._roles_obj = _Roles(self._commcell_object)

    @property
    def all_index_servers(self):
        """Returns the details of all the index server for associated commcell.

                Returns:
                    dict - dictionary consisting details of all the index servers
                    associated with commcell
                    Sample - {
                                <cloud_id_1>   :
                                    {
                                        "engineName" : <property_value>,
                                        "internalCloudName" : <property_value>,
                                        ...
                                    },
                                <cloud_id_2>   :
                                    {
                                        "engineName" : <property_value>,
                                        "cloudID" : <property_value>,
                                        ...
                                    }
                            }
        """
        return self._all_index_servers

    @property
    def roles_data(self):
        """Returns the details of all the cloud roles data

                Returns:
                    list - list of dictionary containing details of the cloud roles
        """
        return self._roles_obj.roles_data

    def refresh(self):
        """Refresh the properties of IndexServers class"""
        self._all_index_servers = {}
        self._get_index_servers()
        if not self._roles_obj:
            self._get_all_roles()

    def update_roles_data(self):
        """Synchronises all the cloud roles details with the commcell"""
        self._roles_obj.update_roles_data()

    def get_properties(self, cloud_name):
        """Returns all details of a index server with the cloud name

                Args:
                    cloud_name     (str)       --  cloud name of index server

                Returns:
                    dict        -   dict consisting details of the index server
        """
        for index_server in self._all_index_servers:
            if self._all_index_servers[index_server]['engineName'] == cloud_name:
                return self._all_index_servers[index_server]
        raise SDKException('IndexServers', '102')

    def has(self, cloud_name):
        """Returns True if the index server with given name is present in commcell.

                Args:
                    cloud_name     (str)       --  the engine name of index server

                Returns:
                    boolean     -   True if index server with given name as is_name
                    is associated with the commcell else returns False

                Raises:
                    SDKExecption:
                        Data type of the input(s) is not valid
        """
        if isinstance(cloud_name, str):
            for index_server in self._all_index_servers:
                if self._all_index_servers[index_server]["engineName"].lower() == cloud_name.lower():
                    return True
            return False
        raise SDKException('IndexServers', '101')

    def get(self, cloud_data):
        """Returns IndexServer object if a index server is found.

                Args:
                    cloud_data        (int/str)       --    cloud name or
                                                            cloud ID of index server

                Returns:
                    object            (IndexServer)   --  Instance on index server with
                    the engine name or cloud id as item

                Raises:
                    SDKException:
                        Index Server not found.

                        Data type of the input(s) is not valid.
        """
        if isinstance(cloud_data, int):
            if cloud_data in self._all_index_servers:
                return IndexServer(
                    self._commcell_object,
                    self._all_index_servers[cloud_data]['engineName'],
                    cloud_data)
            SDKException('IndexServers', '102')
        elif isinstance(cloud_data, str):
            name = cloud_data.lower()
            for itter in self._all_index_servers:
                if self._all_index_servers[itter]['engineName'].lower(
                ) == name:
                    return IndexServer(
                        self._commcell_object,
                        self._all_index_servers[itter]['engineName'],
                        self._all_index_servers[itter]['cloudID'])
            raise SDKException('IndexServers', '102')
        raise SDKException('IndexServers', '101')

    def create(
            self,
            index_server_name,
            index_server_node_names,
            index_directory,
            index_server_roles,
            index_pool_name=None,
            is_cloud=False,
            cloud_param=None):
        """Creates an index server within the commcell

                Args:
                    index_server_node_names         (list)  --  client names for index server node
                    index_server_name               (str)   --  name for the index server
                    index_directory                 (list)  --  list of index locations for the index server
                                                                nodes respectively
                                                    For example:
                                                            [<path_1>] - same index location for all the nodes
                                                            [<path_1>, <path_2>, <path_3>] - different index
                                                    location for index server with 3 nodes
                    index_server_roles              (list)  --  list of role names to be assigned
                    index_pool_name                 (str)   --  name for the index pool to used by cloud index server
                    cloud_param                     (list)  --  list of custom parameters to be parsed
                                                    into the json for index server meta info
                                                    [
                                                        {
                                                            "name": <name>,
                                                            "value": <value>
                                                        }
                                                    ]
                    is_cloud            (bool)  --  if true then creates a cloud mode index server

                Raises:
                    SDKException:
                        Data type of the input(s) is not valid.

                        Response was not success.

                        Response was empty.
        """
        if not (isinstance(index_server_roles, list) and isinstance(index_server_node_names, list)
                and isinstance(index_server_name, str)):
            raise SDKException('IndexServers', '101')
        if isinstance(index_directory, str):
            index_directory = index_directory.split(",")
        node_count = len(index_server_node_names)
        index_directories_count = len(index_directory)
        if index_directories_count != 1 and index_directories_count != node_count:
            raise SDKException('IndexServers', '101')
        cloud_meta_infos = {
            'REPLICATION': '1',
            'LANGUAGE': '0'
        }
        node_meta_infos = {
            'PORTNO': IndexServerConstants.DEFAULT_SOLR_PORT,
            'JVMMAXMEMORY': IndexServerConstants.DEFAULT_JVM_MAX_MEMORY
        }
        role_meta_infos = {}
        req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
        req_json['cloudInfoEntity'] = {
            'cloudName': index_server_name,
            'cloudDisplayName': index_server_name
        }
        if is_cloud:
            index_pool_obj = self._commcell_object.index_pools[index_pool_name]
            req_json['type'] = 5
            req_json['solrCloudInfo']['cloudPoolInfo'] = {
                'cloudId': int(index_pool_obj['pool_id'])
            }
            cloud_meta_infos['INDEXLOCATION'] = index_directory[0]
        for node_name_index in range(len(index_server_node_names)):
            node_name = index_server_node_names[node_name_index]
            location_index = node_name_index - (node_name_index//index_directories_count)
            node_obj = self._commcell_object.clients[node_name]
            node_data = {
                "opType": IndexServerConstants.OPERATION_ADD,
                "nodeClientEntity": {
                    "hostName": node_obj['hostname'],
                    "clientId": int(node_obj['id']),
                    "clientName": node_name
                },
                'nodeMetaInfos': [{
                    "name": "INDEXLOCATION",
                    "value": index_directory[location_index]
                }]
            }
            for node_info in node_meta_infos:
                node_data['nodeMetaInfos'].append({
                    'name': node_info,
                    'value': str(node_meta_infos[node_info])
                })
            req_json['cloudNodes'].append(node_data)
        for role in index_server_roles:
            role_id = self._roles_obj.get_role_id(role)
            if not role_id:
                raise SDKException('IndexServers', '103')
            role_data = {
                "roleId": role_id,
                "roleName": role,
                "operationType": IndexServerConstants.OPERATION_ADD,
                'roleMetaInfos': []
            }
            for role_info in role_meta_infos:
                role_data['roleMetaInfos'].append({
                    'name': role_info,
                    'value': role_meta_infos[role_info]
                })
            req_json['solrCloudInfo']['roles'].append(role_data)
        if cloud_param:
            for param in cloud_param:
                if param['name'] in cloud_meta_infos:
                    del cloud_meta_infos[param['name']]
                req_json['cloudMetaInfos'].append(param)
        for cloud_info in cloud_meta_infos:
            req_json['cloudMetaInfos'].append({
                'name': cloud_info,
                'value': cloud_meta_infos[cloud_info]
            })
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_CREATE'], req_json)
        if flag:
            if response.json():
                error_code = response.json()['genericResp']['errorCode']
                error_string = response.json()['genericResp']['errorMessage']
                if error_code == 0:
                    self.refresh()
                    self._commcell_object.clients.refresh()
                    self._commcell_object.datacube.refresh_engine()
                else:
                    o_str = 'Failed to create Index Server. Error: "{0}"'.format(
                        error_string)
                    raise SDKException('IndexServers', '102', o_str)
            else:
                raise SDKException('Response', '102')
        else:
            self._response_not_success(response)

    def delete(self, cloud_name):
        """Deletes / removes an index server from the commcell

                Args:
                    cloud_name      (str)   --  cloud name of index server
                    to be removed from the commcell

                Raises:
                    SDKException:
                        Data type of the input(s) is not valid.

                        Response was not success.

                        Response was empty.
        """
        if not isinstance(cloud_name, str):
            raise SDKException('IndexServers', '101')
        cloud_id = self.get(cloud_name).cloud_id
        req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
        req_json["opType"] = IndexServerConstants.OPERATION_DELETE
        req_json['cloudInfoEntity']['cloudId'] = cloud_id
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_DELETE'], req_json
        )
        if flag:
            if response.json() and 'genericResp' in response.json() \
                    and 'errorCode' not in response.json()['genericResp']:
                self.refresh()
                self._commcell_object.clients.refresh()
                self._commcell_object.datacube.refresh_engine()
                return
            if response.json() and 'genericResp' in response.json():
                raise SDKException(
                    'Response', '102', response.json()['genericResp'].get(
                        'errorMessage', ''))
            raise SDKException('Response', '102')
        self._response_not_success(response)

    def prune_orphan_datasources(self):
        """Deletes all the orphan datasources
            Raises:
                SDKException:
                    if failed to prune the orphan datasources

                    If response is empty

                    if response is not success
        """
        prune_datasource = self._services['PRUNE_DATASOURCE']
        request_json = IndexServerConstants.PRUNE_REQUEST_JSON
        flag, response = self._cvpysdk_object.make_request(
            'POST', prune_datasource, request_json)
        if flag:
            if response.json():
                error_code = response.json().get('errorCode', 0)
                if error_code != 0:
                    raise SDKException('IndexServers', '104', 'Failed to prune orphan datasources')
                return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101', self._update_response_(response.text))


class IndexServerOSType(enum.Enum):
    """Enum class for Index Server OS Type"""
    WINDOWS = "Windows"
    UNIX = "Unix"
    MIXED = "Mixed"


class IndexServer(object):
    """Class for performing index server operations for a specific index server"""

    def __init__(self, commcell_obj, name, cloud_id=None):
        """Initialize the IndexServer class instance.

            Args:
                commcell_obj    (object)        --  instance of the Commcell class

                name            (str)           --  name of the index server

                cloud_id        (int)           --  cloud id of the index server
                    default: None

            Returns:
                object - instance of the IndexServer class
        """
        self._engine_name = name
        self._commcell_obj = commcell_obj
        self._cvpysdk_object = self._commcell_obj._cvpysdk_object
        self._services = self._commcell_obj._services
        if cloud_id:
            self._cloud_id = cloud_id
        else:
            self._cloud_id = self._get_cloud_id()
        self._properties = None
        self._roles_obj = None
        self.plan_info = None
        self.os_type = None
        self.refresh()

    def __repr__(self):
        """String representation of the instance of this class."""
        return 'IndexServer class instance for index server: "{0}"'.format(
            self._engine_name)

    def _get_cloud_id(self):
        """Get the cloud id for the index server

                Returns:
                    int - cloud id for the index server
        """
        return self._commcell_obj.index_servers.get(self._engine_name).cloud_id

    def _get_properties(self):
        """Get the properties of the index server"""
        self._properties = self._commcell_obj.index_servers.get_properties(
            self._engine_name)

    def refresh(self):
        """Refresh the index server properties"""
        self._commcell_obj.index_servers.refresh()
        self._get_properties()
        if self.os_type is None:
            self.os_type = self.get_os_info()
        if not self._roles_obj:
            self._roles_obj = _Roles(self._commcell_obj)
        if self.plan_info is None:
            self.plan_info = self.get_plan_info()

    def update_roles_data(self):
        """Synchronize the cloud roles data with the commcell"""
        self._roles_obj.update_roles_data()

    def modify(self, index_location, node_name, node_params):
        """Modifies the properties of an index server

            Args:
                index_location      (str)       --  index server data directory
                node_name           (str)       --  index server node name
                node_params         (dict)      --  parameters to be passed
                                                    [
                                                        {
                                                            "name" : <property_name>,
                                                            "value" : <property_value>
                                                        }
                                                    ]
            Raises:
                SDKException:
                    Response was not success.
                    Response was empty.
        """
        json_req = deepcopy(IndexServerConstants.REQUEST_JSON)
        json_req['opType'] = IndexServerConstants.OPERATION_EDIT
        json_req['cloudNodes'] = [{
            "opType": IndexServerConstants.OPERATION_EDIT,
            "nodeClientEntity": {
                "clientId": int(self._commcell_obj.clients.get(node_name).client_id)
            },
            "nodeMetaInfos": [
                {
                    "name": "INDEXLOCATION",
                    "value": index_location
                }
            ]
        }]
        json_req['cloudInfoEntity']['cloudId'] = self.cloud_id
        for param in node_params:
            json_req['cloudNodes'][0]['nodeMetaInfos'].append(param)
        flag, response = self._cvpysdk_object.make_request(
            "POST", self._services['CLOUD_MODIFY'], json_req)
        if flag:
            if response.json():
                if 'cloudId' in response.json():
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def change_plan(self, plan_name):
        """Modifies the plan used by an index server

            Args:
                plan_name      (str)       --  Name of the plan to be used for the index server
            Raises:
                SDKException:
                    Response was not success.
                    Response was empty.
                    if plan with given name doesn't exist
        """
        if not self._commcell_obj.plans.has_plan(plan_name):
            raise SDKException(
                'Plan', '102', f"Plan with name [{plan_name}] doesn't exist")
        request_json = {
            "opType": IndexServerConstants.OPERATION_EDIT,
            "type": 1,
            "planInfo": {
                "planId": int(self._commcell_obj.plans.get(plan_name).plan_id)
            },
            "cloudInfoEntity": {
                "cloudId": self.cloud_id
            }
        }
        flag, response = self._cvpysdk_object.make_request(
            "POST", self._services['CLOUD_MODIFY'], request_json)
        if flag:
            if response.json():
                if 'cloudId' in response.json():
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def update_role(self, props=None):
        """Updates a role of an Index Server

            Args:
                props               (list)  --  array of dictionaries
                consisting details of the roles such as role name
                and operation type.
                                            [{
                                                "roleName": <name>          (str)
                                                "operationType": 1 or 2     (int)
                                                    1 for adding a role
                                                    2 for removing a role
                                            }]

            Raises:
                SDKException:
                    if response is empty

                    if response is not success

        """
        json_req = {"cloudId": self.cloud_id, "roles": []}
        if props:
            for prop in props:
                role_id = self._roles_obj.get_role_id(prop['roleName'])
                if not role_id:
                    raise SDKException('IndexServers', '103')
                prop['roleId'] = role_id
                json_req['roles'].append(prop)
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_ROLE_UPDATE'], json_req
        )
        if flag:
            if response.json() and 'errorCode' in response.json():
                if response.json()['errorCode'] == 0:
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def delete_docs_from_core(self, core_name, select_dict = None):
        """Deletes the docs from the given core name on index server depending on the select dict passed

                Args:

                        core_name               (str)  --  name of the solr core
                        select_dict             (dict) --  dict with query to delete specific documents
                                                    default query - "*:*" (Deletes all the docs)

                    Returns:
                        None

                    Raises:
                        SDKException:

                            if input data is not valid

                            if index server is cloud, not implemented error

                            if response is empty

                            if response is not success
        """
        if not isinstance(core_name, str):
            raise SDKException('IndexServers', '101')
        if self.is_cloud:
            raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
        json_req = {"delete": {"query": self._create_solr_query(select_dict).replace("q=", "").replace("&wt=json", "")}}
        baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commitWithin=1000&overwrite=true&wt=json"
        flag, response = self._cvpysdk_object.make_request("POST", baseurl, json_req)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', f' Failed with error message - '
                                                          f'{response.json().get("error").get("msg")}')
            if 'responseHeader' in response.json():
                commitstatus = str(response.json().get("responseHeader").get("status"))
                if int(commitstatus) != 0:
                    raise SDKException('IndexServers', '104',
                                       f"Deleting docs from the core returned bad status - {commitstatus}")
                return
        raise SDKException('IndexServers', '111')

    def hard_commit(self, core_name):
        """do hard commit for the given core name on index server

                    Args:

                        core_name               (str)  --  name of the solr core

                    Returns:
                        None

                    Raises:
                        SDKException:

                            if input data is not valid

                            if index server is cloud, not implemented error

                            if response is empty

                            if response is not success
        """
        if not isinstance(core_name, str):
            raise SDKException('IndexServers', '101')
        if self.is_cloud:
            raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
        baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commit=true"
        flag, response = self._cvpysdk_object.make_request("GET", baseurl)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', "Hard commit returned error")
            if 'responseHeader' in response.json():
                commitstatus = str(response.json()['responseHeader']['status'])
                if int(commitstatus) != 0:
                    raise SDKException('IndexServers', '104', "Hard commit returned bad status")
                return
        raise SDKException('IndexServers', '104', "Something went wrong with hard commit")

    
    def get_health_indicators(self, client_name=None):
        """Get health indicators for index server node by client name

                Args:
                    client_name     (str)       --  name of the client node

                Returns:
                    (response(str)) -- str json object

                Raises:

                    SDKException:
                        if input data is not valid
                        if client name is not passed for index server cloud
                        if response is not success
                        if response is empty

        """
        server_url = self.server_url[0]
        response = None
        if self.is_cloud or len(self.client_name) > 1:
            if client_name is None:
                raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
            if client_name not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
            server_url = self.server_url[self.client_name.index(client_name)]
        baseurl = f"{server_url}/solr/rest/admin/healthsummary"
        headers = {
            'Accept': 'application/xml'
        }
        flag, response = self._cvpysdk_object.make_request("GET", headers=headers, url=baseurl)
        if flag:
            return response
        raise SDKException('IndexServers', '104', "Could not get health summary for [{}]".format(client_name))

    def get_all_cores(self, client_name=None):
        """gets all cores & core details from index server

                Args:
                    client_name     (str)       --  name of the client node
                        ***Applicable only for solr cloud mode or multi node Index Server***

                Returns:
                    (list,dict)     -- list containing core names
                                    -- dict containing details about cores

                Raises:

                    SDKException:

                        if input data is not valid

                        if client name is not passed for index server cloud

                        if response is not success

                        if response is empty

        """
        server_url = self.server_url[0]
        if self.is_cloud or len(self.client_name) > 1:
            if client_name is None:
                raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
            if client_name not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
            server_url = self.server_url[self.client_name.index(client_name)]
        core_names = []
        baseurl = f"{server_url}/solr/admin/cores"
        flag, response = self._cvpysdk_object.make_request("GET", baseurl)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', "Unable to get core names from index server")
            if 'status' in response.json():
                for core in response.json()['status']:
                    core_names.append(core)
                return core_names, response.json()['status']
        raise SDKException('IndexServers', '104', "Something went wrong while getting core names")

    def _create_solr_query(self, select_dict=None, attr_list=None, op_params=None):
        """Method to create the solr query based on the params
            Args:
                select_dict     (dictionary)     --  Dictionary containing search criteria and value
                                                     Acts as 'q' field in solr query

                attr_list       (set)            --  Column names to be returned in results.
                                                     Acts as 'fl' in solr query

                op_params       (dictionary)     --  Other params and values for solr query
                                                        (Ex: start, rows)

            Returns:
                The solr url based on params

            Raises:
                SDKException:

                        if failed to form solr query
        """
        try:
            search_query = f'q='
            simple_search = 0
            if select_dict:
                for key, value in select_dict.items():
                    if isinstance(key, tuple):
                        if isinstance(value, list):
                            search_query += f'({key[0]}:{str(value[0])}'
                            for val in value[1:]:
                                search_query += f' OR {key[0]}:{str(val)}'
                        else:
                            search_query += f'({key[0]}:{value}'
                        for key_val in key[1:]:
                            if isinstance(value, list):
                                search_query += f' OR {key_val}:{str(value[0])}'
                                for val in value[1:]:
                                    search_query += f' OR {key_val}:{str(val)}'
                            else:
                                search_query += f' OR {key_val}:{value}'
                        search_query += ') AND '
                    elif isinstance(value, list):
                        search_query += f'({key}:{str(value[0])}'
                        for val in value[1:]:
                            search_query += f' OR {key}:{str(val)}'
                        search_query += ") AND "
                    elif key == "keyword":
                        search_query += "(" + value + ")"
                        simple_search = 1
                        break
                    else:
                        search_query = search_query + f'{key}:{str(value)} AND '
                if simple_search == 0:
                    search_query = search_query[:-5]
            else:
                search_query += "*:*"

            field_query = ""
            if attr_list:
                field_query = "&fl="
                for item in attr_list:
                    field_query += f'{str(item)},'
                field_query = field_query[:-1]
            if attr_list and 'content' in attr_list:
                field_query = f"{field_query}&exclude=false"

            ex_query = ""
            if not op_params:
                op_params = {'wt': "json"}
            else:
                op_params['wt'] = "json"
            for key, values in op_params.items():
                if isinstance(values, list):
                    for value in values:
                        ex_query += self.__form_field_query(key, value)
                else:
                    ex_query += self.__form_field_query(key, values)
            final_url = f'{search_query}{field_query}{ex_query}'
            return final_url
        except Exception as excp:
            raise SDKException('IndexServers', '104', f"Something went wrong while creating solr query - {excp}")

    def execute_solr_query(
            self,
            core_name,
            solr_client=None,
            select_dict=None,
            attr_list=None,
            op_params=None):
        """Creates solr url based on input and executes it on solr on given core/collection
            Args:

                core_name               (str)           --  Core name/collection name where we want to query

                solr_client             (str)           --  Index Server client name to execute solr query
                                                                Default : None (picks first client on index server)

                select_dict             (dictionary)    --  Dictionary containing search criteria and
                                                            value. Acts as 'q' field in solr query

                        Example :

                            1. General Criteria to filter results              -   {"jid": 1024, "datatype": 2,clid: 2}
                            2. Keyword Searches on solr                        -   {'keyword': 'SearchKeyword'}
                            3. For multiple value searches on single field     -   {'cvowner': ['xxx','yyy']}
                            4. For single value searches on multiple fields    -   {('cvowner','cvreaddisp') : 'xxx'}

                attr_list               (set)           --  Column names to be returned in results.
                                                                Acts as 'fl' in solr query

                        Example (For Exchange Mailbox IDA, below fields are there in solr) :
                                    {
                                     'msgclass',
                                     'ccsmtp',
                                     'fmsmtp',
                                     'folder'
                                   }

                op_params               (dictionary)    --  Other params and values for solr query. Do not
                                                            mention 'wt' param as it is always json

                                                            Example : {"rows": 0}

            Returns:
                content of the response

            Raises:
                SDKException:

                        if unable to send request

                        if response is not success
        """
        solr_url = f"solr/{core_name}/select?{self._create_solr_query(select_dict, attr_list, op_params)}"
        if solr_client is None:
            solr_url = f"{self.server_url[0]}/{solr_url}"
        else:
            if solr_client not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server')
            server_url = self.server_url[self.client_name.index(solr_client)]
            solr_url = f"{server_url}/{solr_url}"
        flag, response = self._cvpysdk_object.make_request("GET", solr_url)
        if flag and response.json():
            return response.json()
        elif response.status_code == httplib.FORBIDDEN:
            cmd = f"(Invoke-WebRequest -UseBasicParsing -uri \"{solr_url}\").content"
            client_obj = None
            if solr_client:
                client_obj = self._commcell_obj.clients.get(solr_client)
            else:
                # if no client is passed, then take first client in index server cloud
                client_obj = self._commcell_obj.clients.get(self.client_name[0])
            exit_code, output, error_message = client_obj.execute_script(script_type="PowerShell",
                                                                         script=cmd)
            if exit_code != 0:
                raise SDKException(
                    'IndexServers',
                    '104',
                    f"Something went wrong while querying solr - {exit_code}")
            elif error_message:
                raise SDKException(
                    'IndexServers',
                    '104',
                    f"Something went wrong while querying solr - {error_message}")
            try:
                return json.loads(output.strip())
            except Exception:
                raise SDKException('IndexServers', '104', f"Something went wrong while querying solr - {output}")
        raise SDKException('IndexServers', '104', "Something went wrong while querying solr")

    def get_index_node(self, node_name):
        """Returns an Index server node object for given node name
            Args:
                node_name           (str)   --  Index server node name

            Returns:
                IndexNode class object

            Raises:
                SDKException:

                        if node not found for the given node name

        """
        node_name = node_name.lower()
        if node_name in self.client_name:
            return IndexNode(self._commcell_obj, self.engine_name, node_name)
        raise SDKException("IndexServers", '104', 'Index server node not found')

    def get_plan_info(self):
        """Gets the plan information of the index server
            Returns:
                dict - containing the plan information
        """
        client = self._commcell_obj.clients.get(self.index_server_client_id)
        instance_props = client.properties.get("pseudoClientInfo", {}).get("distributedClusterInstanceProperties", {})
        plan_details = instance_props.get("clusterConfig",{}).get("cloudInfo", {}).get("planInfo", {})
        return plan_details

    def get_os_info(self):
        """Returns the OS type for the Index server"""

        nodes_name = self.client_name
        nodes = [self._commcell_obj.clients.get(node) for node in nodes_name]
        nodes_os_info = [node.os_info for node in nodes]
        if IndexServerOSType.WINDOWS.value.lower() in nodes_os_info[0].lower():
            for node in nodes_os_info[1:]:
                if IndexServerOSType.UNIX.value.lower() in node.lower():
                    return IndexServerOSType.MIXED.value
            return IndexServerOSType.WINDOWS.value
        else:
            for node in nodes_os_info[1:]:
                if IndexServerOSType.WINDOWS.value.lower() in node.lower():
                    return IndexServerOSType.MIXED.value
            return IndexServerOSType.UNIX.value

    def __form_field_query(self, key, value):
        """
        Returns the query with the key and value passed
        Args:
                key(str)    -- key for forming the query
                value(str)  -- value for forming the query
            Returns:
                query to be executed against solr
        """
        query = None
        if value is None:
            query = f'&{key}'
        else:
            query = f'&{key}={str(value)}'
        return query

    @property
    def plan_name(self):
        """Returns the plan name associated with index server
            Returns:
                str - name of the plan
        """
        return self.plan_info.get("planName")

    @property
    def os_info(self):
        """Returns the OS type for the Index server"""
        return self.os_type

    @property
    def is_cloud(self):
        """Returns true if the Index server is cloud and false if not"""
        return self.server_type == 5

    @property
    def nodes_count(self):
        """Returns the count of Index server nodes"""
        return len(self.client_id)

    @property
    def roles_data(self):
        """Returns the cloud roles data"""
        return self._roles_obj.roles_data

    @property
    def properties(self):
        """Returns the index server properties"""
        return self._properties

    @property
    def host_name(self):
        """Returns a list of host names of all index server nodes"""
        return self._properties[IndexServerConstants.HOST_NAME]

    @property
    def cloud_name(self):
        """Returns the internal cloud name of index server"""
        return self._properties[IndexServerConstants.CLOUD_NAME]

    @property
    def client_name(self):
        """Returns a list of client names of all index server nodes"""
        return self._properties[IndexServerConstants.CLIENT_NAME]

    @property
    def server_url(self):
        """Returns a list of Solr url of all index server nodes"""
        return self._properties[IndexServerConstants.CI_SERVER_URL]

    @property
    def type(self):
        """Returns the type of index server"""
        return self._properties[IndexServerConstants.TYPE]

    @property
    def base_port(self):
        """Returns a list of base ports of all index server nodes"""
        return self._properties[IndexServerConstants.BASE_PORT]

    @property
    def client_id(self):
        """Returns a list client ids of all index server nodes"""
        return self._properties[IndexServerConstants.CLIENT_ID]

    @property
    def roles(self):
        """Returns a list of roles of index server"""
        return self._properties[IndexServerConstants.ROLES]

    @property
    def role_display_name(self):
        """Returns the roles display name of index server"""
        role_disp_name = []
        for role_version in self.roles:
            for role in self.roles_data:
                if role_version == role['roleVersion']:
                    role_disp_name.append(role['roleName'])
                    break
        return role_disp_name

    @property
    def cloud_id(self):
        """Returns the cloud id of index server"""
        return self._properties[IndexServerConstants.CLOUD_ID]

    @property
    def server_type(self):
        """Returns the server type of index server"""
        return self._properties[IndexServerConstants.SERVER_TYPE]

    @property
    def engine_name(self):
        """Returns the engine name of index server"""
        return self._properties[IndexServerConstants.ENGINE_NAME]

    @property
    def index_server_client_id(self):
        """Returns the index server client id of index server"""
        return self._properties[IndexServerConstants.INDEX_SERVER_CLIENT_ID]


class IndexNode(object):
    """Class for Index server node object"""

    def __init__(self, commcell_obj, index_server_name, node_name):
        """Initialize the IndexNode class

            Args:
                commcell_obj        (object)    --  commcell object
                index_server_name   (int)       --  Index server name
                node_name           (str)       --  Index server node client name

        """
        self.commcell = commcell_obj
        self.index_server_name = index_server_name
        self.data_index = 0
        self.index_server = None
        self.index_node_name = node_name.lower()
        self.index_node_client = None
        self.index_client_properties = None
        self.refresh()

    def refresh(self):
        """Refresh the index node properties"""
        self.commcell.index_servers.refresh()
        self.index_server = self.commcell.index_servers.get(self.index_server_name)
        self.data_index = self.index_server.client_name.index(self.index_node_name)
        self.commcell.clients.refresh()
        self.index_node_client = self.commcell.clients.get(self.index_node_name)
        self.index_client_properties = self.index_node_client.properties['pseudoClientInfo']['indexServerProperties']

    @property
    def node_name(self):
        """Returns Index server node client name"""
        return self.index_server.client_name[self.data_index]

    @property
    def node_id(self):
        """Returns Index server node client id"""
        return self.index_server.client_id[self.data_index]

    @property
    def solr_port(self):
        """Returns port number Solr is running on the Index server node"""
        return self.index_server.base_port[self.data_index]

    @property
    def solr_url(self):
        """Returns Solr URL for Index server node"""
        return self.index_server.server_url[self.data_index]

    @property
    def roles(self):
        """Returns the array of roles installed with the index server within the commcell"""
        return self.index_server.role_display_name

    @property
    def index_location(self):
        """Returns Index directory for the Index server Node"""
        node_meta_infos = self.index_client_properties['nodeMetaInfos']
        for info in node_meta_infos:
            if info['name'] == 'INDEXLOCATION':
                return info['value']
        return None

    @property
    def jvm_memory(self):
        """Returns Solr JVM memory for the Index server Node"""
        node_meta_infos = self.index_client_properties['nodeMetaInfos']
        for info in node_meta_infos:
            if info['name'] == 'JVMMAXMEMORY':
                return info['value']
        return None

    @solr_port.setter
    def solr_port(self, port_no):
        """Setter to set the Solr port number for the node

            Args:
                port_no     (str)   --  Solr port number to be set for node

        """
        solr_port_param = deepcopy(IndexServerConstants.SOLR_PORT_META_INFO)
        solr_port_param['value'] = str(port_no)
        cloud_param = [solr_port_param]
        self.index_server.modify(self.index_location, self.index_node_name, cloud_param)
        self.refresh()

    @jvm_memory.setter
    def jvm_memory(self, memory):
        """Setter to set the Solr JVM memory for the node

                    Args:
                        memory      (str)   --  Solr JVM memory to be set for the node

        """
        solr_jvm_param = deepcopy(IndexServerConstants.SOLR_JVM_META_INFO)
        solr_jvm_param['value'] = str(memory)
        solr_port_param = deepcopy(IndexServerConstants.SOLR_PORT_META_INFO)
        solr_port_param['value'] = str(self.solr_port)
        cloud_param = [solr_jvm_param, solr_port_param]
        self.index_server.modify(self.index_location, self.index_node_name, cloud_param)
        self.refresh()


class _Roles(object):
    """Class for cloud roles data operations"""

    def __init__(self, commcell_object):
        """Initializes _Roles class with commcell object

            Args:
                commcell_object (object)    --  instance of Commcell class

            Returns:
                object  -   instance of _Roles class
        """
        self.commcell_object = commcell_object
        self._roles_data = None
        self.refresh()

    def refresh(self):
        """Refreshes the class data"""
        self._get_all_roles()

    def _get_all_roles(self):
        """Method to get all cloud roles details available on the commcell.

            Raises:
                SDKException:
                    Response was empty.

                    Response was not success.
        """
        flag, response = self.commcell_object._cvpysdk_object.make_request(
            "GET", self.commcell_object._services['GET_ALL_ROLES']
        )
        if flag:
            if response.json():
                if 'rolesInfo' in response.json():
                    self._roles_data = response.json()['rolesInfo']
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def get_role_id(self, role_name):
        """Method to get a cloud role id with given name

            Args:
                role_name       (str)   --  cloud role name of which role id has to be returned

            Returns:
                role_id         (int)   --  if role name is found in roles data then returns the id
                                            else returns None

        """
        for role_data in self._roles_data:
            if role_data['roleName'] == role_name:
                return role_data['roleId']
        return None

    def update_roles_data(self):
        """Synchronize the cloud role data with the commcell database"""
        self._get_all_roles()

    @property
    def roles_data(self):
        """Returns the list of dictionary of details of each cloud role"""
        return self._roles_data

Classes

class IndexNode (commcell_obj, index_server_name, node_name)

Class for Index server node object

Initialize the IndexNode class

Args

commcell_obj (object) – commcell object index_server_name (int) – Index server name node_name (str) – Index server node client name

Expand source code Browse git
class IndexNode(object):
    """Class for Index server node object"""

    def __init__(self, commcell_obj, index_server_name, node_name):
        """Initialize the IndexNode class

            Args:
                commcell_obj        (object)    --  commcell object
                index_server_name   (int)       --  Index server name
                node_name           (str)       --  Index server node client name

        """
        self.commcell = commcell_obj
        self.index_server_name = index_server_name
        self.data_index = 0
        self.index_server = None
        self.index_node_name = node_name.lower()
        self.index_node_client = None
        self.index_client_properties = None
        self.refresh()

    def refresh(self):
        """Refresh the index node properties"""
        self.commcell.index_servers.refresh()
        self.index_server = self.commcell.index_servers.get(self.index_server_name)
        self.data_index = self.index_server.client_name.index(self.index_node_name)
        self.commcell.clients.refresh()
        self.index_node_client = self.commcell.clients.get(self.index_node_name)
        self.index_client_properties = self.index_node_client.properties['pseudoClientInfo']['indexServerProperties']

    @property
    def node_name(self):
        """Returns Index server node client name"""
        return self.index_server.client_name[self.data_index]

    @property
    def node_id(self):
        """Returns Index server node client id"""
        return self.index_server.client_id[self.data_index]

    @property
    def solr_port(self):
        """Returns port number Solr is running on the Index server node"""
        return self.index_server.base_port[self.data_index]

    @property
    def solr_url(self):
        """Returns Solr URL for Index server node"""
        return self.index_server.server_url[self.data_index]

    @property
    def roles(self):
        """Returns the array of roles installed with the index server within the commcell"""
        return self.index_server.role_display_name

    @property
    def index_location(self):
        """Returns Index directory for the Index server Node"""
        node_meta_infos = self.index_client_properties['nodeMetaInfos']
        for info in node_meta_infos:
            if info['name'] == 'INDEXLOCATION':
                return info['value']
        return None

    @property
    def jvm_memory(self):
        """Returns Solr JVM memory for the Index server Node"""
        node_meta_infos = self.index_client_properties['nodeMetaInfos']
        for info in node_meta_infos:
            if info['name'] == 'JVMMAXMEMORY':
                return info['value']
        return None

    @solr_port.setter
    def solr_port(self, port_no):
        """Setter to set the Solr port number for the node

            Args:
                port_no     (str)   --  Solr port number to be set for node

        """
        solr_port_param = deepcopy(IndexServerConstants.SOLR_PORT_META_INFO)
        solr_port_param['value'] = str(port_no)
        cloud_param = [solr_port_param]
        self.index_server.modify(self.index_location, self.index_node_name, cloud_param)
        self.refresh()

    @jvm_memory.setter
    def jvm_memory(self, memory):
        """Setter to set the Solr JVM memory for the node

                    Args:
                        memory      (str)   --  Solr JVM memory to be set for the node

        """
        solr_jvm_param = deepcopy(IndexServerConstants.SOLR_JVM_META_INFO)
        solr_jvm_param['value'] = str(memory)
        solr_port_param = deepcopy(IndexServerConstants.SOLR_PORT_META_INFO)
        solr_port_param['value'] = str(self.solr_port)
        cloud_param = [solr_jvm_param, solr_port_param]
        self.index_server.modify(self.index_location, self.index_node_name, cloud_param)
        self.refresh()

Instance variables

var index_location

Returns Index directory for the Index server Node

Expand source code Browse git
@property
def index_location(self):
    """Returns Index directory for the Index server Node"""
    node_meta_infos = self.index_client_properties['nodeMetaInfos']
    for info in node_meta_infos:
        if info['name'] == 'INDEXLOCATION':
            return info['value']
    return None
var jvm_memory

Returns Solr JVM memory for the Index server Node

Expand source code Browse git
@property
def jvm_memory(self):
    """Returns Solr JVM memory for the Index server Node"""
    node_meta_infos = self.index_client_properties['nodeMetaInfos']
    for info in node_meta_infos:
        if info['name'] == 'JVMMAXMEMORY':
            return info['value']
    return None
var node_id

Returns Index server node client id

Expand source code Browse git
@property
def node_id(self):
    """Returns Index server node client id"""
    return self.index_server.client_id[self.data_index]
var node_name

Returns Index server node client name

Expand source code Browse git
@property
def node_name(self):
    """Returns Index server node client name"""
    return self.index_server.client_name[self.data_index]
var roles

Returns the array of roles installed with the index server within the commcell

Expand source code Browse git
@property
def roles(self):
    """Returns the array of roles installed with the index server within the commcell"""
    return self.index_server.role_display_name
var solr_port

Returns port number Solr is running on the Index server node

Expand source code Browse git
@property
def solr_port(self):
    """Returns port number Solr is running on the Index server node"""
    return self.index_server.base_port[self.data_index]
var solr_url

Returns Solr URL for Index server node

Expand source code Browse git
@property
def solr_url(self):
    """Returns Solr URL for Index server node"""
    return self.index_server.server_url[self.data_index]

Methods

def refresh(self)

Refresh the index node properties

Expand source code Browse git
def refresh(self):
    """Refresh the index node properties"""
    self.commcell.index_servers.refresh()
    self.index_server = self.commcell.index_servers.get(self.index_server_name)
    self.data_index = self.index_server.client_name.index(self.index_node_name)
    self.commcell.clients.refresh()
    self.index_node_client = self.commcell.clients.get(self.index_node_name)
    self.index_client_properties = self.index_node_client.properties['pseudoClientInfo']['indexServerProperties']
class IndexServer (commcell_obj, name, cloud_id=None)

Class for performing index server operations for a specific index server

Initialize the IndexServer class instance.

Args

commcell_obj (object) – instance of the Commcell class

name (str) – name of the index server

cloud_id (int) – cloud id of the index server default: None

Returns

object - instance of the IndexServer class

Expand source code Browse git
class IndexServer(object):
    """Class for performing index server operations for a specific index server"""

    def __init__(self, commcell_obj, name, cloud_id=None):
        """Initialize the IndexServer class instance.

            Args:
                commcell_obj    (object)        --  instance of the Commcell class

                name            (str)           --  name of the index server

                cloud_id        (int)           --  cloud id of the index server
                    default: None

            Returns:
                object - instance of the IndexServer class
        """
        self._engine_name = name
        self._commcell_obj = commcell_obj
        self._cvpysdk_object = self._commcell_obj._cvpysdk_object
        self._services = self._commcell_obj._services
        if cloud_id:
            self._cloud_id = cloud_id
        else:
            self._cloud_id = self._get_cloud_id()
        self._properties = None
        self._roles_obj = None
        self.plan_info = None
        self.os_type = None
        self.refresh()

    def __repr__(self):
        """String representation of the instance of this class."""
        return 'IndexServer class instance for index server: "{0}"'.format(
            self._engine_name)

    def _get_cloud_id(self):
        """Get the cloud id for the index server

                Returns:
                    int - cloud id for the index server
        """
        return self._commcell_obj.index_servers.get(self._engine_name).cloud_id

    def _get_properties(self):
        """Get the properties of the index server"""
        self._properties = self._commcell_obj.index_servers.get_properties(
            self._engine_name)

    def refresh(self):
        """Refresh the index server properties"""
        self._commcell_obj.index_servers.refresh()
        self._get_properties()
        if self.os_type is None:
            self.os_type = self.get_os_info()
        if not self._roles_obj:
            self._roles_obj = _Roles(self._commcell_obj)
        if self.plan_info is None:
            self.plan_info = self.get_plan_info()

    def update_roles_data(self):
        """Synchronize the cloud roles data with the commcell"""
        self._roles_obj.update_roles_data()

    def modify(self, index_location, node_name, node_params):
        """Modifies the properties of an index server

            Args:
                index_location      (str)       --  index server data directory
                node_name           (str)       --  index server node name
                node_params         (dict)      --  parameters to be passed
                                                    [
                                                        {
                                                            "name" : <property_name>,
                                                            "value" : <property_value>
                                                        }
                                                    ]
            Raises:
                SDKException:
                    Response was not success.
                    Response was empty.
        """
        json_req = deepcopy(IndexServerConstants.REQUEST_JSON)
        json_req['opType'] = IndexServerConstants.OPERATION_EDIT
        json_req['cloudNodes'] = [{
            "opType": IndexServerConstants.OPERATION_EDIT,
            "nodeClientEntity": {
                "clientId": int(self._commcell_obj.clients.get(node_name).client_id)
            },
            "nodeMetaInfos": [
                {
                    "name": "INDEXLOCATION",
                    "value": index_location
                }
            ]
        }]
        json_req['cloudInfoEntity']['cloudId'] = self.cloud_id
        for param in node_params:
            json_req['cloudNodes'][0]['nodeMetaInfos'].append(param)
        flag, response = self._cvpysdk_object.make_request(
            "POST", self._services['CLOUD_MODIFY'], json_req)
        if flag:
            if response.json():
                if 'cloudId' in response.json():
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def change_plan(self, plan_name):
        """Modifies the plan used by an index server

            Args:
                plan_name      (str)       --  Name of the plan to be used for the index server
            Raises:
                SDKException:
                    Response was not success.
                    Response was empty.
                    if plan with given name doesn't exist
        """
        if not self._commcell_obj.plans.has_plan(plan_name):
            raise SDKException(
                'Plan', '102', f"Plan with name [{plan_name}] doesn't exist")
        request_json = {
            "opType": IndexServerConstants.OPERATION_EDIT,
            "type": 1,
            "planInfo": {
                "planId": int(self._commcell_obj.plans.get(plan_name).plan_id)
            },
            "cloudInfoEntity": {
                "cloudId": self.cloud_id
            }
        }
        flag, response = self._cvpysdk_object.make_request(
            "POST", self._services['CLOUD_MODIFY'], request_json)
        if flag:
            if response.json():
                if 'cloudId' in response.json():
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def update_role(self, props=None):
        """Updates a role of an Index Server

            Args:
                props               (list)  --  array of dictionaries
                consisting details of the roles such as role name
                and operation type.
                                            [{
                                                "roleName": <name>          (str)
                                                "operationType": 1 or 2     (int)
                                                    1 for adding a role
                                                    2 for removing a role
                                            }]

            Raises:
                SDKException:
                    if response is empty

                    if response is not success

        """
        json_req = {"cloudId": self.cloud_id, "roles": []}
        if props:
            for prop in props:
                role_id = self._roles_obj.get_role_id(prop['roleName'])
                if not role_id:
                    raise SDKException('IndexServers', '103')
                prop['roleId'] = role_id
                json_req['roles'].append(prop)
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_ROLE_UPDATE'], json_req
        )
        if flag:
            if response.json() and 'errorCode' in response.json():
                if response.json()['errorCode'] == 0:
                    self.refresh()
                    return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101')

    def delete_docs_from_core(self, core_name, select_dict = None):
        """Deletes the docs from the given core name on index server depending on the select dict passed

                Args:

                        core_name               (str)  --  name of the solr core
                        select_dict             (dict) --  dict with query to delete specific documents
                                                    default query - "*:*" (Deletes all the docs)

                    Returns:
                        None

                    Raises:
                        SDKException:

                            if input data is not valid

                            if index server is cloud, not implemented error

                            if response is empty

                            if response is not success
        """
        if not isinstance(core_name, str):
            raise SDKException('IndexServers', '101')
        if self.is_cloud:
            raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
        json_req = {"delete": {"query": self._create_solr_query(select_dict).replace("q=", "").replace("&wt=json", "")}}
        baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commitWithin=1000&overwrite=true&wt=json"
        flag, response = self._cvpysdk_object.make_request("POST", baseurl, json_req)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', f' Failed with error message - '
                                                          f'{response.json().get("error").get("msg")}')
            if 'responseHeader' in response.json():
                commitstatus = str(response.json().get("responseHeader").get("status"))
                if int(commitstatus) != 0:
                    raise SDKException('IndexServers', '104',
                                       f"Deleting docs from the core returned bad status - {commitstatus}")
                return
        raise SDKException('IndexServers', '111')

    def hard_commit(self, core_name):
        """do hard commit for the given core name on index server

                    Args:

                        core_name               (str)  --  name of the solr core

                    Returns:
                        None

                    Raises:
                        SDKException:

                            if input data is not valid

                            if index server is cloud, not implemented error

                            if response is empty

                            if response is not success
        """
        if not isinstance(core_name, str):
            raise SDKException('IndexServers', '101')
        if self.is_cloud:
            raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
        baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commit=true"
        flag, response = self._cvpysdk_object.make_request("GET", baseurl)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', "Hard commit returned error")
            if 'responseHeader' in response.json():
                commitstatus = str(response.json()['responseHeader']['status'])
                if int(commitstatus) != 0:
                    raise SDKException('IndexServers', '104', "Hard commit returned bad status")
                return
        raise SDKException('IndexServers', '104', "Something went wrong with hard commit")

    
    def get_health_indicators(self, client_name=None):
        """Get health indicators for index server node by client name

                Args:
                    client_name     (str)       --  name of the client node

                Returns:
                    (response(str)) -- str json object

                Raises:

                    SDKException:
                        if input data is not valid
                        if client name is not passed for index server cloud
                        if response is not success
                        if response is empty

        """
        server_url = self.server_url[0]
        response = None
        if self.is_cloud or len(self.client_name) > 1:
            if client_name is None:
                raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
            if client_name not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
            server_url = self.server_url[self.client_name.index(client_name)]
        baseurl = f"{server_url}/solr/rest/admin/healthsummary"
        headers = {
            'Accept': 'application/xml'
        }
        flag, response = self._cvpysdk_object.make_request("GET", headers=headers, url=baseurl)
        if flag:
            return response
        raise SDKException('IndexServers', '104', "Could not get health summary for [{}]".format(client_name))

    def get_all_cores(self, client_name=None):
        """gets all cores & core details from index server

                Args:
                    client_name     (str)       --  name of the client node
                        ***Applicable only for solr cloud mode or multi node Index Server***

                Returns:
                    (list,dict)     -- list containing core names
                                    -- dict containing details about cores

                Raises:

                    SDKException:

                        if input data is not valid

                        if client name is not passed for index server cloud

                        if response is not success

                        if response is empty

        """
        server_url = self.server_url[0]
        if self.is_cloud or len(self.client_name) > 1:
            if client_name is None:
                raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
            if client_name not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
            server_url = self.server_url[self.client_name.index(client_name)]
        core_names = []
        baseurl = f"{server_url}/solr/admin/cores"
        flag, response = self._cvpysdk_object.make_request("GET", baseurl)
        if flag and response.json():
            if 'error' in response.json():
                raise SDKException('IndexServers', '104', "Unable to get core names from index server")
            if 'status' in response.json():
                for core in response.json()['status']:
                    core_names.append(core)
                return core_names, response.json()['status']
        raise SDKException('IndexServers', '104', "Something went wrong while getting core names")

    def _create_solr_query(self, select_dict=None, attr_list=None, op_params=None):
        """Method to create the solr query based on the params
            Args:
                select_dict     (dictionary)     --  Dictionary containing search criteria and value
                                                     Acts as 'q' field in solr query

                attr_list       (set)            --  Column names to be returned in results.
                                                     Acts as 'fl' in solr query

                op_params       (dictionary)     --  Other params and values for solr query
                                                        (Ex: start, rows)

            Returns:
                The solr url based on params

            Raises:
                SDKException:

                        if failed to form solr query
        """
        try:
            search_query = f'q='
            simple_search = 0
            if select_dict:
                for key, value in select_dict.items():
                    if isinstance(key, tuple):
                        if isinstance(value, list):
                            search_query += f'({key[0]}:{str(value[0])}'
                            for val in value[1:]:
                                search_query += f' OR {key[0]}:{str(val)}'
                        else:
                            search_query += f'({key[0]}:{value}'
                        for key_val in key[1:]:
                            if isinstance(value, list):
                                search_query += f' OR {key_val}:{str(value[0])}'
                                for val in value[1:]:
                                    search_query += f' OR {key_val}:{str(val)}'
                            else:
                                search_query += f' OR {key_val}:{value}'
                        search_query += ') AND '
                    elif isinstance(value, list):
                        search_query += f'({key}:{str(value[0])}'
                        for val in value[1:]:
                            search_query += f' OR {key}:{str(val)}'
                        search_query += ") AND "
                    elif key == "keyword":
                        search_query += "(" + value + ")"
                        simple_search = 1
                        break
                    else:
                        search_query = search_query + f'{key}:{str(value)} AND '
                if simple_search == 0:
                    search_query = search_query[:-5]
            else:
                search_query += "*:*"

            field_query = ""
            if attr_list:
                field_query = "&fl="
                for item in attr_list:
                    field_query += f'{str(item)},'
                field_query = field_query[:-1]
            if attr_list and 'content' in attr_list:
                field_query = f"{field_query}&exclude=false"

            ex_query = ""
            if not op_params:
                op_params = {'wt': "json"}
            else:
                op_params['wt'] = "json"
            for key, values in op_params.items():
                if isinstance(values, list):
                    for value in values:
                        ex_query += self.__form_field_query(key, value)
                else:
                    ex_query += self.__form_field_query(key, values)
            final_url = f'{search_query}{field_query}{ex_query}'
            return final_url
        except Exception as excp:
            raise SDKException('IndexServers', '104', f"Something went wrong while creating solr query - {excp}")

    def execute_solr_query(
            self,
            core_name,
            solr_client=None,
            select_dict=None,
            attr_list=None,
            op_params=None):
        """Creates solr url based on input and executes it on solr on given core/collection
            Args:

                core_name               (str)           --  Core name/collection name where we want to query

                solr_client             (str)           --  Index Server client name to execute solr query
                                                                Default : None (picks first client on index server)

                select_dict             (dictionary)    --  Dictionary containing search criteria and
                                                            value. Acts as 'q' field in solr query

                        Example :

                            1. General Criteria to filter results              -   {"jid": 1024, "datatype": 2,clid: 2}
                            2. Keyword Searches on solr                        -   {'keyword': 'SearchKeyword'}
                            3. For multiple value searches on single field     -   {'cvowner': ['xxx','yyy']}
                            4. For single value searches on multiple fields    -   {('cvowner','cvreaddisp') : 'xxx'}

                attr_list               (set)           --  Column names to be returned in results.
                                                                Acts as 'fl' in solr query

                        Example (For Exchange Mailbox IDA, below fields are there in solr) :
                                    {
                                     'msgclass',
                                     'ccsmtp',
                                     'fmsmtp',
                                     'folder'
                                   }

                op_params               (dictionary)    --  Other params and values for solr query. Do not
                                                            mention 'wt' param as it is always json

                                                            Example : {"rows": 0}

            Returns:
                content of the response

            Raises:
                SDKException:

                        if unable to send request

                        if response is not success
        """
        solr_url = f"solr/{core_name}/select?{self._create_solr_query(select_dict, attr_list, op_params)}"
        if solr_client is None:
            solr_url = f"{self.server_url[0]}/{solr_url}"
        else:
            if solr_client not in self.client_name:
                raise SDKException('IndexServers', '104', 'client name not found in this index server')
            server_url = self.server_url[self.client_name.index(solr_client)]
            solr_url = f"{server_url}/{solr_url}"
        flag, response = self._cvpysdk_object.make_request("GET", solr_url)
        if flag and response.json():
            return response.json()
        elif response.status_code == httplib.FORBIDDEN:
            cmd = f"(Invoke-WebRequest -UseBasicParsing -uri \"{solr_url}\").content"
            client_obj = None
            if solr_client:
                client_obj = self._commcell_obj.clients.get(solr_client)
            else:
                # if no client is passed, then take first client in index server cloud
                client_obj = self._commcell_obj.clients.get(self.client_name[0])
            exit_code, output, error_message = client_obj.execute_script(script_type="PowerShell",
                                                                         script=cmd)
            if exit_code != 0:
                raise SDKException(
                    'IndexServers',
                    '104',
                    f"Something went wrong while querying solr - {exit_code}")
            elif error_message:
                raise SDKException(
                    'IndexServers',
                    '104',
                    f"Something went wrong while querying solr - {error_message}")
            try:
                return json.loads(output.strip())
            except Exception:
                raise SDKException('IndexServers', '104', f"Something went wrong while querying solr - {output}")
        raise SDKException('IndexServers', '104', "Something went wrong while querying solr")

    def get_index_node(self, node_name):
        """Returns an Index server node object for given node name
            Args:
                node_name           (str)   --  Index server node name

            Returns:
                IndexNode class object

            Raises:
                SDKException:

                        if node not found for the given node name

        """
        node_name = node_name.lower()
        if node_name in self.client_name:
            return IndexNode(self._commcell_obj, self.engine_name, node_name)
        raise SDKException("IndexServers", '104', 'Index server node not found')

    def get_plan_info(self):
        """Gets the plan information of the index server
            Returns:
                dict - containing the plan information
        """
        client = self._commcell_obj.clients.get(self.index_server_client_id)
        instance_props = client.properties.get("pseudoClientInfo", {}).get("distributedClusterInstanceProperties", {})
        plan_details = instance_props.get("clusterConfig",{}).get("cloudInfo", {}).get("planInfo", {})
        return plan_details

    def get_os_info(self):
        """Returns the OS type for the Index server"""

        nodes_name = self.client_name
        nodes = [self._commcell_obj.clients.get(node) for node in nodes_name]
        nodes_os_info = [node.os_info for node in nodes]
        if IndexServerOSType.WINDOWS.value.lower() in nodes_os_info[0].lower():
            for node in nodes_os_info[1:]:
                if IndexServerOSType.UNIX.value.lower() in node.lower():
                    return IndexServerOSType.MIXED.value
            return IndexServerOSType.WINDOWS.value
        else:
            for node in nodes_os_info[1:]:
                if IndexServerOSType.WINDOWS.value.lower() in node.lower():
                    return IndexServerOSType.MIXED.value
            return IndexServerOSType.UNIX.value

    def __form_field_query(self, key, value):
        """
        Returns the query with the key and value passed
        Args:
                key(str)    -- key for forming the query
                value(str)  -- value for forming the query
            Returns:
                query to be executed against solr
        """
        query = None
        if value is None:
            query = f'&{key}'
        else:
            query = f'&{key}={str(value)}'
        return query

    @property
    def plan_name(self):
        """Returns the plan name associated with index server
            Returns:
                str - name of the plan
        """
        return self.plan_info.get("planName")

    @property
    def os_info(self):
        """Returns the OS type for the Index server"""
        return self.os_type

    @property
    def is_cloud(self):
        """Returns true if the Index server is cloud and false if not"""
        return self.server_type == 5

    @property
    def nodes_count(self):
        """Returns the count of Index server nodes"""
        return len(self.client_id)

    @property
    def roles_data(self):
        """Returns the cloud roles data"""
        return self._roles_obj.roles_data

    @property
    def properties(self):
        """Returns the index server properties"""
        return self._properties

    @property
    def host_name(self):
        """Returns a list of host names of all index server nodes"""
        return self._properties[IndexServerConstants.HOST_NAME]

    @property
    def cloud_name(self):
        """Returns the internal cloud name of index server"""
        return self._properties[IndexServerConstants.CLOUD_NAME]

    @property
    def client_name(self):
        """Returns a list of client names of all index server nodes"""
        return self._properties[IndexServerConstants.CLIENT_NAME]

    @property
    def server_url(self):
        """Returns a list of Solr url of all index server nodes"""
        return self._properties[IndexServerConstants.CI_SERVER_URL]

    @property
    def type(self):
        """Returns the type of index server"""
        return self._properties[IndexServerConstants.TYPE]

    @property
    def base_port(self):
        """Returns a list of base ports of all index server nodes"""
        return self._properties[IndexServerConstants.BASE_PORT]

    @property
    def client_id(self):
        """Returns a list client ids of all index server nodes"""
        return self._properties[IndexServerConstants.CLIENT_ID]

    @property
    def roles(self):
        """Returns a list of roles of index server"""
        return self._properties[IndexServerConstants.ROLES]

    @property
    def role_display_name(self):
        """Returns the roles display name of index server"""
        role_disp_name = []
        for role_version in self.roles:
            for role in self.roles_data:
                if role_version == role['roleVersion']:
                    role_disp_name.append(role['roleName'])
                    break
        return role_disp_name

    @property
    def cloud_id(self):
        """Returns the cloud id of index server"""
        return self._properties[IndexServerConstants.CLOUD_ID]

    @property
    def server_type(self):
        """Returns the server type of index server"""
        return self._properties[IndexServerConstants.SERVER_TYPE]

    @property
    def engine_name(self):
        """Returns the engine name of index server"""
        return self._properties[IndexServerConstants.ENGINE_NAME]

    @property
    def index_server_client_id(self):
        """Returns the index server client id of index server"""
        return self._properties[IndexServerConstants.INDEX_SERVER_CLIENT_ID]

Instance variables

var base_port

Returns a list of base ports of all index server nodes

Expand source code Browse git
@property
def base_port(self):
    """Returns a list of base ports of all index server nodes"""
    return self._properties[IndexServerConstants.BASE_PORT]
var client_id

Returns a list client ids of all index server nodes

Expand source code Browse git
@property
def client_id(self):
    """Returns a list client ids of all index server nodes"""
    return self._properties[IndexServerConstants.CLIENT_ID]
var client_name

Returns a list of client names of all index server nodes

Expand source code Browse git
@property
def client_name(self):
    """Returns a list of client names of all index server nodes"""
    return self._properties[IndexServerConstants.CLIENT_NAME]
var cloud_id

Returns the cloud id of index server

Expand source code Browse git
@property
def cloud_id(self):
    """Returns the cloud id of index server"""
    return self._properties[IndexServerConstants.CLOUD_ID]
var cloud_name

Returns the internal cloud name of index server

Expand source code Browse git
@property
def cloud_name(self):
    """Returns the internal cloud name of index server"""
    return self._properties[IndexServerConstants.CLOUD_NAME]
var engine_name

Returns the engine name of index server

Expand source code Browse git
@property
def engine_name(self):
    """Returns the engine name of index server"""
    return self._properties[IndexServerConstants.ENGINE_NAME]
var host_name

Returns a list of host names of all index server nodes

Expand source code Browse git
@property
def host_name(self):
    """Returns a list of host names of all index server nodes"""
    return self._properties[IndexServerConstants.HOST_NAME]
var index_server_client_id

Returns the index server client id of index server

Expand source code Browse git
@property
def index_server_client_id(self):
    """Returns the index server client id of index server"""
    return self._properties[IndexServerConstants.INDEX_SERVER_CLIENT_ID]
var is_cloud

Returns true if the Index server is cloud and false if not

Expand source code Browse git
@property
def is_cloud(self):
    """Returns true if the Index server is cloud and false if not"""
    return self.server_type == 5
var nodes_count

Returns the count of Index server nodes

Expand source code Browse git
@property
def nodes_count(self):
    """Returns the count of Index server nodes"""
    return len(self.client_id)
var os_info

Returns the OS type for the Index server

Expand source code Browse git
@property
def os_info(self):
    """Returns the OS type for the Index server"""
    return self.os_type
var plan_name

Returns the plan name associated with index server

Returns

str - name of the plan

Expand source code Browse git
@property
def plan_name(self):
    """Returns the plan name associated with index server
        Returns:
            str - name of the plan
    """
    return self.plan_info.get("planName")
var properties

Returns the index server properties

Expand source code Browse git
@property
def properties(self):
    """Returns the index server properties"""
    return self._properties
var role_display_name

Returns the roles display name of index server

Expand source code Browse git
@property
def role_display_name(self):
    """Returns the roles display name of index server"""
    role_disp_name = []
    for role_version in self.roles:
        for role in self.roles_data:
            if role_version == role['roleVersion']:
                role_disp_name.append(role['roleName'])
                break
    return role_disp_name
var roles

Returns a list of roles of index server

Expand source code Browse git
@property
def roles(self):
    """Returns a list of roles of index server"""
    return self._properties[IndexServerConstants.ROLES]
var roles_data

Returns the cloud roles data

Expand source code Browse git
@property
def roles_data(self):
    """Returns the cloud roles data"""
    return self._roles_obj.roles_data
var server_type

Returns the server type of index server

Expand source code Browse git
@property
def server_type(self):
    """Returns the server type of index server"""
    return self._properties[IndexServerConstants.SERVER_TYPE]
var server_url

Returns a list of Solr url of all index server nodes

Expand source code Browse git
@property
def server_url(self):
    """Returns a list of Solr url of all index server nodes"""
    return self._properties[IndexServerConstants.CI_SERVER_URL]
var type

Returns the type of index server

Expand source code Browse git
@property
def type(self):
    """Returns the type of index server"""
    return self._properties[IndexServerConstants.TYPE]

Methods

def change_plan(self, plan_name)

Modifies the plan used by an index server

Args

plan_name (str) – Name of the plan to be used for the index server

Raises

SDKException: Response was not success. Response was empty. if plan with given name doesn't exist

Expand source code Browse git
def change_plan(self, plan_name):
    """Modifies the plan used by an index server

        Args:
            plan_name      (str)       --  Name of the plan to be used for the index server
        Raises:
            SDKException:
                Response was not success.
                Response was empty.
                if plan with given name doesn't exist
    """
    if not self._commcell_obj.plans.has_plan(plan_name):
        raise SDKException(
            'Plan', '102', f"Plan with name [{plan_name}] doesn't exist")
    request_json = {
        "opType": IndexServerConstants.OPERATION_EDIT,
        "type": 1,
        "planInfo": {
            "planId": int(self._commcell_obj.plans.get(plan_name).plan_id)
        },
        "cloudInfoEntity": {
            "cloudId": self.cloud_id
        }
    }
    flag, response = self._cvpysdk_object.make_request(
        "POST", self._services['CLOUD_MODIFY'], request_json)
    if flag:
        if response.json():
            if 'cloudId' in response.json():
                self.refresh()
                return
        raise SDKException('Response', '102')
    raise SDKException('Response', '101')
def delete_docs_from_core(self, core_name, select_dict=None)

Deletes the docs from the given core name on index server depending on the select dict passed

Args

core_name               (str)  --  name of the solr core
select_dict             (dict) --  dict with query to delete specific documents
                            default query - "*:*" (Deletes all the docs)

Returns: None

Raises: SDKException:

    if input data is not valid

    if index server is cloud, not implemented error

    if response is empty

    if response is not success
Expand source code Browse git
def delete_docs_from_core(self, core_name, select_dict = None):
    """Deletes the docs from the given core name on index server depending on the select dict passed

            Args:

                    core_name               (str)  --  name of the solr core
                    select_dict             (dict) --  dict with query to delete specific documents
                                                default query - "*:*" (Deletes all the docs)

                Returns:
                    None

                Raises:
                    SDKException:

                        if input data is not valid

                        if index server is cloud, not implemented error

                        if response is empty

                        if response is not success
    """
    if not isinstance(core_name, str):
        raise SDKException('IndexServers', '101')
    if self.is_cloud:
        raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
    json_req = {"delete": {"query": self._create_solr_query(select_dict).replace("q=", "").replace("&wt=json", "")}}
    baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commitWithin=1000&overwrite=true&wt=json"
    flag, response = self._cvpysdk_object.make_request("POST", baseurl, json_req)
    if flag and response.json():
        if 'error' in response.json():
            raise SDKException('IndexServers', '104', f' Failed with error message - '
                                                      f'{response.json().get("error").get("msg")}')
        if 'responseHeader' in response.json():
            commitstatus = str(response.json().get("responseHeader").get("status"))
            if int(commitstatus) != 0:
                raise SDKException('IndexServers', '104',
                                   f"Deleting docs from the core returned bad status - {commitstatus}")
            return
    raise SDKException('IndexServers', '111')
def execute_solr_query(self, core_name, solr_client=None, select_dict=None, attr_list=None, op_params=None)

Creates solr url based on input and executes it on solr on given core/collection

Args

core_name (str) – Core name/collection name where we want to query

solr_client (str) – Index Server client name to execute solr query Default : None (picks first client on index server)

select_dict (dictionary) – Dictionary containing search criteria and value. Acts as 'q' field in solr query

    Example :

        1. General Criteria to filter results              -   {"jid": 1024, "datatype": 2,clid: 2}
        2. Keyword Searches on solr                        -   {'keyword': 'SearchKeyword'}
        3. For multiple value searches on single field     -   {'cvowner': ['xxx','yyy']}
        4. For single value searches on multiple fields    -   {('cvowner','cvreaddisp') : 'xxx'}

attr_list (set) – Column names to be returned in results. Acts as 'fl' in solr query

    Example (For Exchange Mailbox IDA, below fields are there in solr) :
                {
                 'msgclass',
                 'ccsmtp',
                 'fmsmtp',
                 'folder'
               }

op_params (dictionary) – Other params and values for solr query. Do not mention 'wt' param as it is always json

                                        Example : {"rows": 0}

Returns

content of the response

Raises

SDKException:

    if unable to send request

    if response is not success
Expand source code Browse git
def execute_solr_query(
        self,
        core_name,
        solr_client=None,
        select_dict=None,
        attr_list=None,
        op_params=None):
    """Creates solr url based on input and executes it on solr on given core/collection
        Args:

            core_name               (str)           --  Core name/collection name where we want to query

            solr_client             (str)           --  Index Server client name to execute solr query
                                                            Default : None (picks first client on index server)

            select_dict             (dictionary)    --  Dictionary containing search criteria and
                                                        value. Acts as 'q' field in solr query

                    Example :

                        1. General Criteria to filter results              -   {"jid": 1024, "datatype": 2,clid: 2}
                        2. Keyword Searches on solr                        -   {'keyword': 'SearchKeyword'}
                        3. For multiple value searches on single field     -   {'cvowner': ['xxx','yyy']}
                        4. For single value searches on multiple fields    -   {('cvowner','cvreaddisp') : 'xxx'}

            attr_list               (set)           --  Column names to be returned in results.
                                                            Acts as 'fl' in solr query

                    Example (For Exchange Mailbox IDA, below fields are there in solr) :
                                {
                                 'msgclass',
                                 'ccsmtp',
                                 'fmsmtp',
                                 'folder'
                               }

            op_params               (dictionary)    --  Other params and values for solr query. Do not
                                                        mention 'wt' param as it is always json

                                                        Example : {"rows": 0}

        Returns:
            content of the response

        Raises:
            SDKException:

                    if unable to send request

                    if response is not success
    """
    solr_url = f"solr/{core_name}/select?{self._create_solr_query(select_dict, attr_list, op_params)}"
    if solr_client is None:
        solr_url = f"{self.server_url[0]}/{solr_url}"
    else:
        if solr_client not in self.client_name:
            raise SDKException('IndexServers', '104', 'client name not found in this index server')
        server_url = self.server_url[self.client_name.index(solr_client)]
        solr_url = f"{server_url}/{solr_url}"
    flag, response = self._cvpysdk_object.make_request("GET", solr_url)
    if flag and response.json():
        return response.json()
    elif response.status_code == httplib.FORBIDDEN:
        cmd = f"(Invoke-WebRequest -UseBasicParsing -uri \"{solr_url}\").content"
        client_obj = None
        if solr_client:
            client_obj = self._commcell_obj.clients.get(solr_client)
        else:
            # if no client is passed, then take first client in index server cloud
            client_obj = self._commcell_obj.clients.get(self.client_name[0])
        exit_code, output, error_message = client_obj.execute_script(script_type="PowerShell",
                                                                     script=cmd)
        if exit_code != 0:
            raise SDKException(
                'IndexServers',
                '104',
                f"Something went wrong while querying solr - {exit_code}")
        elif error_message:
            raise SDKException(
                'IndexServers',
                '104',
                f"Something went wrong while querying solr - {error_message}")
        try:
            return json.loads(output.strip())
        except Exception:
            raise SDKException('IndexServers', '104', f"Something went wrong while querying solr - {output}")
    raise SDKException('IndexServers', '104', "Something went wrong while querying solr")
def get_all_cores(self, client_name=None)

gets all cores & core details from index server

Args

client_name (str) – name of the client node Applicable only for solr cloud mode or multi node Index Server

Returns

(list,dict) – list containing core names – dict containing details about cores

Raises

SDKException:

if input data is not valid

if client name is not passed for index server cloud

if response is not success

if response is empty
Expand source code Browse git
def get_all_cores(self, client_name=None):
    """gets all cores & core details from index server

            Args:
                client_name     (str)       --  name of the client node
                    ***Applicable only for solr cloud mode or multi node Index Server***

            Returns:
                (list,dict)     -- list containing core names
                                -- dict containing details about cores

            Raises:

                SDKException:

                    if input data is not valid

                    if client name is not passed for index server cloud

                    if response is not success

                    if response is empty

    """
    server_url = self.server_url[0]
    if self.is_cloud or len(self.client_name) > 1:
        if client_name is None:
            raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
        if client_name not in self.client_name:
            raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
        server_url = self.server_url[self.client_name.index(client_name)]
    core_names = []
    baseurl = f"{server_url}/solr/admin/cores"
    flag, response = self._cvpysdk_object.make_request("GET", baseurl)
    if flag and response.json():
        if 'error' in response.json():
            raise SDKException('IndexServers', '104', "Unable to get core names from index server")
        if 'status' in response.json():
            for core in response.json()['status']:
                core_names.append(core)
            return core_names, response.json()['status']
    raise SDKException('IndexServers', '104', "Something went wrong while getting core names")
def get_health_indicators(self, client_name=None)

Get health indicators for index server node by client name

Args

client_name (str) – name of the client node

Returns

(response(str)) – str json object

Raises

SDKException: if input data is not valid if client name is not passed for index server cloud if response is not success if response is empty

Expand source code Browse git
def get_health_indicators(self, client_name=None):
    """Get health indicators for index server node by client name

            Args:
                client_name     (str)       --  name of the client node

            Returns:
                (response(str)) -- str json object

            Raises:

                SDKException:
                    if input data is not valid
                    if client name is not passed for index server cloud
                    if response is not success
                    if response is empty

    """
    server_url = self.server_url[0]
    response = None
    if self.is_cloud or len(self.client_name) > 1:
        if client_name is None:
            raise SDKException('IndexServers', '104', 'Client name param missing for solr cloud')
        if client_name not in self.client_name:
            raise SDKException('IndexServers', '104', 'client name not found in this index server cloud')
        server_url = self.server_url[self.client_name.index(client_name)]
    baseurl = f"{server_url}/solr/rest/admin/healthsummary"
    headers = {
        'Accept': 'application/xml'
    }
    flag, response = self._cvpysdk_object.make_request("GET", headers=headers, url=baseurl)
    if flag:
        return response
    raise SDKException('IndexServers', '104', "Could not get health summary for [{}]".format(client_name))
def get_index_node(self, node_name)

Returns an Index server node object for given node name

Args

node_name (str) – Index server node name

Returns

IndexNode class object

Raises

SDKException:

    if node not found for the given node name
Expand source code Browse git
def get_index_node(self, node_name):
    """Returns an Index server node object for given node name
        Args:
            node_name           (str)   --  Index server node name

        Returns:
            IndexNode class object

        Raises:
            SDKException:

                    if node not found for the given node name

    """
    node_name = node_name.lower()
    if node_name in self.client_name:
        return IndexNode(self._commcell_obj, self.engine_name, node_name)
    raise SDKException("IndexServers", '104', 'Index server node not found')
def get_os_info(self)

Returns the OS type for the Index server

Expand source code Browse git
def get_os_info(self):
    """Returns the OS type for the Index server"""

    nodes_name = self.client_name
    nodes = [self._commcell_obj.clients.get(node) for node in nodes_name]
    nodes_os_info = [node.os_info for node in nodes]
    if IndexServerOSType.WINDOWS.value.lower() in nodes_os_info[0].lower():
        for node in nodes_os_info[1:]:
            if IndexServerOSType.UNIX.value.lower() in node.lower():
                return IndexServerOSType.MIXED.value
        return IndexServerOSType.WINDOWS.value
    else:
        for node in nodes_os_info[1:]:
            if IndexServerOSType.WINDOWS.value.lower() in node.lower():
                return IndexServerOSType.MIXED.value
        return IndexServerOSType.UNIX.value
def get_plan_info(self)

Gets the plan information of the index server

Returns

dict - containing the plan information

Expand source code Browse git
def get_plan_info(self):
    """Gets the plan information of the index server
        Returns:
            dict - containing the plan information
    """
    client = self._commcell_obj.clients.get(self.index_server_client_id)
    instance_props = client.properties.get("pseudoClientInfo", {}).get("distributedClusterInstanceProperties", {})
    plan_details = instance_props.get("clusterConfig",{}).get("cloudInfo", {}).get("planInfo", {})
    return plan_details
def hard_commit(self, core_name)

do hard commit for the given core name on index server

Args

core_name (str) – name of the solr core

Returns

None

Raises

SDKException:

if input data is not valid

if index server is cloud, not implemented error

if response is empty

if response is not success
Expand source code Browse git
def hard_commit(self, core_name):
    """do hard commit for the given core name on index server

                Args:

                    core_name               (str)  --  name of the solr core

                Returns:
                    None

                Raises:
                    SDKException:

                        if input data is not valid

                        if index server is cloud, not implemented error

                        if response is empty

                        if response is not success
    """
    if not isinstance(core_name, str):
        raise SDKException('IndexServers', '101')
    if self.is_cloud:
        raise SDKException('IndexServers', '104', "Not implemented for solr cloud")
    baseurl = f"{self.server_url[0]}/solr/{core_name}/update?commit=true"
    flag, response = self._cvpysdk_object.make_request("GET", baseurl)
    if flag and response.json():
        if 'error' in response.json():
            raise SDKException('IndexServers', '104', "Hard commit returned error")
        if 'responseHeader' in response.json():
            commitstatus = str(response.json()['responseHeader']['status'])
            if int(commitstatus) != 0:
                raise SDKException('IndexServers', '104', "Hard commit returned bad status")
            return
    raise SDKException('IndexServers', '104', "Something went wrong with hard commit")
def modify(self, index_location, node_name, node_params)

Modifies the properties of an index server

Args

index_location (str) – index server data directory node_name (str) – index server node name node_params (dict) – parameters to be passed [ { "name" : , "value" : } ]

Raises

SDKException: Response was not success. Response was empty.

Expand source code Browse git
def modify(self, index_location, node_name, node_params):
    """Modifies the properties of an index server

        Args:
            index_location      (str)       --  index server data directory
            node_name           (str)       --  index server node name
            node_params         (dict)      --  parameters to be passed
                                                [
                                                    {
                                                        "name" : <property_name>,
                                                        "value" : <property_value>
                                                    }
                                                ]
        Raises:
            SDKException:
                Response was not success.
                Response was empty.
    """
    json_req = deepcopy(IndexServerConstants.REQUEST_JSON)
    json_req['opType'] = IndexServerConstants.OPERATION_EDIT
    json_req['cloudNodes'] = [{
        "opType": IndexServerConstants.OPERATION_EDIT,
        "nodeClientEntity": {
            "clientId": int(self._commcell_obj.clients.get(node_name).client_id)
        },
        "nodeMetaInfos": [
            {
                "name": "INDEXLOCATION",
                "value": index_location
            }
        ]
    }]
    json_req['cloudInfoEntity']['cloudId'] = self.cloud_id
    for param in node_params:
        json_req['cloudNodes'][0]['nodeMetaInfos'].append(param)
    flag, response = self._cvpysdk_object.make_request(
        "POST", self._services['CLOUD_MODIFY'], json_req)
    if flag:
        if response.json():
            if 'cloudId' in response.json():
                self.refresh()
                return
        raise SDKException('Response', '102')
    raise SDKException('Response', '101')
def refresh(self)

Refresh the index server properties

Expand source code Browse git
def refresh(self):
    """Refresh the index server properties"""
    self._commcell_obj.index_servers.refresh()
    self._get_properties()
    if self.os_type is None:
        self.os_type = self.get_os_info()
    if not self._roles_obj:
        self._roles_obj = _Roles(self._commcell_obj)
    if self.plan_info is None:
        self.plan_info = self.get_plan_info()
def update_role(self, props=None)

Updates a role of an Index Server

Args

props (list) – array of dictionaries consisting details of the roles such as role name and operation type. [{ "roleName": (str) "operationType": 1 or 2 (int) 1 for adding a role 2 for removing a role }]

Raises

SDKException: if response is empty

if response is not success
Expand source code Browse git
def update_role(self, props=None):
    """Updates a role of an Index Server

        Args:
            props               (list)  --  array of dictionaries
            consisting details of the roles such as role name
            and operation type.
                                        [{
                                            "roleName": <name>          (str)
                                            "operationType": 1 or 2     (int)
                                                1 for adding a role
                                                2 for removing a role
                                        }]

        Raises:
            SDKException:
                if response is empty

                if response is not success

    """
    json_req = {"cloudId": self.cloud_id, "roles": []}
    if props:
        for prop in props:
            role_id = self._roles_obj.get_role_id(prop['roleName'])
            if not role_id:
                raise SDKException('IndexServers', '103')
            prop['roleId'] = role_id
            json_req['roles'].append(prop)
    flag, response = self._cvpysdk_object.make_request(
        'POST', self._services['CLOUD_ROLE_UPDATE'], json_req
    )
    if flag:
        if response.json() and 'errorCode' in response.json():
            if response.json()['errorCode'] == 0:
                self.refresh()
                return
        raise SDKException('Response', '102')
    raise SDKException('Response', '101')
def update_roles_data(self)

Synchronize the cloud roles data with the commcell

Expand source code Browse git
def update_roles_data(self):
    """Synchronize the cloud roles data with the commcell"""
    self._roles_obj.update_roles_data()
class IndexServerOSType (value, names=None, *, module=None, qualname=None, type=None, start=1)

Enum class for Index Server OS Type

Expand source code Browse git
class IndexServerOSType(enum.Enum):
    """Enum class for Index Server OS Type"""
    WINDOWS = "Windows"
    UNIX = "Unix"
    MIXED = "Mixed"

Ancestors

  • enum.Enum

Class variables

var MIXED
var UNIX
var WINDOWS
class IndexServers (commcell_object)

Class for representing all the index servers associated with the commcell.

Initialize object of the IndexServers class.

Args

commcell_object (object) – instance of the Commcell class

Returns

object - instance of the IndexServers class

Expand source code Browse git
class IndexServers(object):
    """Class for representing all the index servers associated with the commcell."""

    def __init__(self, commcell_object):
        """Initialize object of the IndexServers class.

            Args:
                commcell_object (object)  --  instance of the Commcell class

            Returns:
                object - instance of the IndexServers class
        """
        self._commcell_object = commcell_object
        self._cvpysdk_object = commcell_object._cvpysdk_object
        self._services = commcell_object._services
        self._update_response_ = commcell_object._update_response_
        self._all_index_servers = None
        self._roles_obj = None
        self.refresh()

    def __str__(self):
        """Representation string consisting of all index servers of the commcell.

                Returns:
                    str - string of all the index servers with different roles associated
                    with the commcell
        """
        representation_string = '{:^5}\t{:^20}\n\n'.format('S. No.', 'IS Name')
        index = 1
        for index_server in self._all_index_servers:
            representation_string += '{:^5}\t{:^20}\n'.format(
                index, index_server['engineName'])
            index += 1
        return representation_string

    def __repr__(self):
        """Representation string for the instance of the IndexServers class."""
        return "IndexServers class instance for Commcell: '{0}'".format(
            self._commcell_object.commserv_name
        )

    def __len__(self):
        """Returns the number of the index servers associated with the commcell"""
        return len(self._all_index_servers)

    def _response_not_success(self, response):
        """Helper method to raise exception when response is not 200 (ok)

                Raises:
                    SDKException:
                        Response was not success
        """
        raise SDKException(
            'Response',
            '101',
            self._update_response_(
                response.text))

    def _get_index_servers(self):
        """Method to retrieve all the index server available on commcell.

            Raises:
                SDKException:
                    Failed to get the list of analytics engines

                    Response was not success
        """
        flag, response = self._cvpysdk_object.make_request(
            'GET', self._services['GET_ALL_INDEX_SERVERS'])
        if flag:
            if response.json() and 'listOfCIServer' in response.json():
                for item in response.json()['listOfCIServer']:
                    if item['cloudID'] in self._all_index_servers:
                        # Add only unique roles to list
                        if item['version'] not in self._all_index_servers[item['cloudID']]['version']:
                            self._all_index_servers[item['cloudID']]['version'].append(item['version'])
                        # check whether we have populated node details earlier. if not, add it to
                        # exisitng respective fields
                        if item['clientName'] not in self._all_index_servers[item['cloudID']]['clientName']:

                            self._all_index_servers[item['cloudID']]['clientId'].append(item['clientId'])
                            self._all_index_servers[item['cloudID']]['clientName'].append(item['clientName'])
                            self._all_index_servers[item['cloudID']]['hostName'].append(item['hostName'])
                            self._all_index_servers[item['cloudID']]['cIServerURL'].append(item['cIServerURL'])
                            self._all_index_servers[item['cloudID']]['basePort'].append(item['basePort'])

                    else:
                        item['version'] = [item['version']]
                        item['clientId'] = [item['clientId']]
                        item['clientName'] = [item['clientName']]
                        item['hostName'] = [item['hostName']]
                        item['cIServerURL'] = [item['cIServerURL']]
                        item['basePort'] = [item['basePort']]
                        self._all_index_servers[item['cloudID']] = item
            else:
                self._all_index_servers = {}
        else:
            self._response_not_success(response)

    def _get_all_roles(self):
        """Creates an instance of _Roles class and adds it to the IndexServer class"""
        self._roles_obj = _Roles(self._commcell_object)

    @property
    def all_index_servers(self):
        """Returns the details of all the index server for associated commcell.

                Returns:
                    dict - dictionary consisting details of all the index servers
                    associated with commcell
                    Sample - {
                                <cloud_id_1>   :
                                    {
                                        "engineName" : <property_value>,
                                        "internalCloudName" : <property_value>,
                                        ...
                                    },
                                <cloud_id_2>   :
                                    {
                                        "engineName" : <property_value>,
                                        "cloudID" : <property_value>,
                                        ...
                                    }
                            }
        """
        return self._all_index_servers

    @property
    def roles_data(self):
        """Returns the details of all the cloud roles data

                Returns:
                    list - list of dictionary containing details of the cloud roles
        """
        return self._roles_obj.roles_data

    def refresh(self):
        """Refresh the properties of IndexServers class"""
        self._all_index_servers = {}
        self._get_index_servers()
        if not self._roles_obj:
            self._get_all_roles()

    def update_roles_data(self):
        """Synchronises all the cloud roles details with the commcell"""
        self._roles_obj.update_roles_data()

    def get_properties(self, cloud_name):
        """Returns all details of a index server with the cloud name

                Args:
                    cloud_name     (str)       --  cloud name of index server

                Returns:
                    dict        -   dict consisting details of the index server
        """
        for index_server in self._all_index_servers:
            if self._all_index_servers[index_server]['engineName'] == cloud_name:
                return self._all_index_servers[index_server]
        raise SDKException('IndexServers', '102')

    def has(self, cloud_name):
        """Returns True if the index server with given name is present in commcell.

                Args:
                    cloud_name     (str)       --  the engine name of index server

                Returns:
                    boolean     -   True if index server with given name as is_name
                    is associated with the commcell else returns False

                Raises:
                    SDKExecption:
                        Data type of the input(s) is not valid
        """
        if isinstance(cloud_name, str):
            for index_server in self._all_index_servers:
                if self._all_index_servers[index_server]["engineName"].lower() == cloud_name.lower():
                    return True
            return False
        raise SDKException('IndexServers', '101')

    def get(self, cloud_data):
        """Returns IndexServer object if a index server is found.

                Args:
                    cloud_data        (int/str)       --    cloud name or
                                                            cloud ID of index server

                Returns:
                    object            (IndexServer)   --  Instance on index server with
                    the engine name or cloud id as item

                Raises:
                    SDKException:
                        Index Server not found.

                        Data type of the input(s) is not valid.
        """
        if isinstance(cloud_data, int):
            if cloud_data in self._all_index_servers:
                return IndexServer(
                    self._commcell_object,
                    self._all_index_servers[cloud_data]['engineName'],
                    cloud_data)
            SDKException('IndexServers', '102')
        elif isinstance(cloud_data, str):
            name = cloud_data.lower()
            for itter in self._all_index_servers:
                if self._all_index_servers[itter]['engineName'].lower(
                ) == name:
                    return IndexServer(
                        self._commcell_object,
                        self._all_index_servers[itter]['engineName'],
                        self._all_index_servers[itter]['cloudID'])
            raise SDKException('IndexServers', '102')
        raise SDKException('IndexServers', '101')

    def create(
            self,
            index_server_name,
            index_server_node_names,
            index_directory,
            index_server_roles,
            index_pool_name=None,
            is_cloud=False,
            cloud_param=None):
        """Creates an index server within the commcell

                Args:
                    index_server_node_names         (list)  --  client names for index server node
                    index_server_name               (str)   --  name for the index server
                    index_directory                 (list)  --  list of index locations for the index server
                                                                nodes respectively
                                                    For example:
                                                            [<path_1>] - same index location for all the nodes
                                                            [<path_1>, <path_2>, <path_3>] - different index
                                                    location for index server with 3 nodes
                    index_server_roles              (list)  --  list of role names to be assigned
                    index_pool_name                 (str)   --  name for the index pool to used by cloud index server
                    cloud_param                     (list)  --  list of custom parameters to be parsed
                                                    into the json for index server meta info
                                                    [
                                                        {
                                                            "name": <name>,
                                                            "value": <value>
                                                        }
                                                    ]
                    is_cloud            (bool)  --  if true then creates a cloud mode index server

                Raises:
                    SDKException:
                        Data type of the input(s) is not valid.

                        Response was not success.

                        Response was empty.
        """
        if not (isinstance(index_server_roles, list) and isinstance(index_server_node_names, list)
                and isinstance(index_server_name, str)):
            raise SDKException('IndexServers', '101')
        if isinstance(index_directory, str):
            index_directory = index_directory.split(",")
        node_count = len(index_server_node_names)
        index_directories_count = len(index_directory)
        if index_directories_count != 1 and index_directories_count != node_count:
            raise SDKException('IndexServers', '101')
        cloud_meta_infos = {
            'REPLICATION': '1',
            'LANGUAGE': '0'
        }
        node_meta_infos = {
            'PORTNO': IndexServerConstants.DEFAULT_SOLR_PORT,
            'JVMMAXMEMORY': IndexServerConstants.DEFAULT_JVM_MAX_MEMORY
        }
        role_meta_infos = {}
        req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
        req_json['cloudInfoEntity'] = {
            'cloudName': index_server_name,
            'cloudDisplayName': index_server_name
        }
        if is_cloud:
            index_pool_obj = self._commcell_object.index_pools[index_pool_name]
            req_json['type'] = 5
            req_json['solrCloudInfo']['cloudPoolInfo'] = {
                'cloudId': int(index_pool_obj['pool_id'])
            }
            cloud_meta_infos['INDEXLOCATION'] = index_directory[0]
        for node_name_index in range(len(index_server_node_names)):
            node_name = index_server_node_names[node_name_index]
            location_index = node_name_index - (node_name_index//index_directories_count)
            node_obj = self._commcell_object.clients[node_name]
            node_data = {
                "opType": IndexServerConstants.OPERATION_ADD,
                "nodeClientEntity": {
                    "hostName": node_obj['hostname'],
                    "clientId": int(node_obj['id']),
                    "clientName": node_name
                },
                'nodeMetaInfos': [{
                    "name": "INDEXLOCATION",
                    "value": index_directory[location_index]
                }]
            }
            for node_info in node_meta_infos:
                node_data['nodeMetaInfos'].append({
                    'name': node_info,
                    'value': str(node_meta_infos[node_info])
                })
            req_json['cloudNodes'].append(node_data)
        for role in index_server_roles:
            role_id = self._roles_obj.get_role_id(role)
            if not role_id:
                raise SDKException('IndexServers', '103')
            role_data = {
                "roleId": role_id,
                "roleName": role,
                "operationType": IndexServerConstants.OPERATION_ADD,
                'roleMetaInfos': []
            }
            for role_info in role_meta_infos:
                role_data['roleMetaInfos'].append({
                    'name': role_info,
                    'value': role_meta_infos[role_info]
                })
            req_json['solrCloudInfo']['roles'].append(role_data)
        if cloud_param:
            for param in cloud_param:
                if param['name'] in cloud_meta_infos:
                    del cloud_meta_infos[param['name']]
                req_json['cloudMetaInfos'].append(param)
        for cloud_info in cloud_meta_infos:
            req_json['cloudMetaInfos'].append({
                'name': cloud_info,
                'value': cloud_meta_infos[cloud_info]
            })
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_CREATE'], req_json)
        if flag:
            if response.json():
                error_code = response.json()['genericResp']['errorCode']
                error_string = response.json()['genericResp']['errorMessage']
                if error_code == 0:
                    self.refresh()
                    self._commcell_object.clients.refresh()
                    self._commcell_object.datacube.refresh_engine()
                else:
                    o_str = 'Failed to create Index Server. Error: "{0}"'.format(
                        error_string)
                    raise SDKException('IndexServers', '102', o_str)
            else:
                raise SDKException('Response', '102')
        else:
            self._response_not_success(response)

    def delete(self, cloud_name):
        """Deletes / removes an index server from the commcell

                Args:
                    cloud_name      (str)   --  cloud name of index server
                    to be removed from the commcell

                Raises:
                    SDKException:
                        Data type of the input(s) is not valid.

                        Response was not success.

                        Response was empty.
        """
        if not isinstance(cloud_name, str):
            raise SDKException('IndexServers', '101')
        cloud_id = self.get(cloud_name).cloud_id
        req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
        req_json["opType"] = IndexServerConstants.OPERATION_DELETE
        req_json['cloudInfoEntity']['cloudId'] = cloud_id
        flag, response = self._cvpysdk_object.make_request(
            'POST', self._services['CLOUD_DELETE'], req_json
        )
        if flag:
            if response.json() and 'genericResp' in response.json() \
                    and 'errorCode' not in response.json()['genericResp']:
                self.refresh()
                self._commcell_object.clients.refresh()
                self._commcell_object.datacube.refresh_engine()
                return
            if response.json() and 'genericResp' in response.json():
                raise SDKException(
                    'Response', '102', response.json()['genericResp'].get(
                        'errorMessage', ''))
            raise SDKException('Response', '102')
        self._response_not_success(response)

    def prune_orphan_datasources(self):
        """Deletes all the orphan datasources
            Raises:
                SDKException:
                    if failed to prune the orphan datasources

                    If response is empty

                    if response is not success
        """
        prune_datasource = self._services['PRUNE_DATASOURCE']
        request_json = IndexServerConstants.PRUNE_REQUEST_JSON
        flag, response = self._cvpysdk_object.make_request(
            'POST', prune_datasource, request_json)
        if flag:
            if response.json():
                error_code = response.json().get('errorCode', 0)
                if error_code != 0:
                    raise SDKException('IndexServers', '104', 'Failed to prune orphan datasources')
                return
            raise SDKException('Response', '102')
        raise SDKException('Response', '101', self._update_response_(response.text))

Instance variables

var all_index_servers

Returns the details of all the index server for associated commcell.

Returns

dict - dictionary consisting details of all the index servers associated with commcell Sample - { : { "engineName" : , "internalCloudName" : , … }, : { "engineName" : , "cloudID" : , … } }

Expand source code Browse git
@property
def all_index_servers(self):
    """Returns the details of all the index server for associated commcell.

            Returns:
                dict - dictionary consisting details of all the index servers
                associated with commcell
                Sample - {
                            <cloud_id_1>   :
                                {
                                    "engineName" : <property_value>,
                                    "internalCloudName" : <property_value>,
                                    ...
                                },
                            <cloud_id_2>   :
                                {
                                    "engineName" : <property_value>,
                                    "cloudID" : <property_value>,
                                    ...
                                }
                        }
    """
    return self._all_index_servers
var roles_data

Returns the details of all the cloud roles data

Returns

list - list of dictionary containing details of the cloud roles

Expand source code Browse git
@property
def roles_data(self):
    """Returns the details of all the cloud roles data

            Returns:
                list - list of dictionary containing details of the cloud roles
    """
    return self._roles_obj.roles_data

Methods

def create(self, index_server_name, index_server_node_names, index_directory, index_server_roles, index_pool_name=None, is_cloud=False, cloud_param=None)

Creates an index server within the commcell

Args

index_server_node_names (list) – client names for index server node index_server_name (str) – name for the index server index_directory (list) – list of index locations for the index server nodes respectively For example: [] - same index location for all the nodes [, , ] - different index location for index server with 3 nodes index_server_roles (list) – list of role names to be assigned index_pool_name (str) – name for the index pool to used by cloud index server cloud_param (list) – list of custom parameters to be parsed into the json for index server meta info [ { "name": , "value": } ] is_cloud (bool) – if true then creates a cloud mode index server

Raises

SDKException: Data type of the input(s) is not valid.

Response was not success.

Response was empty.
Expand source code Browse git
def create(
        self,
        index_server_name,
        index_server_node_names,
        index_directory,
        index_server_roles,
        index_pool_name=None,
        is_cloud=False,
        cloud_param=None):
    """Creates an index server within the commcell

            Args:
                index_server_node_names         (list)  --  client names for index server node
                index_server_name               (str)   --  name for the index server
                index_directory                 (list)  --  list of index locations for the index server
                                                            nodes respectively
                                                For example:
                                                        [<path_1>] - same index location for all the nodes
                                                        [<path_1>, <path_2>, <path_3>] - different index
                                                location for index server with 3 nodes
                index_server_roles              (list)  --  list of role names to be assigned
                index_pool_name                 (str)   --  name for the index pool to used by cloud index server
                cloud_param                     (list)  --  list of custom parameters to be parsed
                                                into the json for index server meta info
                                                [
                                                    {
                                                        "name": <name>,
                                                        "value": <value>
                                                    }
                                                ]
                is_cloud            (bool)  --  if true then creates a cloud mode index server

            Raises:
                SDKException:
                    Data type of the input(s) is not valid.

                    Response was not success.

                    Response was empty.
    """
    if not (isinstance(index_server_roles, list) and isinstance(index_server_node_names, list)
            and isinstance(index_server_name, str)):
        raise SDKException('IndexServers', '101')
    if isinstance(index_directory, str):
        index_directory = index_directory.split(",")
    node_count = len(index_server_node_names)
    index_directories_count = len(index_directory)
    if index_directories_count != 1 and index_directories_count != node_count:
        raise SDKException('IndexServers', '101')
    cloud_meta_infos = {
        'REPLICATION': '1',
        'LANGUAGE': '0'
    }
    node_meta_infos = {
        'PORTNO': IndexServerConstants.DEFAULT_SOLR_PORT,
        'JVMMAXMEMORY': IndexServerConstants.DEFAULT_JVM_MAX_MEMORY
    }
    role_meta_infos = {}
    req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
    req_json['cloudInfoEntity'] = {
        'cloudName': index_server_name,
        'cloudDisplayName': index_server_name
    }
    if is_cloud:
        index_pool_obj = self._commcell_object.index_pools[index_pool_name]
        req_json['type'] = 5
        req_json['solrCloudInfo']['cloudPoolInfo'] = {
            'cloudId': int(index_pool_obj['pool_id'])
        }
        cloud_meta_infos['INDEXLOCATION'] = index_directory[0]
    for node_name_index in range(len(index_server_node_names)):
        node_name = index_server_node_names[node_name_index]
        location_index = node_name_index - (node_name_index//index_directories_count)
        node_obj = self._commcell_object.clients[node_name]
        node_data = {
            "opType": IndexServerConstants.OPERATION_ADD,
            "nodeClientEntity": {
                "hostName": node_obj['hostname'],
                "clientId": int(node_obj['id']),
                "clientName": node_name
            },
            'nodeMetaInfos': [{
                "name": "INDEXLOCATION",
                "value": index_directory[location_index]
            }]
        }
        for node_info in node_meta_infos:
            node_data['nodeMetaInfos'].append({
                'name': node_info,
                'value': str(node_meta_infos[node_info])
            })
        req_json['cloudNodes'].append(node_data)
    for role in index_server_roles:
        role_id = self._roles_obj.get_role_id(role)
        if not role_id:
            raise SDKException('IndexServers', '103')
        role_data = {
            "roleId": role_id,
            "roleName": role,
            "operationType": IndexServerConstants.OPERATION_ADD,
            'roleMetaInfos': []
        }
        for role_info in role_meta_infos:
            role_data['roleMetaInfos'].append({
                'name': role_info,
                'value': role_meta_infos[role_info]
            })
        req_json['solrCloudInfo']['roles'].append(role_data)
    if cloud_param:
        for param in cloud_param:
            if param['name'] in cloud_meta_infos:
                del cloud_meta_infos[param['name']]
            req_json['cloudMetaInfos'].append(param)
    for cloud_info in cloud_meta_infos:
        req_json['cloudMetaInfos'].append({
            'name': cloud_info,
            'value': cloud_meta_infos[cloud_info]
        })
    flag, response = self._cvpysdk_object.make_request(
        'POST', self._services['CLOUD_CREATE'], req_json)
    if flag:
        if response.json():
            error_code = response.json()['genericResp']['errorCode']
            error_string = response.json()['genericResp']['errorMessage']
            if error_code == 0:
                self.refresh()
                self._commcell_object.clients.refresh()
                self._commcell_object.datacube.refresh_engine()
            else:
                o_str = 'Failed to create Index Server. Error: "{0}"'.format(
                    error_string)
                raise SDKException('IndexServers', '102', o_str)
        else:
            raise SDKException('Response', '102')
    else:
        self._response_not_success(response)
def delete(self, cloud_name)

Deletes / removes an index server from the commcell

Args

cloud_name (str) – cloud name of index server to be removed from the commcell

Raises

SDKException: Data type of the input(s) is not valid.

Response was not success.

Response was empty.
Expand source code Browse git
def delete(self, cloud_name):
    """Deletes / removes an index server from the commcell

            Args:
                cloud_name      (str)   --  cloud name of index server
                to be removed from the commcell

            Raises:
                SDKException:
                    Data type of the input(s) is not valid.

                    Response was not success.

                    Response was empty.
    """
    if not isinstance(cloud_name, str):
        raise SDKException('IndexServers', '101')
    cloud_id = self.get(cloud_name).cloud_id
    req_json = deepcopy(IndexServerConstants.REQUEST_JSON)
    req_json["opType"] = IndexServerConstants.OPERATION_DELETE
    req_json['cloudInfoEntity']['cloudId'] = cloud_id
    flag, response = self._cvpysdk_object.make_request(
        'POST', self._services['CLOUD_DELETE'], req_json
    )
    if flag:
        if response.json() and 'genericResp' in response.json() \
                and 'errorCode' not in response.json()['genericResp']:
            self.refresh()
            self._commcell_object.clients.refresh()
            self._commcell_object.datacube.refresh_engine()
            return
        if response.json() and 'genericResp' in response.json():
            raise SDKException(
                'Response', '102', response.json()['genericResp'].get(
                    'errorMessage', ''))
        raise SDKException('Response', '102')
    self._response_not_success(response)
def get(self, cloud_data)

Returns IndexServer object if a index server is found.

Args

cloud_data (int/str) – cloud name or cloud ID of index server

Returns

object (IndexServer) – Instance on index server with the engine name or cloud id as item

Raises

SDKException: Index Server not found.

Data type of the input(s) is not valid.
Expand source code Browse git
def get(self, cloud_data):
    """Returns IndexServer object if a index server is found.

            Args:
                cloud_data        (int/str)       --    cloud name or
                                                        cloud ID of index server

            Returns:
                object            (IndexServer)   --  Instance on index server with
                the engine name or cloud id as item

            Raises:
                SDKException:
                    Index Server not found.

                    Data type of the input(s) is not valid.
    """
    if isinstance(cloud_data, int):
        if cloud_data in self._all_index_servers:
            return IndexServer(
                self._commcell_object,
                self._all_index_servers[cloud_data]['engineName'],
                cloud_data)
        SDKException('IndexServers', '102')
    elif isinstance(cloud_data, str):
        name = cloud_data.lower()
        for itter in self._all_index_servers:
            if self._all_index_servers[itter]['engineName'].lower(
            ) == name:
                return IndexServer(
                    self._commcell_object,
                    self._all_index_servers[itter]['engineName'],
                    self._all_index_servers[itter]['cloudID'])
        raise SDKException('IndexServers', '102')
    raise SDKException('IndexServers', '101')
def get_properties(self, cloud_name)

Returns all details of a index server with the cloud name

Args

cloud_name (str) – cloud name of index server

Returns

dict - dict consisting details of the index server

Expand source code Browse git
def get_properties(self, cloud_name):
    """Returns all details of a index server with the cloud name

            Args:
                cloud_name     (str)       --  cloud name of index server

            Returns:
                dict        -   dict consisting details of the index server
    """
    for index_server in self._all_index_servers:
        if self._all_index_servers[index_server]['engineName'] == cloud_name:
            return self._all_index_servers[index_server]
    raise SDKException('IndexServers', '102')
def has(self, cloud_name)

Returns True if the index server with given name is present in commcell.

Args

cloud_name (str) – the engine name of index server

Returns

boolean - True if index server with given name as is_name is associated with the commcell else returns False

Raises

SDKExecption: Data type of the input(s) is not valid

Expand source code Browse git
def has(self, cloud_name):
    """Returns True if the index server with given name is present in commcell.

            Args:
                cloud_name     (str)       --  the engine name of index server

            Returns:
                boolean     -   True if index server with given name as is_name
                is associated with the commcell else returns False

            Raises:
                SDKExecption:
                    Data type of the input(s) is not valid
    """
    if isinstance(cloud_name, str):
        for index_server in self._all_index_servers:
            if self._all_index_servers[index_server]["engineName"].lower() == cloud_name.lower():
                return True
        return False
    raise SDKException('IndexServers', '101')
def prune_orphan_datasources(self)

Deletes all the orphan datasources

Raises

SDKException: if failed to prune the orphan datasources

If response is empty

if response is not success
Expand source code Browse git
def prune_orphan_datasources(self):
    """Deletes all the orphan datasources
        Raises:
            SDKException:
                if failed to prune the orphan datasources

                If response is empty

                if response is not success
    """
    prune_datasource = self._services['PRUNE_DATASOURCE']
    request_json = IndexServerConstants.PRUNE_REQUEST_JSON
    flag, response = self._cvpysdk_object.make_request(
        'POST', prune_datasource, request_json)
    if flag:
        if response.json():
            error_code = response.json().get('errorCode', 0)
            if error_code != 0:
                raise SDKException('IndexServers', '104', 'Failed to prune orphan datasources')
            return
        raise SDKException('Response', '102')
    raise SDKException('Response', '101', self._update_response_(response.text))
def refresh(self)

Refresh the properties of IndexServers class

Expand source code Browse git
def refresh(self):
    """Refresh the properties of IndexServers class"""
    self._all_index_servers = {}
    self._get_index_servers()
    if not self._roles_obj:
        self._get_all_roles()
def update_roles_data(self)

Synchronises all the cloud roles details with the commcell

Expand source code Browse git
def update_roles_data(self):
    """Synchronises all the cloud roles details with the commcell"""
    self._roles_obj.update_roles_data()