コード例 #1
0
    def generate_template_certificate_authority(self,
                                                valid_for,
                                                connection=None):
        """
        Attempts to generate an template certificate authority.

        :param valid_for: The number of days that the template should be valid.

        :return: The Template object.
        """
        if connection == None:
            connection = self.connection

        struct = {
            'operation': 'generate-template-certificate-authority',
            'valid-for': assert_type(valid_for, int)
        }

        uri = connection.uri("certificate-templates",
                             self.template_id(),
                             properties=None)

        response = connection.post(uri, payload=struct)

        if response.status_code != 201:
            raise UnexpectedManagementAPIResponse(response.text)

        return self
コード例 #2
0
ファイル: __init__.py プロジェクト: twcook/python_api
    def instance_admin(cls,host,realm,admin,password):
        """
        Initializes the security database of a newly initialized server.

        :param host: The name or IP address of the host to initialize
        :param realm: The security realm to install
        :param admin: The name of the admin user
        :param password: The password of the admin user
        """
        conn = Connection(host, None)

        payload = {
            'admin-username': admin,
            'admin-password': password,
            'realm': realm
            }

        uri = "{0}://{1}:8001/admin/v1/instance-admin".format(
            conn.protocol, conn.host)

        logger = logging.getLogger("marklogic")
        logger.debug("Initializing security for {0}".format(host))

        # N.B. Can't use conn.post here because we don't need auth yet
        response = requests.post(uri, json=payload,
                                 headers={'content-type': 'application/json',
                                          'accept': 'application/json'})

        if response.status_code != 202:
            raise UnexpectedManagementAPIResponse(response.text)

        # From now on connections require auth...
        conn = Connection(host, HTTPDigestAuth(admin, password))
        data = json.loads(response.text)
        conn.wait_for_restart(data["restart"]["last-startup"][0]["value"])
コード例 #3
0
ファイル: cluster.py プロジェクト: systemsTeam45/python_api
    def _post_server_config(self, xml, connection):
        """
        Send the server configuration to the a bootstrap host on the
        cluster to which you wish to couple. This is the first half of
        the handshake necessary to join a host to a cluster. The results
        are not intended for introspection.

        :param connection: The connection credentials to use
        :param xml: The XML payload from get_server_config()
        :return: The cluster configuration as a ZIP file.
        """
        uri = "{0}://{1}:8001/admin/v1/cluster-config".format(
            connection.protocol, connection.host)

        struct = {'group': 'Default', 'server-config': xml}

        response = connection.post(
            uri,
            payload=struct,
            content_type='application/x-www-form-urlencoded')

        if response.status_code != 200:
            raise UnexpectedManagementAPIResponse(response.text)

        return response.content
コード例 #4
0
    def list(cls, connection, include_names=False):
        """
        List all the certificate authorities.

        If `include_names` is `True`, then the values in the list will be
        structured values consisting of the certificate ID and the certificate
        name separated by a "|".

        :param connection: The connection to a MarkLogic server
        :param include_names: Indicates if structured names should be returned.

        :return: A list of certificate authority IDs.
        """

        uri = connection.uri("certificate-authorities")
        response = connection.get(uri)

        if response.status_code != 200:
            raise UnexpectedManagementAPIResponse(response.text)

        results = []
        json_doc = json.loads(response.text)

        for item in json_doc['certificate-authorities-default-list'][
                'list-items']['list-item']:
            if include_names:
                results.append("{0}|{1}".format(item['idref'],
                                                item['nameref']))
            else:
                results.append(item['idref'])
        return results
コード例 #5
0
    def exists(self, connection=None):
        """
        Returns true if (and only if) the specified privilege exists.

        If the name is a structured value consisting of the kind and the
        name separated by a "|", as returned by the list() method, then
        the kind is optional.

        :param connection: The connection to the MarkLogic database
        :return: The privilege
        """
        if connection is None:
            connection = self.connection

        parameters = []
        if self.kind() is not None:
            parameters = ["kind=" + self.kind()]
        uri = connection.uri("privileges",
                             self.privilege_name(),
                             parameters=parameters)

        response = connection.head(uri)

        if response.status_code == 200:
            return True
        elif response.status_code == 404:
            return False
        else:
            raise UnexpectedManagementAPIResponse(response.text)
コード例 #6
0
    def instance_init(cls, host):
        """
        Performs first-time initialization of a newly installed server.

        :param host: The name or IP address of the host to initialize
        """
        conn = Connection(host, None)

        uri = "{0}://{1}:8001/admin/v1/init".format(conn.protocol, conn.host)

        logger = logging.getLogger("marklogic")
        logger.debug("Initializing {0}".format(host))

        # This call is a little odd; we special case the 400 error that
        # occurs if the host has alreadya been initialized.
        try:
            response = conn.post(
                uri, content_type='application/x-www-form-urlencoded')
        except UnexpectedManagementAPIResponse:
            response = conn.response
            if response.status_code == 400:
                err = json.loads(response.text)
                if "errorResponse" in err:
                    if "messageCode" in err["errorResponse"]:
                        if err["errorResponse"][
                                "messageCode"] == "MANAGE-ALREADYINIT":
                            return Host(host)
            raise

        if response.status_code != 202:
            raise UnexpectedManagementAPIResponse(response.text)

        return Host(host)._set_just_initialized()
コード例 #7
0
    def create(self, connection=None):
        """
        Creates the certificate template on the MarkLogic server.

        :param connection: The connection to a MarkLogic server
        :return: The Template object
        """
        if connection == None:
            connection = self.connection

        uri = connection.uri("certificate-templates")
        struct = self.marshal()
        response = connection.post(uri, payload=struct)

        # All well and good, but we need to know what ID was assigned
        uri = "{0}://{1}:{2}{3}/properties" \
          .format(connection.protocol, connection.host,
                  connection.management_port,
                  response.headers['location'])

        response = connection.get(uri)

        if response.status_code == 200:
            result = Template.unmarshal(json.loads(response.text))
            self._config = result._config
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return self
コード例 #8
0
    def list(cls, connection):
        """
        Lists the amps on this cluster.

        :param connection: A connection to a MarkLogic server
        :return: A list of amps.
        """

        uri = connection.uri("amps")
        response = connection.get(uri)

        # This one isn't like all the others because they're compound
        # Should return the IDs but the Management API doesn't (yet) allow
        # access by only the ID.
        if response.status_code == 200:
            response_json = json.loads(response.text)
            amp_count = response_json['amp-default-list']['list-items'][
                'list-count']['value']

            result = []
            if amp_count > 0:
                for item in response_json['amp-default-list']['list-items'][
                        'list-item']:
                    result.append({
                        "local-name": item['nameref'],
                        "namespace": item['namespace'],
                        "document-uri": item['document-uri']
                    })
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return result
コード例 #9
0
    def create(self, connection=None):
        """
        Create a new amp.

        :param connection: The server connection

        :return: The amp object
        """
        if connection is None:
            connection = self.connection

        uri = connection.uri("amps")

        struct = self.marshal()

        self.logger.debug("Creating {0} amp".format(self.local_name()))

        response = connection.post(uri, payload=struct)

        if response.status_code != 201:
            raise UnexpectedManagementAPIResponse(response.text)

        if 'etag' in response.headers:
            self.etag = response.headers['etag']

        return self
コード例 #10
0
    def list(cls, connection):
        """
        Lists the IDs of tasks available on this cluster.

        :param connection: A connection to a MarkLogic server
        :return: A list of task IDs.
        """

        uri = connection.uri("tasks")
        response = connection.get(uri)

        if response.status_code == 200:
            response_json = json.loads(response.text)
            task_count = response_json['tasks-default-list']['list-items'][
                'list-count']['value']

            result = []
            if task_count > 0:
                for item in response_json['tasks-default-list']['list-items'][
                        'list-item']:
                    result.append(item['idref'])
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return result
コード例 #11
0
    def create(cls, connection, pem):
        """
        Creates a new certificate authority

        Note that this is a class method, you cannot create a certificate
        authority except by uploading a PEM-encoded "certificate authority"
        certificate.

        :param connection: The connection to a MarkLogic server
        :param pem: The PEM-encoded certificate authority certificate

        :return: The Authority object
        """
        uri = connection.uri("certificate-authorities")
        response = connection.post(uri, payload=pem, content_type="text/plain")

        # All well and good, but we need to know what ID was assigned
        uri = "{0}://{1}:{2}{3}/properties" \
          .format(connection.protocol, connection.host,
                  connection.management_port,
                  response.headers['location'])

        response = connection.get(uri)

        if response.status_code == 200:
            result = Authority.unmarshal(json.loads(response.text))
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return result
コード例 #12
0
    def create(self, group="Default", connection=None):
        """
        Create a new scheduled task.

        :param connection: The server connection

        :return: The task object
        """
        if connection is None:
            connection = self.connection

        uri = connection.uri("tasks", parameters=["group-id=" + group])

        struct = self.marshal()

        self.logger.debug("Creating {0} task".format(self.type()))

        response = connection.post(uri, payload=struct)

        if response.status_code != 201:
            raise UnexpectedManagementAPIResponse(response.text)

        if 'etag' in response.headers:
            self.etag = response.headers['etag']

        # All well and good, but we need to know what ID was assigned
        location = response.headers['location']
        qpos = location.index("?")
        location = location[0:qpos]

        uri = "{0}://{1}:{2}{3}/properties?group-id={4}" \
              .format(connection.protocol, connection.host,
                      connection.management_port, location, group)

        response = connection.get(uri)

        if response.status_code == 200:
            result = Task.unmarshal(json.loads(response.text))
            self._config = result._config
            self.taskid = self._config['task-id']
            self.group = group
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return self
コード例 #13
0
    def wait_for_restart(self, last_startup, timestamp_uri="/admin/v1/timestamp"):
        """Wait for the host to restart.

        :param last_startup: The last startup time reported in the
        restart message
        """

        uri = "{0}://{1}:8001{2}".format(self.protocol, self.host,
                                         timestamp_uri)

        done = False
        count = 24
        while not done:
            try:
                self.logger.debug("Waiting for restart of {0}"
                                  .format(self.host))
                response = requests.get(uri, auth=self.auth,
                                        headers={'accept': 'application/json'},
                                        verify=self.verify)
                done = (response.status_code == 200
                        and response.text != last_startup)
            except TypeError:
                self.logger.debug("{0}: {1}".format(response.status_code,
                                                    response.text))
                pass
            except BadStatusLine:
                self.logger.debug("{0}: {1}".format(response.status_code,
                                                    response.text))
                pass
            except ProtocolError:
                self.logger.debug("{0}: {1}".format(response.status_code,
                                                    response.text))
                pass
            except ReadTimeoutError:
                self.logger.debug("ReadTimeoutError error...")
                pass
            except ReadTimeout:
                self.logger.debug("ReadTimeout error...")
                pass
            except ConnectionError:
                self.logger.debug("Connection error...")
                pass
            time.sleep(4)  # Sleep one more time even after success...
            count -= 1

            if count <= 0:
                raise UnexpectedManagementAPIResponse("Restart hung?")

        self.logger.debug("{0} restarted".format(self.host))
コード例 #14
0
    def _get_server_config(self):
        """
        Obtain the server configuration. This is the data necessary for
        the first part of the handshake necessary to join a host to a
        cluster. The returned data is not intended for introspection.

        :return: The config. This is always XML.
        """
        connection = Connection(self.host_name(), None)
        uri = "http://{0}:8001/admin/v1/server-config".format(connection.host)
        response = connection.get(uri, accept="application/xml")
        if response.status_code != 200:
            raise UnexpectedManagementAPIResponse(response.text)

        return response.text  # this is always XML
コード例 #15
0
    def list(cls, connection):
        uri = connection.uri("forests")
        response = connection.get(uri)

        if response.status_code == 200:
            response_json = json.loads(response.text)
            list_items = response_json['forest-default-list']['list-items']
            db_count = list_items['list-count']['value']

            result = []
            if db_count > 0:
                for item in list_items['list-item']:
                    result.append(item['nameref'])
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        return result
コード例 #16
0
    def generate_temporary_certificate(self,
                                       valid_for,
                                       common_name,
                                       dns_name,
                                       ip_addr,
                                       connection=None,
                                       if_necessary=True):
        """
        Attempts to generate a temporary certificate.

        If `if_necessary` is true, the server will only generate a new
        temporary certificate if it does not already have one for the
        specified server.

        :param valid_for: The number of days that the template should be valid.
        :param common_name: The common name for the certificate ("Example Corp")
        :param dns_name: The DNS name for the cert ("example.com")
        :param ip_addr: The IP address of the server
        :param if_necessary: Only generate the cert if it's necessary

        :return: The Template object.
        """
        if connection == None:
            connection = self.connection

        struct = {
            'operation': 'generate-temporary-certificate',
            'valid-for': assert_type(valid_for, int),
            'common-name': common_name,
            'dns-name': dns_name,
            'ip-addr': ip_addr,
            'if-necessary': 'true' if if_necessary else 'false'
        }

        uri = connection.uri("certificate-templates",
                             self.template_id(),
                             properties=None)
        response = connection.post(uri, payload=struct)

        if response.status_code != 201:
            raise UnexpectedManagementAPIResponse(response.text)

        return self
コード例 #17
0
    def _response(self):
        response = self.response

        if response.status_code < 300:
            pass
        elif response.status_code == 404:
            pass
        elif response.status_code == 401:
            raise UnauthorizedAPIRequest(response.text)
        else:
            raise UnexpectedManagementAPIResponse(response.text)

        if response.status_code == 202:
            data = json.loads(response.text)
            # restart isn't in data, for example, if you execute a shutdown
            if "restart" in data:
                self.wait_for_restart(
                    data["restart"]["last-startup"][0]["value"])

        return response
コード例 #18
0
    def _post_cluster_config(self, cfgzip, connection):
        """
        Send the cluster configuration to the the server that's joining
        the cluster. This is the second half of
        the handshake necessary to join a host to a cluster.

        :param connection: The connection credentials to use
        :param cfgzip: The ZIP payload from post_server_config()
        """
        uri = "{0}://{1}:8001/admin/v1/cluster-config" \
              .format(connection.protocol, connection.host)

        response = connection.post(uri,
                                   payload=cfgzip,
                                   content_type="application/zip")

        if response.status_code != 202:
            raise UnexpectedManagementAPIResponse(response.text)

        data = json.loads(response.text)
コード例 #19
0
    def delete(self, connection=None):
        """
        Remove the given amp.

        :param connection: The server connection

        :return: The amp object
        """
        if connection is None:
            connection = self.connection

        uri = connection.uri("amps",
                             self.local_name(),
                             properties=None,
                             parameters=self._params())

        response = connection.delete(uri)
        if response.status_code != 204:
            raise UnexpectedManagementAPIResponse(response.text)

        return self
コード例 #20
0
    def list(cls, connection, kind=None, include_actions=False):
        """
        List all the privilege names. Privilege names are structured values,
        they consist of a kind and a name separated by "|".

        If `include_actions` is true, the structured values consist of
        kind, name, and action separated by "|".

        :param connection: The connection to a MarkLogic server
        :return: A list of Privilege names.
        """

        uri = connection.uri("privileges")
        response = connection.get(uri)

        if response.status_code != 200:
            raise UnexpectedManagementAPIResponse(response.text)

        results = []
        json_doc = json.loads(response.text)

        for item in json_doc['privilege-default-list']['list-items'][
                'list-item']:
            if kind is None:
                if include_actions:
                    results.append("{0}|{1}|{2}".format(
                        item['kind'], item['nameref'], item['action']))
                else:
                    results.append("{0}|{1}".format(item['kind'],
                                                    item['nameref']))
            else:
                if item['kind'] == kind:
                    if include_actions:
                        results.append("{1}|{2}".format(
                            item['nameref'], item['action']))
                    else:
                        results.append(item['nameref'])

        return results
コード例 #21
0
    def update(self, connection=None):
        """
        Save the configuration changes with the given connection.

        :param connection:The server connection

        :return: The host object
        """
        if connection is None:
            connection = self.connection

        uri = connection.uri("tasks",
                             self.taskid,
                             parameters=["group-id=" + self.group])
        struct = self.marshal()
        response = connection.put(uri, payload=struct, etag=self.etag)
        if response.status_code != 204:
            raise UnexpectedManagementAPIResponse(response.text)

        if 'etag' in response.headers:
            self.etag = response.headers['etag']

        return self
コード例 #22
0
    def unmarshal(cls, config, connection=None, save_connection=True):
        result = Forest("temp",
                        connection=connection, save_connection=save_connection)
        result._config = config
        result.name = result._config['forest-name']

        logger = logging.getLogger("marklogic.forest")

        atomic = {'availability', 'data-directory',
                  'database-replication', 'enabled',
                  'failover-enable', 'fast-data-directory', 'fast-data-max-size',
                  'forest-name', 'host', 'large-data-directory',
                  'range', 'rebalancer-enable', 'updates-allowed',
                  'database'
                 }

        for key in result._config:
            olist = []

            if key in atomic:
                pass
            elif key == 'forest-backup':
                for backup in result._config['forest-backup']:
                    #logger.debug(backup)
                    temp = None
                    if backup['backup-type'] == 'minutely':
                        temp = ScheduledForestBackup.minutely(
                            backup['backup-directory'],
                            backup['backup-period'])
                    elif backup['backup-type'] == 'hourly':
                        minute = int(backup['backup-start-time'].split(':')[1])
                        temp = ScheduledForestBackup.hourly(
                            backup['backup-directory'],
                            backup['backup-period'],
                            minute)
                    elif backup['backup-type'] == 'daily':
                        temp = ScheduledForestBackup.daily(
                            backup['backup-directory'],
                            backup['backup-period'],
                            backup['backup-start-time'])
                    elif backup['backup-type'] == 'weekly':
                        temp = ScheduledForestBackup.weekly(
                            backup['backup-directory'],
                            backup['backup-period'],
                            backup['backup-day'],
                            backup['backup-start-time'])
                    elif backup['backup-type'] == 'monthly':
                        temp = ScheduledForestBackup.monthly(
                            backup['backup-directory'],
                            backup['backup-period'],
                            backup['backup-month-day'],
                            backup['backup-start-time'])
                    elif backup['backup-type'] == 'once':
                        temp = ScheduledForestBackup.once(
                            backup['backup-directory'],
                            backup['backup-start-date'],
                            backup['backup-start-time'])
                    else:
                        raise UnexpectedManagementAPIResponse("Unparseable backup")
                    temp._config['backup-id'] = backup['backup-id']
                    olist.append(temp)
                result._config['forest-backup'] = olist
            elif key == 'forest-replica':
                for rep in result._config['forest-replica']:
                    temp = ForestReplica(rep['replica-name'], rep['host'],
                                         rep['data-directory'],
                                         rep['large-data-directory'],
                                         rep['fast-data-directory'])
                    olist.append(temp)
                result._config['forest-replica'] = olist
            else:
                logger.warning("Unexpected forest property: " + key)

        return result