diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..66bf88a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,17 @@ +#### Additional Information +(The following information is very important in order to help us to help you. Omission of the following details may delay your support request or receive no attention at all.) + +- Version of k2hdkc_dbaas (commit hash) + ``` + ``` + +- System information (uname -a) + ``` + ``` + +- Distro (cat /etc/issue) + ``` + ``` + +#### Details about issue + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..40f1ac1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +## Relevant Issue (if applicable) +(If there are Issues related to this PullRequest, please list it.) + +## Details +(Please describe the details of PullRequest.) diff --git a/.gitignore b/.gitignore index eca14dc..61d4188 100644 --- a/.gitignore +++ b/.gitignore @@ -33,8 +33,6 @@ # # Logs # -log -logs *.log # @@ -60,6 +58,7 @@ id_rsa # Local file according to the environment # # ex) .custom +custom_internal_* # # Local variables: diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..c49127f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +1. Takeshi Nakatani + +Develops and wrote from scratch the initial version. + +2. Hirotaka Wakabayashi + +Develops and wrote from scratch the initial version. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..07c5750 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,5 @@ +k2hdkc-dbaas (1.0.0) unstable; urgency=low + + * First version of open sorce on Github + + -- Takeshi Nakatani Fri, 09 Oct 2020 12:17:49 +0900 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..40f0f8f --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Yahoo Japan Corporation + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..aaaf1b9 --- /dev/null +++ b/README.md @@ -0,0 +1,70 @@ +K2HDKC DBaaS +----- +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/yahoojapan/k2hdkc_dbaas/master/LICENSE) +[![GitHub forks](https://img.shields.io/github/forks/yahoojapan/k2hdkc_dbaas.svg)](https://github.com/yahoojapan/k2hdkc_dbaas/network) +[![GitHub stars](https://img.shields.io/github/stars/yahoojapan/k2hdkc_dbaas.svg)](https://github.com/yahoojapan/k2hdkc_dbaas/stargazers) +[![GitHub issues](https://img.shields.io/github/issues/yahoojapan/k2hdkc_dbaas.svg)](https://github.com/yahoojapan/k2hdkc_dbaas/issues) + +## **K2HDKC** **DBaaS** based on **Trove** +![K2HDKC DBaaS](https://dbaas.k2hdkc.antpick.ax/images/top_k2hdkc_dbaas.png) + +## Overview +**K2HDKC DBaaS** (Database as a Service for K2HDKC) is a **Database as a Service** that is provided by [Trove(Trove is Database as a Service for OpenStack)](https://wiki.openstack.org/wiki/Trove) which incorporates [K2HDKC(K2Hash based Distributed Kvs Cluster)](https://k2hdkc.antpick.ax/index.html) as one of the Database. +K2HDKC DBaaS works with OpenStack components to provide Database as a Service functionality. + +Users can easily launch, scale, backup, and restore K2HDKC clusters through the Trove Dashboard(GUI) and through the CLI provided by Trove(openstack CLI). + +Detailed documentation for K2HDKC DBaaS can be found [here](https://dbaas.k2hdkc.antpick.ax/). + +## K2HKDC DBaaS system +K2HDKC DBaaS provides its functionality through Trove as a panel(feature) of OpenStack. +And the [K2HR3](https://k2hr3.antpick.ax/) system is used as the back end as an RBAC(Role Base Access Control) system dedicated to K2HDKC DBaaS. +Normally, users do not need to use the K2HR3 system directly, and the function as DBaaS uses Trove Dashboard(or Trove CLI). + +The overall system overview diagram is shown below. +![K2HDKC DBaaS system](https://dbaas.k2hdkc.antpick.ax/images/overview.png) + +## Trial +For the K2HDKC DBaaS experience, you can build a minimum K2HDKC DBaaS system. +This minimum system has all the features of K2HDKC DBaaS. +So you can use it to try out all the features provided by K2HDKC DBaaS. + +This minimum system(trial environment) is very easy to build by simply running the script provided by this repository. +For how to use it, refer to the [Build document](https://dbaas.k2hdkc.antpick.ax/build.html). + +## Usage +See [Usage document](https://dbaas.k2hdkc.antpick.ax/usage.html) for the features provided by K2HDKC DBaaS and how to use them. +This document describes all usage, including how to use K2HDKC DBaaS to create a K2HDKC cluster, how to launch a K2HDKC slave node, and more. + +Let's get started. + +## Documents +[K2HDKC DBaaS Document](https://dbaas.k2hdkc.antpick.ax/index.html) +[Github wiki page](https://github.com/yahoojapan/k2hdkc_dbaas/wiki) + +[About k2hdkc Document](https://k2hdkc.antpick.ax/index.html) +[About chmpx Document](https://chmpx.antpick.ax/index.html) +[About k2hr3 Document](https://k2hr3.antpick.ax/index.html) + +[About AntPickax](https://antpick.ax/) + +## Repositories +[k2hdkc](https://github.com/yahoojapan/k2hdkc) +[chmpx](https://github.com/yahoojapan/chmpx) +[k2hr3](https://github.com/yahoojapan/k2hr3) +[k2hr3_app](https://github.com/yahoojapan/k2hr3_app) +[k2hr3_api](https://github.com/yahoojapan/k2hr3_api) + +## Packages +[k2hdkc(packagecloud.io)](https://packagecloud.io/app/antpickax/stable/search?q=k2hdkc) +[chmpx(packagecloud.io)](https://packagecloud.io/app/antpickax/stable/search?q=chmpx) +[k2hr3-app(npm packages)](https://www.npmjs.com/package/k2hr3-app) +[k2hr3-api(npm packages)](https://www.npmjs.com/package/k2hr3-api) + +### License +This software is released under the 2.0 version of the Apache License, see the license file. + +### AntPickax +K2HDKC DBaaS is one of [AntPickax](https://antpick.ax/) products. + +Copyright(C) 2020 Yahoo Japan Corporation. diff --git a/devstack/common/strategies/cluster/experimental/k2hdkc/__init__.py b/devstack/common/strategies/cluster/experimental/k2hdkc/__init__.py new file mode 100644 index 0000000..5639d53 --- /dev/null +++ b/devstack/common/strategies/cluster/experimental/k2hdkc/__init__.py @@ -0,0 +1,27 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/devstack/common/strategies/cluster/experimental/k2hdkc/api.py b/devstack/common/strategies/cluster/experimental/k2hdkc/api.py new file mode 100644 index 0000000..878f476 --- /dev/null +++ b/devstack/common/strategies/cluster/experimental/k2hdkc/api.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# +"""OpenStack Trove for K2HDKC.""" + +from oslo_log import log as logging +from trove.cluster import models +from trove.cluster.tasks import ClusterTasks +from trove.cluster.views import ClusterView +from trove.common import cfg +from trove.common import exception +from trove.common import server_group as srv_grp +from trove.common import utils +from trove.common.strategies.cluster import base +from trove.extensions.mgmt.clusters.views import MgmtClusterView +from trove.instance import models as inst_models +from trove.quota.quota import check_quotas +from trove.taskmanager import api as task_api + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +class K2hdkcAPIStrategy(base.BaseAPIStrategy): + """OpenStack Clusters API endpoint implementation.""" + + @property + def cluster_class(self): + """Implement BaseAPIStrategy.cluster_class.""" + LOG.debug("cluster_class") + return K2hdkcCluster + + @property + def cluster_controller_actions(self): + """Implement BaseAPIStrategy.cluster_controller_actions.""" + LOG.debug("cluster_controller_actions") + return { + 'grow': self._action_grow_cluster, + 'shrink': self._action_shrink_cluster + } + + def _action_grow_cluster(self, cluster, body): # pylint: disable=no-self-use + """Grow cluster.""" + LOG.debug("_action_grow_cluster cluster={} body={}" + .format(cluster, body)) + nodes = body['grow'] + instances = [] + for node in nodes: + instance = {'flavor_id': utils.get_id_from_href(node['flavorRef'])} + if 'name' in node: + instance['name'] = node['name'] + if 'volume' in node: + instance['volume_size'] = int(node['volume']['size']) + instances.append(instance) + return cluster.grow(instances) + + def _action_shrink_cluster(self, cluster, body): # pylint: disable=no-self-use + """Shrink cluster.""" + LOG.debug("_action_shrink_cluster cluster={} body={}".format( + cluster, body)) + nodes = body['shrink'] + instance_ids = [node['id'] for node in nodes] + return cluster.shrink(instance_ids) + + @property + def cluster_view_class(self): + """Implement BaseAPIStrategy.cluster_view_class.""" + return K2hdkcClusterView + + @property + def mgmt_cluster_view_class(self): + """Implement. BaseAPIStrategy.mgmt_cluster_view_class.""" + return K2hdkcMgmtClusterView + + +class K2hdkcCluster(models.Cluster): + """Create K2hdkc Cluster data to Trove DB and OpenStack services.""" + + @staticmethod + def _create_insts(context, cluster_id, cluster_name, datastore, + datastore_version, instances, locality, configuration_id + ): # pylint: disable=too-many-arguments, too-many-locals + + # 1. Check quotas + num = len(instances) + manager_conf = CONF.get(datastore_version.manager) + total_volume_allocation = models.get_required_volume_size( + instances, manager_conf.volume_support) + quota_request = {'instances': num, 'volumes': total_volume_allocation} + check_quotas(context.project_id, quota_request) + + # 2. Name new instances + alls = inst_models.DBInstance.find_all(cluster_id=cluster_id).all() + index = 1 + if alls: + index += len(alls) + + # 3. Create instances + new_insts = [] + member_config = {"id": cluster_id, "instance_type": "member"} + for instance in instances: + if not instance.get('name'): + instance['name'] = "%s-member-%s" % (cluster_name, index) + index += 1 + instance_name = instance.get('name') + instance_az = instance.get('availability_zone', None) + LOG.debug("new instance_name=%s instance_az=%s", instance_name, + instance_az) + new_inst = inst_models.Instance.create( + context, + instance_name, + instance['flavor_id'], + datastore_version.image_id, [], [], + datastore, + datastore_version, + instance['volume_size'], + None, + nics=instance.get('nics', None), + availability_zone=instance_az, + configuration_id=configuration_id, + cluster_config=member_config, + volume_type=instance.get('volume_type', None), + modules=instance.get('modules'), + locality=locality, + region_name=instance.get('region_name')) + new_insts.append(new_inst) + return new_insts + + @classmethod + def create(cls, context, name, datastore, datastore_version, instances, + extended_properties, locality, configuration + ): # pylint: disable=too-many-arguments, too-many-locals + """Create Clusters API endpoint. + + main function to create a cluster is here + https://github.com/openstack/trove/blob/master/trove/cluster/service.py#L162-L234 + """ + + # 1. validates args + if context is None: + LOG.error("no context") + return None + if name is None: + LOG.error("no name") + return None + if datastore is None: + LOG.error("no datastore") + return None + if datastore_version is None: + LOG.error("no datastore_version") + return None + if instances is None: + LOG.error("no instances") + return None + models.assert_homogeneous_cluster(instances) + manager_conf = CONF.get(datastore_version.manager) + models.validate_instance_flavors(context, instances, + manager_conf.volume_support, + manager_conf.device_path) + models.validate_instance_nics(context, instances) + + # 2. Insert a cluster data to clusters table + db_info = models.DBCluster.create( + name=name, + tenant_id=context.project_id, + datastore_version_id=datastore_version.id, + configuration_id=configuration, + task_status=ClusterTasks.BUILDING_INITIAL) + + # 3. Create instances in OpenStack + cls._create_insts(context, db_info.id, db_info.name, datastore, + datastore_version, instances, locality, + configuration) + + # 4. Calling taskmanager to further proceed for cluster-configuration + LOG.debug( + "Calling taskmanager to further proceed for " + "cluster-configuration of %s", db_info.id) + task_api.load(context, + datastore_version.manager).create_cluster(db_info.id) + + # 5. Returns cluster instance to render HTTP response. + return K2hdkcCluster(context, db_info, datastore, datastore_version) + + def grow(self, instances): + """Grow Cluster API endpoint. + + main function to grow a cluster is here. + https://github.com/openstack/trove/blob/master/trove/cluster/service.py#L60-L86 + https://github.com/openstack/trove/blob/master/trove/cluster/models.py#L305 + """ + LOG.debug("Growing cluster. %s", "{}".format(instances)) + + # 1. validates args + if not instances: + LOG.error("no instances") + return False + models.assert_homogeneous_cluster(instances) + manager_conf = CONF.get(self.datastore_version.manager) + models.validate_instance_flavors(self.context, instances, + manager_conf.volume_support, + manager_conf.device_path) + self.validate_cluster_available() + + # 2. updates the cluster status + self.db_info.update(task_status=ClusterTasks.GROWING_CLUSTER) + + # 3. creates new instances by using self._create_insts + locality = srv_grp.ServerGroup.convert_to_hint(self.server_group) + new_insts = self._create_insts(self.context, self.db_info.id, + self.db_info.name, self.ds, + self.ds_version, instances, + locality, self.db_info.configuration_id) + # 4. calls the taskmanager's grow_cluster endpoint + task_api.load(self.context, self.ds_version.manager).grow_cluster( + self.db_info.id, [instance.id for instance in new_insts]) + + return True + + def shrink(self, removal_ids): # pylint: disable=arguments-differ + """Shrink Cluster API endpoint. + + main function to shrink a cluster is here. + https://github.com/openstack/trove/blob/master/trove/cluster/service.py#L60-L86 + https://github.com/openstack/trove/blob/master/trove/cluster/models.py#L305 + """ + LOG.debug("Shrinking cluster {} {}".format(self.id, removal_ids)) + + # 1. validates args + if not removal_ids: + LOG.error("no removal_ids") + return False + self.validate_cluster_available() + + # 2. updates the cluster status + self.db_info.update(task_status=ClusterTasks.SHRINKING_CLUSTER) + + # 3. calls the taskmanager's grow_cluster endpoint + task_api.load(self.context, self.ds_version.manager).shrink_cluster( + self.db_info.id, removal_ids) + + return True + + def upgrade(self, datastore_version): # pylint: disable=no-self-use + """Return the source code for the definition.""" + LOG.debug("Upgrading cluster %s", datastore_version) + if not datastore_version: + LOG.error("no datastore_version") + return False + raise exception.BadRequest("Action 'upgrade' not supported") + + +class K2hdkcClusterView(ClusterView): # pylint: disable=too-few-public-methods + """K2hdkcClusterView class.""" + + def build_instances(self): + """Build instances.""" + return self._build_instances(['member'], ['member']) + + +class K2hdkcMgmtClusterView(MgmtClusterView): # pylint: disable=too-few-public-methods + """K2hdkcMgmtClusterView class.""" + + def build_instances(self): + """Build instances.""" + return self._build_instances(['member'], ['member']) +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/devstack/common/strategies/cluster/experimental/k2hdkc/guestagent.py b/devstack/common/strategies/cluster/experimental/k2hdkc/guestagent.py new file mode 100644 index 0000000..cc233e7 --- /dev/null +++ b/devstack/common/strategies/cluster/experimental/k2hdkc/guestagent.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# +"""OpenStack Clusters API guestagent client implementation.""" + +from oslo_log import log as logging +from trove.common import cfg +from trove.common import exception +from trove.common.strategies.cluster import base +from trove.guestagent import api as guest_api + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +class K2hdkcGuestAgentStrategy(base.BaseGuestAgentStrategy): # pylint: disable=too-few-public-methods + """OpenStack Clusters API guest-agent client implementation.""" + + @property + def guest_client_class(self): + """Return Clusters API guest-agent client implementation.""" + return K2hdkcGuestAgentAPI + + +class K2hdkcGuestAgentAPI(guest_api.API): # pylint: disable=too-few-public-methods + """OpenStack Clusters API guest-agent client implementation.""" + + def cluster_complete(self): + """Execute syncronously RPC cluster_complete command.""" + LOG.debug("Execute syncronously RPC cluster_complete command.") + try: + version = guest_api.API.API_BASE_VERSION + # cluster_complete endpoint is required on GuestAgent + return self._call("cluster_complete", self.agent_high_timeout, + version=version) + except (exception.GuestError, exception.GuestTimeout) as rpc_exception: + LOG.error("exception {}".format(rpc_exception)) + raise + except Exception: + LOG.error("unknown exception") + raise + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/devstack/common/strategies/cluster/experimental/k2hdkc/taskmanager.py b/devstack/common/strategies/cluster/experimental/k2hdkc/taskmanager.py new file mode 100644 index 0000000..b702e40 --- /dev/null +++ b/devstack/common/strategies/cluster/experimental/k2hdkc/taskmanager.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# +"""OpenStack Clusters API taskmanager implementation.""" + +from eventlet.timeout import Timeout +from oslo_log import log as logging +import trove.taskmanager.models as task_models +from trove.common import cfg +from trove.common.exception import GuestError, GuestTimeout +from trove.common.strategies.cluster import base +from trove.instance import tasks as inst_tasks +from trove.instance.models import DBInstance +from trove.instance.models import Instance +from trove.taskmanager import api as task_api + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +class K2hdkcTaskManagerStrategy(base.BaseTaskManagerStrategy): + """OpenStack Clusters API taskmanager implementation.""" + + @property + def task_manager_api_class(self): # pylint: disable=arguments-differ + """Implement BaseTaskManagerStrategy.task_manager_api_class.""" + return K2hdkcTaskManagerAPI + + @property + def task_manager_cluster_tasks_class(self): # pylint: disable=arguments-differ + """Implement BaseTaskManagerStrategy.task_manager_tasks_class.""" + return K2hdkcClusterTasks + + +class K2hdkcClusterTasks(task_models.ClusterTasks): + """Create Clusters API taskmanager endpoint.""" + + def create_cluster(self, context, cluster_id): + """Create K2hdkcClusterTasks. + + This function is called in trove.taskmanager.Manager.create_cluster. + """ + + LOG.debug("Begins create_cluster for %s.", cluster_id) + + # 1. validates args + if context is None: + LOG.error("no context") + return + if cluster_id is None: + LOG.error("no cluster_id") + return + + timeout = Timeout(CONF.cluster_usage_timeout) + LOG.debug("CONF.cluster_usage_timeout %s.", timeout) + try: + # 2. Retrieves db_instances from the database + db_instances = DBInstance.find_all(cluster_id=cluster_id, + deleted=False).all() + # 3. Retrieves instance ids from the db_instances + instance_ids = [db_instance.id for db_instance in db_instances] + # 4. Checks if instances are ready + if not self._all_instances_running(instance_ids, cluster_id): + LOG.error("instances are not ready yet") + return + # 5. Loads instances + instances = [ + Instance.load(context, instance_id) + for instance_id in instance_ids + ] + # 6. Instantiates GuestAgent for each guest instance + # 7. Calls cluster_complete endpoint of K2hdkcGuestAgent + for instance in instances: + self.get_guest(instance).cluster_complete() + # 8. reset the current cluster task status to None + LOG.debug("reset cluster task to None") + self.reset_task() + except Timeout: + # Note adminstrators should reset task via CLI in this case. + if Timeout is not timeout: + raise # not my timeout + LOG.exception("Timeout for building cluster.") + self.update_statuses_on_failure(cluster_id) + finally: + timeout.cancel() + + LOG.debug("Completed create_cluster for %s.", cluster_id) + + def grow_cluster(self, context, cluster_id, new_instance_ids): + """Grow a K2hdkc Cluster.""" + LOG.debug("Begins grow_cluster for %s. new_instance_ids:{}" + .format(new_instance_ids), cluster_id) + + # 1. validates args + if context is None: + LOG.error("no context") + return + if cluster_id is None: + LOG.error("no cluster_id") + return + if new_instance_ids is None: + LOG.error("no new_instance_ids") + return + + timeout = Timeout(CONF.cluster_usage_timeout) + try: + # 2. Retrieves db_instances from the database + db_instances = DBInstance.find_all(cluster_id=cluster_id, + deleted=False).all() + LOG.debug("len(db_instances) {}".format(len(db_instances))) + # 3. Checks if new instances are ready + if not self._all_instances_running(new_instance_ids, cluster_id): + LOG.error("instances are not ready yet") + return + # 4. Loads instances + instances = [ + Instance.load(context, instance_id) + for instance_id in new_instance_ids + ] + LOG.debug("len(instances) {}".format(len(instances))) + + # 5. Instances GuestAgent class + # 6. Calls cluster_complete endpoint of K2hdkcGuestAgent + LOG.debug("Calling cluster_complete as a final hook to each node in the cluster") + for instance in instances: + self.get_guest(instance).cluster_complete() + # 7. reset the current cluster task status to None + LOG.debug("reset cluster task to None") + self.reset_task() + except Timeout: + # Note adminstrators should reset task via CLI in this case. + if Timeout is not timeout: + raise # not my timeout + LOG.exception("Timeout for growing cluster.") + self.update_statuses_on_failure( + cluster_id, status=inst_tasks.InstanceTasks.GROWING_ERROR) + finally: + timeout.cancel() + + LOG.debug("Completed grow_cluster for %s.", cluster_id) + + def shrink_cluster(self, context, cluster_id, removal_ids): + """Shrink a K2hdkc Cluster.""" + LOG.debug("Begins shrink_cluster for %s. removal_ids:{}" + .format(removal_ids), cluster_id) + + # 1. validates args + if context is None: + LOG.error("no context") + return + if cluster_id is None: + LOG.error("no cluster_id") + return + if removal_ids is None: + LOG.error("no removal_ids") + return + + timeout = Timeout(CONF.cluster_usage_timeout) + try: + # 2. Retrieves db_instances from the database + db_instances = DBInstance.find_all(cluster_id=cluster_id, + deleted=False).all() + # 3. Retrieves instance ids from the db_instances + instance_ids = [db_instance.id for db_instance in db_instances] + # 4. Checks if instances are running + if not self._all_instances_running(instance_ids, cluster_id): + LOG.error("instances are not ready yet") + return + # 4. Loads instances + instances = [ + Instance.load(context, instance_id) + for instance_id in removal_ids + ] + LOG.debug("len(instances) {}".format(len(instances))) + + # 5. Instances GuestAgent class + # 6.2. Checks if removing instances are + # if not self._all_instances_shutdown(removal_ids, cluster_id): + # LOG.error("removing instances are not shutdown yet") + # return + # 7. Calls cluster_complete endpoint of K2hdkcGuestAgent + LOG.debug("Calling cluster_complete as a final hook to each node in the cluster") + for instance in instances: + self.get_guest(instance).cluster_complete() + # 8. delete node from OpenStack + LOG.debug("delete node from OpenStack") + for instance in instances: + Instance.delete(instance) + # 9. reset the current cluster task status to None + LOG.debug("reset cluster task to None") + self.reset_task() + except Timeout: + # Note adminstrators should reset task via CLI in this case. + if Timeout is not timeout: + raise # not my timeout + LOG.exception("Timeout for shrink cluster.") + self.update_statuses_on_failure( + cluster_id, status=inst_tasks.InstanceTasks.SHRINKING_ERROR) + finally: + timeout.cancel() + + LOG.debug("Completed shrink_cluster for %s.", cluster_id) + + +class K2hdkcTaskManagerAPI(task_api.API): # pylint: disable=too-few-public-methods + """OpenStack Clusters API taskmanager API class implementation.""" + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/devstack/patches/etc-trove-trove.conf b/devstack/patches/etc-trove-trove.conf new file mode 100644 index 0000000..6593065 --- /dev/null +++ b/devstack/patches/etc-trove-trove.conf @@ -0,0 +1,33 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /etc/trove/trove.conf 2020-05-14 01:35:21.189626000 +0000 +--- trove.conf 2020-05-14 08:27:24.575853312 +0000 +*************** +*** 55,60 **** +--- 55,63 ---- + [db2] + tcp_ports = 50000 + ++ [k2hdkc] ++ tcp_ports = 8020,8021,8031 ++ + [mariadb] + tcp_ports = 3306,4444,4567,4568 + diff --git a/devstack/patches/trove-common-cfg.py b/devstack/patches/trove-common-cfg.py new file mode 100644 index 0000000..17c8bc8 --- /dev/null +++ b/devstack/patches/trove-common-cfg.py @@ -0,0 +1,160 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** cfg.py.orig 2020-07-07 06:01:09.406819592 +0900 +--- cfg.py 2020-07-07 06:03:31.937204382 +0900 +*************** +*** 370,376 **** + 'couchdb': 'f0a9ab7b-66f7-4352-93d7-071521d44c7c', + 'vertica': 'a8d805ae-a3b2-c4fd-gb23-b62cee5201ae', + 'db2': 'e040cd37-263d-4869-aaa6-c62aa97523b5', +! 'mariadb': '7a4f82cc-10d2-4bc6-aadc-d9aacc2a3cb5'}, + help='Unique ID to tag notification events.'), + cfg.StrOpt('network_label_regex', default='^private$', + help='Regular expression to match Trove network labels.'), +--- 370,377 ---- + 'couchdb': 'f0a9ab7b-66f7-4352-93d7-071521d44c7c', + 'vertica': 'a8d805ae-a3b2-c4fd-gb23-b62cee5201ae', + 'db2': 'e040cd37-263d-4869-aaa6-c62aa97523b5', +! 'mariadb': '7a4f82cc-10d2-4bc6-aadc-d9aacc2a3cb5', +! 'k2hdkc': '07e220a2-a8c6-4061-b9a6-a654b2f5fc2e'}, + help='Unique ID to tag notification events.'), + cfg.StrOpt('network_label_regex', default='^private$', + help='Regular expression to match Trove network labels.'), +*************** +*** 1517,1525 **** +--- 1518,1615 ---- + 'logic.'), + cfg.IntOpt('default_password_length', + default='${mysql.default_password_length}', ++ help='Character length of generted passwords.', ++ deprecated_name='default_password_length', ++ deprecated_group='DEFAULT'), ++ ] ++ ++ # K2hdkc ++ k2hdkc_group = cfg.OptGroup( ++ 'k2hdkc', title='K2HDKC options', ++ help="Oslo option group designed for K2hdkc datastore") ++ k2hdkc_opts = [ ++ cfg.BoolOpt('icmp', default=False, ++ help='Whether to permit ICMP.', ++ deprecated_for_removal=True), ++ cfg.ListOpt('tcp_ports', default=["8020", "8021", "8031"], ++ item_type=ListOfPortsType, ++ help='List of TCP ports and/or port ranges to open ' ++ 'in the security group (only applicable ' ++ 'if trove_security_groups_support is True).'), ++ cfg.ListOpt('udp_ports', default=[], item_type=ListOfPortsType, ++ help='List of UDP ports and/or port ranges to open ' ++ 'in the security group (only applicable ' ++ 'if trove_security_groups_support is True).'), ++ cfg.StrOpt('mount_point', default='/var/lib/k2hdkc', ++ help="Filesystem path for mounting " ++ "volumes if volume support is enabled."), ++ cfg.BoolOpt('root_on_create', default=False, ++ help='Enable the automatic creation of the root user for the ' ++ 'service during instance-create. The generated password for ' ++ 'the root user is immediately returned in the response of ' ++ "instance-create as the 'password' field."), ++ cfg.IntOpt('ctrl_port', default=8021, ++ help='Control Port to connet with chmpx process.'), ++ cfg.IntOpt('usage_timeout', default=400, ++ help='Maximum time (in seconds) to wait for a Guest to become ' ++ 'active.'), ++ cfg.BoolOpt('volume_support', default=True, ++ help='Whether to provision a Cinder volume for datadir.'), ++ cfg.StrOpt('device_path', default='/dev/vdb', ++ help='Device path for volume if volume support is enabled.'), ++ cfg.StrOpt('root_controller', ++ default='trove.extensions.common.service.DefaultRootController', ++ help='Root controller implementation for k2hdkc.'), ++ cfg.ListOpt('ignore_users', default=['os_admin', 'root'], ++ help='Users to exclude when listing users.', ++ deprecated_name='ignore_users', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('api_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.api.K2hdkcAPIStrategy', ++ help='Class that implements datastore-specific API logic.'), ++ cfg.StrOpt('taskmanager_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.taskmanager.K2hdkcTaskManagerStrategy', ++ help='Class that implements datastore-specific task manager logic.'), ++ cfg.StrOpt('guestagent_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.guestagent.K2hdkcGuestAgentStrategy', ++ help='Class that implements datastore-specific Guest Agent API logic.'), ++ cfg.BoolOpt('cluster_support', default=True, ++ help='Enable clusters to be created and managed.'), ++ cfg.IntOpt('min_cluster_member_count', default=3, ++ help='Minimum number of members in K2hdkc cluster.'), ++ cfg.IntOpt('default_password_length', ++ default='${mysql.default_password_length}', + help='Character length of generated passwords.', + deprecated_name='default_password_length', + deprecated_group='DEFAULT'), ++ ++ cfg.StrOpt('backup_strategy', default='K2hdkcArchive', ++ help='Default strategy to perform backups.', ++ deprecated_name='backup_strategy', ++ deprecated_group='DEFAULT'), ++ cfg.DictOpt('backup_incremental_strategy', default={}, ++ help='Incremental Backup Runner based on the default ' ++ 'strategy. For strategies that do not implement an ' ++ 'incremental, the runner will use the default full backup.', ++ deprecated_name='backup_incremental_strategy', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('backup_namespace', ++ default="trove.guestagent.strategies.backup.experimental." ++ "k2hdkc_impl", ++ help='Namespace to load backup strategies from.', ++ deprecated_name='backup_namespace', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('restore_namespace', ++ default='trove.guestagent.strategies.restore.experimental.' ++ 'k2hdkc_impl', ++ help='Namespace to load restore strategies from.', ++ deprecated_name='restore_namespace', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('replication_strategy', default=None, ++ help='Default strategy for replication.'), ++ cfg.StrOpt('replication_namespace', default=None, ++ help='Namespace to load replication strategies from.'), ++ + ] + + # RPC version groups +*************** +*** 1615,1620 **** +--- 1705,1711 ---- + CONF.register_group(vertica_group) + CONF.register_group(db2_group) + CONF.register_group(mariadb_group) ++ CONF.register_group(k2hdkc_group) + CONF.register_group(network_group) + CONF.register_group(service_credentials_group) + +*************** +*** 1630,1635 **** +--- 1721,1727 ---- + CONF.register_opts(vertica_opts, vertica_group) + CONF.register_opts(db2_opts, db2_group) + CONF.register_opts(mariadb_opts, mariadb_group) ++ CONF.register_opts(k2hdkc_opts, k2hdkc_group) + CONF.register_opts(network_opts, network_group) + CONF.register_opts(service_credentials_opts, service_credentials_group) + diff --git a/devstack/patches/trove-common-configurations.py b/devstack/patches/trove-common-configurations.py new file mode 100644 index 0000000..ddfd2d6 --- /dev/null +++ b/devstack/patches/trove-common-configurations.py @@ -0,0 +1,37 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /opt/stack/trove/trove/common/configurations.py 2020-06-09 16:18:00.762190008 +0900 +--- configurations.py 2020-06-11 13:28:21.189458201 +0900 +*************** +*** 95,97 **** +--- 95,107 ---- + + def parse(self): + return self.CODEC.deserialize(self.config).items() ++ ++ class K2hdkcConfParser(object): ++ ++ CODEC = stream_codecs.KeyValueCodec(delimiter='=', comment_marker='#', line_terminator='\n') ++ ++ def __init__(self, config): ++ self.config = config ++ ++ def parse(self): ++ return self.CODEC.deserialize(self.config).items() diff --git a/devstack/patches/trove-common-template.py b/devstack/patches/trove-common-template.py new file mode 100644 index 0000000..331048f --- /dev/null +++ b/devstack/patches/trove-common-template.py @@ -0,0 +1,31 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /opt/stack/trove/trove/common/template.py 2020-06-09 16:18:00.770190167 +0900 +--- template.py 2020-06-11 13:28:27.540584594 +0900 +*************** +*** 38,43 **** +--- 38,44 ---- + 'redis': configurations.RedisConfParser, + 'vertica': configurations.VerticaConfParser, + 'db2': configurations.DB2ConfParser, ++ 'k2hdkc': configurations.K2hdkcConfParser, + } + + diff --git a/devstack/patches/trove-db-sqlalchemy-migrate_repo-versions-020_configurations.py b/devstack/patches/trove-db-sqlalchemy-migrate_repo-versions-020_configurations.py new file mode 100644 index 0000000..2a291f1 --- /dev/null +++ b/devstack/patches/trove-db-sqlalchemy-migrate_repo-versions-020_configurations.py @@ -0,0 +1,38 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /opt/stack/trove/trove/db/sqlalchemy/migrate_repo/versions/020_configurations.py 2020-06-09 16:18:00.773190227 +0900 +--- 020_configurations.py 2020-06-11 11:16:37.957435544 +0900 +*************** +*** 44,50 **** + Column('configuration_id', String(36), ForeignKey("configurations.id"), + nullable=False, primary_key=True), + Column('configuration_key', String(128), nullable=False, primary_key=True), +! Column('configuration_value', String(128)), + Column('deleted', Boolean(), nullable=False, default=False), + Column('deleted_at', DateTime()), + ) +--- 44,50 ---- + Column('configuration_id', String(36), ForeignKey("configurations.id"), + nullable=False, primary_key=True), + Column('configuration_key', String(128), nullable=False, primary_key=True), +! Column('configuration_value', String(512)), + Column('deleted', Boolean(), nullable=False, default=False), + Column('deleted_at', DateTime()), + ) diff --git a/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-04-baseline-tools.patch b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-04-baseline-tools.patch new file mode 100644 index 0000000..215e2a5 --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-04-baseline-tools.patch @@ -0,0 +1,35 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff -rc /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/pre-install.d/04-baseline-tools /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/pre-install.d/04-baseline-tools +*** /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/pre-install.d/04-baseline-tools 2020-09-13 07:06:08.851039227 +0900 +--- /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/pre-install.d/04-baseline-tools 2020-09-13 12:19:05.523637974 +0900 +*************** +*** 4,7 **** + set -e + set -o xtrace + +! apt-get --allow-unauthenticated install -y language-pack-en python-software-properties software-properties-common +\ No newline at end of file +--- 4,7 ---- + set -e + set -o xtrace + +! #apt-get --allow-unauthenticated install -y language-pack-en python-software-properties software-properties-common + diff --git a/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-05-base-apps.patch b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-05-base-apps.patch new file mode 100644 index 0000000..52db49b --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-05-base-apps.patch @@ -0,0 +1,35 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff -rc /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/05-base-apps /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/05-base-apps +*** /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/05-base-apps 2020-09-13 07:06:08.851039227 +0900 +--- /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/05-base-apps 2020-09-13 12:14:12.939799696 +0900 +*************** +*** 6,10 **** + set -e + set -o xtrace + +! export DEBIAN_FRONTEND=noninteractive +! apt-get --allow-unauthenticated -y install ntp apparmor-utils +--- 6,10 ---- + set -e + set -o xtrace + +! #export DEBIAN_FRONTEND=noninteractive +! #apt-get --allow-unauthenticated -y install ntp apparmor-utils diff --git a/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-98-ssh.patch b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-98-ssh.patch new file mode 100644 index 0000000..3af036c --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-98-ssh.patch @@ -0,0 +1,34 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff -rc /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/98-ssh /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/98-ssh +*** /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/98-ssh 2020-09-13 07:06:08.851039227 +0900 +--- /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/98-ssh 2020-09-13 12:16:16.378262786 +0900 +*************** +*** 5,8 **** + set -e + set -o xtrace + +! dpkg-reconfigure openssh-server +--- 5,8 ---- + set -e + set -o xtrace + +! #dpkg-reconfigure openssh-server + diff --git a/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-99-clean-apt.patch b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-99-clean-apt.patch new file mode 100644 index 0000000..2dbc3f5 --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-centos-8-guest-99-clean-apt.patch @@ -0,0 +1,36 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff -rc /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/99-clean-apt /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/99-clean-apt +*** /opt/stack/trove/integration/scripts/files/elements/ubuntu-guest/install.d/99-clean-apt 2020-09-13 07:06:08.851039227 +0900 +--- /opt/stack/trove/integration/scripts/files/elements/centos-8-guest/install.d/99-clean-apt 2020-09-13 12:17:54.299216736 +0900 +*************** +*** 6,11 **** + set -e + set -o xtrace + +! apt-get clean + + +--- 6,11 ---- + set -e + set -o xtrace + +! dnf clean all + diff --git a/devstack/patches/trove-integration-scripts-files-elements-guest-agent-50-user.patch b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-50-user.patch new file mode 100644 index 0000000..355fab6 --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-50-user.patch @@ -0,0 +1,19 @@ +*** trove/integration/scripts/files/elements/guest-agent/install.d/50-user 2020-09-13 07:06:08.850039206 +0900 +--- trove/integration/scripts/files/elements/guest-agent-k2hdkc/install.d/50-user 2020-09-13 07:06:08.850039206 +0900 +*************** +*** 13,19 **** + + if ! id -u ${GUEST_USERNAME} >/dev/null 2>&1; then + echo "Adding ${GUEST_USERNAME} user" +! useradd -G sudo -m ${GUEST_USERNAME} -s /bin/bash + chown ${GUEST_USERNAME}:${GUEST_USERNAME} /home/${GUEST_USERNAME} + passwd ${GUEST_USERNAME} <<_EOF_ + ${GUEST_USERNAME} +--- 13,19 ---- + + if ! id -u ${GUEST_USERNAME} >/dev/null 2>&1; then + echo "Adding ${GUEST_USERNAME} user" +! useradd -G users -m ${GUEST_USERNAME} -s /bin/bash + chown ${GUEST_USERNAME}:${GUEST_USERNAME} /home/${GUEST_USERNAME} + passwd ${GUEST_USERNAME} <<_EOF_ + ${GUEST_USERNAME} diff --git a/devstack/patches/trove-integration-scripts-files-elements-guest-agent-99-clean-apt.patch b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-99-clean-apt.patch new file mode 100644 index 0000000..2bf7bfb --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-99-clean-apt.patch @@ -0,0 +1,14 @@ +diff -rc trove/integration/scripts/files/elements/guest-agent/post-install.d/99-clean-apt trove/integration/scripts/files/elements/guest-agent-k2hdkc/post-install.d/99-clean-apt +*** trove/integration/scripts/files/elements/guest-agent/post-install.d/99-clean-apt 2020-09-13 07:06:08.850039206 +0900 +--- trove/integration/scripts/files/elements/guest-agent-k2hdkc/post-install.d/99-clean-apt 2020-09-13 10:27:36.708267761 +0900 +*************** +*** 6,9 **** + set -e + set -o xtrace + +! apt-get clean +--- 6,9 ---- + set -e + set -o xtrace + +! dnf clean all diff --git a/devstack/patches/trove-integration-scripts-files-elements-guest-agent-package-installs.yaml.patch b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-package-installs.yaml.patch new file mode 100644 index 0000000..f8002d7 --- /dev/null +++ b/devstack/patches/trove-integration-scripts-files-elements-guest-agent-package-installs.yaml.patch @@ -0,0 +1,42 @@ +diff -rc trove/integration/scripts/files/elements/guest-agent/package-installs.yaml trove/integration/scripts/files/elements/guest-agent-k2hdkc/package-installs.yaml +*** trove/integration/scripts/files/elements/guest-agent/package-installs.yaml 2020-09-13 07:06:08.850039206 +0900 +--- trove/integration/scripts/files/elements/guest-agent-k2hdkc/package-installs.yaml 2020-09-13 10:40:21.096498779 +0900 +*************** +*** 6,18 **** + installtype: source + libssl-dev: + installtype: source +! python-dev: + installtype: source + + acl: + acpid: + apparmor: +- apparmor-utils: + apt-transport-https: + at: + bash-completion: +--- 6,17 ---- + installtype: source + libssl-dev: + installtype: source +! python3-devel: + installtype: source + + acl: + acpid: + apparmor: + apt-transport-https: + at: + bash-completion: +*************** +*** 50,53 **** + ureadahead: + uuid-runtime: + vim-tiny: +! vlan: +--- 49,52 ---- + ureadahead: + uuid-runtime: + vim-tiny: +! iproute: diff --git a/devstack/patches/trove_dashboard-api-trove.py b/devstack/patches/trove_dashboard-api-trove.py new file mode 100644 index 0000000..51b8d46 --- /dev/null +++ b/devstack/patches/trove_dashboard-api-trove.py @@ -0,0 +1,270 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff --git a/trove_dashboard/api/trove.py b/trove_dashboard/api/trove.py +index 83208de..2201a92 100644 +--- a/trove_dashboard/api/trove.py ++++ b/trove_dashboard/api/trove.py +@@ -25,6 +25,16 @@ from keystoneauth1 import loading + from keystoneauth1 import session + from novaclient import client as nova_client + ++import json ++import re ++from pathlib import Path ++ ++from k2hr3client.http import K2hr3Http ++from k2hr3client.policy import K2hr3Policy ++from k2hr3client.resource import K2hr3Resource ++from k2hr3client.role import K2hr3Role ++from k2hr3client.token import K2hr3Token, K2hr3RoleToken, K2hr3RoleTokenList ++ + # Supported compute versions + NOVA_VERSIONS = base.APIVersionManager("compute", preferred_version=2) + NOVA_VERSIONS.load_supported_version(1.1, +@@ -67,7 +77,8 @@ def cluster_delete(request, cluster_id): + + def cluster_create(request, name, volume, flavor, num_instances, + datastore, datastore_version, +- nics=None, root_password=None, locality=None): ++ nics=None, root_password=None, locality=None, ++ configuration=None): + instances = [] + for i in range(num_instances): + instance = {} +@@ -84,7 +95,8 @@ def cluster_create(request, name, volume, flavor, num_instances, + datastore, + datastore_version, + instances=instances, +- locality=locality) ++ locality=locality, ++ configuration=configuration) + + + def cluster_grow(request, cluster_id, new_instances): +@@ -414,9 +426,207 @@ def configuration_instances(request, group_id): + return troveclient(request).configurations.instances(group_id) + + +-def configuration_update(request, group_id, values): +- return troveclient(request).configurations.update(group_id, values) ++def _get_extdata_url(request, values, k2hr3_url): ++ try: ++ k2hr3_token = K2hr3Token(request.user.project_name, request.user.token.id) ++ http = K2hr3Http(k2hr3_url) ++ http.POST(k2hr3_token) ++ server_role_name = "/".join([values["cluster-name"],"server"]) ++ k2hr3_role_token = K2hr3RoleToken( ++ k2hr3_token.token, ++ role=server_role_name, ++ expire=0 ++ ) ++ http.GET(k2hr3_role_token) ++ roletoken = k2hr3_role_token.token ++ if roletoken: ++ LOG.debug("roletoken {}".format(roletoken)) ++ k2hr3_role_token_list = K2hr3RoleTokenList( ++ k2hr3_token.token, ++ role=server_role_name, ++ expand=True ++ ) ++ http.GET(k2hr3_role_token_list) ++ registerpath = k2hr3_role_token_list.registerpath(roletoken) ++ if registerpath: ++ LOG.debug("registerpath {}".format(registerpath)) ++ extdata_url = "{}/extdata/trove/{}".format(k2hr3_url, registerpath) ++ LOG.debug(extdata_url) ++ return extdata_url ++ else: ++ raise Exception("no registerpath") ++ else: ++ raise Exception("no roletoken") ++ except Exception as e: ++ error_msg = 'create_k2hr3_role error {}'.format(e) ++ LOG.error(error_msg) ++ raise Exception(error_msg) ++ ++def _create_k2hr3_role(request, values, k2hr3_url): ++ try: ++ k2hr3_token = K2hr3Token(request.user.project_name, request.user.token.id) ++ http = K2hr3Http(k2hr3_url) ++ http.POST(k2hr3_token) ++ policy_name="yrn:yahoo:::{}:policy:{}".format(request.user.project_name, values["cluster-name"]) ++ k2hr3_role = K2hr3Role( ++ k2hr3_token.token, ++ name=values["cluster-name"], ++ policies=[policy_name], ++ alias=[] ++ ) ++ http.POST(k2hr3_role) ++ server_role = K2hr3Role( ++ k2hr3_token.token, ++ name="/".join([values["cluster-name"],"server"]), ++ policies=[], ++ alias=[] ++ ) ++ http.POST(server_role) ++ slave_role = K2hr3Role( ++ k2hr3_token.token, ++ name="/".join([values["cluster-name"],"slave"]), ++ policies=[], ++ alias=[] ++ ) ++ http.POST(slave_role) ++ except Exception as e: ++ error_msg = 'create_k2hr3_role error {}'.format(e) ++ LOG.error(error_msg) ++ raise Exception(error_msg) ++ ++ ++def _create_k2hr3_policy(request, values, k2hr3_url): ++ try: ++ k2hr3_token = K2hr3Token(request.user.project_name, request.user.token.id) ++ http = K2hr3Http(k2hr3_url) ++ http.POST(k2hr3_token) ++ server_resource="yrn:yahoo:::{}:resource:{}/server".format(request.user.project_name, values["cluster-name"]) ++ slave_resource="yrn:yahoo:::{}:resource:{}/slave".format(request.user.project_name, values["cluster-name"]) ++ k2hr3_policy = K2hr3Policy( ++ k2hr3_token.token, ++ name=values["cluster-name"], ++ effect='allow', ++ action=['yrn:yahoo::::action:read'], ++ resource=[server_resource, slave_resource], ++ condition=None, ++ alias=[] ++ ) ++ http.POST(k2hr3_policy) ++ except Exception as e: ++ error_msg = 'create_k2hr3_policy error {}'.format(e) ++ LOG.error(error_msg) ++ raise Exception(error_msg) ++ ++ ++def _create_k2hr3_resource(request, values, k2hr3_url): ++ try: ++ k2hr3_token = K2hr3Token(request.user.project_name, request.user.token.id) ++ http = K2hr3Http(k2hr3_url) ++ http.POST(k2hr3_token) ++ k2hr3_resource = K2hr3Resource( ++ k2hr3_token.token, ++ name=values["cluster-name"], ++ data_type='string', ++ data=Path('/opt/stack/k2hdkc_dbaas/utils/python-k2hr3client/examples/example_resource.txt'), ++ keys={ ++ "cluster-name": values["cluster-name"], ++ "chmpx-server-port": values["chmpx-server-port"], ++ "chmpx-server-ctlport": values["chmpx-server-ctlport"], ++ "chmpx-slave-ctlport": values["chmpx-slave-ctlport"] ++ }, ++ alias=[] ++ ) ++ http.POST(k2hr3_resource) ++ k2hr3_resource_server = K2hr3Resource( ++ k2hr3_token.token, ++ name="/".join([values["cluster-name"],"server"]), ++ data_type='string', ++ data="", ++ keys={ ++ "chmpx-mode": "SERVER" ++ }, ++ alias=[] ++ ) ++ http.POST(k2hr3_resource_server) ++ k2hr3_resource_slave = K2hr3Resource( ++ k2hr3_token.token, ++ name="/".join([values["cluster-name"],"slave"]), ++ data_type='string', ++ data="", ++ keys={ ++ "chmpx-mode": "SLAVE" ++ }, ++ alias=[] ++ ) ++ http.POST(k2hr3_resource_slave) ++ except Exception as e: ++ error_msg = 'create_k2hr3_resource error {}'.format(e) ++ LOG.error(error_msg) ++ raise Exception(error_msg) + ++def configuration_update(request, group_id, values): ++ try: ++ LOG.debug("before values={} request.user.token.id={} request.user={} request.user.project_name={}".format(values, request.user.token.id, request.user, request.user.project_name)) ++ python_values = json.loads(values) ++ # Applies default values ++ if not 'chmpx-server-ctlport' in python_values: ++ python_values["chmpx-server-ctlport"] = 8021 ++ if not 'chmpx-slave-ctlport' in python_values: ++ python_values["chmpx-slave-ctlport"] = 8031 ++ if not 'chmpx-server-port' in python_values: ++ python_values["chmpx-server-port"] = 8020 ++ if not 'cluster-name' in python_values: ++ python_values["cluster-name"] = "k2hdkccluster" ++ ++ # Creates k2hr3 resources ++ # Gets k2hr3_url ++ horizon_config = getattr(settings, 'HORIZON_CONFIG', False) ++ if horizon_config is False: ++ raise Exception("HORIZON_CONFIG should exist in local_settings.py") ++ if not 'k2hr3' in horizon_config: ++ raise Exception("k2hr3 should exist in HORIZON_CONFIG of local_settings.py") ++ if not 'http_scheme' in horizon_config['k2hr3']: ++ raise Exception("http_scheme should exist in HORIZON_CONFIG['k2hr3'] of local_settings.py") ++ k2hr3_http_scheme = horizon_config['k2hr3']['http_scheme'] ++ if not 'host' in horizon_config['k2hr3']: ++ raise Exception("host should exist in HORIZON_CONFIG['k2hr3'] of local_settings.py") ++ k2hr3_host = horizon_config['k2hr3']['host'] ++ if not 'port' in horizon_config['k2hr3']: ++ raise Exception("port should exist in HORIZON_CONFIG['k2hr3'] of local_settings.py") ++ k2hr3_port = horizon_config['k2hr3']['port'] ++ k2hr3_url = "{}://{}:{}/v1".format(k2hr3_http_scheme, k2hr3_host, k2hr3_port) ++ _create_k2hr3_resource(request, python_values, k2hr3_url) ++ ++ # Creates k2hr3 policies ++ _create_k2hr3_policy(request, python_values, k2hr3_url) ++ ++ # Creates k2hr3 roles ++ _create_k2hr3_role(request, python_values, k2hr3_url) ++ ++ # Creates k2hr3 roletoken ++ # Gets k2hr3_url_from_private_network ++ if not 'k2hr3_from_private_network' in horizon_config: ++ raise Exception("k2hr3_from_private_network should exist in HORIZON_CONFIG of local_settings.py") ++ if not 'http_scheme' in horizon_config['k2hr3_from_private_network']: ++ raise Exception("http_scheme should exist in HORIZON_CONFIG['k2hr3_from_private_network'] of local_settings.py") ++ k2hr3_http_scheme_from_private_network = horizon_config['k2hr3_from_private_network']['http_scheme'] ++ if not 'host' in horizon_config['k2hr3_from_private_network']: ++ raise Exception("host should exist in HORIZON_CONFIG['k2hr3_from_private_network'] of local_settings.py") ++ k2hr3_host_from_private_network = horizon_config['k2hr3_from_private_network']['host'] ++ if not 'port' in horizon_config['k2hr3_from_private_network']: ++ raise Exception("port should exist in HORIZON_CONFIG['k2hr3_from_private_network'] of local_settings.py") ++ k2hr3_port_from_private_network = horizon_config['k2hr3_from_private_network']['port'] ++ k2hr3_url_from_private_network = "{}://{}:{}/v1".format( ++ k2hr3_http_scheme_from_private_network, ++ k2hr3_host_from_private_network, ++ k2hr3_port_from_private_network) ++ extdata_url = _get_extdata_url(request, python_values, k2hr3_url_from_private_network) ++ ++ python_values["extdata-url"] = extdata_url ++ return troveclient(request).configurations.update(group_id, json.dumps(python_values)) ++ except Exception as e: ++ LOG.error('error {}'.format(e)) ++ return False + + def configuration_default(request, instance_id): + return troveclient(request).instances.configuration(instance_id) diff --git a/devstack/patches/trove_dashboard-content-database_clusters-forms.py b/devstack/patches/trove_dashboard-content-database_clusters-forms.py new file mode 100644 index 0000000..447d74d --- /dev/null +++ b/devstack/patches/trove_dashboard-content-database_clusters-forms.py @@ -0,0 +1,212 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff --git a/trove_dashboard/content/database_clusters/forms.py b/trove_dashboard/content/database_clusters/forms.py +index 6539055..803d4f3 100644 +--- a/trove_dashboard/content/database_clusters/forms.py ++++ b/trove_dashboard/content/database_clusters/forms.py +@@ -40,7 +40,51 @@ from trove_dashboard.utils import common as common_utils + LOG = logging.getLogger(__name__) + + +-class LaunchForm(forms.SelfHandlingForm): ++class BaseClusterForm(forms.SelfHandlingForm): ++ def __init__(self, request, *args, **kwargs): ++ super(BaseClusterForm, self).__init__(request, *args, **kwargs) ++ ++ @memoized.memoized_method ++ def populate_network_choices(self, request): ++ network_list = [] ++ try: ++ if api.base.is_service_enabled(request, 'network'): ++ tenant_id = self.request.user.tenant_id ++ networks = api.neutron.network_list_for_tenant(request, ++ tenant_id) ++ network_list = [(network.id, network.name_or_id) ++ for network in networks] ++ else: ++ self.fields['network'].widget = forms.HiddenInput() ++ except exceptions.ServiceCatalogException: ++ network_list = [] ++ redirect = reverse('horizon:project:database_clusters:index') ++ exceptions.handle(request, ++ _('Unable to retrieve networks.'), ++ redirect=redirect) ++ return network_list ++ ++ @memoized.memoized_method ++ def populate_cg_choices(self, request): ++ try: ++ configs = trove_api.trove.configuration_list(request) ++ config_name = "%(name)s (%(datastore)s - %(version)s)" ++ choices = [(c.id, ++ config_name % {'name': c.name, ++ 'datastore': c.datastore_name, ++ 'version': c.datastore_version_name}) ++ for c in configs] ++ except Exception: ++ choices = [] ++ ++ if choices: ++ choices.insert(0, ("", _("Select configuration"))) ++ else: ++ choices.insert(0, ("", _("No configurations available"))) ++ return choices ++ ++ ++class LaunchForm(BaseClusterForm): + name = forms.CharField(label=_("Cluster Name"), + max_length=80) + datastore = forms.ChoiceField( +@@ -68,6 +112,10 @@ class LaunchForm(forms.SelfHandlingForm): + help_text=_("Specify whether instances in the cluster will " + "be created on the same hypervisor (affinity) or on " + "different hypervisors (anti-affinity).")) ++ configuration = forms.ChoiceField( ++ label=_("ConfigurationGroup"), ++ help_text=_("ConfigurationGroup attached to instances."), ++ required=False) + root_password = forms.CharField( + label=_("Root Password"), + required=False, +@@ -127,6 +175,8 @@ class LaunchForm(forms.SelfHandlingForm): + request) + self.fields['network'].choices = self.populate_network_choices( + request) ++ self.fields['configuration'].choices = self.populate_cg_choices( ++ request) + + def clean(self): + datastore_field_value = self.data.get("datastore", None) +@@ -158,6 +208,9 @@ class LaunchForm(forms.SelfHandlingForm): + if not self.data.get("locality", None): + self.cleaned_data["locality"] = None + ++ if not self.data.get("configuration", None): ++ self.cleaned_data["configuration"] = None ++ + return self.cleaned_data + + @memoized.memoized_method +@@ -173,26 +226,6 @@ class LaunchForm(forms.SelfHandlingForm): + _('Unable to obtain flavors.'), + redirect=redirect) + +- @memoized.memoized_method +- def populate_network_choices(self, request): +- network_list = [] +- try: +- if api.base.is_service_enabled(request, 'network'): +- tenant_id = self.request.user.tenant_id +- networks = api.neutron.network_list_for_tenant(request, +- tenant_id) +- network_list = [(network.id, network.name_or_id) +- for network in networks] +- else: +- self.fields['network'].widget = forms.HiddenInput() +- except exceptions.ServiceCatalogException: +- network_list = [] +- redirect = reverse('horizon:project:database_clusters:index') +- exceptions.handle(request, +- _('Unable to retrieve networks.'), +- redirect=redirect) +- return network_list +- + @memoized.memoized_method + def datastores(self, request): + try: +@@ -354,9 +387,10 @@ class LaunchForm(forms.SelfHandlingForm): + LOG.info("Launching cluster with parameters " + "{name=%s, volume=%s, flavor=%s, " + "datastore=%s, datastore_version=%s", +- "locality=%s", ++ "locality=%s, configuration=%s", + data['name'], data['volume'], flavor, +- datastore, datastore_version, self._get_locality(data)) ++ datastore, datastore_version, self._get_locality(data), ++ configuration=data['configuration']) + + trove_api.trove.cluster_create(request, + data['name'], +@@ -367,7 +401,8 @@ class LaunchForm(forms.SelfHandlingForm): + datastore_version=datastore_version, + nics=data['network'], + root_password=root_password, +- locality=self._get_locality(data)) ++ locality=self._get_locality(data), ++ configuration=data['configuration']) + messages.success(request, + _('Launched cluster "%s"') % data['name']) + return True +@@ -378,7 +413,7 @@ class LaunchForm(forms.SelfHandlingForm): + redirect=redirect) + + +-class ClusterAddInstanceForm(forms.SelfHandlingForm): ++class ClusterAddInstanceForm(BaseClusterForm): + cluster_id = forms.CharField( + required=False, + widget=forms.HiddenInput()) +@@ -408,6 +443,10 @@ class ClusterAddInstanceForm(forms.SelfHandlingForm): + label=_("Network"), + help_text=_("Network attached to instance."), + required=False) ++ configuration = forms.ChoiceField( ++ label=_("ConfigurationGroup"), ++ help_text=_("ConfigurationGroup attached to instance."), ++ required=False) + + def __init__(self, request, *args, **kwargs): + super(ClusterAddInstanceForm, self).__init__(request, *args, **kwargs) +@@ -415,6 +454,8 @@ class ClusterAddInstanceForm(forms.SelfHandlingForm): + self.fields['flavor'].choices = self.populate_flavor_choices(request) + self.fields['network'].choices = self.populate_network_choices( + request) ++ self.fields['configuration'].choices = self.populate_cg_choices( ++ request) + + @memoized.memoized_method + def flavors(self, request): +@@ -441,26 +482,6 @@ class ClusterAddInstanceForm(forms.SelfHandlingForm): + flavor_list = [(f.id, "%s" % f.name) for f in self.flavors(request)] + return sorted(flavor_list) + +- @memoized.memoized_method +- def populate_network_choices(self, request): +- network_list = [] +- try: +- if api.base.is_service_enabled(request, 'network'): +- tenant_id = self.request.user.tenant_id +- networks = api.neutron.network_list_for_tenant(request, +- tenant_id) +- network_list = [(network.id, network.name_or_id) +- for network in networks] +- else: +- self.fields['network'].widget = forms.HiddenInput() +- except exceptions.ServiceCatalogException: +- network_list = [] +- redirect = reverse('horizon:project:database_clusters:index') +- exceptions.handle(request, +- _('Unable to retrieve networks.'), +- redirect=redirect) +- return network_list +- + def handle(self, request, data): + try: + flavor = trove_api.trove.flavor_get(request, data['flavor']) diff --git a/devstack/patches/trove_dashboard-content-databases-db_capability.py b/devstack/patches/trove_dashboard-content-databases-db_capability.py new file mode 100644 index 0000000..0f014bf --- /dev/null +++ b/devstack/patches/trove_dashboard-content-databases-db_capability.py @@ -0,0 +1,49 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** db_capability.py 2020-07-07 14:24:35.181997910 +0900 +--- db_capability.py.new 2020-07-07 14:24:12.208540068 +0900 +*************** +*** 21,32 **** + PERCONA_CLUSTER = "pxc" + REDIS = "redis" + VERTICA = "vertica" + + _mysql_compatible_datastores = (MYSQL, MARIA, PERCONA, PERCONA_CLUSTER) + _cluster_capable_datastores = (CASSANDRA, MARIA, MONGODB, PERCONA_CLUSTER, +! REDIS, VERTICA) + _cluster_grow_shrink_capable_datastores = (CASSANDRA, MARIA, MONGODB, +! PERCONA_CLUSTER, REDIS) + + + def can_modify_cluster(datastore): +--- 21,33 ---- + PERCONA_CLUSTER = "pxc" + REDIS = "redis" + VERTICA = "vertica" ++ K2HDKC = "k2hdkc" + + _mysql_compatible_datastores = (MYSQL, MARIA, PERCONA, PERCONA_CLUSTER) + _cluster_capable_datastores = (CASSANDRA, MARIA, MONGODB, PERCONA_CLUSTER, +! REDIS, VERTICA, K2HDKC) + _cluster_grow_shrink_capable_datastores = (CASSANDRA, MARIA, MONGODB, +! PERCONA_CLUSTER, REDIS, K2HDKC) + + + def can_modify_cluster(datastore): diff --git a/devstack/patches/trove_dashboard-enabled-_1740_project_database_clusters_panel.py b/devstack/patches/trove_dashboard-enabled-_1740_project_database_clusters_panel.py new file mode 100644 index 0000000..e7bdffe --- /dev/null +++ b/devstack/patches/trove_dashboard-enabled-_1740_project_database_clusters_panel.py @@ -0,0 +1,32 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff --git a/trove_dashboard/enabled/_1740_project_database_clusters_panel.py b/trove_dashboard/enabled/_1740_project_database_clusters_panel.py +index a5d3164..ccada2d 100644 +--- a/trove_dashboard/enabled/_1740_project_database_clusters_panel.py ++++ b/trove_dashboard/enabled/_1740_project_database_clusters_panel.py +@@ -22,7 +22,7 @@ PANEL_DASHBOARD = 'project' + # The slug of the panel group the PANEL is associated with. + PANEL_GROUP = 'database' + +-DISABLED = True ++DISABLED = False + + # Python panel class of the PANEL to be added. + ADD_PANEL = ('trove_dashboard.content.database_clusters.panel.Clusters') diff --git a/devstack/plugin.sh b/devstack/plugin.sh new file mode 100755 index 0000000..794434f --- /dev/null +++ b/devstack/plugin.sh @@ -0,0 +1,308 @@ +#!/bin/bash + +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# plugin for k2hdkc dbaas +# +# interface +# source $PATH/TO/plugin.sh [phase] +# +# mode: stack, unstack, clean +# phase: pre-install, install, post-config, extra, test-config + +# plugin.sh - DevStack plugin.sh dispatch script template + +# Save trace setting +XTRACE=$(set +o | grep xtrace) +set +o xtrace + +TROVE_PATCH_SRCDIR=$DEST/k2hdkc_dbaas/devstack + +function k2hdkc_patch_file { + ORIGINAL_FILE=$1 + PATCH_FILE=$2 + if test -f "${ORIGINAL_FILE}"; then + if test -f "${PATCH_FILE}" ; then + echo "patch for ${ORIGINAL_FILE}" + patch ${ORIGINAL_FILE} < ${PATCH_FILE} + else + echo "NO ${PATCH_FILE}" + exit 1 + fi + else + echo "NO ${ORIGINAL_FILE}" + exit 1 + fi +} + +function k2hdkc_install_dir { + SRC_DIR=$1 + DEST_DIR=$2 + DEST_BASE_DIR=$(dirname ${DEST_DIR}) + if test -d "${DEST_BASE_DIR}"; then + echo "install -o stack -d ${DEST_DIR}" + install -o stack -d ${DEST_DIR} + echo "install -C -D -m 0444 -o stack -v ${SRCDIR}/* ${DEST_DIR}" + install -C -D -m 0444 -o stack -v ${SRC_DIR}/* ${DEST_DIR} + else + echo "NO ${DEST_BASE_DIR}" + exit 1 + fi +} + +echo_summary "start k2hdkc dbaas plugin" + +function install_k2hdkc_dbaas { + echo "install_k2hdkc_dbaas" + + echo "Trove API for k2hdkc" + # 1. DEST/trove/trove/common/cfg.py + k2hdkc_patch_file "$DEST/trove/trove/common/cfg.py" "${TROVE_PATCH_SRCDIR}/patches/trove-common-cfg.py" + + # 2. $DEST/trove/trove/common/strategies/cluster/experimental/k2hdkc + k2hdkc_install_dir ${TROVE_PATCH_SRCDIR}/common/strategies/cluster/experimental/k2hdkc $DEST/trove/trove/common/strategies/cluster/experimental/k2hdkc + + echo "Trove TaskManager for k2hdkc" + # 3. opt/stack/trove/trove/templates/k2hdkc/config.template + k2hdkc_install_dir ${TROVE_PATCH_SRCDIR}/templates/k2hdkc $DEST/trove/trove/templates/k2hdkc + + # 4. /trove/common/configurations.py + k2hdkc_patch_file $DEST/trove/trove/common/configurations.py ${TROVE_PATCH_SRCDIR}/patches/trove-common-configurations.py + + # 5. /trove/common/template.py + k2hdkc_patch_file $DEST/trove/trove/common/template.py ${TROVE_PATCH_SRCDIR}/patches/trove-common-template.py + + # 6. trove-db-sqlalchemy-migrate_repo-versions-020_configurations.py + k2hdkc_patch_file $DEST/trove/trove/db/sqlalchemy/migrate_repo/versions/020_configurations.py ${TROVE_PATCH_SRCDIR}/patches/trove-db-sqlalchemy-migrate_repo-versions-020_configurations.py + + # 7. trove_dashboard/api/trove.py + k2hdkc_patch_file $DEST/trove-dashboard/trove_dashboard/api/trove.py ${TROVE_PATCH_SRCDIR}/patches/trove_dashboard-api-trove.py + + # 8. trove_dashboard/api/trove.py + k2hdkc_patch_file $DEST/trove-dashboard/trove_dashboard/content/databases/db_capability.py ${TROVE_PATCH_SRCDIR}/patches/trove_dashboard-content-databases-db_capability.py + + # 9. trove_dashboard-content-database_clusters-forms.py + k2hdkc_patch_file $DEST/trove-dashboard/trove_dashboard/content/database_clusters/forms.py ${TROVE_PATCH_SRCDIR}/patches/trove_dashboard-content-database_clusters-forms.py + + # 10. trove_dashboard-enabled-_1740_project_database_clusters_panel.py + k2hdkc_patch_file $DEST/trove-dashboard/trove_dashboard/enabled/_1740_project_database_clusters_panel.py ${TROVE_PATCH_SRCDIR}/patches/trove_dashboard-enabled-_1740_project_database_clusters_panel.py +} + +function create_k2hdkc_dbaas_guest_image { + echo "create_k2hdkc_dbaas_guest_image" + if ! test -d "$DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc"; then + cp -r $DEST/trove/integration/scripts/files/elements/guest-agent $DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc/post-install.d/99-clean-apt ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-guest-agent-99-clean-apt.patch + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc/package-installs.yaml ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-guest-agent-package-installs.yaml.patch + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc/install.d/50-user ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-guest-agent-50-user.patch + else + echo "NO $DEST/trove/integration/scripts/files/elements/guest-agent-k2hdkc alread exists. Run unstack.sh firstly." + exit 1 + fi + # 2. copy the ubuntu-guest element + if ! test -d "$DEST/trove/integration/scripts/files/elements/centos-8-guest"; then + cp -r $DEST/trove/integration/scripts/files/elements/ubuntu-guest $DEST/trove/integration/scripts/files/elements/centos-8-guest + # 2.1. move files + mv -f $DEST/trove/integration/scripts/files/elements/centos-8-guest/environment.d/99-reliable-apt-key-importing.bash \ + $DEST/trove/integration/scripts/files/elements/centos-8-guest/environment.d/99-reliable-apt-key-importing.bash.orig + mv -f $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/15-trove-dep \ + $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/15-trove-dep.orig + mv -f $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/50-user \ + $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/50-user.orig + # 2.2. patch files + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/05-base-apps ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-centos-8-guest-05-base-apps.patch + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/98-ssh ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-centos-8-guest-98-ssh.patch + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/centos-8-guest/install.d/99-clean-apt ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-centos-8-guest-99-clean-apt.patch + k2hdkc_patch_file $DEST/trove/integration/scripts/files/elements/centos-8-guest/pre-install.d/04-baseline-tools ${TROVE_PATCH_SRCDIR}/patches/trove-integration-scripts-files-elements-centos-8-guest-04-baseline-tools.patch + else + echo "NO $DEST/trove/integration/scripts/files/elements/centos-8-guest. Run unstack.sh firstly." + exit 1 + fi + $DEST/k2hdkc_dbaas/utils/disk-image-create.sh + IMAGE_FILE=$DEST/images/trove-datastore-centos-8-k2hdkc.qcow2 + IMAGE_NAME="trove-datastore-centos-8-k2hdkc" + if [ ! -f ${IMAGE_FILE} ]; then + echo "NO Image file found at ${IMAGE_FILE}" + exit 1 + fi + TROVE_DATASTORE_TYPE_K2HDKC=k2hdkc + TROVE_DATASTORE_VERSION_K2HDKC=0.9.30 + + echo "Add the image to glance" + glance_image_id=$(openstack --os-region-name RegionOne --os-password ${SERVICE_PASSWORD} \ + --os-project-name service --os-username trove \ + image create ${IMAGE_NAME} \ + --disk-format qcow2 --container-format bare --property hw_rng_model='virtio' --file ${IMAGE_FILE} \ + -c id -f value) + + echo "Register the image in datastore" + $TROVE_MANAGE datastore_update $TROVE_DATASTORE_TYPE_K2HDKC "" + $TROVE_MANAGE datastore_version_update $TROVE_DATASTORE_TYPE_K2HDKC $TROVE_DATASTORE_VERSION_K2HDKC $TROVE_DATASTORE_TYPE_K2HDKC $glance_image_id "" 1 + $TROVE_MANAGE datastore_update $TROVE_DATASTORE_TYPE_K2HDKC $TROVE_DATASTORE_VERSION_K2HDKC + + echo "Add parameter validation rules if available" + if [ -f $DEST/trove/trove/templates/$TROVE_DATASTORE_TYPE_K2HDKC/validation-rules.json ]; then + $TROVE_MANAGE db_load_datastore_config_parameters "$TROVE_DATASTORE_TYPE_K2HDKC" "$TROVE_DATASTORE_VERSION_K2HDKC" \ + $DEST/trove/trove/templates/$TROVE_DATASTORE_TYPE_K2HDKC/validation-rules.json + else + echo "NO $DEST/trove/trove/templates/$TROVE_DATASTORE_TYPE_K2HDKC/validation-rules.json" + exit 1 + fi + +} + +function configure_k2hdkc_dbaas { + echo "configure_k2hdkc_dbaas" + + # 1. /etc/trove/trove.conf + k2hdkc_patch_file /etc/trove/trove.conf ${TROVE_PATCH_SRCDIR}/patches/etc-trove-trove.conf + + # 2. /etc/trove/trove-guestagent.conf + if test -f "/etc/trove/trove-guestagent.conf"; then + if test -f "$DEST/trove/integration/scripts/functions"; then + iniset $TROVE_GUESTAGENT_CONF DEFAULT backup_swift_container k2hdkc_backups + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_use_gzip_compression True + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_use_openssl_encryption True + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_aes_cbc_key "default_aes_cbc_key" + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_use_snet False + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_chunk_size 65536 + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_segment_max_size 2147483648 + iniset $TROVE_GUESTAGENT_CONF service_credentials backup_use_gzip_compression True + else + echo "NO $DEST/trove/integration/scripts/functions" + exit 1 + fi + else + echo "NO /etc/trove/trove.conf" + exit 1 + fi +} + +function configure_horizonf_for_k2hr3 { + echo "configure_horizonf_for_k2hr3" + + echo "changes local_settings.py for k2hr3" + LOCAL_SETTINGS_PY="/opt/stack/horizon/openstack_dashboard/local/local_settings.py" + # 1. local_settings.py + if test -f "${LOCAL_SETTINGS_PY}"; then + if test -n "${KEYSTONE_SERVICE_HOST}" ; then + cat > local_settings_for_k2hr3 <> ${LOCAL_SETTINGS_PY} + if test -f "local_settings_for_k2hr3"; then + rm -f "local_settings_for_k2hr3" + fi + else + echo "NO ${KEYSTONE_SERVICE_HOST}" + exit 1 + fi + else + echo "NO ${LOCAL_SETTINGS_PY}" + exit 1 + fi +} + + +# check for service enabled +if is_service_enabled k2hdkc-dbaas; then + + if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then + # Set up system services + echo_summary "Configuring system services K2hdkc" + + elif [[ "$1" == "stack" && "$2" == "install" ]]; then + # Perform installation of service source + echo_summary "Installing k2hdkc_dbaas" + install_k2hdkc_dbaas + + elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then + # Configure after the other layer 1 and 2 services have been configured + echo_summary "Configuring K2hdkc" + configure_k2hdkc_dbaas + echo_summary "Configuring Horizon for k2hr3" + configure_horizonf_for_k2hr3 + echo_summary "Installing a python k2hr3 library for trove-dashboard" + $DEST/k2hdkc_dbaas/utils/install_python-k2hr3client.sh + + elif [[ "$1" == "stack" && "$2" == "extra" ]]; then + # Initialize and start the template service + echo_summary "Initializing K2hdkc" + # 1. create k2hdkc guest image + create_k2hdkc_dbaas_guest_image + fi + + if [[ "$1" == "unstack" ]]; then + # Shut down template services + # no-op + cd $DEST/trove && git checkout -- . + cd $DEST/trove-dashboard && git checkout -- . + if test -d "$DEST/trove/common/strategies/cluster/experimental/k2hdkc"; then + echo "rm -rf $DEST/trove/common/strategies/cluster/experimental/k2hdkc" + rm -rf $DEST/trove/common/strategies/cluster/experimental/k2hdkc + fi + if test -d "$DEST/trove/templates/k2hdkc"; then + echo "rm -rf $DEST/trove/templates/k2hdkc" + rm -rf $DEST/trove/templates/k2hdkc + fi + if test -d "$DEST/integration/scripts/files/elements/centos-8-guest"; then + echo "rm -rf $DEST/integration/scripts/files/elements/centos-8-guest" + rm -rf $DEST/integration/scripts/files/elements/centos-8-guest + fi + if test -d "$DEST/integration/scripts/files/elements/guest-agent-k2hdkc"; then + echo "rm -rf $DEST/integration/scripts/files/elements/guest-agent-k2hdkc" + rm -rf $DEST/integration/scripts/files/elements/guest-agent-k2hdkc + fi + + fi + + if [[ "$1" == "clean" ]]; then + # Remove state and transient data + # Remember clean.sh first calls unstack.sh + # no-op + : + fi +else + echo "NO is_service_enabled" +fi + +echo_summary "end k2hdkc dbaas plugin" + +# Restore xtrace +$XTRACE + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/devstack/settings b/devstack/settings new file mode 100644 index 0000000..a3932cc --- /dev/null +++ b/devstack/settings @@ -0,0 +1,36 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# settings file for k2hdkc dbaas +# +# include a define_plugin line to indicate the plugin's name +define_plugin k2hdkc-dbaas + +# include any enable_service lines required by your plugin. +enable_service trove k2hdkc-dbaas + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# + diff --git a/devstack/templates/k2hdkc/config.template b/devstack/templates/k2hdkc/config.template new file mode 100644 index 0000000..ed2bc04 --- /dev/null +++ b/devstack/templates/k2hdkc/config.template @@ -0,0 +1,5 @@ +cluster-name=None +extdata-url=None +chmpx-server-port=8020 +chmpx-server-ctlport=8021 +chmpx-slave-ctlport=8031 diff --git a/devstack/templates/k2hdkc/validation-rules.json b/devstack/templates/k2hdkc/validation-rules.json new file mode 100644 index 0000000..eb7a7c0 --- /dev/null +++ b/devstack/templates/k2hdkc/validation-rules.json @@ -0,0 +1,40 @@ +{ + "configuration-parameters": [ + { + "name": "cluster-name", + "description": "K2HDKC Cluster name", + "restart_required": false, + "type": "string" + }, + { + "name": "extdata-url", + "description": "extdata URL to K2HR3 (Do NOT set this value because sets automatically)", + "restart_required": false, + "type": "string" + }, + { + "name": "chmpx-server-port", + "description": "CHMPX server node port number", + "restart_required": false, + "max": 65535, + "min": 1000, + "type": "integer" + }, + { + "name": "chmpx-server-ctlport", + "description": "CHMPX server node control port number", + "restart_required": false, + "max": 65535, + "min": 1000, + "type": "integer" + }, + { + "name": "chmpx-slave-ctlport", + "description": "CHMPX slave node port number", + "restart_required": false, + "max": 65535, + "min": 1000, + "type": "integer" + } + ] +} diff --git a/dib/elements/centos-8-k2hdkc/install.d/10-k2hdkc b/dib/elements/centos-8-k2hdkc/install.d/10-k2hdkc new file mode 100755 index 0000000..b394414 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/10-k2hdkc @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e +set -o xtrace + +# Install the k2hdkc and run it. +SRCDIR=$(cd $(dirname "$0") && pwd) +sh ${SRCDIR}/dkc/setup_dkc.sh -d + diff --git a/dib/elements/centos-8-k2hdkc/install.d/76-k2hdkc b/dib/elements/centos-8-k2hdkc/install.d/76-k2hdkc new file mode 100755 index 0000000..c7a41b3 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/76-k2hdkc @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e +set -o xtrace + +# Apply patch +SRCDIR=$(cd $(dirname "$0") && pwd) +sh ${SRCDIR}/trove/patch.sh -d diff --git a/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_centos.ini b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_centos.ini new file mode 100644 index 0000000..c9d45fa --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_centos.ini @@ -0,0 +1,32 @@ +# +# K2HR3 Utilities +# +# Copyright 2018 Yahoo! Japan Corporation. +# +# K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers +# common management information for the cloud. +# K2HR3 can dynamically manage information as "who", "what", "operate". +# These are stored as roles, resources, policies in K2hdkc, and the +# client system can dynamically read and modify these information. +# +# For the full copyright and license information, please view +# the licenses file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Jul 9 2018 +# REVISION: +# + +#[chmpx] +chmpx_msg_max=1024 +chmpx_server_name=localhost +k2hdkc_pkgs= + +#[package] +package_script_base_url= + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_debian.ini b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_debian.ini new file mode 100644 index 0000000..02ccb76 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_debian.ini @@ -0,0 +1,31 @@ +# +# K2HR3 Utilities +# +# Copyright 2018 Yahoo! Japan Corporation. +# +# K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers +# common management information for the cloud. +# K2HR3 can dynamically manage information as "who", "what", "operate". +# These are stored as roles, resources, policies in K2hdkc, and the +# client system can dynamically read and modify these information. +# +# For the full copyright and license information, please view +# the licenses file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Jul 9 2018 +# REVISION: +# + +#[chmpx] +chmpx_msg_max=1024 +chmpx_server_name=localhost + +#[package] +package_script_base_url= + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_default.ini b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_default.ini new file mode 100644 index 0000000..c51d962 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_default.ini @@ -0,0 +1,47 @@ +# +# K2HR3 Utilities +# +# Copyright 2018 Yahoo! Japan Corporation. +# +# K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers +# common management information for the cloud. +# K2HR3 can dynamically manage information as "who", "what", "operate". +# These are stored as roles, resources, policies in K2hdkc, and the +# client system can dynamically read and modify these information. +# +# For the full copyright and license information, please view +# the licenses file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Jul 9 2018 +# REVISION: +# + +#[chmpx] +chmpx_conf_file=/etc/k2hdkc/server.ini +chmpx_msg_max=1024 +chmpx_server_name=localhost +chmpx_systemd_unit_file=/etc/systemd/system/chmpx.service +chmpx_loglevel=dump + +#[k2hdkc] +k2hdkc_data_dir="/var/lib/k2hdkc" +k2hdkc_systemd_unit_file=/etc/systemd/system/k2hdkc.service +k2hdkc_loglevel=dump + +#[k2hr3] +k2hr3_dkc_runuser=k2hdkc + +#[package] +package_script_base_url= +package_install_pkgs="k2htpdtor libfullock k2hash chmpx k2hdkc" +package_dnf_repo=PowerTools + +#[other] +service_manager_plugin=trove + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_fedora.ini b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_fedora.ini new file mode 100644 index 0000000..02ccb76 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/dkc/setup_dkc_fedora.ini @@ -0,0 +1,31 @@ +# +# K2HR3 Utilities +# +# Copyright 2018 Yahoo! Japan Corporation. +# +# K2HR3 is K2hdkc based Resource and Roles and policy Rules, gathers +# common management information for the cloud. +# K2HR3 can dynamically manage information as "who", "what", "operate". +# These are stored as roles, resources, policies in K2hdkc, and the +# client system can dynamically read and modify these information. +# +# For the full copyright and license information, please view +# the licenses file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Jul 9 2018 +# REVISION: +# + +#[chmpx] +chmpx_msg_max=1024 +chmpx_server_name=localhost + +#[package] +package_script_base_url= + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/chmpx-trovectl.service b/dib/elements/centos-8-k2hdkc/install.d/service_manager/chmpx-trovectl.service new file mode 100644 index 0000000..39c8637 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/chmpx-trovectl.service @@ -0,0 +1,16 @@ +[Unit] +Description=service controler for chmpx on trove +After=network-online.target + +[Service] +Type=simple +User=k2hdkc +PermissionsStartOnly=true +ExecStartPre=/sbin/sysctl fs.mqueue.msg_max=1024 +ExecStart=/usr/libexec/k2hdkc-trovectl chmpx -cgp /etc/k2hdkc -conf server.ini -initwait 120 -d msg +ExecStop=/bin/kill -HUP $MAINPID +Restart=always +PIDFile=/var/run/k2hdkc-trovectl-chmpx.pid + +[Install] +WantedBy=multi-user.target diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.service b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.service new file mode 100644 index 0000000..210f1c5 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.service @@ -0,0 +1,8 @@ +[Unit] +Description=k2hdkc check configration timer +ConditionPathExists=/etc/k2hdkc/extdata_k2hr3_trove.sh + +[Service] +Type=oneshot +User=root +ExecStart=/usr/libexec/k2hdkc-check-conf -cgp /etc/k2hdkc -extdata extdata_k2hr3_trove.sh -conf server.ini diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.timer b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.timer new file mode 100644 index 0000000..0e75a2a --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-check-conf.timer @@ -0,0 +1,10 @@ +[Unit] +Description=k2hdkc check configration timer + +[Timer] +OnStartupSec=5min +OnUnitInactiveSec=1min +Unit=k2hdkc-check-conf.service + +[Install] +WantedBy=multi-user.target diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trove.service b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trove.service new file mode 100644 index 0000000..1e86209 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trove.service @@ -0,0 +1,15 @@ +[Unit] +Description=k2hdkc trove service +After=network-online.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/libexec/k2hdkc-trove-helper -conf server.ini -cgp /etc/k2hdkc -startup_timeout 60 -normal_timeout 1 +ExecReload=/usr/libexec/k2hdkc-trove-helper -conf server.ini -cgp /etc/k2hdkc -startup_timeout 60 -normal_timeout 1 +ExecStop=/usr/libexec/k2hdkc-trove-helper -stop +RemainAfterExit=yes +Restart=no + +[Install] +WantedBy=multi-user.target diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trovectl.service b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trovectl.service new file mode 100644 index 0000000..5163011 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/k2hdkc-trovectl.service @@ -0,0 +1,15 @@ +[Unit] +Description=service controler for k2hdkc on trove +After=network-online.target + +[Service] +Type=simple +User=k2hdkc +PermissionsStartOnly=true +ExecStart=/usr/libexec/k2hdkc-trovectl k2hdkc -cgp /etc/k2hdkc -conf server.ini -initwait 120 -wait /tmp/k2hdkc-trovectl-chmpx.pid -d msg +ExecStop=/bin/kill -HUP $MAINPID +Restart=always +PIDFile=/var/run/k2hdkc-trovectl-k2hdkc.pid + +[Install] +WantedBy=multi-user.target diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/plugin/trove.sh b/dib/elements/centos-8-k2hdkc/install.d/service_manager/plugin/trove.sh new file mode 100755 index 0000000..644ad7e --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/plugin/trove.sh @@ -0,0 +1,290 @@ +#!/bin/sh +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: + +# +# A simple script to create a k2hr3-dkc server on localhost +# + +# Sets the default locale. LC_ALL has precedence over other LC* variables. +unset LANG +unset LANGUAGE +LC_ALL=en_US.utf8 +export LC_ALL + +# Sets PATH. setup_*.sh uses useradd command +PATH=${PATH}:/usr/sbin:/sbin + +# an unset parameter expansion will fail +set -u + +# umask 022 is enough +umask 022 + +# defines environments + +function setup_service_manager { +logger -t ${TAG} -p user.info "trove.sh configure_systemd" + +######## +# 8. Configures the chmpx's service manager default configuration +# We recommend chmpx process works as a service by systemd. +# +logger -t ${TAG} -p user.info "8. Configures the chmpx's service manager default configuration" + +# Determines the service management file which file format depends on a service manager of the target OS +if test "${SERVICE_MANAGER}" = "systemd"; then +service_manager_file=${SRCDIR}/../service_manager/chmpx-trovectl.service +else +logger -t ${TAG} -p user.err "SERVICE_MANAGER must be either systemd, not ${SERVICE_MANAGER}" +return 1 +fi +# Configures the chmpx's service manager default configuration +is_k2hdkc=0 +configure_chmpx_service_manager_file ${SERVICE_MANAGER} ${service_manager_file} ${k2hr3_dkc_runuser} ${chmpx_conf_file} ${chmpx_msg_max} ${is_k2hdkc} ${chmpx_loglevel} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "configure_chmpx_service_manager_file should return zero, not ${RET}" +return 1 +fi + +######## +# 9. Installs the chmpx service manager configuration and enables it +# systemd controls chmpx. +# +logger -t ${TAG} -p user.info "9. Installs the chmpx service manager configuration and enables it" + +if test -f "${SRCDIR}/../service_manager/scripts/k2hdkc-trovectl"; then +logger -t ${TAG} -p user.debug "sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-trovectl /usr/libexec/k2hdkc-trovectl" +sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-trovectl /usr/libexec/k2hdkc-trovectl +RESULT=$? +if test "${RESULT}" -ne 0; then + logger -t ${TAG} -p user.err "RESULT should be zero, not ${RESULT}" + return 1 +fi +else +logger -t ${TAG} -p user.err "${SRCDIR}/../service_manager/scripts/k2hdkc-trovectl should exist" +return 1 +fi + +install_service_manager_conf ${SERVICE_MANAGER} chmpx-trovectl +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "install_service_manager_conf should return zero, not ${RET}" +return 1 +fi + +######## +# 10. Configures the k2hdkc's service manager default configuration +# We recommend k2hdkc processes work as a service by systemd. +# +logger -t ${TAG} -p user.info "10. Configures the k2hdkc's service manager default configuration" + +# Determines the service management file which file format depends on a service manager of the target OS +if test "${SERVICE_MANAGER}" = "systemd"; then +service_manager_file=${SRCDIR}/../service_manager/k2hdkc-trove.service +else +logger -t ${TAG} -p user.err "SERVICE_MANAGER must be either systemd, not ${SERVICE_MANAGER}" +return 1 +fi +# Configures the k2hdkc's service manager default configuration +is_k2hdkc=1 +configure_chmpx_service_manager_file ${SERVICE_MANAGER} ${service_manager_file} ${k2hr3_dkc_runuser} ${chmpx_conf_file} ${chmpx_msg_max} ${is_k2hdkc} ${k2hdkc_loglevel} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "configure_chmpx_service_manager_file should return zero, not ${RET}" +return 1 +fi + +######## +# 11. Installs the k2hdkc service manager configuration and enables it +# systemd controls k2hdkc +# +logger -t ${TAG} -p user.info "11. Installs the k2hdkc service manager configuration and enables it" + +if test -f "${SRCDIR}/../service_manager/scripts/k2hdkc-trove-helper"; then +logger -t ${TAG} -p user.debug "sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-trove-helper /usr/libexec/k2hdkc-trove-helper" +sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-trove-helper /usr/libexec/k2hdkc-trove-helper +RESULT=$? +if test "${RESULT}" -ne 0; then + logger -t ${TAG} -p user.err "RESULT should be zero, not ${RESULT}" + return 1 +fi +else +logger -t ${TAG} -p user.err "${SRCDIR}/../service_manager/scripts/k2hdkc-trove-helper should exist" +return 1 +fi + +install_service_manager_conf ${SERVICE_MANAGER} k2hdkc-trove +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "install_service_manager_conf should return zero, not ${RET}" +return 1 +fi + +######## +# 12. Configures the k2hdkc-trovectl's service manager default configuration +# We recommend k2hdkc-trovectl processes work as a service by systemd. +# +logger -t ${TAG} -p user.info "12. Configures the k2hdkc-trovectl's service manager default configuration" + +# Determines the service management file which file format depends on a service manager of the target OS +if test "${SERVICE_MANAGER}" = "systemd"; then +service_manager_file=${SRCDIR}/../service_manager/k2hdkc-trovectl.service +else +logger -t ${TAG} -p user.err "SERVICE_MANAGER must be either systemd, not ${SERVICE_MANAGER}" +return 1 +fi +# Configures the k2hdkc's service manager default configuration +is_k2hdkc=1 +configure_chmpx_service_manager_file ${SERVICE_MANAGER} ${service_manager_file} ${k2hr3_dkc_runuser} ${chmpx_conf_file} ${chmpx_msg_max} ${is_k2hdkc} ${k2hdkc_loglevel} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "configure_chmpx_service_manager_file should return zero, not ${RET}" +return 1 +fi + +######## +# 13. Installs the k2hdkc service manager configuration and enables it +# systemd controls k2hdkc +# +logger -t ${TAG} -p user.info "13. Installs the k2hdkc-trovectl service manager configuration and enables it" + +install_service_manager_conf ${SERVICE_MANAGER} k2hdkc-trovectl +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "install_service_manager_conf should return zero, not ${RET}" +return 1 +fi + +######## +# 14. Configures the k2hdkc-check-conf's service manager default configuration +# We recommend k2hdkc-check-conf processes work as a service by systemd. +# +logger -t ${TAG} -p user.info "14. Configures the k2hdkc-check-conf's service manager default configuration" + +# Determines the service management file which file format depends on a service manager of the target OS +if test "${SERVICE_MANAGER}" = "systemd"; then +service_manager_file=${SRCDIR}/../service_manager/k2hdkc-check-conf.service +else +logger -t ${TAG} -p user.err "SERVICE_MANAGER must be either systemd, not ${SERVICE_MANAGER}" +return 1 +fi +# Configures the k2hdkc's service manager default configuration +is_k2hdkc=1 +configure_chmpx_service_manager_file ${SERVICE_MANAGER} ${service_manager_file} ${k2hr3_dkc_runuser} ${chmpx_conf_file} ${chmpx_msg_max} ${is_k2hdkc} ${k2hdkc_loglevel} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "configure_chmpx_service_manager_file should return zero, not ${RET}" +return 1 +fi + +######## +# 15. Installs the k2hdkc service manager configuration and enables it +# systemd controls k2hdkc +# +logger -t ${TAG} -p user.info "15. Installs the k2hdkc-check-conf service manager configuration and enables it" + +if test -f "${SRCDIR}/../service_manager/scripts/k2hdkc-check-conf"; then +logger -t ${TAG} -p user.debug "sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-check-conf /usr/libexec/k2hdkc-check-conf" +sudo install -C -m 0755 -o root -v ${SRCDIR}/../service_manager/scripts/k2hdkc-check-conf /usr/libexec/k2hdkc-check-conf +RESULT=$? +if test "${RESULT}" -ne 0; then + logger -t ${TAG} -p user.err "RESULT should be zero, not ${RESULT}" + return 1 +fi +else +logger -t ${TAG} -p user.err "${SRCDIR}/../service_manager/scripts/k2hdkc-check-conf should exist" +return 1 +fi + +install_service_manager_conf ${SERVICE_MANAGER} k2hdkc-check-conf +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "install_service_manager_conf should return zero, not ${RET}" +return 1 +fi + +######## +# 16. Configures the k2hdkc-check-conf's timer default configuration +# We recommend k2hdkc-check-conf processes work as a service by systemd. +# +logger -t ${TAG} -p user.info "16. Configures the k2hdkc-check-conf's timer default configuration" + +# Determines the service management file which file format depends on a service manager of the target OS +if test "${SERVICE_MANAGER}" = "systemd"; then +service_manager_file=${SRCDIR}/../service_manager/k2hdkc-check-conf.timer +else +logger -t ${TAG} -p user.err "SERVICE_MANAGER must be either systemd, not ${SERVICE_MANAGER}" +return 1 +fi +# Configures the k2hdkc's service manager default configuration +is_k2hdkc=1 +configure_chmpx_service_manager_file ${SERVICE_MANAGER} ${service_manager_file} ${k2hr3_dkc_runuser} ${chmpx_conf_file} ${chmpx_msg_max} ${is_k2hdkc} ${k2hdkc_loglevel} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "configure_chmpx_service_manager_file should return zero, not ${RET}" +return 1 +fi + +######## +# 17. Installs the k2hdkc service manager configuration and enables it +# systemd controls k2hdkc +# +logger -t ${TAG} -p user.info "17. Installs the k2hdkc-check-conf timer configuration and enables it" +is_timer=1 +install_service_manager_conf ${SERVICE_MANAGER} k2hdkc-check-conf ${is_timer} +RET=$? +if test "${RET}" -ne 0; then +logger -t ${TAG} -p user.err "install_service_manager_conf should return zero, not ${RET}" +return 1 +fi + +######## +# Start the service! +# +logger -t ${TAG} -p user.debug "sudo systemctl restart chmpx.service" +if test -z "${DRYRUN-}"; then +sudo systemctl restart chmpx.service +RESULT=$? +if test "${RESULT}" -ne 0; then + logger -t ${TAG} -p user.err "'sudo systemctl restart chmpx.service' should return zero, not ${RESULT}" + return 1 +fi + +logger -t ${TAG} -p user.debug "sudo systemctl restart k2hdkc-trove.service" +sudo systemctl restart k2hdkc-trove.service +RESULT=$? +if test "${RESULT}" -ne 0; then + logger -t ${TAG} -p user.err "'sudo systemctl restart k2hdkc-trove.service' should return zero, not ${RESULT}" + return 1 +fi +fi + +logger -t ${TAG} -p user.info "trove.sh configure_systemd done" +return 0 +} + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-check-conf b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-check-conf new file mode 100755 index 0000000..a00968e --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-check-conf @@ -0,0 +1,186 @@ +#!/bin/sh +# +# K2HDKC Cluster on OpenStack Trove +# +# Copyright 2020 Yahoo! Japan Corporation. +# +# A utility that links the K2HDKC cluster as a Database as a Service +# (DBaaS) with the OpenStack Trove system. +# This system is a DBaaS that operates a K2HDKC cluster by controlling +# from Trove (OpenStack) and K2HR3. +# K2HDKC is a distributed KVS(Key Value Store) provided by Yahoo! JAPAN. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Thr Jun 4 2020 +# REVISION: +# + +#---------------------------------------------------------- +# Common variables +#---------------------------------------------------------- +ECHO="/bin/echo" +MV="/bin/mv" +RM="/bin/rm" + +# +# Escape sequence +# +CDEF=$(printf '\033[0m') +CREV=$(printf '\033[7m') +CRED=$(printf '\033[31m') +CGRN=$(printf '\033[32m') + +# +# Local variables +# +CURRENT_TIME=`date "+%Y-%m-%d %H:%M:%S,%3N"` + +#-------------------------------------------------------------- +# Usage and Options +#-------------------------------------------------------------- +# +# Usage +# +func_usage() +{ + ${ECHO} "" + ${ECHO} "Usage: $1 {-h | --help} {options}" + ${ECHO} " -h(--help) print help." + ${ECHO} " -cgp specify output directory path for configuration group parameters and etc.(default: /etc/k2hdkc)" + ${ECHO} " -extdata specify shell script name which loaded from extdata on k2hr3(default: extdata_k2hr3_trove.sh)" + ${ECHO} " -conf specify output configuration(ini) file name(default: server.ini)" + ${ECHO} "" +} + +# +# Check options +# +PRGNAME=`/bin/basename $0` +SCRIPTDIR=`/bin/dirname $0` +CONFIGGROUP_PARAM_DIR="" +K2HDKC_CONF_NAME="" +TROVE_EXTDATA_SH_NAME="" + +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break; + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--HELP" -o "X$1" = "X--help" ]; then + func_usage $PRGNAME + exit 0 + + elif [ "X$1" = "X-conf" -o "X$1" = "X-CONF" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} No parameter is specified for option(-conf), check usage with the -h option.${CDEF}" 1>&2 + exit 1 + fi + K2HDKC_CONF_NAME=$1 + + elif [ "X$1" = "X-cgp" -o "X$1" = "X-CGP" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} No parameter is specified for option(-cgp), check usage with the -h option.${CDEF}" 1>&2 + exit 1 + fi + CONFIGGROUP_PARAM_DIR=$1 + + elif [ "X$1" = "X-extdata" -o "X$1" = "X-EXTDATA" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} No parameter is specified for option(-extdata), check usage with the -h option.${CDEF}" 1>&2 + exit 1 + fi + TROVE_EXTDATA_SH_NAME=$1 + + else + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} Unknown option: $1, check usage with the -h option.${CDEF}" 1>&2 + exit 1 + fi + shift +done + +# +# Set default values +# +if [ "X${K2HDKC_CONF_NAME}" = "X" ]; then + K2HDKC_CONF_NAME="server.ini" +fi +if [ "X${CONFIGGROUP_PARAM_DIR}" = "X" ]; then + CONFIGGROUP_PARAM_DIR="/etc/k2hdkc" +fi + +if [ "X${TROVE_EXTDATA_SH_NAME}" = "X" ]; then + TROVE_EXTDATA_SH_NAME="extdata_k2hr3_trove.sh" +fi +K2HDKC_CONF_FILE="${CONFIGGROUP_PARAM_DIR}/${K2HDKC_CONF_NAME}" +K2HDKC_CONF_TMP_NAME="${K2HDKC_CONF_NAME}.tmp" +K2HDKC_CONF_TMP_FILE="${CONFIGGROUP_PARAM_DIR}/${K2HDKC_CONF_TMP_NAME}" +TROVE_EXTDATA_SH_FILE="${CONFIGGROUP_PARAM_DIR}/${TROVE_EXTDATA_SH_NAME}" + +#-------------------------------------------------------------- +# Main +#-------------------------------------------------------------- +echo "${CGRN}${CREV}[MSG]${CDEF} ${CURRENT_TIME} Start to check and update configration file(${K2HDKC_CONF_FILE}).${CDEF}" 1>&2 + +# +# Check shell script +# +if [ ! -f ${TROVE_EXTDATA_SH_FILE} -o ! -s ${TROVE_EXTDATA_SH_FILE} ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} ${CURRENT_TIME} ${TROVE_EXTDATA_SH_FILE} is not found or empty file.${CDEF}" 1>&2 + exit 1 +fi + +# +# Remove temporary file if exists +# +if [ -f ${K2HDKC_CONF_TMP_FILE} ]; then + ${ECHO} "${CRED}${CREV}[WARN]${CDEF}${CRED} Found ${K2HDKC_CONF_TMP_FILE} for temporary file, thus remove it.${CDEF}" 1>&2 + ${RM} -f ${K2HDKC_CONF_TMP_FILE} +fi + +# +# Create configuration file +# +CREATE_CONF_RESULT_MSG=`${TROVE_EXTDATA_SH_FILE} -l -c ${CONFIGGROUP_PARAM_DIR} -s ${K2HDKC_CONF_TMP_NAME}` +if [ $? -ne 0 ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} ${CURRENT_TIME} Failed to create configuration temporary file(${K2HDKC_CONF_TMP_FILE}) by ${CREATE_CONF_RESULT_MSG}.${CDEF}" 1>&2 + exit 1 +fi + +# +# Check updates +# +diff ${K2HDKC_CONF_TMP_FILE} ${K2HDKC_CONF_FILE} >/dev/null 2>&1 +if [ $? -eq 0 ]; then + ${RM} -f ${K2HDKC_CONF_TMP_FILE} + if [ $? -ne 0 ]; then + ${ECHO} "${CRED}${CREV}[WARN]${CDEF}${CRED} Could not remove the temporary configuration file(${K2HDKC_CONF_TMP_FILE}), but continue...${CDEF}" 1>&2 + fi + ${ECHO} "${CGRN}${CREV}[SUCCESS]${CDEF} ${CURRENT_TIME} There are no changes to the configuration file(${K2HDKC_CONF_FILE}).${CDEF}" 1>&2 + exit 0 +fi + +# +# Update the file +# +${MV} ${K2HDKC_CONF_TMP_FILE} ${K2HDKC_CONF_FILE} >/dev/null 2>&1 +if [ $? -ne 0 ]; then + ${ECHO} "${CRED}${CREV}[ERROR]${CDEF}${CRED} ${CURRENT_TIME} Could not update the configuration file(${K2HDKC_CONF_FILE}).${CDEF}" 1>&2 + exit 1 +fi + +# +# Finish +# +${ECHO} "${CGRN}${CREV}[SUCCESS]${CDEF} ${CURRENT_TIME} Updated the configuration file(${K2HDKC_CONF_FILE}).${CDEF}" 1>&2 +exit 0 + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trove-helper b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trove-helper new file mode 100755 index 0000000..ec14e60 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trove-helper @@ -0,0 +1,756 @@ +#!/bin/sh +# +# K2HDKC Cluster on OpenStack Trove +# +# Copyright 2020 Yahoo! Japan Corporation. +# +# A utility that links the K2HDKC cluster as a Database as a Service +# (DBaaS) with the OpenStack Trove system. +# This system is a DBaaS that operates a K2HDKC cluster by controlling +# from Trove (OpenStack) and K2HR3. +# K2HDKC is a distributed KVS(Key Value Store) provided by Yahoo! JAPAN. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Tue May 26 2020 +# REVISION: +# + +ECHO="/bin/echo" +SLEEP="/bin/sleep" +CP="/bin/cp" +CAT="/bin/cat" +TR="/bin/tr" +PS="/bin/ps" +SUDO="/bin/sudo" +KILL="/bin/kill" +RM="/bin/rm" +TOUCH="/bin/touch" +DATE="/bin/date" +MV="/bin/mv" + +#-------------------------------------------------------------- +# Usage and Options +#-------------------------------------------------------------- +# +# Usage +# +func_usage() +{ + ${ECHO} "" + ${ECHO} "Usage: $1 {-h(--help) | -stop | options}" + ${ECHO} " -h(--help) print help." + ${ECHO} " -stop stop k2hdkc processes" + ${ECHO} " -cgp specify output directory path for configuration group parameters and etc.(default: /etc/k2hdkc)" + ${ECHO} " -conf specify output configuration(ini) file name(default: server.ini)" + ${ECHO} " -startup_timeout specify starup timeout seconds(default: 60s)" + ${ECHO} " -normal_timeout specify normal(after startup) timeout seconds(default: 1s)" + ${ECHO} "" +} + +# +# Check options +# +PRGNAME=`/bin/basename $0` +SCRIPTDIR=`/bin/dirname $0` +CONFIGGROUP_PARAM_DIR="" +K2HDKC_CONF_NAME="" +STARTUP_TIMEOUT= +NORMAL_TIMEOUT= +STOP_SERVICE=0 + +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break; + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--HELP" -o "X$1" = "X--help" ]; then + func_usage $PRGNAME + exit 0 + + elif [ "X$1" = "X-stop" -o "X$1" = "X-STOP" ]; then + STOP_SERVICE=1 + + elif [ "X$1" = "X-conf" -o "X$1" = "X-CONF" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-conf), check usage with the -h option." + exit 1 + fi + K2HDKC_CONF_NAME=$1 + + elif [ "X$1" = "X-cgp" -o "X$1" = "X-CGP" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-cgp), check usage with the -h option." + exit 1 + fi + CONFIGGROUP_PARAM_DIR=$1 + + elif [ "X$1" = "X-startup_timeout" -o "X$1" = "X-STARTUP_TIMOUT" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-startup_timeout), check usage with the -h option." + exit 1 + fi + # check number + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 1 ]; then + ${ECHO} "The option(-startup_timeout) parameter is not number($1), check usage with the -h option." + exit 1 + fi + if [ $1 -lt 0 ]; then + ${ECHO} "The option(-startup_timeout) parameter must be positive value($1) or zero, check usage with the -h option." + exit 1 + fi + STARTUP_TIMEOUT=$1 + + elif [ "X$1" = "X-normal_timeout" -o "X$1" = "X-NORMAL_TIMOUT" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-normal_timeout), check usage with the -h option." + exit 1 + fi + # check number + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 1 ]; then + ${ECHO} "The option(-normal_timeout) parameter is not number($1), check usage with the -h option." + exit 1 + fi + if [ $1 -lt 0 ]; then + ${ECHO} "The option(-normal_timeout) parameter must be positive value($1) or zero, check usage with the -h option." + exit 1 + fi + NORMAL_TIMEOUT=$1 + + else + ${ECHO} "Unknown option: $1, check usage with the -h option." + exit 1 + fi + shift +done + +# +# Set default values +# +if [ "X${K2HDKC_CONF_NAME}" = "X" ]; then + K2HDKC_CONF_NAME="server.ini" +fi +if [ "X${CONFIGGROUP_PARAM_DIR}" = "X" ]; then + CONFIGGROUP_PARAM_DIR="/etc/k2hdkc" +fi + +if [ "X${STARTUP_TIMEOUT}" = "X" ]; then + STARTUP_TIMEOUT=60 +fi +if [ "X${NORMAL_TIMEOUT}" = "X" ]; then + NORMAL_TIMEOUT=1 +fi + +#-------------------------------------------------------------- +# Commmon values +#-------------------------------------------------------------- +# +# Configuration Group parameters +# +CONFFILE_EXTDATA_URL="extdata-url" +CONFFILE_GROUP="cluster-name" +CONFFILE_PORT="chmpx-server-port" +CONFFILE_CTLPORT="chmpx-server-ctlport" +CONFFILE_SLAVE_CTLPORT="chmpx-slave-ctlport" + +STARTUP_MARKING_FILE="${CONFIGGROUP_PARAM_DIR}/k2hdkc-startup-time" +K2HDKC_CONF_FILE="${CONFIGGROUP_PARAM_DIR}/${K2HDKC_CONF_NAME}" +OLD_MANDATORY_PARAM_FILE="${CONFIGGROUP_PARAM_DIR}/mandatory-params" +CHMPX_PROC_PIDFILE="/tmp/k2hdkc-trovectl-chmpx.pid" +K2HDKC_PROC_PIDFILE="/tmp/k2hdkc-trovectl-k2hdkc.pid" + +CONFFILE_EXTDATA_SH="extdata_k2hr3_trove.sh" +TROVE_EXTDATA_SH_FILE="${CONFIGGROUP_PARAM_DIR}/${CONFFILE_EXTDATA_SH}" +CLIENT_USER_AGENT="extdata_k2hr3_trove" + +# +# Check running at startup +# +if [ ! -f ${STARTUP_MARKING_FILE} ]; then + ${DATE} > ${STARTUP_MARKING_FILE} 2>/dev/null + TIMEOUT_SECOND=${STARTUP_TIMEOUT} +else + ${DATE} >> ${STARTUP_MARKING_FILE} 2>/dev/null + TIMEOUT_SECOND=${NORMAL_TIMEOUT} +fi + +#-------------------------------------------------------------- +# Utility functions +#-------------------------------------------------------------- +# +# Message functions +# +ERROR_MESSAGE_BUFF="" +DEBUG_MESSAGE_BUFF="" +reset_message() +{ + ERROR_MESSAGE_BUFF="" + DEBUG_MESSAGE_BUFF="" +} + +set_error() +{ + ERROR_MESSAGE_BUFF="$1" +} + +add_error() +{ + if [ "X${ERROR_MESSAGE_BUFF}" = "X" ]; then + ERROR_MESSAGE_BUFF="$1" + else + ERROR_MESSAGE_BUFF="${ERROR_MESSAGE_BUFF} : $1" + fi +} + +insert_error() +{ + if [ "X${ERROR_MESSAGE_BUFF} "= "X" ]; then + ERROR_MESSAGE_BUFF="$1" + else + ERROR_MESSAGE_BUFF="$1 : ${ERROR_MESSAGE_BUFF}" + fi +} + +set_debug() +{ + DEBUG_MESSAGE_BUFF="$1" +} + +print_message() +{ + if [ "X${ERROR_MESSAGE_BUFF}" != "X" ]; then + echo "[ERROR] ${ERROR_MESSAGE_BUFF}" + fi + if [ "X${DEBUG_MESSAGE_BUFF}" != "X" ]; then + echo "[DEBUG] ${DEBUG_MESSAGE_BUFF}" + fi + reset_message + + if [ "X$1" != "X" ]; then + echo "[MESSAGE] $1" + fi +} + +# +# Get pid from file +# +# $1 - pid file +# +get_pid() +{ + reset_message + PIDFILE=$1 + if [ "X${PIDFILE}" = "X" ]; then + set_error "Pid file path is empty" + echo "0" + return 1 + fi + if [ -f ${PIDFILE} -a -s ${PIDFILE} ]; then + PROC_PID=`${CAT} ${PIDFILE} | ${TR} -d '\n'` + if [ "X${PROC_PID}" != "X" ]; then + ${PS} -p ${PROC_PID} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + set_debug "Pid(${PROC_PID}) is not running" + PROC_PID=0 + fi + else + set_debug "Pid file(${PIDFILE}) has empty value" + PROC_PID=0 + fi + else + set_debug "Not found pid file(${PIDFILE})" + PROC_PID=0 + fi + echo "${PROC_PID}" + return 0 +} + +# +# Stop process +# +# $1 - PID file path +# $2 - Process name +# +stop_process() +{ + reset_message + + if [ "X$1" = "X" -o "X$2" = "X" ]; then + set_error "This function needs two parameters." + return 1 + fi + PROC_PIDFILE=$1 + PROC_NAME=$2 + MAX_LOOP_COUNT=10 + + while [ ${MAX_LOOP_COUNT} -ne 0 ]; do + PROC_PID=`get_pid ${PROC_PIDFILE}` + if [ ${PROC_PID} -eq 0 ]; then + set_debug "${PROC_NAME} process id=${PROC_PID} is 0, so do not need to stop it." + break; + fi + + ${SUDO} ${KILL} -HUP ${PROC_PID} + ${SLEEP} 1 + ${PS} -p ${PROC_PID} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + set_debug "Stopped ${PROC_NAME} process(pid=${PROC_PID}) by signal HUP" + break; + fi + + ${SUDO} ${KILL} -TERM ${PROC_PID} + ${SLEEP} 1 + ${PS} -p ${PROC_PID} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + set_debug "Stopped ${PROC_NAME} process(pid=${PROC_PID}) by signal TERM" + break; + fi + + ${SUDO} ${KILL} -KILL ${PROC_PID} + ${SLEEP} 1 + ${PS} -p ${PROC_PID} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + set_debug "Stopped ${PROC_NAME} process(pid=${PROC_PID}) by signal KILL" + break; + fi + + MAX_LOOP_COUNT=`expr ${MAX_LOOP_COUNT} - 1` + ${SLEEP} 1 + done + + if [ ${MAX_LOOP_COUNT} -eq 0 ]; then + set_error "Could not stop ${PROC_NAME} process(pid=${PROC_PID}) despite ${MAX_LOOP_COUNT} attempts" + return 1 + fi + return 0 +} + +# +# Load extdata for script +# +# $1 extdata url +# +load_extdata_script() +{ + _LOAD_LOCAL_EXTDATA_URL=$1 + + if [ "X${_LOAD_LOCAL_EXTDATA_URL}" = "X" ]; then + add_error "The parameter is empty(extdata url=${_LOAD_LOCAL_EXTDATA_URL})" + return 1 + fi + + # + # Get extdata for script + # + GET_EXTDATA_RESULT=`curl -s -S -X GET -H "User-Agent: ${CLIENT_USER_AGENT}" -w "%{http_code}\n" -o ${TROVE_EXTDATA_SH_FILE} ${_LOAD_LOCAL_EXTDATA_URL} 2>&1` + if [ "X${GET_EXTDATA_RESULT}" != "X200" ];then + add_error "Could not get extdata with status(${GET_EXTDATA_RESULT}) from \"${_LOAD_LOCAL_EXTDATA_URL}\"" + return 1 + fi + if [ ! -f ${TROVE_EXTDATA_SH_FILE} -o ! -s ${TROVE_EXTDATA_SH_FILE} ]; then + add_error "Could not get extdata(empty) from \"${_LOAD_LOCAL_EXTDATA_URL}\"" + return 1 + fi + + # + # Check extdata contents(it must be shell script) + # + CHECK_WORDS=`head -1 ${TROVE_EXTDATA_SH_FILE} 2>/dev/null | cut -c 1-2 2>/dev/null` + if [ "X${CHECK_WORDS}" != "X#!" ]; then + add_error "Loaded extdata does not start #! at first line." + return 1 + fi + chmod 0555 ${TROVE_EXTDATA_SH_FILE} 2>/dev/null + if [ $? -ne 0 ]; then + add_error "Could not set executable permission to ${TROVE_EXTDATA_SH_FILE}." + return 1 + fi + + return 0; +} + + +# +# Register Instance +# +# $1 extdata url +# +register_instance() +{ + reset_message + + # + # Get extdata for script + # + LOAD_EXTDATA_RESULT_MSG=`load_extdata_script $1` + if [ $? -ne 0 ]; then + insert_error "Failed to load extdata for script" + return 1 + fi + + # + # Register instance + # + REGISTER_RESULT_MSG=`${TROVE_EXTDATA_SH_FILE} -r` + if [ $? -ne 0 ]; then + set_error "Failed to register instance" + add_error "${REGISTER_RESULT_MSG}" + return 1 + fi + + return 0 +} + +# +# Delete Instance +# +delete_instance() +{ + reset_message + + # + # Check extdata for script + # + if [ ! -f ${TROVE_EXTDATA_SH_FILE} ]; then + set_error "Not found ${TROVE_EXTDATA_SH_FILE} for deleting instance." + return 1; + fi + + # + # Delete instance + # + DELETE_RESULT_MSG=`${TROVE_EXTDATA_SH_FILE} -d` + if [ $? -ne 0 ]; then + set_error "Failed to delete instance" + add_error "${DELETE_RESULT_MSG}" + return 1 + fi + + return 0 +} + +# +# Stop and Serviceout +# +do_stop_k2hdkc() +{ + reset_message + + # + # Stop k2hdkc process + # + # [NOTE] + # The status will automatically change to SUSPEND. + # + stop_process ${K2HDKC_PROC_PIDFILE} "k2hdkc" + if [ $? -ne 0 ]; then + insert_error "Something error is occurred in stopping k2hdkc process, but continue..." + fi + + # + # Stop chmpx process + # + # [NOTE] + # The status will automatically change to SERVICEOUT. + # It is assumed that AUTOMERGE is ON, and I expect it to become SERVICEOUT + # at the same time as the chmpx process ends. + # + stop_process ${CHMPX_PROC_PIDFILE} "chmpx" + if [ $? -ne 0 ]; then + insert_error "Something error is occurred in stopping chmpx process, but continue..." + fi + + return 0 +} + +# +# Create configuration file +# +# $1 - configuration file name +# +create_configuration_file() +{ + reset_message + + _LOAD_LOCAL_CONF_NAME=$1 + + if [ "X${_LOAD_LOCAL_CONF_NAME}" = "X" ]; then + add_error "The parameter is empty(conf file name=${_LOAD_LOCAL_CONF_NAME})" + return 1 + fi + + # + # Check extdata for script + # + if [ ! -f ${TROVE_EXTDATA_SH_FILE} ]; then + set_error "Not found ${TROVE_EXTDATA_SH_FILE} for creating configuration file." + return 1; + fi + + # + # Create configuration file + # + CREATE_CONF_RESULT_MSG=`${TROVE_EXTDATA_SH_FILE} -l -s ${_LOAD_LOCAL_CONF_NAME}` + if [ $? -ne 0 ]; then + set_error "Failed to create configuration file(${_LOAD_LOCAL_CONF_NAME})." + add_error "${CREATE_CONF_RESULT_MSG}" + return 1 + fi + + return 0 +} + +#-------------------------------------------------------------- +# Main +#-------------------------------------------------------------- +if [ ${STOP_SERVICE} -ne 1 ]; then + ########################### + # Start + ########################### + START_UNIXTIME=`/bin/date '+%s'` + LAG_UNIXTIME=0 + + ${ECHO} "Start at ${START_UNIXTIME}" + while [ ${LAG_UNIXTIME} -le ${TIMEOUT_SECOND} ]; do + IS_BREAK_LOOP=0 + + reset_message + print_message "Start to main loop" + + # + # Load new mandatory parameters + # + if [ -f ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_EXTDATA_URL} -a -s ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_EXTDATA_URL} ]; then + CURRENT_EXTDATA_URL=`${CAT} ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_EXTDATA_URL} | ${TR} -d '\n'` + if [ "X${CURRENT_EXTDATA_URL}" = "XNone" ]; then + CURRENT_EXTDATA_URL="" + fi + else + CURRENT_EXTDATA_URL="" + fi + if [ -f ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_GROUP} -a -s ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_GROUP} ]; then + CURRENT_GROUP=`${CAT} ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_GROUP} | ${TR} -d '\n'` + if [ "X${CURRENT_GROUP}" = "XNone" ]; then + CURRENT_GROUP="" + fi + else + CURRENT_GROUP="" + fi + if [ -f ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_PORT} -a -s ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_PORT} ]; then + CURRENT_PORT=`${CAT} ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_PORT} | ${TR} -d '\n'` + if [ "X${CURRENT_PORT}" = "XNone" ]; then + CURRENT_PORT="" + fi + else + CURRENT_PORT="" + fi + if [ -f ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_CTLPORT} -a -s ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_CTLPORT} ]; then + CURRENT_CTLPORT=`${CAT} ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_CTLPORT} | ${TR} -d '\n'` + if [ "X${CURRENT_CTLPORT}" = "XNone" ]; then + CURRENT_CTLPORT="" + fi + else + CURRENT_CTLPORT="" + fi + if [ -f ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_SLAVE_CTLPORT} -a -s ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_SLAVE_CTLPORT} ]; then + CURRENT_SLAVE_CTLPORT=`${CAT} ${CONFIGGROUP_PARAM_DIR}/${CONFFILE_SLAVE_CTLPORT} | ${TR} -d '\n'` + if [ "X${CURRENT_SLAVE_CTLPORT}" = "XNone" ]; then + CURRENT_SLAVE_CTLPORT="" + fi + else + CURRENT_SLAVE_CTLPORT="" + fi + + # + # Load old mandatory compressed parameters + # + if [ -f ${OLD_MANDATORY_PARAM_FILE} ]; then + OLD_MANDATORY_PARAMS=`${CAT} ${OLD_MANDATORY_PARAM_FILE} 2>/dev/null | ${TR} -d '\n'` + if [ "X${OLD_MANDATORY_PARAMS}" = "X" ]; then + OLD_MANDATORY_PARAMS=",,,," + fi + else + OLD_MANDATORY_PARAMS=",,,," + fi + + # + # Check mandatory parameters + # + NEW_MANDATORY_PARAMS="${CURRENT_EXTDATA_URL},${CURRENT_GROUP},${CURRENT_PORT},${CURRENT_CTLPORT},${CURRENT_SLAVE_CTLPORT}" + if [ "X${NEW_MANDATORY_PARAMS}" = "X${OLD_MANDATORY_PARAMS}" ]; then + NOCHANGE_MANDATORY_PARAMS=1 + else + NOCHANGE_MANDATORY_PARAMS=0 + fi + if [ "X${CURRENT_EXTDATA_URL}" = "X" -o "X${CURRENT_GROUP}" = "X" -o "X${CURRENT_PORT}" = "X" -o "X${CURRENT_CTLPORT}" = "X" -o "X${CURRENT_SLAVE_CTLPORT}" = "X" ]; then + DEFICIENT_MANDATORY_PARAMS=1 + else + DEFICIENT_MANDATORY_PARAMS=0 + fi + + # + # Update configuration files and control processes + # + if [ ${NOCHANGE_MANDATORY_PARAMS} -eq 1 ]; then + # + # Same mandatory parameters + # + print_message "Required parameters remain empty as before" + + if [ ${DEFICIENT_MANDATORY_PARAMS} -eq 1 ]; then + # + # Nothing to do + # + print_message "The process should not have been started because there were no required parameters before. Again, there is no parameter, so nothing is done." + IS_BREAK_LOOP=1 + + else + # + # Check new server.ini from K2HR3, if changed, only update. + # + create_configuration_file ${K2HDKC_CONF_NAME} + if [ $? -ne 0 ]; then + print_message "Something error is occurred in creating configuration, but continue..." + else + print_message + IS_BREAK_LOOP=1 + fi + fi + + else + # + # Changed mandatory parameters + # + + # + # Delete registration for this instance from K2HR3 + # + delete_instance + if [ $? -ne 0 ]; then + print_message "Something error is occurred in removing instance, but continue..." + else + print_message + fi + + # + # Do stop and serviceout + # + do_stop_k2hdkc + if [ $? -ne 0 ]; then + print_message "Something error is occurred in stop and serviceout, but continue..." + else + print_message + fi + + # + # Remove configuration file + # + if [ -f ${K2HDKC_CONF_FILE} ]; then + ${RM} -f ${K2HDKC_CONF_FILE} + print_message "Succeed to remove ${K2HDKC_CONF_FILE}" + fi + + # + # New mandatory parameters are existed, restart processes + # + if [ ${DEFICIENT_MANDATORY_PARAMS} -ne 1 ]; then + # + # Register instance to K2HR3 + # + register_instance ${CURRENT_EXTDATA_URL} + if [ $? -ne 0 ]; then + print_message "Something error is occurred in registering instance, but continue..." + else + print_message + fi + + # + # Create configuration file + # + create_configuration_file ${K2HDKC_CONF_NAME} + if [ $? -ne 0 ]; then + print_message "Something error is occurred in creating configuration, but continue..." + else + print_message + IS_BREAK_LOOP=1 + fi + else + IS_BREAK_LOOP=1 + fi + fi + + if [ ${IS_BREAK_LOOP} -eq 1 ]; then + echo ${NEW_MANDATORY_PARAMS} > ${OLD_MANDATORY_PARAM_FILE} + print_message "Finish to run without any error" + break; + fi + + ${SLEEP} 1 + EXEC_UNIXTIME=`/bin/date '+%s'` + LAG_UNIXTIME=`expr ${EXEC_UNIXTIME} - ${START_UNIXTIME}` + done + + if [ ${LAG_UNIXTIME} -gt ${TIMEOUT_SECOND} ]; then + print_message "Failed to create(update) ${K2HDKC_CONF_FILE} by timeout(${TIMEOUT_SECOND}s)" + fi + +else + ########################### + # Stop + ########################### + STOP_UNIXTIME=`/bin/date '+%s'` + ${ECHO} "Stop at ${STOP_UNIXTIME}" + + # + # Delete registration for this instance from K2HR3 + # + delete_instance + if [ $? -ne 0 ]; then + print_message "Something error is occurred in removing instance, but continue..." + else + print_message + fi + + # + # Do stop and serviceout + # + do_stop_k2hdkc + if [ $? -ne 0 ]; then + print_message "Something error is occurred in stop and serviceout, but continue..." + else + print_message + fi + + # + # Remove configuration file + # + if [ -f ${K2HDKC_CONF_FILE} ]; then + ${RM} -f ${K2HDKC_CONF_FILE} + print_message "Succeed to remove ${K2HDKC_CONF_FILE}" + fi + + # + # Remove mandatory compressed parameter file + # + if [ -f ${OLD_MANDATORY_PARAM_FILE} ]; then + ${RM} -f ${OLD_MANDATORY_PARAM_FILE} + print_message "Succeed to remove ${OLD_MANDATORY_PARAM_FILE}" + fi + + print_message "Finish to stop processes" +fi + +exit 0 + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trovectl b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trovectl new file mode 100755 index 0000000..21ce44e --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/service_manager/scripts/k2hdkc-trovectl @@ -0,0 +1,273 @@ +#!/bin/sh +# +# K2HDKC Cluster on OpenStack Trove +# +# Copyright 2020 Yahoo! Japan Corporation. +# +# A utility that links the K2HDKC cluster as a Database as a Service +# (DBaaS) with the OpenStack Trove system. +# This system is a DBaaS that operates a K2HDKC cluster by controlling +# from Trove (OpenStack) and K2HR3. +# K2HDKC is a distributed KVS(Key Value Store) provided by Yahoo! JAPAN. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Tue May 26 2020 +# REVISION: +# + +ECHO="/bin/echo" +CAT="/bin/cat" +PS="/bin/ps" +SLEEP="/bin/sleep" +KILL="/bin/kill" +RM="/bin/rm" + +# +# Usage +# +func_usage() +{ + ${ECHO} "" + ${ECHO} "Usage: $1 {-h | --help} [chmpx | k2hdkc] {options}" + ${ECHO} " -h(--help) print help." + ${ECHO} " -cgp specify output directory path for configuration group parameters and etc.(default: /etc/k2hdkc)" + ${ECHO} " -conf specify configuration file path" + ${ECHO} " -initwait specify wait seconds at initial startup" + ${ECHO} " -wait specify wait process id by file path" + ${ECHO} " -pidwait specify wait process after detecting pid file" + ${ECHO} " -d specify debug message level parameter:" + ${ECHO} " silent - no output" + ${ECHO} " err - error level" + ${ECHO} " wan - warning level" + ${ECHO} " msg - debug(message) level" + ${ECHO} " dump - communication debug level" + ${ECHO} "" +} + +# +# Signal handler +# +SigHandle() +{ + ${ECHO} "Caught signal $1, try to stop chmpx process." + ${KILL} -$1 ${TARGET_PROC_PID} + EXIT_BY_SIGNAL=1 +} + +# +# Set trap signals +# +# SIGHUP(1) / SIGINT(2) / SIGQUIT(3) / SIGABRT(6) / SIGTERM(15) +# +trap 'SigHandle 1' 1 +trap 'SigHandle 2' 2 +trap 'SigHandle 3' 3 +trap 'SigHandle 6' 6 +trap 'SigHandle 15' 15 + +# +# Check options +# +PRGNAME=`/bin/basename $0` +SCRIPTDIR=`/bin/dirname $0` +CONFIGGROUP_PARAM_DIR="" +CONF_FILE_NAME="" +TARGET_PROC_PATH="/usr/bin" +TARGET_PROC_NAME="" +TARGET_PROC_PIDPATH="/tmp" +DEBUG_LEVEL="silent" +INIT_WAIT_SEC= +PID_WAIT_SEC=15 +WAIT_PID_FILE="" + +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break; + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--HELP" -o "X$1" = "X--help" ]; then + func_usage $PRGNAME + exit 0 + + elif [ "X$1" = "X-cgp" -o "X$1" = "X-CGP" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-cgp), check usage with the -h option." + exit 1 + fi + CONFIGGROUP_PARAM_DIR=$1 + + elif [ "X$1" = "X-conf" -o "X$1" = "X-CONF" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-conf), check usage with the -h option." + exit 1 + fi + CONF_FILE_NAME=$1 + + elif [ "X$1" = "X-wait" -o "X$1" = "X-WAIT" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-wait), check usage with the -h option." + exit 1 + fi + WAIT_PID_FILE=$1 + + elif [ "X$1" = "X-initwait" -o "X$1" = "X-INITWAIT" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-initwait), check usage with the -h option." + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + ${ECHO} "The parameter of option(-initwait) must be number, check usage with the -h option." + exit 1 + fi + INIT_WAIT_SEC=$1 + + elif [ "X$1" = "X-pidwait" -o "X$1" = "X-PIDWAIT" ]; then + shift + if [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-pidwait), check usage with the -h option." + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + ${ECHO} "The parameter of option(-pidwait) must be number, check usage with the -h option." + exit 1 + fi + PID_WAIT_SEC=$1 + + elif [ "X$1" = "X-d" -o "X$1" = "X-D" ]; then + shift + if [ "X$1" = "Xsilent" -o "X$1" = "XSILENT" ]; then + DEBUG_LEVEL="silent" + elif [ "X$1" = "Xerr" -o "X$1" = "XERR" ]; then + DEBUG_LEVEL="err" + elif [ "X$1" = "Xwan" -o "X$1" = "XWAN" ]; then + DEBUG_LEVEL="wan" + elif [ "X$1" = "Xmsg" -o "X$1" = "XMSG" ]; then + DEBUG_LEVEL="msg" + elif [ "X$1" = "Xdump" -o "X$1" = "XDUMP" ]; then + DEBUG_LEVEL="dump" + elif [ "X$1" = "X" ]; then + ${ECHO} "No parameter is specified for option(-d), check usage with the -h option." + exit 1 + else + ${ECHO} "Unknown option(-d) parameter: $1, check usage with the -h option." + exit 1 + fi + + elif [ "X$1" = "Xchmpx" -o "X$1" = "XCHMPX" ]; then + TARGET_PROC_NAME="chmpx" + + elif [ "X$1" = "Xk2hdkc" -o "X$1" = "XK2HDKC" ]; then + TARGET_PROC_NAME="k2hdkc" + + else + ${ECHO} "Unknown option: $1, check usage with the -h option." + exit 1 + fi + shift +done + +# +# Configuration file +# +if [ "X${CONF_FILE_NAME}" = "X" ]; then + CONF_FILE_NAME="server.ini" +fi +if [ "X${CONFIGGROUP_PARAM_DIR}" = "X" ]; then + CONFIGGROUP_PARAM_DIR="/etc/k2hdkc" +fi +CONF_FILE_PATH="${CONFIGGROUP_PARAM_DIR}/${CONF_FILE_NAME}" + +if [ "X${TARGET_PROC_NAME}" = "X" ]; then + ${ECHO} "$PRGNAME must specify \"chmpx\" or \"k2hdkc\" program type, check usage with the -h option." + exit 1 +fi + +# +# Wait for seconds at initial startup +# +if [ "X${INIT_WAIT_SEC}" != "X" ]; then + ${ECHO} "Wait for ${INIT_WAIT_SEC} seconds specified at initial startup." + ${SLEEP} ${INIT_WAIT_SEC} +fi + +# +# Run main process +# +START_MSG_PREFIX="Start" +EXIT_BY_SIGNAL=0 +while true; do + # + # Wait configuration file + # + ${ECHO} "Wait for making configuration file(${CONF_FILE_PATH})" + while true; do + FOUND_CONF_FILE=0 + if [ -f ${CONF_FILE_PATH} ]; then + if [ -s ${CONF_FILE_PATH} ]; then + ${ECHO} "Found configuration file(${CONF_FILE_PATH}), stop waiting." + # + # Check other process running + # + if [ "X${WAIT_PID_FILE}" != "X" ]; then + ${ECHO} "Check for other process by ${WAIT_PID_FILE}" + if [ -f ${WAIT_PID_FILE} ]; then + WAIT_PID=`${CAT} ${WAIT_PID_FILE} 2>/dev/null` + if [ "X${WAIT_PID}" != "X" ]; then + ${PS} -p ${WAIT_PID} >/dev/null 2>&1 + if [ $? -eq 0 ]; then + ${ECHO} "Wait for ${PID_WAIT_SEC} seconds after detecting pid file." + ${SLEEP} ${PID_WAIT_SEC} + break; + fi + fi + fi + else + break; + fi + fi + fi + ${SLEEP} 1 + done + + ${ECHO} "${START_MSG_PREFIX} process ${TARGET_PROC_NAME}." + ${TARGET_PROC_PATH}/${TARGET_PROC_NAME} -conf ${CONF_FILE_PATH} -d ${DEBUG_LEVEL} & + TARGET_PROC_PID=$! + ${ECHO} "${TARGET_PROC_PID}" > ${TARGET_PROC_PIDPATH}/${PRGNAME}-${TARGET_PROC_NAME}.pid + + wait ${TARGET_PROC_PID} >/dev/null 2>&1 + + if [ -f ${TARGET_PROC_PIDPATH}/${PRGNAME}-${TARGET_PROC_NAME}.pid ]; then + CURRENT_PID=`${CAT} ${TARGET_PROC_PIDPATH}/${PRGNAME}-${TARGET_PROC_NAME}.pid 2>/dev/null` + if [ "X${CURRENT_PID}" != "X" ]; then + if [ ${CURRENT_PID} -eq ${TARGET_PROC_PID} ]; then + ${RM} -f ${TARGET_PROC_PIDPATH}/${PRGNAME}-${TARGET_PROC_NAME}.pid + fi + else + ${RM} -f ${TARGET_PROC_PIDPATH}/${PRGNAME}-${TARGET_PROC_NAME}.pid + fi + fi + ${ECHO} "Process ${TARGET_PROC_NAME}(${PID}) is exited." + + if [ ${EXIT_BY_SIGNAL} -ne 0 ]; then + exit 0 + fi + + ${SLEEP} 1 + START_MSG_PREFIX="Restart" +done + +exit 0 + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/__init__.py b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/__init__.py new file mode 100644 index 0000000..6b27c09 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/__init__.py @@ -0,0 +1,27 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/manager.py b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/manager.py new file mode 100644 index 0000000..8497bd9 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/manager.py @@ -0,0 +1,302 @@ +# -*- coding: utf-8 -*- +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# +"""OpenStack Clusters API guestagent client implementation.""" + +from oslo_log import log as logging +from trove.common import cfg +from trove.common import exception +from trove.common import utils +from trove.guestagent import backup +from trove.guestagent.datastore import manager +from trove.guestagent.datastore.experimental.k2hdkc import service +from trove.guestagent.common import operating_system +from trove.guestagent import volume +from trove.common.instance import ServiceStatuses +from trove.common.notification import EndNotification +import os.path +from pathlib import Path + +CONF = cfg.CONF +K2HDKC_MANAGER = 'k2hdkc' +LOG = logging.getLogger(__name__) +SERVICE_STATUS_TIMEOUT = 60 +K2HDKC_CONFIG_PARAM_DIR = '/etc/k2hdkc' + + +class Manager(manager.Manager): + """OpenStack Clusters API guest-agent server implementation.""" + def __init__(self): + """MUST be implemented.""" + super().__init__(K2HDKC_MANAGER) + self._service_status_timeout = SERVICE_STATUS_TIMEOUT + conf_dir = Path(K2HDKC_CONFIG_PARAM_DIR) + if not conf_dir.exists(): + try: + utils.execute_with_timeout( + "/bin/sudo mkdir -p {}".format(K2HDKC_CONFIG_PARAM_DIR), + shell=True) + except exception.ProcessExecutionError: + LOG.warning("Failure: sudo mkdir -p {}".format( + K2HDKC_CONFIG_PARAM_DIR)) + try: + utils.execute_with_timeout( + "/bin/sudo chmod 0777 {}".format(K2HDKC_CONFIG_PARAM_DIR), + shell=True) + except exception.ProcessExecutionError: + LOG.warning( + "Failure: sudo chmod 0777 {}".format(K2HDKC_CONFIG_PARAM_DIR)) + self._appstatus = service.K2hdkcAppStatus() + self._app = service.K2hdkcApp(self._appstatus) + + @property + def status(self): + """MUST be implemented. + + GuestAgent periodically calls self.status.update() that + means self._appstatus.update() should be implemented. + """ + return self._appstatus + + ################# + # Instance related + ################# + def do_prepare(self, context, packages, databases, memory_mb, users, + device_path, mount_point, backup_info, config_contents, + root_password, overrides, cluster_config, snapshot): + # pylint: disable=too-many-arguments + """MUST be implemented. trove.guestagent.datastore. + trove.guestagent.datastore.manager calls self.do_prepare in + trove.guestagent.datastore.manager.prepare() + """ + LOG.debug("Starting initial configuration.") + if device_path: + device = volume.VolumeDevice(device_path) + # unmount if device is already mounted + device.unmount_device(device_path) + device.format() + device.mount(mount_point) + operating_system.chown(mount_point, 'k2hdkc', 'k2hdkc', as_root=True) + operating_system.create_directory(mount_point + '/data', + 'k2hdkc', + 'k2hdkc', + force=True, + as_root=True) + operating_system.create_directory(mount_point + '/data/snapshots', + 'k2hdkc', + 'k2hdkc', + force=True, + as_root=True) + LOG.debug('Mounted the volume.') + + if config_contents: + LOG.debug("Applying configuration.") + self._app.configuration_manager.save_configuration(config_contents) + + if overrides: + LOG.debug("Applying self._app.update_overrides") + self._app.update_overrides(context, overrides) + + LOG.debug("Applying _create_k2hdkc_overrides_files") + self._create_k2hdkc_overrides_files() + + ################# + # Backup + ################# + if not cluster_config: + if backup_info: + self._perform_restore(backup_info, context, mount_point) + + def update_overrides(self, context, overrides, remove=False): + # pylint: disable=arguments-differ + """trove.guestagent.datastore.manager invokes this method + only if overrides defined. + """ + LOG.debug("k2hdkc update_overrides %(overrides)s", + {'overrides': overrides}) + if remove: + self._app.remove_overrides() + else: + self._app.update_overrides(context, overrides, remove) + + self._create_k2hdkc_overrides_files() + + def apply_overrides(self, context, overrides): + """Configuration changes are made in the config YAML file and + require restart, so this is a no-op. + """ + + def _create_k2hdkc_key_files(self, key, empty_is_changed=False): + """Detects the key from the overrides. + Returns true if the key exists in the overrides. false otherwise. + Returns true if the empty_is_changed is true and the key is null. + """ + result = False + file_path = K2HDKC_CONFIG_PARAM_DIR + '/' + key + value = self._app.get_value(key) + + current_param_value = None + file_exist = False + if os.path.isfile(file_path): + file_exist = True + with open(file_path, 'r') as override_param_file: + current_param_value = override_param_file.read().replace( + '\n', '') + if not current_param_value or len(current_param_value) == 0: + current_param_value = None + + if not value: + if not current_param_value: + if empty_is_changed: + result = True + else: + result = True + + # Remove file + if file_exist: + os.remove(file_path) + + else: + if value != current_param_value: + result = True + + # Update file + with open(file_path, 'w') as override_param_file: + override_param_file.write(str(value)) + + return result + + def _create_k2hdkc_overrides_files(self): + """puts values to files in /etc/k2hdkc. + """ + is_changed = False + + if self._create_k2hdkc_key_files('cluster-name', True): + is_changed = True + + if self._create_k2hdkc_key_files('extdata-url', True): + is_changed = True + + if self._create_k2hdkc_key_files('chmpx-server-port', True): + is_changed = True + + if self._create_k2hdkc_key_files('chmpx-server-ctlport', True): + is_changed = True + + if self._create_k2hdkc_key_files('chmpx-slave-ctlport', True): + is_changed = True + + if is_changed: + try: + utils.execute_with_timeout( + "/bin/sudo /usr/bin/systemctl restart k2hdkc-trove", + shell=True, + timeout=60) + except exception.ProcessExecutionError: + LOG.warning("Failed to restart k2hdkc.") + + def post_prepare(self, context, packages, databases, memory_mb, users, + device_path, mount_point, backup_info, config_contents, + root_password, overrides, cluster_config, snapshot): + """Be invoked after successful prepare. + """ + services = [ + 'chmpx-trovectl', 'k2hdkc-trovectl', 'k2hdkc-check-conf.timer' + ] + service_error = False + for my_service in services: + try: + out, err = utils.execute_with_timeout( + "/usr/bin/systemctl is-active {}".format(my_service), + shell=True) + LOG.debug("out=(%s) err=(%s)", out, err) + except exception.ProcessExecutionError as exc: + if "activating" in exc.stdout: + LOG.debug("k2hdkc is activating now.") + elif "inactive" in exc.stdout: + out, err = utils.execute_with_timeout( + "sudo systemctl start {}".format(my_service), + shell=True) + LOG.debug("out=(%s) err=(%s)", out, err) + else: + LOG.exception("Error getting K2HDKC status.") + service_error = True + for my_service in services: + try: + out, err = utils.execute_with_timeout( + "/usr/bin/systemctl is-enabled {}".format(my_service), + shell=True) + LOG.debug("out=(%s) err=(%s)", out, err) + except exception.ProcessExecutionError as exc: + if "disabled" in exc.stdout: + out, err = utils.execute_with_timeout( + "sudo systemctl enable {}".format(my_service), + shell=True) + LOG.debug("out=(%s) err=(%s)", out, err) + else: + LOG.exception("Error getting K2HDKC status.") + service_error = True + + # put PREPARE_END_FILENAME in GUESTAGENT_DIR + if service_error: + LOG.error("Error starting k2hdkc services") + else: + self.status.set_ready() + + ################# + # Service related + ################# + def restart(self, context): + """MUST be implemented.""" + self.status.restart_db_service(service.K2HDKC_SERVICE, + self._service_status_timeout) + + def stop_db(self, context, do_not_start_on_reboot=False): + """Stop the database server. + + This function is called at: + https://github.com/openstack/trove/blob/master/trove/guestagent/api.py#L412 + """ + LOG.debug("do_not_start_on_reboot %(do_not_start_on_reboot)s", + {'do_not_start_on_reboot': do_not_start_on_reboot}) + + self._app.stop_db(do_not_start_on_reboot=do_not_start_on_reboot) + + ###################### + # Backup + ###################### + def _perform_restore(self, backup_info, context, restore_location): + try: + backup.restore(context, backup_info, restore_location) + if self._appstatus.is_running: + raise RuntimeError("Cannot reset the cluster name." + "The service is still running.") + self._app.stop_db() + except Exception as exp: + LOG.error("backup_info[id] = %s.", backup_info['id']) + self._app.status.set_status(ServiceStatuses.FAILED) + raise exp + LOG.info("Restored database successfully.") + + # pylint: disable=no-self-use + def create_backup(self, context, backup_info): + """ invokes the k2hdkc backup implementation + """ + with EndNotification(context): + backup.backup(context, backup_info) diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/service.py b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/service.py new file mode 100644 index 0000000..2a06262 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/datastore/experimental/k2hdkc/service.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +from oslo_log import log as logging +from trove.common import cfg +from trove.common import exception +from trove.common import instance as rd_instance +from trove.common import utils +from trove.common.stream_codecs import KeyValueCodec +from trove.guestagent.common.configuration import ConfigurationManager +from trove.guestagent.datastore import service +from trove.guestagent.common import guestagent_utils + +CONF = cfg.CONF +LOG = logging.getLogger(__name__) +SERVER_INI = '/etc/k2hdkc/server.ini' +K2HDKC_TROVE_INI = '/etc/k2hdkc/k2hdkc-trove.cfg' +K2HDKC_SERVICE = ['k2hdkc-trove'] + +# [TODO] +# At this time, the guest operating system only supports CentOS. +# Therefore, the values ??of the following variables are set, +# but if the supported OS expands in the future, please change +# the values ??variably. +OWNER = 'centos' +GROUP = 'centos' + +class K2hdkcApp(object): + """ + Handles installation and configuration of K2hdkc + on a Trove instance. + """ + def __init__(self, status, state_change_wait_time=None): + LOG.debug("K2hdkcApp init") + self._status = status + self.k2hdkc_owner = OWNER + self.k2hdkc_group = GROUP + self.configuration_manager = (ConfigurationManager( + K2HDKC_TROVE_INI, + OWNER, + GROUP, + KeyValueCodec(delimiter='=', + comment_marker='#', + line_terminator='\n'), + requires_root=True)) + self.state_change_wait_time = CONF.state_change_wait_time + + def update_overrides(self, context, overrides, remove=False): + """ invokes the configuration_manager.apply_user_override() """ + LOG.debug( + "update_overrides - implement as like as others(but not test)") + if overrides: + LOG.debug("K2hdkcApp update_overrides") + self.configuration_manager.apply_user_override(overrides) + + def remove_overrides(self): + """ invokes the configuration_manager.remove_user_override() """ + self.configuration_manager.remove_user_override() + + def get_value(self, key): + """ returns the k2hdkc configuration_manager """ + return self.configuration_manager.get_value(key) + + @property + def k2hdkc_data_dir(self): + """ returns the k2hdkc data directory """ + return guestagent_utils.build_file_path(CONF.k2hdkc.mount_point, + 'data') + + @property + def service_candidates(self): + """ returns the k2hdkc list """ + return ['k2hdkc-trove'] + + def stop_db(self, update_db=False, do_not_start_on_reboot=False): + """ stops k2hdkc database """ + LOG.debug("stop_db - called") + self._status.stop_db_service(self.service_candidates, + self.state_change_wait_time, + disable_on_boot=do_not_start_on_reboot, + update_db=update_db) + + +class K2hdkcAppStatus(service.BaseDbStatus): # pylint: disable=too-few-public-methods + """ + Handles all of the status updating for the K2hdkc guest agent. + """ + def __init__(self): + LOG.debug("K2hdkcAppStatus::__init__") + super().__init__() + + def _get_actual_db_status(self): # pylint: disable=no-self-use + """ It is called from wait_for_real_status_to_change_to of BaseDbStatus class. + """ + LOG.debug("K2hdkcAppStatus::_get_actual_db_status") + try: + out, err = utils.execute_with_timeout( + "/usr/bin/systemctl is-active k2hdkc-trove", shell=True) + LOG.debug("out=(%s) err=(%s)", out, err) + return rd_instance.ServiceStatuses.RUNNING + except exception.ProcessExecutionError as exc: + if "activating" in exc.stdout: + LOG.debug("k2hdkc is activating now, so return running.") + return rd_instance.ServiceStatuses.RUNNING + elif "inactive" in exc.stdout: + LOG.debug("k2hdkc is inactive, so return shutdown.") + return rd_instance.ServiceStatuses.SHUTDOWN + else: + LOG.exception("Error getting K2HDKC status.") + return rd_instance.ServiceStatuses.SHUTDOWN diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/backup/experimental/k2hdkc_impl.py b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/backup/experimental/k2hdkc_impl.py new file mode 100644 index 0000000..2d7631c --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/backup/experimental/k2hdkc_impl.py @@ -0,0 +1,136 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# This product includes software developed at +# The Apache Software Foundation (http://www.apache.org/). +# +# Copyright 2014 Mirantis Inc. +# All Rights Reserved. +# Copyright 2015 Tesora Inc. +# All Rights Reserved.s +# + +from oslo_log import log as logging + +from trove.common import exception +from trove.common.i18n import _ +from trove.common import utils +from trove.guestagent.common import operating_system +from trove.guestagent.datastore.experimental.k2hdkc import service +from trove.guestagent.strategies.backup import base + +LOG = logging.getLogger(__name__) + + +class K2hdkcArchive(base.BackupRunner): + """Implementation of backup using the Nodetool (http://goo.gl/QtXVsM) + utility. + """ + + # It is recommended to include the system keyspace in the backup. + # Keeping the system keyspace will reduce the restore time + # by avoiding need to rebuilding indexes. + + __strategy_name__ = 'k2hdkcarchive' + _SNAPSHOT_EXTENSION = 'k2har' + + def __init__(self, filename, **kwargs): + self._appstatus = service.K2hdkcAppStatus() + self._app = service.K2hdkcApp(self._appstatus) + super().__init__(filename, **kwargs) + + def _run_pre_backup(self): + """Take snapshot(s) for all keyspaces. + Remove existing ones first if any. + Snapshot(s) will be stored in the data directory tree: + ///snapshots/ + """ + self._remove_snapshot(self.filename) + self._snapshot_all_keyspaces(self.filename) + + # Commonly 'self.command' gets resolved in the base constructor, + # but we can build the full command only after having taken the + # keyspace snapshot(s). + self.command = self._backup_cmd + self.command + + def _run_post_backup(self): + """Remove the created snapshot(s). + """ + self._remove_snapshot(self.filename) + + def _remove_snapshot(self, snapshot_name): + utils.execute('/usr/libexec/k2hdkc-snapshot', '--remove', + '%s' % self._app.k2hdkc_data_dir, '%s' % snapshot_name) + + def _snapshot_all_keyspaces(self, snapshot_name): + utils.execute('/usr/libexec/k2hdkc-snapshot', '--save', + '%s' % self._app.k2hdkc_data_dir, '%s' % snapshot_name) + + @property + def cmd(self): + """Gets the command name.""" + return self.zip_cmd + self.encrypt_cmd + " -pbkdf2 -iter 100000" + + @property + def _backup_cmd(self): + """Command to collect and package keyspace snapshot(s). + """ + return self._build_snapshot_package_cmd(self._app.k2hdkc_data_dir, + self.filename) + + def _build_snapshot_package_cmd(self, data_dir, snapshot_name): + """Collect all files for a given snapshot and build a package + command for them. + Transform the paths such that the backup can be restored simply by + extracting the archive right to an existing data directory + (i.e. place the root into the and + remove the 'snapshots/' portion of the path). + Attempt to preserve access modifiers on the archived files. + Assert the backup is not empty as there should always be + at least the system keyspace. Fail if there is nothing to backup. + """ + snapshot_files = operating_system.list_files_in_directory( + data_dir, + recursive=True, + include_dirs=False, + pattern=r'.*/snapshots/%s.%s' % + (snapshot_name, self._SNAPSHOT_EXTENSION), + as_root=True) + num_snapshot_files = len(snapshot_files) + LOG.debug('Found %(num)d snapshot (*.%(ext)s) files.', { + 'num': num_snapshot_files, + 'ext': self._SNAPSHOT_EXTENSION + }) + if num_snapshot_files > 0: + return ('sudo tar ' + '--transform="s#snapshots/%s/##" -cpPf - -C "%s" "%s"' % + (snapshot_name, data_dir, '" "'.join(snapshot_files))) + + # There should always be at least the system keyspace snapshot. + raise exception.BackupCreationError(_("No data found.")) + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/restore/experimental/k2hdkc_impl.py b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/restore/experimental/k2hdkc_impl.py new file mode 100644 index 0000000..9dc5056 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/guestagent/strategies/restore/experimental/k2hdkc_impl.py @@ -0,0 +1,120 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# This product includes software developed at +# The Apache Software Foundation (http://www.apache.org/). +# +# Copyright 2014 Mirantis Inc. +# All Rights Reserved. +# Copyright 2015 Tesora Inc. +# All Rights Reserved.s +# + +import re +from oslo_log import log as logging + +from trove.common import utils +from trove.guestagent.common import operating_system +from trove.guestagent.datastore.experimental.k2hdkc import service +from trove.guestagent.strategies.restore import base + +LOG = logging.getLogger(__name__) + + +class K2hdkcArchive(base.RestoreRunner): + """Implementation of restore for k2hdkc. + """ + + __strategy_name__ = 'k2hdkcarchive' + + def __init__(self, storage, **kwargs): + self._appstatus = service.K2hdkcAppStatus() + self._app = service.K2hdkcApp(self._appstatus) + """ + Get the filename from the swift url to restore. + """ + is_match = re.search(r'http:/(/(.*))/(.*)?\.gz\.enc$', + kwargs.get('location')) + if is_match is not None: + self._id = re.findall(r'http:/(/(.*))/(.*)?\.gz\.enc$', + kwargs.get('location'))[0][2] + else: + self._id = None + + kwargs.update({'restore_location': self._app.k2hdkc_data_dir}) + super().__init__(storage, **kwargs) + + def pre_restore(self): + """Prepare the data directory for restored files. + The directory itself is not included in the backup archive + (i.e. the archive is rooted inside the data directory). + This is to make sure we can always restore an old backup + even if the standard guest agent data directory changes. + """ + + LOG.debug('Initializing a data directory.') + operating_system.create_directory(self.restore_location, + user=self._app.k2hdkc_owner, + group=self._app.k2hdkc_group, + force=True, + as_root=True) + + def post_restore(self): + """Updated ownership on the restored files. + """ + LOG.debug('Updating ownership of the restored files.') + # Owner of the files should be k2hdkc:k2hdkc. + operating_system.chown(self.restore_location, + 'k2hdkc', + 'k2hdkc', + recursive=True, + force=True, + as_root=True) + + utils.execute('/usr/libexec/k2hdkc-snapshot', '--restore', + '%s' % self.restore_location, '%s' % self._id) + + @property + def decrypt_cmd(self): + """command to decrypt. + """ + # Adds openssl options to avoid warings. + if self.is_encrypted: + return ( + 'openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -salt -pass pass:%s | ' + % self.decrypt_key) + return () + + @property + def base_restore_cmd(self): + """Command to extract a backup archive into a given location. + Attempt to preserve access modifiers on the archived files. + """ + return 'sudo tar -xpPf - -C "%(restore_location)s"' + + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/patch.sh b/dib/elements/centos-8-k2hdkc/install.d/trove/patch.sh new file mode 100755 index 0000000..cebacea --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/patch.sh @@ -0,0 +1,158 @@ +#!/bin/sh +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# A simple script to create a k2hr3-dkc server on localhost +# + +# Sets the default locale. LC_ALL has precedence over other LC* variables. +unset LANG +unset LANGUAGE +LC_ALL=en_US.utf8 +export LC_ALL + +# Sets PATH. setup_*.sh uses useradd command +PATH=${PATH}:/bin:/usr/bin:/usr/sbin:/sbin + +# an unset parameter expansion will fail +set -u + +# umask 022 is enough +umask 022 + +# defines environments +SRCDIR=$(cd $(dirname "$0") && pwd) + +function k2hdkc_patch_file { + ORIGINAL_FILE=$1 + PATCH_FILE=$2 + if test -f "${ORIGINAL_FILE}"; then + if test -f "${PATCH_FILE}" ; then + echo "patch for ${ORIGINAL_FILE}" + patch ${ORIGINAL_FILE} < ${PATCH_FILE} + else + echo "NO ${PATCH_FILE}" + exit 1 + fi + else + echo "NO ${ORIGINAL_FILE}" + exit 1 + fi +} + +if test -f "/etc/os-release"; then + . /etc/os-release + OS_NAME=$ID + OS_VERSION=$VERSION_ID +else + echo "unknown OS, no /etc/os-release and /etc/centos-release" + exit 1 +fi + +if test -z "${OS_NAME}" -o -z "${OS_VERSION}"; then + echo "unknown OS, neither /etc/os-release nor /etc/centos-release" + exit 1 +fi +echo "${OS_NAME} ${OS_VERSION}" + +# 1. sets the package repository root +SITE_PACKAGES_ROOT=/opt/guest-agent-venv/lib64/python3.6/site-packages + +# 2. applies patches +which patch +if test "${?}" != 0; then + echo "patch not found" + if test "${OS_NAME}" = "centos" -a "${OS_VERSION}" = "8"; then + echo "sudo dnf install -y patch" + sudo dnf install -y patch + if test "${?}" != 0; then + echo "patch install failed" + exit 1 + fi + else + echo "Currently ${OS_NAME} && ${OS_VERSION} not supported" + exit 1 + fi +else + echo "patch command found" +fi +# 2.1. trove/common/cfg.py +k2hdkc_patch_file ${SITE_PACKAGES_ROOT}/trove/common/cfg.py ${SRCDIR}/patches/trove-common-cfg.py + +# 2.2. trove/guestagent/datastore/experimental/k2hdkc +if ! test -d "${SITE_PACKAGES_ROOT}/trove/guestagent/datastore/experimental"; then + sudo mkdir -p ${SITE_PACKAGES_ROOT}/trove/guestagent/datastore/experimental +fi + +echo "installing ${SITE_PACKAGES_ROOT}/trove/guestagent/datastore/experimental" +sudo cp -r ${SRCDIR}/guestagent/datastore/experimental/k2hdkc ${SITE_PACKAGES_ROOT}/trove/guestagent/datastore/experimental + +# 2.3. trove/guestagent/dbaas.py +k2hdkc_patch_file ${SITE_PACKAGES_ROOT}/trove/guestagent/dbaas.py ${SRCDIR}/patches/trove-guestagent-dbaas.py + +# 2.4. trove/common/configurations.py +k2hdkc_patch_file ${SITE_PACKAGES_ROOT}/trove/common/configurations.py ${SRCDIR}/patches/trove-common-configurations.py + +# 2.5. trove/common/template.py +k2hdkc_patch_file ${SITE_PACKAGES_ROOT}/trove/common/template.py ${SRCDIR}/patches/trove-common-template.py + +# 2.6. trove/guestagent/strategies/backup/experimental/k2hdkc_impl.py +if ! test -d "${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/backup/experimental"; then + sudo mkdir -p ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/backup/experimental +fi + +for file in $(find ${SRCDIR}/guestagent/strategies/backup/experimental -maxdepth 1 -type f); do + echo "cp ${file} ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/backup/experimental" + cp ${file} ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/backup/experimental +done + + +# 2.7. trove/guestagent/strategies/restore/experimental/k2hdkc_impl.py +if ! test -d "${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/restore/experimental"; then + sudo mkdir -p ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/restore/experimental +fi + +for file in $(find ${SRCDIR}/guestagent/strategies/restore/experimental -maxdepth 1 -type f); do + echo "cp ${file} ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/restore/experimental" + cp ${file} ${SITE_PACKAGES_ROOT}/trove/guestagent/strategies/restore/experimental +done + +# 2.8. usr/libexec/k2hdkc-snapshot +if test -f "${SRCDIR}/usr/libexec/k2hdkc-snapshot"; then + echo "sudo install -C -m 0755 -o root -v ${SRCDIR}/usr/libexec/k2hdkc-snapshot /usr/libexec/k2hdkc-snapshot" + sudo install -C -m 0755 -o root -v ${SRCDIR}/usr/libexec/k2hdkc-snapshot /usr/libexec/k2hdkc-snapshot + RESULT=$? + if test "${RESULT}" -ne 0; then + echo "RESULT should be zero, not ${RESULT}" + exit 1 + fi +else + echo "${SRCDIR}/usr/libexec/k2hdkc-snapshot should exist" + exit 1 +fi + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-cfg.py b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-cfg.py new file mode 100644 index 0000000..ac9fa29 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-cfg.py @@ -0,0 +1,148 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +diff --git a/trove/common/cfg.py b/trove/common/cfg.py +index a97623f6..4793725d 100644 +--- a/trove/common/cfg.py ++++ b/trove/common/cfg.py +@@ -370,7 +370,8 @@ common_opts = [ + 'couchdb': 'f0a9ab7b-66f7-4352-93d7-071521d44c7c', + 'vertica': 'a8d805ae-a3b2-c4fd-gb23-b62cee5201ae', + 'db2': 'e040cd37-263d-4869-aaa6-c62aa97523b5', +- 'mariadb': '7a4f82cc-10d2-4bc6-aadc-d9aacc2a3cb5'}, ++ 'mariadb': '7a4f82cc-10d2-4bc6-aadc-d9aacc2a3cb5', ++ 'k2hdkc': '07e220a2-a8c6-4061-b9a6-a654b2f5fc2e'}, + help='Unique ID to tag notification events.'), + cfg.StrOpt('network_label_regex', default='^private$', + help='Regular expression to match Trove network labels.'), +@@ -1515,11 +1516,98 @@ mariadb_opts = [ + 'galera_common.guestagent.GaleraCommonGuestAgentStrategy', + help='Class that implements datastore-specific Guest Agent API ' + 'logic.'), ++ cfg.IntOpt('default_password_length', ++ default='${mysql.default_password_length}', ++ help='Character length of generted passwords.', ++ deprecated_name='default_password_length', ++ deprecated_group='DEFAULT'), ++] ++ ++# K2hdkc ++k2hdkc_group = cfg.OptGroup( ++ 'k2hdkc', title='K2HDKC options', ++ help="Oslo option group designed for K2hdkc datastore") ++k2hdkc_opts = [ ++ cfg.BoolOpt('icmp', default=False, ++ help='Whether to permit ICMP.', ++ deprecated_for_removal=True), ++ cfg.ListOpt('tcp_ports', default=["8020", "8021", "8031"], ++ item_type=ListOfPortsType, ++ help='List of TCP ports and/or port ranges to open ' ++ 'in the security group (only applicable ' ++ 'if trove_security_groups_support is True).'), ++ cfg.ListOpt('udp_ports', default=[], item_type=ListOfPortsType, ++ help='List of UDP ports and/or port ranges to open ' ++ 'in the security group (only applicable ' ++ 'if trove_security_groups_support is True).'), ++ cfg.StrOpt('mount_point', default='/var/lib/k2hdkc', ++ help="Filesystem path for mounting " ++ "volumes if volume support is enabled."), ++ cfg.BoolOpt('root_on_create', default=False, ++ help='Enable the automatic creation of the root user for the ' ++ 'service during instance-create. The generated password for ' ++ 'the root user is immediately returned in the response of ' ++ "instance-create as the 'password' field."), ++ cfg.IntOpt('ctrl_port', default=8021, ++ help='Control Port to connet with chmpx process.'), ++ cfg.IntOpt('usage_timeout', default=400, ++ help='Maximum time (in seconds) to wait for a Guest to become ' ++ 'active.'), ++ cfg.BoolOpt('volume_support', default=True, ++ help='Whether to provision a Cinder volume for datadir.'), ++ cfg.StrOpt('device_path', default='/dev/vdb', ++ help='Device path for volume if volume support is enabled.'), ++ cfg.StrOpt('root_controller', ++ default='trove.extensions.common.service.DefaultRootController', ++ help='Root controller implementation for k2hdkc.'), ++ cfg.ListOpt('ignore_users', default=['os_admin', 'root'], ++ help='Users to exclude when listing users.', ++ deprecated_name='ignore_users', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('api_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.api.K2hdkcAPIStrategy', ++ help='Class that implements datastore-specific API logic.'), ++ cfg.StrOpt('taskmanager_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.taskmanager.K2hdkcTaskManagerStrategy', ++ help='Class that implements datastore-specific task manager logic.'), ++ cfg.StrOpt('guestagent_strategy', ++ default='trove.common.strategies.cluster.experimental.k2hdkc.guestagent.K2hdkcGuestAgentStrategy', ++ help='Class that implements datastore-specific Guest Agent API logic.'), ++ cfg.BoolOpt('cluster_support', default=True, ++ help='Enable clusters to be created and managed.'), ++ cfg.IntOpt('min_cluster_member_count', default=3, ++ help='Minimum number of members in K2hdkc cluster.'), + cfg.IntOpt('default_password_length', + default='${mysql.default_password_length}', + help='Character length of generated passwords.', + deprecated_name='default_password_length', + deprecated_group='DEFAULT'), ++ cfg.StrOpt('backup_strategy', default='K2hdkcArchive', ++ help='Default strategy to perform backups.', ++ deprecated_name='backup_strategy', ++ deprecated_group='DEFAULT'), ++ cfg.DictOpt('backup_incremental_strategy', default={}, ++ help='Incremental Backup Runner based on the default ' ++ 'strategy. For strategies that do not implement an ' ++ 'incremental, the runner will use the default full backup.', ++ deprecated_name='backup_incremental_strategy', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('backup_namespace', ++ default="trove.guestagent.strategies.backup.experimental." ++ "k2hdkc_impl", ++ help='Namespace to load backup strategies from.', ++ deprecated_name='backup_namespace', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('restore_namespace', ++ default='trove.guestagent.strategies.restore.experimental.' ++ 'k2hdkc_impl', ++ help='Namespace to load restore strategies from.', ++ deprecated_name='restore_namespace', ++ deprecated_group='DEFAULT'), ++ cfg.StrOpt('replication_strategy', default=None, ++ help='Default strategy for replication.'), ++ cfg.StrOpt('replication_namespace', default=None, ++ help='Namespace to load replication strategies from.'), + ] + + # RPC version groups +@@ -1615,6 +1703,7 @@ CONF.register_group(couchdb_group) + CONF.register_group(vertica_group) + CONF.register_group(db2_group) + CONF.register_group(mariadb_group) ++CONF.register_group(k2hdkc_group) + CONF.register_group(network_group) + CONF.register_group(service_credentials_group) + +@@ -1630,6 +1719,7 @@ CONF.register_opts(couchdb_opts, couchdb_group) + CONF.register_opts(vertica_opts, vertica_group) + CONF.register_opts(db2_opts, db2_group) + CONF.register_opts(mariadb_opts, mariadb_group) ++CONF.register_opts(k2hdkc_opts, k2hdkc_group) + CONF.register_opts(network_opts, network_group) + CONF.register_opts(service_credentials_opts, service_credentials_group) + diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-configurations.py b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-configurations.py new file mode 100644 index 0000000..0312f74 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-configurations.py @@ -0,0 +1,37 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /opt/stack/trove/trove/common/configurations.py 2020-06-09 16:18:00.762190008 +0900 +--- configurations.py 2020-06-11 13:28:21.189458201 +0900 +*************** +*** 95,97 **** +--- 95,107 ---- + + def parse(self): + return self.CODEC.deserialize(self.config).items() ++ ++ class K2hdkcConfParser(object): ++ ++ CODEC = stream_codecs.KeyValueCodec(delimiter='=', comment_marker='#', line_terminator='\n') ++ ++ def __init__(self, config): ++ self.config = config ++ ++ def parse(self): ++ return self.CODEC.deserialize(self.config).items() diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-template.py b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-template.py new file mode 100644 index 0000000..14ba3bb --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-common-template.py @@ -0,0 +1,31 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** /opt/stack/trove/trove/common/template.py 2020-06-09 16:18:00.770190167 +0900 +--- template.py 2020-06-11 13:28:27.540584594 +0900 +*************** +*** 38,43 **** +--- 38,44 ---- + 'redis': configurations.RedisConfParser, + 'vertica': configurations.VerticaConfParser, + 'db2': configurations.DB2ConfParser, ++ 'k2hdkc': configurations.K2hdkcConfParser, + } + + diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-guestagent-dbaas.py b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-guestagent-dbaas.py new file mode 100644 index 0000000..4a32f92 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/patches/trove-guestagent-dbaas.py @@ -0,0 +1,40 @@ +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +*** trove-guestagent-dbaas.py 2020-05-07 04:45:33.958268000 +0000 +--- dbaas.py 2020-05-07 04:47:38.404460003 +0000 +*************** +*** 58,64 **** + 'db2': + 'trove.guestagent.datastore.experimental.db2.manager.Manager', + 'mariadb': +! 'trove.guestagent.datastore.experimental.mariadb.manager.Manager' + } + CONF = cfg.CONF + +--- 58,66 ---- + 'db2': + 'trove.guestagent.datastore.experimental.db2.manager.Manager', + 'mariadb': +! 'trove.guestagent.datastore.experimental.mariadb.manager.Manager', +! 'k2hdkc': +! 'trove.guestagent.datastore.experimental.k2hdkc.manager.Manager' + } + CONF = cfg.CONF + diff --git a/dib/elements/centos-8-k2hdkc/install.d/trove/usr/libexec/k2hdkc-snapshot b/dib/elements/centos-8-k2hdkc/install.d/trove/usr/libexec/k2hdkc-snapshot new file mode 100755 index 0000000..7abc063 --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/install.d/trove/usr/libexec/k2hdkc-snapshot @@ -0,0 +1,243 @@ +#!/bin/sh +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +ECHO="/bin/echo" +CAT="/bin/cat" +RM="/bin/rm" +MKDIR="/bin/mkdir" +CHMOD="/bin/chmod" +CHOWN="/bin/chown" +TOUCH="/bin/touch" +GREP="/bin/grep" +HEAD="/bin/head" +TAIL="/bin/tail" +SED="/bin/sed" +AWK="/bin/awk" +WC="/bin/wc" +SUDO="/bin/sudo" + +# +# Usage +# +func_usage() +{ + ${ECHO} "" + ${ECHO} "Usage: $1 {--save(-s) | --remove(-rm) | --restore(-r)} " + ${ECHO} " $1 {--help(-h)}" + ${ECHO} " -s(--save) create(save) backup mode." + ${ECHO} " -rm(--remove) remove backup mode." + ${ECHO} " specify the k2hdkc data base directory.(ex: /var/lib/k2hdkc/data)" + ${ECHO} " specify snapshot name which is prefix for backup file." + ${ECHO} " -h(--help) print help." + ${ECHO} "" +} + +# +# Input Variables +# +SCRIPT_NAME=`basename $0` +PROC_ID=$$ +LOG_FILE="/tmp/.${SCRIPT_NAME}-${PROC_ID}.log" +CMD_TMP_FILE="/tmp/.${SCRIPT_NAME}-${PROC_ID}.cmd" +MODE=$1 +K2HDKC_BASE_DIR=$2 +SNAPSHOT_NAME=$3 + +# +# Check Variables +# +if [ "X${MODE}" = "X-s" -o "X${MODE}" = "X-S" -o "X${MODE}" = "X--save" -o "X${MODE}" = "X--SAVE" ]; then + MODE="-s" +elif [ "X${MODE}" = "X-rm" -o "X${MODE}" = "X-RM" -o "X${MODE}" = "X--remove" -o "X${MODE}" = "X--REMOVE" ]; then + MODE="-rm" +elif [ "X${MODE}" = "X-r" -o "X${MODE}" = "X-R" -o "X${MODE}" = "X--restore" -o "X${MODE}" = "X--RESTORE" ]; then + MODE="-r" +else + ${ECHO} "[ERROR] Unknown mode option(${MODE})." >${LOG_FILE} + exit 1 +fi +if [ "X${K2HDKC_BASE_DIR}" = "X" ]; then + ${ECHO} "[ERROR] Second parameter is empty, it must be the output base directory path(ex: /var/lib/k2hdkc/data)." >${LOG_FILE} + exit 1 +elif [ ! -d ${K2HDKC_BASE_DIR} ]; then + ${ECHO} "[ERROR] ${K2HDKC_BASE_DIR} is not directory." >${LOG_FILE} + exit 1 +fi +if [ "X${SNAPSHOT_NAME}" = "X" ]; then + ${ECHO} "[ERROR] Third parameter is empty, it must be snap shot name." >${LOG_FILE} + exit 1 +fi + +# +# Make local variables +# +K2HDKC_USER="k2hdkc" +K2HDKC_GROUP="k2hdkc" + +ARCHIVE_FILE="${SNAPSHOT_NAME}.k2har" +ARCHIVE_FILE_DIR="${K2HDKC_BASE_DIR}/snapshots" + +CONFFILE="/etc/k2hdkc/server.ini" + +K2HDKC_SERVER_INI_LINECNT=`${WC} -l ${CONFFILE} | ${AWK} '{print $1}'` +K2HDKC_SECTION_START_POS=`${GREP} -n '\[K2HDKC\]' ${CONFFILE} | ${SED} -e 's/:.*//g'` +K2HDKC_SECTION_LINECNT=`expr ${K2HDKC_SERVER_INI_LINECNT} - ${K2HDKC_SECTION_START_POS}` + +K2HFILE=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HFILE 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HFILE\s*=\s*//' 2>/dev/null` +K2HMASKBIT=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HMASKBIT 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HMASKBIT\s*=\s*//' 2>/dev/null` +K2HCMASKBIT=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HCMASKBIT 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HCMASKBIT\s*=\s*//' 2>/dev/null` +K2HMAXELE=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HMAXELE 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HMAXELE\s*=\s*//' 2>/dev/null` +K2HPAGESIZE=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HPAGESIZE 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HPAGESIZE\s*=\s*//' 2>/dev/null` +K2HFULLMAP=`${TAIL} -${K2HDKC_SECTION_LINECNT} ${CONFFILE} | ${GREP} K2HFULLMAP 2>/dev/null | ${HEAD} -1 | ${SED} -e 's/K2HFULLMAP\s*=\s*//' 2>/dev/null` + +if [ ! -f ${K2HFILE} ]; then + if [ "X${MODE}" = "X-s" ]; then + ${ECHO} "[ERROR] k2hdkc data file does not exist." >${LOG_FILE} + exit 1 + else + ${ECHO} "[WARNING] k2hdkc data file does not exist." >${LOG_FILE} + fi +fi + +# +# Main +# +if [ "X${MODE}" = "X-rm" ]; then + # + # Mode: remove + # + if [ -f ${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE} ]; then + ${SUDO} ${RM} -f ${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE} + if [ $? -ne 0 ]; then + ${ECHO} "Failed to remove snapshot file(${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE})" >${LOG_FILE} + exit 1 + fi + fi + +elif [ "X${MODE}" = "X-s" ]; then + # + # Mode: save + # + ${CAT} < ${CMD_TMP_FILE} +ar put ${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE} +exit +EOF + + # check output directory + if [ ! -d ${K2HDKC_BASE_DIR} ]; then + ${SUDO} ${MKDIR} -p ${K2HDKC_BASE_DIR} + ${SUDO} ${CHOWN} ${K2HDKC_USER}:${K2HDKC_GROUP} ${K2HDKC_BASE_DIR} + fi + ${SUDO} ${CHMOD} 0777 ${K2HDKC_BASE_DIR} + + if [ ! -d ${ARCHIVE_FILE_DIR} ]; then + ${SUDO} ${MKDIR} -p ${ARCHIVE_FILE_DIR} + ${SUDO} ${CHOWN} ${K2HDKC_USER}:${K2HDKC_GROUP} ${ARCHIVE_FILE_DIR} + fi + ${SUDO} ${CHMOD} 0777 ${ARCHIVE_FILE_DIR} + + ${SUDO} -u ${K2HDKC_USER} k2hlinetool -f ${K2HFILE} -run ${CMD_TMP_FILE} >${LOG_FILE} 2>&1 + if [ $? -ne 0 ]; then + echo "Failed to create snapshot file(${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE})" >${LOG_FILE} + exit 1 + fi + +elif [ "X${MODE}" = "X-r" ]; then + # check output directory + if [ ! -d ${ARCHIVE_FILE_DIR} ]; then + echo "${ARCHIVE_FILE_DIR} is not existed." >${LOG_FILE} + exit 1 + fi + + # check k2hash file and its directory + if [ ! -f ${K2HFILE} ]; then + # [NOTE] + # If k2hash file is not existed, this script creates it. + # Thus this script must check directory permission(owner) for k2hdkc user:group + # + K2HFILE_DIR=`dirname ${K2HFILE}` + + ${SUDO} -u ${K2HDKC_USER} ${TOUCH} ${K2HFILE} 2>/dev/null + if [ $? -ne 0 ]; then + # could not create file, try to change owner:group + ${SUDO} ${CHOWN} ${K2HDKC_USER}:${K2HDKC_GROUP} ${K2HFILE_DIR} + fi + ${SUDO} ${RM} -f ${K2HFILE} + fi + + # make k2hlinetool options + if [ "X${K2HMASKBIT}" != "X" ]; then + K2HMASKBIT_OPT="-mask ${K2HMASKBIT}" + else + K2HMASKBIT_OPT="" + fi + if [ "X${K2HCMASKBIT}" != "X" ]; then + K2HCMASKBIT_OPT="-cmask ${K2HCMASKBIT}" + else + K2HCMASKBIT_OPT="" + fi + if [ "X${K2HMAXELE}" != "X" ]; then + K2HMAXELE_OPT="-elementcnt ${K2HMAXELE}" + else + K2HMAXELE_OPT="" + fi + if [ "X${K2HPAGESIZE}" != "X" ]; then + K2HPAGESIZE_OPT="-pagesize ${K2HPAGESIZE}" + else + K2HPAGESIZE_OPT="" + fi + if [ "X${K2HFULLMAP}" = "Xon" -o "X${K2HFULLMAP}" = "XON" -o "X${K2HFULLMAP}" = "Xyes" -o "X${K2HFULLMAP}" = "XYES" -o "X${K2HFULLMAP}" = "Xy" -o "X${K2HFULLMAP}" = "XY" ]; then + K2HFULLMAP_OPT="-fullmap" + else + K2HFULLMAP_OPT="" + fi + + # + # Mode: save + # + ${CAT} < ${CMD_TMP_FILE} +ar load ${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE} +exit +EOF + + ${SUDO} -u ${K2HDKC_USER} k2hlinetool -f ${K2HFILE} ${K2HMASKBIT_OPT} ${K2HCMASKBIT_OPT} ${K2HMAXELE_OPT} ${K2HPAGESIZE_OPT} ${K2HFULLMAP_OPT} -run ${CMD_TMP_FILE} >${LOG_FILE} 2>&1 + if [ $? -ne 0 ]; then + echo "Failed to load snapshot file(${ARCHIVE_FILE_DIR}/${ARCHIVE_FILE})" >${LOG_FILE} + exit 1 + fi +fi + +# +# Remove tempolary files +# +${RM} -f ${CMD_TMP_FILE} +${RM} -f ${LOG_FILE} + +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# + diff --git a/dib/elements/centos-8-k2hdkc/post-install.d/98-k2hdkc b/dib/elements/centos-8-k2hdkc/post-install.d/98-k2hdkc new file mode 100755 index 0000000..718a6ac --- /dev/null +++ b/dib/elements/centos-8-k2hdkc/post-install.d/98-k2hdkc @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e +set -o xtrace + +# Replace /etc/resolv.conf.ORIG with new resolver +if test -f "/etc/resolv.conf.ORIG"; then + echo > /etc/resolv.conf.ORIG +else + echo "/etc/resolv.conf.ORIG not found" +fi diff --git a/utils/README.md b/utils/README.md new file mode 100644 index 0000000..f0c10ad --- /dev/null +++ b/utils/README.md @@ -0,0 +1,15 @@ +K2HDKC DBaaS Utilities +----- + +## Utilities +This directory contains utilities for building K2HDKC DBaaS systems. + +### Build a trial environment +You can easily build a trial environment for **K2HDKC DBaaS** by using the utilities. +You need a Bearmetal or a Virtual Machine for the trial environment. +See this [document](https://dbaas.k2hdkc.antpick.ax/build.html) for instructions on creating a trial environment. + +### Trial environment +You can try all K2HDKC DBaaS functions in the trial environment. + +Let's get started first. diff --git a/utils/custom_devstack_local.conf.sh b/utils/custom_devstack_local.conf.sh new file mode 100755 index 0000000..00cf121 --- /dev/null +++ b/utils/custom_devstack_local.conf.sh @@ -0,0 +1,111 @@ +#!/bin/sh +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: + +# +# A script to create a local.conf for devstack. +## +# NOTE: +# This script fixes OpenStack version to Ussuri. +# + +cat > ~/devstack/local.conf < database name" + echo " -o OSNAME" + echo " -r OSRELEASE" + echo " -h print usage" + echo "" + exit 1 +} + +MY_DB=k2hdkc +while true; do + case "${1-}" in + -n) shift; MY_DB="${1}";; + -o) shift; DISTRO_NAME="${1}";; + -r) shift; DIB_RELEASE="${1}";; + -h) print_usage;; + *) break;; + esac + shift +done + +# defines environments +BRANCH_OVERRIDE=stable/ussuri +SRCDIR=/opt/stack +MY_HOST_IP=$(ip route get 8.8.8.8 | head -1 | awk '{print $7}') +MY_DIB_ELEMENTS_PATH=${SRCDIR}/k2hdkc_dbaas/dib/elements +ELEMENTS_PATH=${SRCDIR}/trove/integration/scripts/files/elements +ELEMENTS_PATH=${ELEMENTS_PATH}:${MY_DIB_ELEMENTS_PATH} +DIB_RELEASE=${DIB_RELEASE:-8} +DIB_PYTHON_VERSION=3 +DIB_PYTHON=python3 +DISTRO_NAME=${DISTRO_NAME:-centos} +GUEST_LOGDIR=${GUEST_LOGDIR:-"/var/log/trove/"} +HOST_SCP_USERNAME=${HOST_SCP_USERNAME:-$(whoami)} +PATH_TROVE=${PATH_TROVE:-${SRCDIR}/trove} +SSH_DIR=${SSH_DIR:-"${SRCDIR}/ssh"} +if [ -d ${SSH_DIR} ]; then + echo "${SSH_DIR} already exists" +else + echo "Creating ${SSH_DIR} for ${HOST_SCP_USERNAME}" + sudo -Hiu ${HOST_SCP_USERNAME} mkdir -m go-w -p ${SSH_DIR} +fi +if [ ! -f ${SSH_DIR}/id_rsa.pub ]; then + /usr/bin/ssh-keygen -f ${SSH_DIR}/id_rsa -q -N "" +fi +cat ${SSH_DIR}/id_rsa.pub >> ${SSH_DIR}/authorized_keys +sort ${SSH_DIR}/authorized_keys | uniq > ${SSH_DIR}/authorized_keys.uniq +mv ${SSH_DIR}/authorized_keys.uniq ${SSH_DIR}/authorized_keys +chmod 600 ${SSH_DIR}/authorized_keys +export CONTROLLER_IP=${CONTROLLER_IP:-${MY_HOST_IP}} +export DIB_CLOUD_INIT_DATASOURCES="ConfigDrive" +export DIB_PYTHON=python3 +export DIB_PYTHON_VERSION +export DIB_IMAGE_SIZE=2G +export DIB_INIT_SYSTEM=systemd +export DISTRO_NAME=${DISTRO_NAME} +export DIB_RELEASE=${DIB_RELEASE} +export ELEMENTS_PATH=${ELEMENTS_PATH}:${MY_DIB_ELEMENTS_PATH} +export ESCAPED_GUEST_LOGDIR=$(echo ${GUEST_LOGDIR} | sed 's/\//\\\//g') +export ESCAPED_PATH_TROVE=$(echo ${PATH_TROVE} | sed 's/\//\\\//g') +export GUEST_LOGDIR=${GUEST_LOGDIR:-"/var/log/trove/"} +export GUEST_USERNAME=${GUEST_USERNAME:-centos} +export HOST_SCP_USERNAME=${HOST_SCP_USERNAME:-$(whoami)} +export HOST_USERNAME=${HOST_SCP_USERNAME} +export PATH_TROVE=${PATH_TROVE:-${SRCDIR}/trove} +export SSH_DIR=${SSH_DIR} +export TROVESTACK_SCRIPTS=${TROVESTACK_SCRIPTS:-$PATH_TROVE/integration/scripts} + +ELEMENTS="base vm pip-and-virtualenv pip-cache" +if [ "${DISTRO_NAME}" = "centos" ]; then + ELEMENTS="${ELEMENTS} centos-8-guest guest-agent-${MY_DB} centos centos-8-${MY_DB}" +else + ELEMENTS="${ELEMENTS} ubuntu-guest-stable-ussuri guest-agent-${MY_DB} ubuntu ubuntu-${MY_DB} no-resolvconf" +fi + +# install k2hr3_utils scripts +install -CD -m 0444 -v ${SRCDIR}/k2hr3_utils/devcluster/cluster_functions ${MY_DIB_ELEMENTS_PATH}/centos-8-${MY_DB}/install.d/cluster_functions +install -CD -m 0755 -v ${SRCDIR}/k2hr3_utils/devcluster/cluster.sh ${MY_DIB_ELEMENTS_PATH}/centos-8-${MY_DB}/install.d/cluster.sh +install -CD -m 0444 -v ${SRCDIR}/k2hr3_utils/devcluster/chmpx/setup_chmpx_functions ${MY_DIB_ELEMENTS_PATH}/centos-8-${MY_DB}/install.d/chmpx/setup_chmpx_functions +install -CD -m 0755 -v ${SRCDIR}/k2hr3_utils/devcluster/dkc/setup_dkc.sh ${MY_DIB_ELEMENTS_PATH}/centos-8-${MY_DB}/install.d/dkc/setup_dkc.sh + +disk-image-create -x -a amd64 -o ${SRCDIR}/images/trove-datastore-${DISTRO_NAME}-${DIB_RELEASE}-${MY_DB} -t qcow2 \ + --image-size 6 \ + --image-cache ~/.cache/image-create \ + --logfile build.log \ + --no-tmpfs ${ELEMENTS} +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/install_python-k2hr3client.sh b/utils/install_python-k2hr3client.sh new file mode 100755 index 0000000..0094d04 --- /dev/null +++ b/utils/install_python-k2hr3client.sh @@ -0,0 +1,83 @@ +#!/bin/sh +# +# K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Hirotaka Wakabayashi +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# Sets the default locale. LC_ALL has precedence over other LC* variables. +unset LANG +unset LANGUAGE +LC_ALL=en_US.utf8 +export LC_ALL + +# Sets PATH. setup_*.sh uses useradd command +PATH=${PATH}:/usr/sbin:/sbin + +# an unset parameter expansion will fail +set -u + +# umask 022 is enough +umask 022 + +if test "${USER}" != "stack"; then + echo "[NO] USER must be stack: USER=${USER}" + exit 1 +fi + +which python3 +if test "$?" != "0"; then + echo "[NO] no python3. Please install python3 package" + exit 1 +fi +which pip +if test "$?" != "0"; then + echo "[NO] no pip. Please install pip package" + exit 1 +fi + +# defines environments +SRCDIR=$(cd $(dirname "$0") && pwd) +PKGDIR=${SRCDIR}/python-k2hr3client/ +if ! test -d "${PKGDIR}"; then + echo "[NO] no ${PKGDIR}. Please check the dir where python-k2hr3client exists" + exit 1 +fi +CLIENT_VERSION=$(cat ${PKGDIR}/HISTORY.rst | perl -lne 'print $1 if /^([0-9]+.[0-9]+.[0-9]+) \([0-9]{4}-[0-9]{2}-[0-9]{2}\)$/') + +cd ${PKGDIR} +python3 setup.py sdist +if test "$?" != "0"; then + echo "[NO] python3 setup.py sdist should return zero" + exit 1 +fi +sudo pip install dist/python-k2hr3client-${CLIENT_VERSION}.tar.gz +if test "$?" != "0"; then + echo "[NO] sudo pip install dist/python-k2hr3client-${CLIENT_VERSION}.tar.gz should return zero" + exit 1 +fi + +echo "[OK] sudo pip install dist/python-k2hr3client-${CLIENT_VERSION}.tar.gz" +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/README.md b/utils/k2hr3_pack/README.md new file mode 100644 index 0000000..b23dffa --- /dev/null +++ b/utils/k2hr3_pack/README.md @@ -0,0 +1,45 @@ +# K2HR3 PACK for K2HDKC DBaaS + +## Overview +This directory is a developer development tool for booting K2HR3 systems on a single Virtaul Machine. +By running the scripts in this directory, you can boot the entire K2HR3 system with one Virtaul Machine. +The booted K2HR3 system can act as a backend for K2HD KC DBaaS. + +## Start-up +### About the environment +This tool launches a minimal process on your K2HR3 system in one OpenStack Virtual Machine. + +To use it, execute the script provided under this directory in the Virtual Machine started by OpenStack. +The K2HR3 system boots on the OpenStack private network, so to access it from the outside, use haproxy etc. on the parent HOST to proxy the request. +_Outputs a sample configuration for launching HAProxy._ + +#### Execution environment +- (1) Start the Virtual Machine with OpenStack. +- (2) Copy this directory to this Virtual Machine and execute the script. + +### Run processes +The following example uses Openstack of K2HDKC DBaaS and starts ubuntu as one Virtual Machine. +This is the command line when running this K2HR3 pack script on ubuntu (Virtual Machine). +And it is assumed that HAProxy will also start. +``` +[Example 1: Not using HAproxy] + $ bin/onepack.sh -ni -nc --run_user nobody --openstack_region RegionOne --keystone_url http:///identity --app_port 80 --app_host --api_port 18080 --api_host + +[Example 2: Using HAproxy] + $ bin/onepack.sh -ni -nc --run_user nobody --openstack_region RegionOne --keystone_url http:///identity --app_port 80 --app_port_external 28080 --app_host --app_host_external --api_port 18080 --api_port_external 18080 --api_host --api_host_external +``` +_http://\/identity is the Openstack Keystone URL and RegionOne is the region name._ + +When starting HAProxy, the `conf/haproxy_example.cfg` file will be created after executing the above command. +Use this to start HAProxy (`haproxy -f haproxy_example.cfg`) on the parent HOST. + +### Stop processes +We provide a tool to stop K2HR3 started by this tool. +Please execute as follows. +``` +$ bin/stoppack.sh +``` +If you want to delete unnecessary files, specify the options as follows. +``` +$ bin/stoppack.sh --clear +``` diff --git a/utils/k2hr3_pack/bin/onepack.sh b/utils/k2hr3_pack/bin/onepack.sh new file mode 100755 index 0000000..2bfa721 --- /dev/null +++ b/utils/k2hr3_pack/bin/onepack.sh @@ -0,0 +1,912 @@ +#!/bin/sh +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +#---------------------------------------------------------- +# Environments +#---------------------------------------------------------- +CMDLINE_PROCESS_NAME=$0 +PROGRAM_NAME=`basename ${CMDLINE_PROCESS_NAME}` +SCRIPTPATH=`dirname ${CMDLINE_PROCESS_NAME}` +BINDIR=`cd ${SCRIPTPATH}; pwd` +SRCTOP=`cd ${SCRIPTPATH}/..; pwd` +CURRENT_TIME=`date -R` + +# +# Escape sequence +# +CDEF=$(printf '\033[0m') +CREV=$(printf '\033[7m') +CRED=$(printf '\033[31m') +CGRN=$(printf '\033[32m') + +#---------------------------------------------------------- +# Options +#---------------------------------------------------------- +func_usage() +{ + # + # $1: Program name + # + echo "" + echo "Usage: $1 [--no_interaction(-ni)] [--no_confirmation(-nc)] [--run_user(-ru) ] [--server_port(-svrp) ]" + echo " [--server_ctlport(-svrcp) ] [--slave_ctlport(-slvcp) ] [--keystone_url(-ks) ]" + echo " [--app_port(-appp) ] [--app_port_external(-apppe) ]" + echo " [--app_host(-apph) ] [--app_host_external(-apphe) ]" + echo " [--api_port(-apip) ] [--api_port_external(-apipe) ]" + echo " [--api_host(-apih) ] [--api_host_external(-apihe) ]" + echo " [--help(-h)]" + echo "" + echo " --no_interaction(-ni) Turn off interactive mode for unspecified option input and use default value" + echo " --run_user(-ru) Specify the execution user of each process" + echo " --server_port(-svrp) Specify CHMPX server node process port" + echo " --server_ctlport(-svrcp) Specify CHMPX server node process control port" + echo " --slave_ctlport(-slvcp) Specify CHMPX slave node process control port" + echo " --openstack_region(-osr) Specify OpenStack(Keystone) Region(ex: RegionOne)" + echo " --keystone_url(-ks) Specify OpenStack Keystone URL(ex: https://dummy.keystone.openstack/)" + echo " --app_port(-appp) Specify K2HR3 Application port" + echo " --app_port_external(-apppe) Specify K2HR3 Application external port(optional: specify when using a proxy)" + echo " --app_host(-apph) Specify K2HR3 Application host" + echo " --app_host_external(-apphe) Specify K2HR3 Application external host(optional: host as javascript download server)" + echo " --api_port(-apip) Specify K2HR3 REST API port" + echo " --api_port_external(-apipe) Specify K2HR3 REST API external port(optional: specify when using a proxy)" + echo " --api_host(-apih) Specify K2HR3 REST API host" + echo " --api_host_external(-apihe) Specify K2HR3 REST API external host(optional: specify when using a proxy)" + echo " --yes(-y) Specified when you do not want confirmation" + echo " --help(-h) print help" + echo "" +} + +input_interaction() +{ + # + # $1: Input Message(puts stderr) + # $2: Input data type is number = yes(1)/no(0) + # $3: Whether to allow empty = yes(1)/no(0, empty) + # + INPUT_MSG=$1 + if [ "X$2" = "Xyes" -o "X$2" = "XYES" -o "X$2" = "X1" ]; then + IS_NUMBER=1 + else + IS_NUMBER=0 + fi + if [ "X$3" = "Xyes" -o "X$3" = "XYES" -o "X$3" = "X1" ]; then + IS_ALLOW_EMPTY=1 + else + IS_ALLOW_EMPTY=0 + fi + + while true; do + echo -n "${INPUT_MSG} : " 1>&2 + read INPUT_DATA + + if [ "X${INPUT_DATA}" = "X" ]; then + if [ ${IS_ALLOW_EMPTY} -eq 1 ]; then + break; + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Not allow to input empty.${CDEF}" 1>&2 + fi + else + if [ ${IS_NUMBER} -ne 1 ]; then + break; + else + expr "${INPUT_DATA}" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The input data must be number.${CDEF}" 1>&2 + else + break; + fi + fi + fi + done + + echo ${INPUT_DATA} +} + +# +# Check options +# +OPT_NO_INTERACTIVE= +OPT_NO_COMFIRMATION= +OPT_RUNUSER= +OPT_CHMPX_SERVER_PORT= +OPT_CHMPX_SERVER_CTLPORT= +OPT_CHMPX_SLAVE_CTLPORT= +OPT_OPENSTACK_REGION= +OPT_KEYSTONE_URL= +OPT_K2HR3_APP_PORT= +OPT_K2HR3_APP_PORT_EXTERNAL= +OPT_K2HR3_APP_HOST= +OPT_K2HR3_APP_HOST_EXTERNAL= +OPT_K2HR3_API_PORT= +OPT_K2HR3_API_PORT_EXTERNAL= +OPT_K2HR3_API_HOST= +OPT_K2HR3_API_HOST_EXTERNAL= +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--help" -o "X$1" = "X--HELP" ]; then + func_usage $PROGRAM_NAME + exit 0 + + elif [ "X$1" = "X-ni" -o "X$1" = "X-NI" -o "X$1" = "X--no_interaction" -o "X$1" = "X--NO_INTERACTION" ]; then + if [ "X${OPT_NO_INTERACTIVE}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --no_interaction(-ni) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_NO_INTERACTIVE="yes" + + elif [ "X$1" = "X-nc" -o "X$1" = "X-NC" -o "X$1" = "X--no_confirmation" -o "X$1" = "X--NO_CONFIRMATION" ]; then + if [ "X${OPT_NO_COMFIRMATION}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --no_confirmation(-nc) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_NO_COMFIRMATION="yes" + + elif [ "X$1" = "X-ru" -o "X$1" = "X-RU" -o "X$1" = "X--run_user" -o "X$1" = "X--RUN_USER" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --run_user(-ru) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_RUNUSER}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --run_user(-ru) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_RUNUSER=$1 + + elif [ "X$1" = "X-svrp" -o "X$1" = "X-SVRP" -o "X$1" = "X--server_port" -o "X$1" = "X--SERVER_PORT" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --server_port(-svrp) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_CHMPX_SERVER_PORT}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --server_port(-svrp) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --server_port(-svrp) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_CHMPX_SERVER_PORT=$1 + + elif [ "X$1" = "X-svrcp" -o "X$1" = "X-SVRCP" -o "X$1" = "X--server_ctlport" -o "X$1" = "X--SERVER_CTLPORT" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --server_ctlport(-svrcp) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_CHMPX_SERVER_CTLPORT}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --server_ctlport(-svrcp) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --server_ctlport(-svrcp) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_CHMPX_SERVER_CTLPORT=$1 + + elif [ "X$1" = "X-slvcp" -o "X$1" = "X-SLVCP" -o "X$1" = "X--slave_ctlport" -o "X$1" = "X--SLAVE_CTLPORT" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --slave_ctlport(-slvcp) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_CHMPX_SLAVE_CTLPORT}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --slave_ctlport(-slvcp) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --slave_ctlport(-slvcp) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_CHMPX_SLAVE_CTLPORT=$1 + + elif [ "X$1" = "X-osr" -o "X$1" = "X-OSR" -o "X$1" = "X--openstack_region" -o "X$1" = "X--OPENSTACK_REGION" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --openstack_region(-osr) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_OPENSTACK_REGION}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --openstack_region(-osr) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_OPENSTACK_REGION=$1 + + elif [ "X$1" = "X-ks" -o "X$1" = "X-KS" -o "X$1" = "X--keystone_url" -o "X$1" = "X--KEYSTONE_URL" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --keystone_url(-ks) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_KEYSTONE_URL}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --keystone_url(-ks) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_KEYSTONE_URL=$1 + + elif [ "X$1" = "X-appp" -o "X$1" = "X-APPP" -o "X$1" = "X--app_port" -o "X$1" = "X--APP_PORT" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_port(-appp) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_APP_PORT}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_port(-appp) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --app_port(-appp) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_APP_PORT=$1 + + elif [ "X$1" = "X-apppe" -o "X$1" = "X-APPPE" -o "X$1" = "X--app_port_external" -o "X$1" = "X--APP_PORT_EXTERNAL" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_port_external(-apppe) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_port_external(-apppe) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --app_port_external(-apppe) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_APP_PORT_EXTERNAL=$1 + + elif [ "X$1" = "X-apph" -o "X$1" = "X-APPH" -o "X$1" = "X--app_host" -o "X$1" = "X--APP_HOST" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_host(-apph) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_APP_HOST}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_host(-apph) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_APP_HOST=$1 + + elif [ "X$1" = "X-apphe" -o "X$1" = "X-APPHE" -o "X$1" = "X--app_host_external" -o "X$1" = "X--APP_HOST_EXTERNAL" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_host_external(-apphe) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --app_host_external(-apphe) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_APP_HOST_EXTERNAL=$1 + + elif [ "X$1" = "X-apip" -o "X$1" = "X-APIP" -o "X$1" = "X--api_port" -o "X$1" = "X--API_PORT" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_port(-apip) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_API_PORT}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_port(-apip) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --api_port(-apip) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_API_PORT=$1 + + elif [ "X$1" = "X-apipe" -o "X$1" = "X-APIPE" -o "X$1" = "X--api_port_external" -o "X$1" = "X--API_PORT_EXTERNAL" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_port_external(-apipe) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_port_external(-apipe) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + expr "$1" + 1 >/dev/null 2>&1 + if [ $? -ge 2 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The parameter of --api_port_external(-apipe) option must be number.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_API_PORT_EXTERNAL=$1 + + elif [ "X$1" = "X-apih" -o "X$1" = "X-APIH" -o "X$1" = "X--api_host" -o "X$1" = "X--API_HOST" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_host(-apih) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_API_HOST}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_host(-apih) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_API_HOST=$1 + + elif [ "X$1" = "X-apihe" -o "X$1" = "X-APIHE" -o "X$1" = "X--api_host_external" -o "X$1" = "X--API_HOST_EXTERNAL" ]; then + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_host_external(-apihe) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --api_host_external(-apihe) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_K2HR3_API_HOST_EXTERNAL=$1 + + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} $1 option is unknown.${CDEF}" 1>&2 + exit 1 + fi + shift +done + +# +# Interaction +# +if [ "X${OPT_NO_INTERACTIVE}" != "Xyes" ]; then + if [ "X${OPT_RUNUSER}" = "X" -o "X${OPT_CHMPX_SERVER_PORT}" = "X" -o "X${OPT_CHMPX_SERVER_CTLPORT}" = "X" -o "X${OPT_CHMPX_SLAVE_CTLPORT}" = "X" -o "X${OPT_OPENSTACK_REGION}" = "X" -o "X${OPT_KEYSTONE_URL}" = "X" -o "X${OPT_K2HR3_APP_PORT}" = "X" -o "X${OPT_K2HR3_APP_PORT_EXTERNAL}" = "X" -o "X${OPT_K2HR3_APP_HOST}" = "X" -o "X${OPT_K2HR3_APP_HOST_EXTERNAL}" = "X" -o "X${OPT_K2HR3_API_PORT}" = "X" -o "X${OPT_K2HR3_API_PORT_EXTERNAL}" = "X" -o "X${OPT_K2HR3_API_HOST}" = "X" -o "X${OPT_K2HR3_API_HOST_EXTERNAL}" = "X" ]; then + echo "-----------------------------------------------------------" 1>&2 + echo "${CGRN}Input options${CDEF}" 1>&2 + echo "-----------------------------------------------------------" 1>&2 + + if [ "X${OPT_RUNUSER}" = "X" ]; then + OPT_RUNUSER=`input_interaction "Execution user of all processes" "no"` + fi + if [ "X${OPT_CHMPX_SERVER_PORT}" = "X" ]; then + OPT_CHMPX_SERVER_PORT=`input_interaction "CHMPX Server node port number" "yes"` + fi + if [ "X${OPT_CHMPX_SERVER_CTLPORT}" = "X" ]; then + OPT_CHMPX_SERVER_CTLPORT=`input_interaction "CHMPX Server node control port number" "yes"` + fi + if [ "X${OPT_CHMPX_SLAVE_CTLPORT}" = "X" ]; then + OPT_CHMPX_SLAVE_CTLPORT=`input_interaction "CHMPX Slave node control port number" "yes"` + fi + if [ "X${OPT_OPENSTACK_REGION}" = "X" ]; then + OPT_OPENSTACK_REGION=`input_interaction "OpenStack(Keystone) Region(ex. \"RegionOne\")" "no"` + fi + if [ "X${OPT_KEYSTONE_URL}" = "X" ]; then + OPT_KEYSTONE_URL=`input_interaction "OpenStack Keystone URL(ex. \"http(s)://....\")" "no"` + fi + if [ "X${OPT_K2HR3_APP_PORT}" = "X" ]; then + OPT_K2HR3_APP_PORT=`input_interaction "K2HR3 Application port number" "yes"` + fi + if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" = "X" ]; then + OPT_K2HR3_APP_PORT_EXTERNAL=`input_interaction "K2HR3 Application external port number(enter empty if not present)" "yes" "yes"` + fi + if [ "X${OPT_K2HR3_APP_HOST}" = "X" ]; then + OPT_K2HR3_APP_HOST=`input_interaction "K2HR3 Application hostname or IP address" "no"` + fi + if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" = "X" ]; then + OPT_K2HR3_APP_HOST_EXTERNAL=`input_interaction "K2HR3 Application external hostanme or IP address(enter empty if not present)" "no" "yes"` + fi + if [ "X${OPT_K2HR3_API_PORT}" = "X" ]; then + OPT_K2HR3_API_PORT=`input_interaction "K2HR3 REST API port number" "yes"` + fi + if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" = "X" ]; then + OPT_K2HR3_API_PORT_EXTERNAL=`input_interaction "K2HR3 REST API external port number(enter empty if not present)" "yes" "yes"` + fi + if [ "X${OPT_K2HR3_API_HOST}" = "X" ]; then + OPT_K2HR3_API_HOST=`input_interaction "K2HR3 REST API hostname or IP address" "no"` + fi + if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" = "X" ]; then + OPT_K2HR3_API_HOST_EXTERNAL=`input_interaction "K2HR3 REST API external hostanme or IP address(enter empty if not present)" "no" "yes"` + fi + fi +else + if [ "X${OPT_RUNUSER}" = "X" ]; then + #OPT_RUNUSER="nobody" + OPT_RUNUSER="root" + fi + if [ "X${OPT_CHMPX_SERVER_PORT}" = "X" ]; then + OPT_CHMPX_SERVER_PORT=18020 + fi + if [ "X${OPT_CHMPX_SERVER_CTLPORT}" = "X" ]; then + OPT_CHMPX_SERVER_CTLPORT=18021 + fi + if [ "X${OPT_CHMPX_SLAVE_CTLPORT}" = "X" ]; then + OPT_CHMPX_SLAVE_CTLPORT=18031 + fi + if [ "X${OPT_OPENSTACK_REGION}" = "X" ]; then + OPT_OPENSTACK_REGION="RegionOne" + fi + if [ "X${OPT_KEYSTONE_URL}" = "X" ]; then + OPT_KEYSTONE_URL="https://dummy.keystone.openstack/" + fi + if [ "X${OPT_K2HR3_APP_PORT}" = "X" ]; then + OPT_K2HR3_APP_PORT=80 + fi + if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" = "X" ]; then + OPT_K2HR3_APP_PORT_EXTERNAL= + fi + if [ "X${OPT_K2HR3_APP_HOST}" = "X" ]; then + OPT_K2HR3_APP_HOST="localhost" + fi + if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" = "X" ]; then + OPT_K2HR3_APP_HOST_EXTERNAL= + fi + if [ "X${OPT_K2HR3_API_PORT}" = "X" ]; then + OPT_K2HR3_API_PORT=18080 + fi + if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" = "X" ]; then + OPT_K2HR3_API_PORT_EXTERNAL= + fi + if [ "X${OPT_K2HR3_API_HOST}" = "X" ]; then + OPT_K2HR3_API_HOST="localhost" + fi + if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" = "X" ]; then + OPT_K2HR3_API_HOST_EXTERNAL= + fi +fi + +# +# Print options +# +if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" = "X" ]; then + DISP_K2HR3_APP_PORT_EXTERNAL="(empty: using K2HR3 Application port)" +else + DISP_K2HR3_APP_PORT_EXTERNAL=${OPT_K2HR3_APP_PORT_EXTERNAL} +fi +if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" = "X" ]; then + DISP_K2HR3_APP_HOST_EXTERNAL="(empty: using K2HR3 Application host instead)" +else + DISP_K2HR3_APP_HOST_EXTERNAL=${OPT_K2HR3_APP_HOST_EXTERNAL} +fi +if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" = "X" ]; then + DISP_K2HR3_API_PORT_EXTERNAL="(empty: using K2HR3 REST API port)" +else + DISP_K2HR3_API_PORT_EXTERNAL=${OPT_K2HR3_API_PORT_EXTERNAL} +fi +if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" = "X" ]; then + DISP_K2HR3_API_HOST_EXTERNAL="(empty: using K2HR3 REST API host instead)" +else + DISP_K2HR3_API_HOST_EXTERNAL=${OPT_K2HR3_API_HOST_EXTERNAL} +fi + +echo "-----------------------------------------------------------" +echo "${CGRN}Options${CDEF}" +echo "-----------------------------------------------------------" +echo "Execution user name: ${OPT_RUNUSER}" +echo "CHMPX server port: ${OPT_CHMPX_SERVER_PORT}" +echo "CHMPX server control port: ${OPT_CHMPX_SERVER_CTLPORT}" +echo "CHMPX slave port: ${OPT_CHMPX_SLAVE_CTLPORT}" +echo "OpenStack(keystone) Region: ${OPT_OPENSTACK_REGION}" +echo "OpenStack keystone URL: ${OPT_KEYSTONE_URL}" +echo "K2HR3 Application port: ${OPT_K2HR3_APP_PORT}" +echo "K2HR3 Application external port: ${DISP_K2HR3_APP_PORT_EXTERNAL}" +echo "K2HR3 Application host: ${OPT_K2HR3_APP_HOST}" +echo "K2HR3 Application external host: ${DISP_K2HR3_APP_HOST_EXTERNAL}" +echo "K2HR3 REST API port: ${OPT_K2HR3_API_PORT}" +echo "K2HR3 REST API external port: ${DISP_K2HR3_API_PORT_EXTERNAL}" +echo "K2HR3 REST API host: ${OPT_K2HR3_API_HOST}" +echo "K2HR3 REST API external host: ${DISP_K2HR3_API_HOST_EXTERNAL}" +echo "" + +if [ "X${OPT_NO_COMFIRMATION}" != "Xyes" ]; then + while true; do + echo -n " Do you want to continue? [Y/N]: " 1>&2 + read CONFIRM_DATA + + if [ "X${CONFIRM_DATA}" = "XY" -o "X${CONFIRM_DATA}" = "Xy" ]; then + echo "" + break; + elif [ "X${CONFIRM_DATA}" = "XN" -o "X${CONFIRM_DATA}" = "Xn" ]; then + echo "${CRED}${CREV}[BREAK]${CDEF}${CRED} Terminate this process.${CDEF}" 1>&2 + exit 0 + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The input data must be \"Y\" or \"N\"${CDEF}" 1>&2 + fi + done +fi + +#---------------------------------------------------------- +# Setup repositories +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Setup repositories${CDEF}" +echo "-----------------------------------------------------------" +# +# add packagecloud.io AntPickax +# +curl -s https://packagecloud.io/install/repositories/antpickax/stable/script.deb.sh | sudo bash +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not set repository to packagecloud.io for AntPickax${CDEF}" 1>&2 + exit 1 +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Setup packagecloud.io AntPickax repository.${CDEF}" + +#---------------------------------------------------------- +# Install packages +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Install packages${CDEF}" +echo "-----------------------------------------------------------" +sudo apt update +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not update package repository${CDEF}" 1>&2 + exit 1 +fi + +# [NOTE] +# Default nodejs/npm in ubuntu is old and has some problem. +# So do upgrade nodejs and npm at first. +# +curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - +sudo apt-get install -y nodejs + +sudo apt-get install -y k2hdkc-dev k2htpdtor +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not install k2hdkc k2htpdtor${CDEF}" 1>&2 + exit 1 +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Installed k2hdkc-dev k2htpdtor nodejs npm${CDEF}" + +#---------------------------------------------------------- +# Generate configurations +#---------------------------------------------------------- +cd ${SRCTOP} +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Generate CHMPX configurations${CDEF}" +echo "-----------------------------------------------------------" +# +# For permission +# +chmod 777 ${SRCTOP}/log >/dev/null 2>&1 +chmod 777 ${SRCTOP}/data >/dev/null 2>&1 + +# +# For CHMPX +# +echo 512 | sudo tee -a /proc/sys/fs/mqueue/msg_max > /dev/null 2>&1 +RESULT=`cat /proc/sys/fs/mqueue/msg_max` +if [ ${RESULT} -lt 512 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not set msg_max for mqueue${CDEF}" 1>&2 + exit 1 +fi + +cat ${SRCTOP}/conf/config.templ | sed -e "s/__DATE__/${CURRENT_TIME}/g" -e "s#__BASE_DIR__#${SRCTOP}#g" -e "s/__MODE_SETTING__/MODE\t\t\t= SERVER\nPORT\t\t\t= ${OPT_CHMPX_SERVER_PORT}\nCTLPORT\t\t\t= ${OPT_CHMPX_SERVER_CTLPORT}\nSELFCTLPORT\t\t= ${OPT_CHMPX_SERVER_CTLPORT}\n/g" -e "s/__SERVER_PORT__/${OPT_CHMPX_SERVER_PORT}/g" -e "s/__SERVER_CTLPORT__/${OPT_CHMPX_SERVER_CTLPORT}/g" -e "s/__SLAVE_CTLPORT__/${OPT_CHMPX_SLAVE_CTLPORT}/g" > ${SRCTOP}/conf/server.ini +cat ${SRCTOP}/conf/config.templ | sed -e "s/__DATE__/${CURRENT_TIME}/g" -e "s#__BASE_DIR__#${SRCTOP}#g" -e "s/__MODE_SETTING__/MODE\t\t\t= SLAVE\nCTLPORT\t\t\t= 18031\nSELFCTLPORT\t\t= 18031/g" -e "s/__SERVER_PORT__/${OPT_CHMPX_SERVER_PORT}/g" -e "s/__SERVER_CTLPORT__/${OPT_CHMPX_SERVER_CTLPORT}/g" -e "s/__SLAVE_CTLPORT__/${OPT_CHMPX_SLAVE_CTLPORT}/g" > ${SRCTOP}/conf/slave.ini +if [ ! -f ${SRCTOP}/conf/server.ini -o ! -f ${SRCTOP}/conf/slave.ini ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create(copy) ini configuration files${CDEF}" 1>&2 + exit 1 +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Generated configuration files : ${SRCTOP}/conf/server.ini, ${SRCTOP}/conf/slave.ini${CDEF}" + +#---------------------------------------------------------- +# Setup K2HR3 API +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Setup and Generate K2HR3 REST API configuration${CDEF}" +echo "-----------------------------------------------------------" + +# check build-essential package +dpkg -l | grep build-essential >/dev/null 2>&1 +if [ $? -ne 0 ]; then + # install build-essential package for building k2hdkc nodejs addon + sudo apt install -y build-essential +fi + +cd ${SRCTOP} +npm pack k2hr3-api +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not get k2hr3-api npm package archive${CDEF}" 1>&2 + exit 1 +fi + +tar xvfz k2hr3-api*.tgz +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not decompress k2hr3-api npm package archive${CDEF}" 1>&2 + exit 1 +fi +if [ ! -d package ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not find \"package\" directory${CDEF}" 1>&2 + exit 1 +fi + +mv package k2hr3-api +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not rename directory from \"package\" to \"k2hr3-api\"${CDEF}" 1>&2 + exit 1 +fi + +cd k2hr3-api +npm install +if [ $? -ne 0 ]; then + # It rarely fails, but sometimes retrying succeeds + sleep 5 + npm install + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Failed to install dependency packages for k2hr3-api${CDEF}" 1>&2 + exit 1 + fi +fi + +if [ "X${OPT_K2HR3_APP_HOST}" != "Xlocalhost" ]; then + # Always set localhost + TMP_K2HR3_APP_HOSTS="'localhost',\n\t\t" +fi +if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" != "X" ]; then + TMP_K2HR3_APP_HOSTS="${TMP_K2HR3_APP_HOSTS}'${OPT_K2HR3_APP_HOST}',\n\t\t'${OPT_K2HR3_APP_HOST_EXTERNAL}'" +else + TMP_K2HR3_APP_HOSTS="${TMP_K2HR3_APP_HOSTS}'${OPT_K2HR3_APP_HOST}'" +fi +if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" != "X" ]; then + TMP_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT_EXTERNAL} +else + TMP_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT} +fi +if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" != "X" ]; then + TMP_K2HR3_API_HOST_EXT=${OPT_K2HR3_API_HOST_EXTERNAL} +else + TMP_K2HR3_API_HOST_EXT=${OPT_K2HR3_API_HOST} +fi + +cat ${SRCTOP}/conf/production_api.templ | sed -e "s#__BASE_DIR__#${SRCTOP}#g" -e "s/__OS_REGION__/${OPT_OPENSTACK_REGION}/g" -e "s#__KEYSTONE_URL__#${OPT_KEYSTONE_URL}#g" -e "s/__RUNUSER__/${OPT_RUNUSER}/g" -e "s/__SLAVE_CTLPORT__/${OPT_CHMPX_SLAVE_CTLPORT}/g" -e "s/__K2HR3_APP_HOSTS__/${TMP_K2HR3_APP_HOSTS}/g" -e "s/__K2HR3_API_HOST__/${OPT_K2HR3_API_HOST}/g" -e "s/__K2HR3_API_PORT__/${OPT_K2HR3_API_PORT}/g" -e "s/__K2HR3_API_HOST_EXT__/${TMP_K2HR3_API_HOST_EXT}/g" -e "s/__K2HR3_API_PORT_EXT__/${TMP_K2HR3_API_PORT_EXT}/g" > ${SRCTOP}/k2hr3-api/config/production.json +if [ ! -f ${SRCTOP}/k2hr3-api/config/production.json ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create(copy) production.json configuration file${CDEF}" 1>&2 + exit 1 +fi + +cp ${SRCTOP}/conf/extdata_k2hr3_trove.sh.templ ${SRCTOP}/k2hr3-api/config/extdata_k2hr3_trove.sh.templ + +cat ${SRCTOP}/k2hr3-api/bin/run.sh | sed -e 's/\.pid/_api.pid/g' > ${SRCTOP}/k2hr3-api/bin/mod_run.sh +chmod +x ${SRCTOP}/k2hr3-api/bin/mod_run.sh +mv ${SRCTOP}/k2hr3-api/bin/run.sh ${SRCTOP}/k2hr3-api/bin/run_orig.sh +mv ${SRCTOP}/k2hr3-api/bin/mod_run.sh ${SRCTOP}/k2hr3-api/bin/run.sh +if [ ! -f ${SRCTOP}/k2hr3-api/bin/run.sh -o ! -f ${SRCTOP}/k2hr3-api/bin/run_orig.sh ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not modify run.sh for this one pack${CDEF}" 1>&2 + exit 1 +fi + +cp ${SRCTOP}/conf/k2hr3-init.sh.templ ${SRCTOP}/k2hr3-api/config/k2hr3-init.sh.templ +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not copy k2hr3-init.sh.templ in k2hr3_api config directory for this one pack${CDEF}" 1>&2 + exit 1 +fi + +if [ ! -d ${SRCTOP}/k2hr3-api/log ]; then + mkdir ${SRCTOP}/k2hr3-api/log + chmod 0777 ${SRCTOP}/k2hr3-api/log + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create ${SRCTOP}/k2hr3-api/log directory${CDEF}" 1>&2 + exit 1 + fi +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Setup and Generated K2HR3 REST API configuration files : ${SRCTOP}/k2hr3-api/config/production.json${CDEF}" + +#---------------------------------------------------------- +# Setup K2HR3 APP +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Setup and Generate K2HR3 Application configuration${CDEF}" +echo "-----------------------------------------------------------" +cd ${SRCTOP} +npm pack k2hr3-app +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not get k2hr3-app npm package archive${CDEF}" 1>&2 + exit 1 +fi + +tar xvfz k2hr3-app*.tgz +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not decompress k2hr3-app npm package archive${CDEF}" 1>&2 + exit 1 +fi +if [ ! -d package ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not find \"package\" directory${CDEF}" 1>&2 + exit 1 +fi + +mv package k2hr3-app +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not rename directory from \"package\" to \"k2hr3-app\"${CDEF}" 1>&2 + exit 1 +fi + +cd k2hr3-app +npm install +if [ $? -ne 0 ]; then + # It rarely fails, but sometimes retrying succeeds + sleep 5 + npm install + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Failed to install dependency packages for k2hr3-app${CDEF}" 1>&2 + exit 1 + fi +fi + +if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" != "X" ]; then + TMP_K2HR3_APP_HOSTS="'${OPT_K2HR3_APP_HOST}',\n\t\t'${OPT_K2HR3_APP_HOST_EXTERNAL}'" +else + TMP_K2HR3_APP_HOSTS="'${OPT_K2HR3_APP_HOST}'" +fi +if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" != "X" ]; then + TMP_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT_EXTERNAL} +else + TMP_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT} +fi +if [ "X${OPT_K2HR3_API_HOST_EXTERNAL}" != "X" ]; then + TMP_K2HR3_API_HOST_EXT=${OPT_K2HR3_API_HOST_EXTERNAL} +else + TMP_K2HR3_API_HOST_EXT=${OPT_K2HR3_API_HOST} +fi +if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" != "X" ]; then + TMP_K2HR3_APP_PORT_EXT=${OPT_K2HR3_APP_PORT_EXTERNAL} +else + TMP_K2HR3_APP_PORT_EXT=${OPT_K2HR3_APP_PORT} +fi +if [ "X${OPT_K2HR3_APP_HOST_EXTERNAL}" != "X" ]; then + TMP_K2HR3_APP_HOST_EXT=${OPT_K2HR3_APP_HOST_EXTERNAL} +else + TMP_K2HR3_APP_HOST_EXT=${OPT_K2HR3_APP_HOST} +fi + +cat ${SRCTOP}/conf/production_app.templ | sed -e "s#__BASE_DIR__#${SRCTOP}#g" -e "s/__RUNUSER__/${OPT_RUNUSER}/g" -e "s/__K2HR3_APP_PORT__/${OPT_K2HR3_APP_PORT}/g" -e "s/__K2HR3_APP_HOST__/${OPT_K2HR3_APP_HOST}/g" -e "s/__K2HR3_APP_PORT_EXT__/${TMP_K2HR3_APP_PORT_EXT}/g" -e "s/__K2HR3_APP_HOST_EXT__/${TMP_K2HR3_APP_HOST_EXT}/g" -e "s/__K2HR3_API_HOST__/${OPT_K2HR3_API_HOST}/g" -e "s/__K2HR3_API_PORT__/${OPT_K2HR3_API_PORT}/g" -e "s/__K2HR3_API_HOST_EXT__/${TMP_K2HR3_API_HOST_EXT}/g" -e "s/__K2HR3_API_PORT_EXT__/${TMP_K2HR3_API_PORT_EXT}/g" > ${SRCTOP}/k2hr3-app/config/production.json +if [ ! -f ${SRCTOP}/k2hr3-app/config/production.json ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create(copy) production.json configuration file${CDEF}" 1>&2 + exit 1 +fi + +cat ${SRCTOP}/k2hr3-app/bin/run.sh | sed -e 's/\.pid/_app.pid/g' > ${SRCTOP}/k2hr3-app/bin/mod_run.sh +chmod +x ${SRCTOP}/k2hr3-app/bin/mod_run.sh +mv ${SRCTOP}/k2hr3-app/bin/run.sh ${SRCTOP}/k2hr3-app/bin/run_orig.sh +mv ${SRCTOP}/k2hr3-app/bin/mod_run.sh ${SRCTOP}/k2hr3-app/bin/run.sh +if [ ! -f ${SRCTOP}/k2hr3-app/bin/run.sh -o ! -f ${SRCTOP}/k2hr3-app/bin/run_orig.sh ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not modify run.sh for this one pack${CDEF}" 1>&2 + exit 1 +fi + +if [ ! -d ${SRCTOP}/k2hr3-app/log ]; then + mkdir ${SRCTOP}/k2hr3-app/log + chmod 0777 ${SRCTOP}/k2hr3-app/log + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create ${SRCTOP}/k2hr3-app/log directory${CDEF}" 1>&2 + exit 1 + fi +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Setup and Generated K2HR3 Application configuration files : ${SRCTOP}/k2hr3-app/config/production.json${CDEF}" + +#---------------------------------------------------------- +# Create HAProxy configuration for sample +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Generate HAProxy sample configuration${CDEF}" +echo "-----------------------------------------------------------" +cd ${SRCTOP} + +if [ "X${OPT_K2HR3_APP_PORT_EXTERNAL}" != "X" ]; then + HA_K2HR3_APP_PORT_EXT=${OPT_K2HR3_APP_PORT_EXTERNAL} +else + HA_K2HR3_APP_PORT_EXT=${OPT_K2HR3_APP_PORT} +fi +if [ "X${OPT_K2HR3_API_PORT_EXTERNAL}" != "X" ]; then + HA_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT_EXTERNAL} +else + HA_K2HR3_API_PORT_EXT=${OPT_K2HR3_API_PORT} +fi +cat ${SRCTOP}/conf/haproxy_example.templ | sed -e "s/__K2HR3_APP_PORT_EXT__/${HA_K2HR3_APP_PORT_EXT}/g" -e "s/__K2HR3_APP_PORT__/${OPT_K2HR3_APP_PORT}/g" -e "s/__K2HR3_APP_HOST__/${OPT_K2HR3_APP_HOST}/g" -e "s/__K2HR3_API_PORT_EXT__/${HA_K2HR3_API_PORT_EXT}/g" -e "s/__K2HR3_API_PORT__/${OPT_K2HR3_API_PORT}/g" -e "s/__K2HR3_API_HOST__/${OPT_K2HR3_API_HOST}/g" > ${SRCTOP}/conf/haproxy_example.cfg +if [ ! -f ${SRCTOP}/conf/haproxy_example.cfg ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} could not create HAProxy configuration sample file${CDEF}" 1>&2 + exit 1 +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} Generated HAProxy sample configuration files : ${SRCTOP}/conf/haproxy_example.cfg${CDEF}" + +#---------------------------------------------------------- +# Run processes +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Start all processes${CDEF}" +echo "-----------------------------------------------------------" + +echo "${CGRN}${CREV}[RUN]${CDEF} CHMPX server node..." +sudo -u ${OPT_RUNUSER} chmpx -conf ${SRCTOP}/conf/server.ini -d err >> ${SRCTOP}/log/chmpx_server.log 2>&1 & +sleep 5 +ps ax | grep chmpx | grep server.ini >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not run chmpx server node${CDEF}" 1>&2 + exit 1 +fi + +echo "${CGRN}${CREV}[RUN]${CDEF} K2HDKC server process..." +sudo -u ${OPT_RUNUSER} k2hdkc -conf ${SRCTOP}/conf/server.ini -d err >> ${SRCTOP}/log/k2hdkc.log 2>&1 & +sleep 5 +ps ax | grep k2hdkc | grep server.ini >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not run k2hdkc server process${CDEF}" 1>&2 + exit 1 +fi + +echo "${CGRN}${CREV}[RUN]${CDEF} CHMPX slave node..." +sudo -u ${OPT_RUNUSER} chmpx -conf ${SRCTOP}/conf/slave.ini -d err >> ${SRCTOP}/log/chmpx_slave.log 2>&1 & +sleep 5 +ps ax | grep chmpx | grep slave.ini >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not run chmpx slave node${CDEF}" 1>&2 + exit 1 +fi + +# +# [NOTE] +# Nodejs will be started as root, but internally it will be setuid and run as nobody. +# In k2hr3, log files and directories are created as root, which causes permission issues. +# rotating-file-stream(and fs.createWriteStream, etc.) has a mode option, but which doesn't work. +# Therefore, we use helper script for sudo and umask. +# +echo "${CGRN}${CREV}[RUN]${CDEF} K2HR3 REST API..." +sudo ${BINDIR}/run_node_helper.sh ${SRCTOP}/k2hr3-api +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not run k2hr3-api node process${CDEF}" 1>&2 + exit 1 +fi +sleep 5 + +echo "${CGRN}${CREV}[RUN]${CDEF} K2HR3 Application..." +sudo ${BINDIR}/run_node_helper.sh ${SRCTOP}/k2hr3-app +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not run k2hr3-app node process${CDEF}" 1>&2 + exit 1 +fi +sleep 5 + +#---------------------------------------------------------- +# Success +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}K2HR3 one pack launcher completed${CDEF}" +echo "-----------------------------------------------------------" +ps -ax | grep -v grep | grep -e chmpx -e k2hdkc -e www | grep -v '\-u nobody' | grep -v 'node bin/www' +echo "--------------------------------------------------" +PROCESSES=`ps -ax | grep -v grep | grep -e chmpx -e k2hdkc -e www | grep -v '\-u nobody' | grep -v 'node bin/www' | wc -l` +if [ "X${PROCESSES}" != "X5" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Some important processes could not be started.${CDEF}" 1>&2 + exit 1 +fi +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} All K2HR3 processes has been run.${CDEF}" + +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/bin/run_node_helper.sh b/utils/k2hr3_pack/bin/run_node_helper.sh new file mode 100755 index 0000000..3e15984 --- /dev/null +++ b/utils/k2hr3_pack/bin/run_node_helper.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# [NOTE] +# We need to set an arbitrary umask when running npm with sudo. +# However, it is assumed that umask cannot be specified due to system sudoers. +# So instead of running npm directly with sudo, run it via this script. +# This script sets the umask before running npm. +# +if [ $# -ne 1 ]; then + exit 1 +fi + +BASE_DIR=$1 +if [ ! -d ${BASE_DIR} ]; then + exit 1 +fi +cd ${BASE_DIR} >/dev/null 2>&1 + +OLD_UMASK=`umask` +umask 0000 + +npm run start +if [ $? -ne 0 ]; then + exit $? +fi + +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/bin/stoppack.sh b/utils/k2hr3_pack/bin/stoppack.sh new file mode 100755 index 0000000..5dd58a4 --- /dev/null +++ b/utils/k2hr3_pack/bin/stoppack.sh @@ -0,0 +1,246 @@ +#!/bin/sh +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +#---------------------------------------------------------- +# Environments +#---------------------------------------------------------- +CMDLINE_PROCESS_NAME=$0 +PROGRAM_NAME=`basename ${CMDLINE_PROCESS_NAME}` +SCRIPTPATH=`dirname ${CMDLINE_PROCESS_NAME}` +BINDIR=`cd ${SCRIPTPATH}; pwd` +SRCTOP=`cd ${SCRIPTPATH}/..; pwd` + +# +# Escape sequence +# +CDEF=$(printf '\033[0m') +CREV=$(printf '\033[7m') +CRED=$(printf '\033[31m') +CGRN=$(printf '\033[32m') + +#---------------------------------------------------------- +# Options +#---------------------------------------------------------- +func_usage() +{ + # + # $1: Program name + # + echo "" + echo "Usage: $1 [--clear(-c)] [--help(-h)]" + echo "" + echo " --clear(-c) clear configuration, data and log files." + echo " --help(-h) print help" + echo "" +} + +# +# Check options +# +OPT_CLEAR= +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--help" -o "X$1" = "X--HELP" ]; then + func_usage $PROGRAM_NAME + exit 0 + + elif [ "X$1" = "X-c" -o "X$1" = "X-C" -o "X$1" = "X--clear" -o "X$1" = "X--CLEAR" ]; then + if [ "X${OPT_CLEAR}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --clear(-c) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + OPT_CLEAR="yes" + + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} $1 option is unknown.${CDEF}" 1>&2 + exit 1 + fi + shift +done + +#---------------------------------------------------------- +# Current processes state +#---------------------------------------------------------- +echo "-----------------------------------------------------------" +echo "${CGRN}Current processes state${CDEF}" +echo "-----------------------------------------------------------" +ps -ax | grep -v grep | grep -e chmpx -e k2hdkc -e www | grep -v '\-u nobody' | grep -v 'node bin/www' + +#---------------------------------------------------------- +# Stop processes +#---------------------------------------------------------- +echo "" +echo "-----------------------------------------------------------" +echo "${CGRN}Stop all processes${CDEF}" +echo "-----------------------------------------------------------" +echo "" +echo "${CGRN}${CREV}[STOP]${CDEF} K2HR3 Application..." +cd ${SRCTOP}/k2hr3-app +ps ax 2>/dev/null | grep -v grep | grep k2hr3-app | grep node | grep www >/dev/null +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Already stop k2hr3-app node process${CDEF}" 1>&2 +else + sudo npm run stop + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop k2hr3-app node process${CDEF}" 1>&2 + exit 1 + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop k2hr3-app node process${CDEF}" + fi +fi + +echo "" +echo "${CGRN}${CREV}[STOP]${CDEF} K2HR3 REST API..." +cd ${SRCTOP}/k2hr3-api +ps ax 2>/dev/null | grep -v grep | grep k2hr3-api | grep node | grep www >/dev/null +if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Already stop k2hr3-api node process${CDEF}" 1>&2 +else + sudo npm run stop + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop k2hr3-api node process${CDEF}" 1>&2 + exit 1 + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop k2hr3-api node process${CDEF}" + fi +fi + +echo "" +echo "${CGRN}${CREV}[STOP]${CDEF} CHMPX slave node..." +cd ${SRCTOP} +CHMPX_SLAVE_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep slave.ini | grep -v '\-u nobody' | awk '{print $1}'` +if [ "X${CHMPX_SLAVE_PROCID}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Already stop CHMPX slave process${CDEF}" 1>&2 +else + sudo kill -HUP ${CHMPX_SLAVE_PROCID} + sleep 10 + CHMPX_SLAVE_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep slave.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${CHMPX_SLAVE_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop CHMPX slave process by HUP, then retry by KILL${CDEF}" 1>&2 + + sudo kill -KILL ${CHMPX_SLAVE_PROCID} + sleep 10 + CHMPX_SLAVE_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep slave.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${CHMPX_SLAVE_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop CHMPX slave process by KILL${CDEF}" 1>&2 + exit 1 + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop CHMPX slave process${CDEF}" + fi + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop CHMPX slave process${CDEF}" + fi +fi + +echo "" +echo "${CGRN}${CREV}[STOP]${CDEF} K2HDKC server process..." +cd ${SRCTOP} +K2HDKC_PROCID=`ps ax 2>/dev/null | grep -v grep | grep k2hdkc | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` +if [ "X${K2HDKC_PROCID}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Already stop K2HDKC server process${CDEF}" 1>&2 +else + sudo kill -HUP ${K2HDKC_PROCID} + sleep 10 + K2HDKC_PROCID=`ps ax 2>/dev/null | grep -v grep | grep k2hdkc | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${K2HDKC_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop K2HDKC server process by HUP, then retry by KILL${CDEF}" 1>&2 + + sudo kill -KILL ${K2HDKC_PROCID} + sleep 10 + K2HDKC_PROCID=`ps ax 2>/dev/null | grep -v grep | grep k2hdkc | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${K2HDKC_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop K2HDKC server process by KILL${CDEF}" 1>&2 + exit 1 + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop K2HDKC server process${CDEF}" + fi + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop K2HDKC server process${CDEF}" + fi +fi + +echo "" +echo "${CGRN}${CREV}[STOP]${CDEF} CHMPX server node..." +cd ${SRCTOP} +CHMPX_SERVER_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` +if [ "X${CHMPX_SERVER_PROCID}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Already stop CHMPX server process${CDEF}" 1>&2 +else + sudo kill -HUP ${CHMPX_SERVER_PROCID} + sleep 10 + CHMPX_SERVER_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${CHMPX_SERVER_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop CHMPX server process by HUP, then retry by KILL${CDEF}" 1>&2 + + sudo kill -KILL ${CHMPX_SERVER_PROCID} + sleep 10 + CHMPX_SERVER_PROCID=`ps ax 2>/dev/null | grep -v grep | grep chmpx | grep server.ini | grep -v '\-u nobody' | awk '{print $1}'` + if [ "X${CHMPX_SERVER_PROCID}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop CHMPX server process by KILL${CDEF}" 1>&2 + exit 1 + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop CHMPX server process${CDEF}" + fi + else + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} stop CHMPX server process${CDEF}" + fi +fi + +#---------------------------------------------------------- +# Check processes +#---------------------------------------------------------- +ps -ax 2>/dev/null | grep -v grep | grep -e chmpx -e k2hdkc -e www | grep -v '\-u nobody' | grep -v 'node bin/www' >/dev/null +if [ $? -eq 0 ]; then + echo "" + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not stop some processes${CDEF}" 1>&2 + echo "" + ps -ax 2>/dev/null | grep -v grep | grep -e chmpx -e k2hdkc -e www | grep -v '\-u nobody' | grep -v 'node bin/www' + echo "" + exit 1 +fi + +#---------------------------------------------------------- +# Clear files +#---------------------------------------------------------- +if [ "X${OPT_CLEAR}" = "Xyes" ]; then + echo "" + echo "-----------------------------------------------------------" + echo "${CGRN}Clean up files${CDEF}" + echo "-----------------------------------------------------------" + sudo rm -rf log/* data/* conf/*.ini conf/*.cfg k2hr3-ap* + + echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} cleaned up files.${CDEF}" +fi + +echo "" +echo "${CGRN}${CREV}[SUCCESS]${CDEF}${CGRN} All processes has been stop.${CDEF}" + +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/conf/config.templ b/utils/k2hr3_pack/conf/config.templ new file mode 100644 index 0000000..39a452d --- /dev/null +++ b/utils/k2hr3_pack/conf/config.templ @@ -0,0 +1,96 @@ +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# GLOBAL SECTION +# +[GLOBAL] +FILEVERSION = 1 +DATE = __DATE__ +GROUP = K2HR3_K2HDKC +__MODE_SETTING__ +DELIVERMODE = hash +MAXCHMPX = 16 +REPLICA = 1 +MAXMQSERVER = 8 +MAXMQCLIENT = 8 +MQPERATTACH = 4 +MAXQPERSERVERMQ = 4 +MAXQPERCLIENTMQ = 4 +MAXMQPERCLIENT = 4 +MAXHISTLOG = 0 +RWTIMEOUT = 1000000 +RETRYCNT = 1000 +CONTIMEOUT = 500000 +MQRWTIMEOUT = 1000 +MQRETRYCNT = 10000 +MQACK = no +AUTOMERGE = on +DOMERGE = on +MERGETIMEOUT = 0 +SOCKTHREADCNT = 8 +MQTHREADCNT = 8 +MAXSOCKPOOL = 16 +SOCKPOOLTIMEOUT = 0 +SSL = no +K2HFULLMAP = on +K2HMASKBIT = 4 +K2HCMASKBIT = 4 +K2HMAXELE = 4 + +# +# SERVER NODES SECTION +# +[SVRNODE] +NAME = localhost +PORT = __SERVER_PORT__ +CTLPORT = __SERVER_CTLPORT__ +SSL = no + +# +# SLAVE NODES SECTION +# +[SLVNODE] +NAME = [.]* +CTLPORT = __SLAVE_CTLPORT__ + +# +# K2HDKC SECTION +# +[K2HDKC] +RCVTIMEOUT = 1000 +DTORTHREADCNT = 1 +K2HTYPE = file +K2HFILE = __BASE_DIR__/data/k2hdkc.k2h +K2HFULLMAP = on +K2HINIT = no +K2HMASKBIT = 4 +K2HCMASKBIT = 4 +K2HMAXELE = 8 +K2HPAGESIZE = 512 +MAXTHREAD = 16 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/conf/extdata_k2hr3_trove.sh.templ b/utils/k2hr3_pack/conf/extdata_k2hr3_trove.sh.templ new file mode 100644 index 0000000..75c84b7 --- /dev/null +++ b/utils/k2hr3_pack/conf/extdata_k2hr3_trove.sh.templ @@ -0,0 +1,468 @@ +#!/bin/sh +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +#---------------------------------------------------------- +# Values expanded by the K2HR3 EXTDATA API +#---------------------------------------------------------- +ROLE_NAME={{= %K2HR3_ROLE_NAME% }} +ROLE_TENANT={{= %K2HR3_ROLE_TENANT% }} +ROLE_TOKEN={{= %K2HR3_ROLE_TOKEN% }} +K2HR3_API_HOST={{= %K2HR3_API_HOST_URI% }} +ERROR_MSG={{= %K2HR3_ERROR_MSG% }} + +#---------------------------------------------------------- +# Common variables +#---------------------------------------------------------- +# +# Escape sequence +# +if [ -t 1 ]; then + CDEF=$(printf '\033[0m') + CREV=$(printf '\033[7m') + CRED=$(printf '\033[31m') + CGRN=$(printf '\033[32m') +else + CDEF="" + CREV="" + CRED="" + CGRN="" +fi + +# +# Arguments +# +CMDLINE_PROCESS_NAME=$0 +PROGRAM_NAME=`basename ${CMDLINE_PROCESS_NAME}` +SCRIPTPATH=`dirname ${CMDLINE_PROCESS_NAME}` + +# +# Local variables +# +CURRENT_TIME=`date "+%Y-%m-%d %H:%M:%S,%3N"` + +# +# Cloud-init +# +CLOUDINIT_DATA_DIR="/var/lib/cloud/data" +INSTANCE_ID_FILE="${CLOUDINIT_DATA_DIR}/instance-id" + +# +# Trove Configuration Group +# +TROVE_INPUT_GROUP_FILE="cluster-name" +TROVE_INPUT_PORT_FILE="chmpx-server-port" +TROVE_INPUT_CTLPORT_FILE="chmpx-server-ctlport" +TROVE_INPUT_SLAVE_CTLPORT_FILE="chmpx-slave-ctlport" + +# +# Output file names +# +OUTPUT_ROLE_NAME_FILE="extdata_role_name" +OUTPUT_ROLE_TENANT_FILE="extdata_role_tenant" +OUTPUT_ROLE_TOKEN_FILE="extdata_role_token" +OUTPUT_K2HR3_API_HOST_FILE="extdata_role_api_host_uri" + +# +# Python +# +python --version >/dev/null 2>&1 +if [ $? -eq 0 ]; then + PYBIN="python" +else + python3 --version >/dev/null 2>&1 + if [ $? -eq 0 ]; then + PYBIN="python3" + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} The python program could not be found${CDEF}" 1>&2 + exit 1 + fi +fi + +#---------------------------------------------------------- +# Functions +#---------------------------------------------------------- +# +# $1: Program name +# +func_usage() +{ + echo "" + echo "Usage: $1 [--register(-r) | --delete(-d) | --load_resource(-l)] [--config_dir(-c) ] [--serverini_name(-s) ] [--help(-h)]" + echo "" + echo " --register(-r) Register host(vm) to role member on k2hr3" + echo " --delete(-d) Delete host(vm) from role member on k2hr3" + echo " --load_resource(-l) Load resource and save it" + echo " --config_dir(-c) Configuarion directory path for loading/saving files(default: /etc/k2hdkc)" + echo " --serverini_name(-s) Configuration file name for K2HDKC(default: server.ini)" + echo " --help(-h) print help" + echo "" +} + +# +# $1: filepath +# $2: value +# +check_and_overwrite_file() +{ + _LOCAL_CO_FILE=$1 + _LOCAL_CO_VALUE=$2 + + if [ -f ${_LOCAL_CO_FILE} ]; then + _LOCAL_CO_TMP=`cat ${_LOCAL_CO_FILE} 2>/dev/null | tr -d '\n' 2>/dev/null` + if [ "X${_LOCAL_CO_TMP}" = "X${_LOCAL_CO_VALUE}" ]; then + # + # Same content value + # + return 0; + fi + fi + + echo -n "${_LOCAL_CO_VALUE}" > ${_LOCAL_CO_FILE} 2>/dev/null + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not save "${_LOCAL_CO_VALUE}" to ${_LOCAL_CO_FILE}.${CDEF}" + return 1; + fi + chmod 600 ${_LOCAL_CO_FILE} 2>/dev/null + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not change mode 600 to ${_LOCAL_CO_FILE}.${CDEF}" + return 1; + fi + echo "${CGRN}${CREV}[MSG]${CDEF} Succeed to save the value to ${_LOCAL_CO_FILE}." + return 0; +} + +# +# $1: filepath +# +check_and_load_file() +{ + _LOCAL_CL_FILE=$1 + + if [ ! -f ${_LOCAL_CL_FILE} ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not read ${_LOCAL_CL_FILE}.${CDEF}" 1>&2 + return 1; + fi + + _LOCAL_CO_RESULT=`cat ${_LOCAL_CL_FILE} 2>/dev/null | tr -d '\n' 2>/dev/null` + echo ${_LOCAL_CO_RESULT} + + return 0; +} + +#---------------------------------------------------------- +# Options +#---------------------------------------------------------- +PROG_MODE= +CONFIGDIR= +OUTPUT_SERVER_INI_FILE= +while [ $# -ne 0 ]; do + if [ "X$1" = "X" ]; then + break + + elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--help" -o "X$1" = "X--HELP" ]; then + func_usage $PROGRAM_NAME + exit 0 + + elif [ "X$1" = "X-r" -o "X$1" = "X-R" -o "X$1" = "X--register" -o "X$1" = "X--REGISTER" ]; then + if [ "X${PROG_MODE}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --register(-r) option cannot be set, because another mode option has already been set.${CDEF}" 1>&2 + exit 1 + fi + PROG_MODE="r" + + elif [ "X$1" = "X-d" -o "X$1" = "X-D" -o "X$1" = "X--delete" -o "X$1" = "X--DELETE" ]; then + if [ "X${PROG_MODE}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --delete(-d) option cannot be set, because another mode option has already been set.${CDEF}" 1>&2 + exit 1 + fi + PROG_MODE="d" + + elif [ "X$1" = "X-l" -o "X$1" = "X-L" -o "X$1" = "X--load_resource" -o "X$1" = "X--LOAD_RESOURCE" ]; then + if [ "X${PROG_MODE}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --load_resource(-l) option cannot be set, because another mode option has already been set.${CDEF}" 1>&2 + exit 1 + fi + PROG_MODE="l" + + elif [ "X$1" = "X-c" -o "X$1" = "X-C" -o "X$1" = "X--config_dir" -o "X$1" = "X--CONFIG_DIR" ]; then + if [ "X${CONFIGDIR}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --config_dir(-c) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --config_dir(-c) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + if [ ! -d $1 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} \"$1\" directory specified by the --config_dir(-c) option does not exist.${CDEF}" 1>&2 + exit 1 + fi + CONFIGDIR=$1 + + elif [ "X$1" = "X-s" -o "X$1" = "X-S" -o "X$1" = "X--serverini_name" -o "X$1" = "X--SERVERINI_NAME" ]; then + if [ "X${OUTPUT_SERVER_INI_FILE}" != "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --serverini_name(-s) option is already specified.${CDEF}" 1>&2 + exit 1 + fi + shift + if [ $# -eq 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} --serverini_name(-s) option needs parameter.${CDEF}" 1>&2 + exit 1 + fi + OUTPUT_SERVER_INI_FILE=$1 + + else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} $1 option is unknown.${CDEF}" 1>&2 + exit 1 + fi + shift +done + +if [ "X${PROG_MODE}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} You must specify one of the \"--register(-r)\", \"--delete(-d)\" or \"--load_resource(-l)\" options.${CDEF}" 1>&2 + exit 1 +fi +if [ "X${CONFIGDIR}" = "X" ]; then + CONFIGDIR="/etc/k2hdkc" + if [ ! -d ${CONFIGDIR} ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} \"${CONFIGDIR}\" directory does not exist.${CDEF}" 1>&2 + exit 1 + fi +fi +if [ "X${OUTPUT_SERVER_INI_FILE}" = "X" ]; then + OUTPUT_SERVER_INI_FILE="server.ini" +fi + +#---------------------------------------------------------- +# Check and Save common parameters +#---------------------------------------------------------- +# +# Check instance id and file for CUK +# +if [ ! -f ${INSTANCE_ID_FILE} ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not read ${INSTANCE_ID_FILE}.${CDEF}" 1>&2 + exit 1 +fi +INSTANCE_ID=`cat ${INSTANCE_ID_FILE} 2>/dev/null | tr -d '\n' 2>/dev/null` +CUK_PARAMETER="cuk=${INSTANCE_ID}" +EXTRA_PARAMETER="extra=openstack-auto-v1" +LOCAL_HOSTNAME=`hostname` +TAG_PARAMETER="tag=${LOCAL_HOSTNAME}" + +# +# Check common values +# +if [ "X${ROLE_NAME}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} ROLE_NAME value is empty.${CDEF}" 1>&2 + exit 1 +fi +if [ "X${ROLE_TENANT}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} ROLE_TENANT value is empty.${CDEF}" 1>&2 + exit 1 +fi +if [ "X${ROLE_TOKEN}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} ROLE_TOKEN value is empty.${CDEF}" 1>&2 + exit 1 +fi +if [ "X${K2HR3_API_HOST}" = "X" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} K2HR3_API_HOST value is empty.${CDEF}" 1>&2 + exit 1 +fi +if [ "X${ERROR_MSG}" != "X" -a "X${ERROR_MSG}" != "Xnull" ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} This ${PROGRAM_NAME} script cannot work properly because an error(\"${ERROR_MSG}\") occurred while getting EXTDATA.${CDEF}" 1>&2 + exit 1 +fi + +# +# Over writes values if the value is changed +# +TMP_RESULT_MSG=`check_and_overwrite_file "${CONFIGDIR}/${OUTPUT_ROLE_NAME_FILE}" "${ROLE_NAME}"` +TMP_RESULT_CODE=$? +if [ "X${TMP_RESULT_MSG}" != "X" ]; then + echo ${TMP_RESULT_MSG} 1>&2 +fi +if [ ${TMP_RESULT_CODE} -ne 0 ]; then + exit 1; +fi +TMP_RESULT_MSG=`check_and_overwrite_file "${CONFIGDIR}/${OUTPUT_ROLE_TENANT_FILE}" "${ROLE_TENANT}"` +TMP_RESULT_CODE=$? +if [ "X${TMP_RESULT_MSG}" != "X" ]; then + echo ${TMP_RESULT_MSG} 1>&2 +fi +if [ ${TMP_RESULT_CODE} -ne 0 ]; then + exit 1; +fi +TMP_RESULT_MSG=`check_and_overwrite_file "${CONFIGDIR}/${OUTPUT_ROLE_TOKEN_FILE}" "${ROLE_TOKEN}"` +TMP_RESULT_CODE=$? +if [ "X${TMP_RESULT_MSG}" != "X" ]; then + echo ${TMP_RESULT_MSG} 1>&2 +fi +if [ ${TMP_RESULT_CODE} -ne 0 ]; then + exit 1; +fi +TMP_RESULT_MSG=`check_and_overwrite_file "${CONFIGDIR}/${OUTPUT_K2HR3_API_HOST_FILE}" "${K2HR3_API_HOST}"` +TMP_RESULT_CODE=$? +if [ "X${TMP_RESULT_MSG}" != "X" ]; then + echo ${TMP_RESULT_MSG} 1>&2 +fi +if [ ${TMP_RESULT_CODE} -ne 0 ]; then + exit 1; +fi + +#---------------------------------------------------------- +# Registration +#---------------------------------------------------------- +if [ "X${PROG_MODE}" = "Xr" ]; then + echo "${CGRN}${CREV}[MSG]${CDEF} ${CURRENT_TIME} Start to register host(vm) to K2HR3." 1>&2 + + # + # Register host(vm) + # + REGISTER_RESULT=`curl -s -S -X PUT -H "x-auth-token: R=${ROLE_TOKEN}" "${K2HR3_API_HOST}/v1/role/${ROLE_NAME}?${CUK_PARAMETER}&${EXTRA_PARAMETER}&${TAG_PARAMETER}" 2>&1` + if [ $? -ne 0 ];then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not register to role member with curl error.${CDEF}" 1>&2 + exit 1 + fi + REGISTER_RESULT_VALUE=`echo ${REGISTER_RESULT} | ${PYBIN} -m json.tool | grep result | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g' | tr '[:lower:]' '[:upper:]'` + if [ "X${REGISTER_RESULT_VALUE}" != "XTRUE" ]; then + REGISTER_RESULT_MSG=`echo ${REGISTER_RESULT} | ${PYBIN} -m json.tool | grep message | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g'` + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Failed to put access for registering by \"${REGISTER_RESULT_MSG}\".${CDEF}" 1>&2 + exit 1 + fi + + echo "${CGRN}${CREV}[SUCCESS]${CDEF} ${CURRENT_TIME} Register host(vm: ${INSTANCE_ID}) to K2HR3 role(${ROLE_NAME})." 1>&2 + +#---------------------------------------------------------- +# Deletion +#---------------------------------------------------------- +elif [ "X${PROG_MODE}" = "Xd" ]; then + echo "${CGRN}${CREV}[MSG]${CDEF} ${CURRENT_TIME} Start to delete host(vm) from K2HR3." 1>&2 + + # + # Delete host(vm) + # + DELETE_RESULT=`curl -s -S -X DELETE -o /dev/null -w "%{http_code}\n" "${K2HR3_API_HOST}/v1/role/${ROLE_NAME}?${CUK_PARAMETER}&${EXTRA_PARAMETER}" 2>&1` + if [ "X${DELETE_RESULT}" != "X204" ];then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not delete from role member with curl result status(${DELETE_RESULT}).${CDEF}" 1>&2 + exit 1 + fi + + echo "${CGRN}${CREV}[SUCCESS]${CDEF} ${CURRENT_TIME} Delete host(vm: ${INSTANCE_ID}) from K2HR3 role(${ROLE_NAME})." 1>&2 + +#---------------------------------------------------------- +# Get and Save resource +#---------------------------------------------------------- +elif [ "X${PROG_MODE}" = "Xl" ]; then + echo "${CGRN}${CREV}[MSG]${CDEF} ${CURRENT_TIME} Start to load resource(${OUTPUT_SERVER_INI_FILE}) from K2HR3." 1>&2 + + # + # Check group name + # + GROUP_NAME=`check_and_load_file "${CONFIGDIR}/${TROVE_INPUT_GROUP_FILE}"` + if [ $? -ne 0 ]; then + echo ${GROUP_NAME} 1>&2 + exit 1; + fi + + # + # Make resource name(yrn path) + # + RESOURCE_NAME="${ROLE_TENANT}:resource:${GROUP_NAME}/server" + + # + # Check ports + # + # [NOTE] These are only for checking, these value are not used in this script. + # + PORT_NUMBER=`check_and_load_file "${CONFIGDIR}/${TROVE_INPUT_PORT_FILE}"` + if [ $? -ne 0 ]; then + echo ${PORT_NUMBER} 1>&2 + exit 1; + fi + CTLPORT_NUMBER=`check_and_load_file "${CONFIGDIR}/${TROVE_INPUT_CTLPORT_FILE}"` + if [ $? -ne 0 ]; then + echo ${CTLPORT_NUMBER} 1>&2 + exit 1; + fi + SLAVE_CTLPORT_NUMBER=`check_and_load_file "${CONFIGDIR}/${TROVE_INPUT_SLAVE_CTLPORT_FILE}"` + if [ $? -ne 0 ]; then + echo ${SLAVE_CTLPORT_NUMBER} 1>&2 + exit 1; + fi + + # + # Get resource + # + GET_RESOURCE_RESULT=`curl -s -S -X GET -H "Content-Type: application/json" "${K2HR3_API_HOST}/v1/resource/${RESOURCE_NAME}?${CUK_PARAMETER}&role=${ROLE_NAME}&type=string" 2>&1` + if [ $? -ne 0 ];then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not get resource.${CDEF}" 1>&2 + exit 1 + fi + GET_RESOURCE_RESULT_VALUE=`echo ${GET_RESOURCE_RESULT} | ${PYBIN} -m json.tool | grep result | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g' | tr '[:lower:]' '[:upper:]'` + if [ "X${GET_RESOURCE_RESULT_VALUE}" != "XTRUE" ]; then + GET_RESOURCE_RESULT_MSG=`echo ${GET_RESOURCE_RESULT} | ${PYBIN} -m json.tool | grep message | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g'` + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Failed to get resource by \"${GET_RESOURCE_RESULT_MSG}\".${CDEF}" 1>&2 + exit 1 + fi + + # + # Save resource as OUTPUT_SERVER_INI_FILE + # + OUTPUT_SERVER_INI_PATH="${CONFIGDIR}/${OUTPUT_SERVER_INI_FILE}" + rm -f ${OUTPUT_SERVER_INI_PATH} + echo ${GET_RESOURCE_RESULT} | ${PYBIN} -m json.tool | grep '"resource": ' | sed -e 's/"resource"://g' -e 's/^[ ,]\+\|[ ,]\+$//g' -e 's/^\"//g' -e 's/\"$//g' -e 's/\\n/\n/g' | sed -e "s/__TROVE_K2HDKC_SELF_CUK__/${INSTANCE_ID}/g" > ${OUTPUT_SERVER_INI_PATH} + if [ ! -f ${OUTPUT_SERVER_INI_PATH} ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not make ${OUTPUT_SERVER_INI_PATH} from resource.${CDEF}" 1>&2 + exit 1 + fi + if [ ! -s ${OUTPUT_SERVER_INI_PATH} ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not make ${OUTPUT_SERVER_INI_PATH} from resource.${CDEF}" 1>&2 + rm -f ${OUTPUT_SERVER_INI_PATH} + exit 1 + fi + chmod 644 ${OUTPUT_SERVER_INI_PATH} 2>/dev/null + if [ $? -ne 0 ]; then + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Could not change mode 600 to ${OUTPUT_SERVER_INI_PATH}, but continue...${CDEF}" 1>&2 + fi + + echo "${CGRN}${CREV}[SUCCESS]${CDEF} ${CURRENT_TIME} Make ${OUTPUT_SERVER_INI_PATH} from resource." 1>&2 + +#---------------------------------------------------------- +# Error +#---------------------------------------------------------- +else + echo "${CRED}${CREV}[ERROR]${CDEF}${CRED} Internal error in ${PROGRAM_NAME} script.${CDEF}" 1>&2 + exit 1 +fi + +#---------------------------------------------------------- +# Finish +#---------------------------------------------------------- +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/conf/haproxy_example.templ b/utils/k2hr3_pack/conf/haproxy_example.templ new file mode 100644 index 0000000..a9e4472 --- /dev/null +++ b/utils/k2hr3_pack/conf/haproxy_example.templ @@ -0,0 +1,47 @@ +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +# +# for K2HR3 Web application +# +frontend web_proxy + default_backend web_servers + bind *:__K2HR3_APP_PORT_EXT__ + +backend web_servers + server k2hr3web __K2HR3_APP_HOST__:__K2HR3_APP_PORT__ + +# +# for K2HR3 REST API +# +frontend api_proxy + default_backend api_servers + bind *:__K2HR3_API_PORT_EXT__ + +backend api_servers + server k2hr3api __K2HR3_API_HOST__:__K2HR3_API_PORT__ + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/conf/k2hr3-init.sh.templ b/utils/k2hr3_pack/conf/k2hr3-init.sh.templ new file mode 100644 index 0000000..7d13748 --- /dev/null +++ b/utils/k2hr3_pack/conf/k2hr3-init.sh.templ @@ -0,0 +1,503 @@ +#!/bin/sh +# +# K2HR3 PACK for K2HDKC DBaaS based on Trove +# +# Copyright 2020 Yahoo Japan Corporation +# +# K2HDKC DBaaS is a Database as a Service compatible with Trove which +# is DBaaS for OpenStack. +# Using K2HR3 as backend and incorporating it into Trove to provide +# DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components +# provided as AntPickax. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Mon Sep 14 2020 +# REVISION: +# + +SCRIPTNAME="k2hr3-init-trove" +LOGFILE="/var/log/${SCRIPTNAME}.log" +CLOUDINIT_DATA_DIR="/var/lib/cloud/data" +INSTANCE_ID_FILE="${CLOUDINIT_DATA_DIR}/instance-id" +K2HR3_ROLE_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-role" +K2HR3_RESOURCE_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-resource" +K2HR3_API_RESOURCE_URI_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-resource-uri" +K2HR3_CUK_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-cuk" +K2HR3_APIARG_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-apiarg" +K2HR3_EXTRAARG_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-extraarg" +K2HR3_TAGARG_FILE="${CLOUDINIT_DATA_DIR}/k2hr3-tagarg" + +K2HR3_USER_ROLE_TOKEN="{{= %K2HR3_ROLE_TOKEN% }}" +K2HR3_API_HOST_URI="{{= %K2HR3_API_HOST_URI% }}/v1/role" +K2HR3_ROLE_NAME="{{= %K2HR3_ROLE_NAME% }}" + +#-------------------------------------------------------------- +# Start +#-------------------------------------------------------------- +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Start to initialize information for k2hr3" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# OS Environment +#-------------------------------------------------------------- +OS_NAME=`cat /etc/os-release | grep '^ID=' | sed -e 's/\"/ /g' -e 's/=/ /g' | awk '{print $2}'` +if [ "X${OS_NAME}" = "Xubuntu" ]; then + PACKAGECLOUD_IO_URI="https://packagecloud.io/install/repositories/antpickax/stable/script.deb.sh" + PACKAGEMAN="apt-get" + SYSTEMD_SERVICE_DIR="/lib/systemd/system" + SYSTEMD_EXEC_DIR="/usr/bin" +elif [ "X${OS_NAME}" = "Xcentos" ]; then + PACKAGECLOUD_IO_URI="https://packagecloud.io/install/repositories/antpickax/stable/script.rpm.sh" + PACKAGEMAN="yum" + SYSTEMD_SERVICE_DIR="/usr/lib/systemd/system" + SYSTEMD_EXEC_DIR="/usr/libexec" +else + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Unknown os name ${OS_NAME} which is not supported." | tee -a ${LOGFILE} + exit 1 +fi + +# +# Python +# +python --version >/dev/null 2>&1 +if [ $? -eq 0 ]; then + PYBIN="python" +else + python3 --version >/dev/null 2>&1 + if [ $? -eq 0 ]; then + PYBIN="python3" + else + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Not found python nor python3." | tee -a ${LOGFILE} + exit 1 + fi +fi + +#-------------------------------------------------------------- +# Check instance-id +#-------------------------------------------------------------- +if [ ! -f ${INSTANCE_ID_FILE} ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not read ${INSTANCE_ID_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +INSTANCE_ID=`cat ${INSTANCE_ID_FILE}` +if [ "X${INSTANCE_ID}" = "X" ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Unknown Instance Id in ${INSTANCE_ID_FILE}" | tee -a ${LOGFILE} + exit 1 +fi + +#-------------------------------------------------------------- +# Registration +#-------------------------------------------------------------- +CUK_PARAMETER="cuk=${INSTANCE_ID}" +EXTRA_PARAMETER="extra=openstack-auto-v1" +LOCAL_HOSTNAME=`hostname` +TAG_PARAMETER="tag=${LOCAL_HOSTNAME}" + +REGISTER_RESULT=`curl -s -S -X PUT -H "x-auth-token: R=${K2HR3_USER_ROLE_TOKEN}" "${K2HR3_API_HOST_URI}/${K2HR3_ROLE_NAME}?${CUK_PARAMETER}&${EXTRA_PARAMETER}&${TAG_PARAMETER}" 2>&1` +if [ $? -ne 0 ];then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not register to role member with curl error" | tee -a ${LOGFILE} + exit 1 +fi +REGISTER_RESULT_VALUE=`echo ${REGISTER_RESULT} | ${PYBIN} -m json.tool | grep result | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g' | tr '[:lower:]' '[:upper:]'` +if [ "X${REGISTER_RESULT_VALUE}" != "XTRUE" ]; then + REGISTER_RESULT_MSG=`echo ${REGISTER_RESULT} | ${PYBIN} -m json.tool | grep message | cut -d':' -f2,2 | sed 's/^[ ,]\+\|[ ,]\+$//g'` + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Failed to put access for registering by ${REGISTER_RESULT_MSG}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Set this host to k2hr3 role(${K2HR3_ROLE_NAME})" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# Save parameters to files +#-------------------------------------------------------------- +K2HR3_RESOURCE_NAME=`echo ${K2HR3_ROLE_NAME} | sed 's/:role:/:resource:/'` +K2HR3_API_RESOURCE_URI=`echo ${K2HR3_API_HOST_URI} | sed 's#/v1/role#/v1/resource#'` + +# +# ROLE name +# +echo "${K2HR3_ROLE_NAME}" > ${K2HR3_ROLE_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put k2hr3 role name(${K2HR3_ROLE_NAME}) to ${K2HR3_ROLE_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create k2hr3 role(${K2HR3_ROLE_NAME}) file(${K2HR3_ROLE_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_ROLE_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_ROLE_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize role name information for k2hr3" | tee -a ${LOGFILE} + +# +# RESOURCE name +# +echo "${K2HR3_RESOURCE_NAME}" > ${K2HR3_RESOURCE_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put k2hr3 resource name(${K2HR3_RESOURCE_NAME}) to ${K2HR3_RESOURCE_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create k2hr3 resource(${K2HR3_RESOURCE_NAME}) file(${K2HR3_RESOURCE_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_RESOURCE_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_RESOURCE_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize resoruce name information for k2hr3" | tee -a ${LOGFILE} + +# +# RESOURCE API url +# +echo "${K2HR3_API_RESOURCE_URI}" > ${K2HR3_API_RESOURCE_URI_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put k2hr3 api resource uri(${K2HR3_API_RESOURCE_URI}) to ${K2HR3_API_RESOURCE_URI_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create k2hr3 api resource uri(${K2HR3_API_RESOURCE_URI}) file(${K2HR3_API_RESOURCE_URI_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_API_RESOURCE_URI_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_API_RESOURCE_URI_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize resoruce uri information for k2hr3" | tee -a ${LOGFILE} + +# +# CUK(instance-id) +# +echo "${INSTANCE_ID}" > ${K2HR3_CUK_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put cuk=instanceid(${INSTANCE_ID}) to ${K2HR3_CUK_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create cuk=instanceid(${INSTANCE_ID}) file(${K2HR3_CUK_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_CUK_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_CUK_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize cuk(instanceid) information for k2hr3" | tee -a ${LOGFILE} + +# +# CUK apiarg +# +echo "${CUK_PARAMETER}" > ${K2HR3_APIARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put api url argument(${CUK_PARAMETER}) to ${K2HR3_APIARG_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create api url argument(${CUK_PARAMETER}) file(${K2HR3_APIARG_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_APIARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_APIARG_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize cuk information for k2hr3" | tee -a ${LOGFILE} + + +# +# EXTRA apiarg +# +echo "${EXTRA_PARAMETER}" > ${K2HR3_EXTRAARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put extra url argument(${EXTRA_PARAMETER}) to ${K2HR3_EXTRAARG_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create extra url argument(${EXTRA_PARAMETER}) file(${K2HR3_EXTRAARG_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_EXTRAARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_EXTRAARG_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize extra api arg information for k2hr3" | tee -a ${LOGFILE} + +# +# TAG apiarg +# +echo "${TAG_PARAMETER}" > ${K2HR3_TAGARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not put tag url argument(${TAG_PARAMETER}) to ${K2HR3_TAGARG_FILE}" | tee -a ${LOGFILE} + exit 1 +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create tag url argument(${TAG_PARAMETER}) file(${K2HR3_TAGARG_FILE})" | tee -a ${LOGFILE} + +chmod 444 ${K2HR3_TAGARG_FILE} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not change mode for ${K2HR3_TAGARG_FILE}, but continue..." | tee -a ${LOGFILE} +fi +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: initialize tag api arg information for k2hr3" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# Systemd symbols +#-------------------------------------------------------------- +K2HR3_SLAVE_CHECK_CONF_SERVICE="k2hdkc-slave-check-conf.service" +K2HR3_SLAVE_CHECK_CONF_SERVICE_FILE="${SYSTEMD_SERVICE_DIR}/${K2HR3_SLAVE_CHECK_CONF_SERVICE}" + +K2HR3_SLAVE_CHECK_CONF_TIMER="k2hdkc-slave-check-conf.timer" +K2HR3_SLAVE_CHECK_CONF_TIMER_FILE="${SYSTEMD_SERVICE_DIR}/${K2HR3_SLAVE_CHECK_CONF_TIMER}" + +K2HR3_SLAVE_CHECK_CONF_SH="k2hdkc-slave-check-conf" +K2HR3_SLAVE_CHECK_CONF_SH_FILE="${SYSTEMD_EXEC_DIR}/${K2HR3_SLAVE_CHECK_CONF_SH}" + +#-------------------------------------------------------------- +# Output k2hdkc-slave-check-conf.service +#-------------------------------------------------------------- +cat < ${K2HR3_SLAVE_CHECK_CONF_SERVICE_FILE} +[Unit] +Description=k2hdkc slave check configration service + +[Service] +Type=oneshot +User=root +ExecStart=${K2HR3_SLAVE_CHECK_CONF_SH_FILE} +EOF + +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create ${K2HR3_SLAVE_CHECK_CONF_SERVICE_FILE} file" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# Output k2hdkc-slave-check-conf.timer +#-------------------------------------------------------------- +cat < ${K2HR3_SLAVE_CHECK_CONF_TIMER_FILE} +[Unit] +Description=k2hdkc slave check configration timer + +[Timer] +OnStartupSec=2min +OnUnitInactiveSec=1min +Unit=${K2HR3_SLAVE_CHECK_CONF_SERVICE} + +[Install] +WantedBy=multi-user.target +EOF + +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create ${K2HR3_SLAVE_CHECK_CONF_TIMER_FILE} file" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# Output k2hdkc-slave-check-conf script +#-------------------------------------------------------------- +cat < ${K2HR3_SLAVE_CHECK_CONF_SH_FILE} +#!/bin/sh +# +# K2HDKC Cluster on OpenStack Trove +# +# Copyright 2020 Yahoo! Japan Corporation. +# +# A utility that links the K2HDKC cluster as a Database as a Service +# (DBaaS) with the OpenStack Trove system. +# This system is a DBaaS that operates a K2HDKC cluster by controlling +# from Trove (OpenStack) and K2HR3. +# K2HDKC is a distributed KVS(Key Value Store) provided by Yahoo! JAPAN. +# +# For the full copyright and license information, please view +# the license file that was distributed with this source code. +# +# AUTHOR: Takeshi Nakatani +# CREATE: Thr Jun 4 2020 +# REVISION: +# + +################################### +# Common variables +################################### +ECHO="/bin/echo" +MV="/bin/mv" +RM="/bin/rm" +MKDIR="/bin/mkdir" +GREP="/bin/grep" +SED="/bin/sed" + +# +# Escape sequence +# +CDEF=\$(printf '\033[0m') +CREV=\$(printf '\033[7m') +CRED=\$(printf '\033[31m') +CGRN=\$(printf '\033[32m') + +# +# Local variables +# +CURRENT_TIME=\`date "+%Y-%m-%d %H:%M:%S,%3N"\` + +################################### +# Variables +################################### +PRGNAME=\`basename \$0\` +SCRIPTDIR=\`dirname \$0\` + +K2HDKC_CONF_DIR="/etc/k2hdkc" +K2HDKC_CONF_NAME="slave.ini" +K2HDKC_CONF_TMP_NAME="\${K2HDKC_CONF_NAME}.tmp" +K2HDKC_CONF_FILE="\${K2HDKC_CONF_DIR}/\${K2HDKC_CONF_NAME}" +K2HDKC_CONF_TMP_FILE="\${K2HDKC_CONF_DIR}/\${K2HDKC_CONF_TMP_NAME}" + +# +# Instance id / resource name / resource uri +# +CLOUDINIT_DATA_DIR="/var/lib/cloud/data" +INSTANCE_ID_FILE="\${CLOUDINIT_DATA_DIR}/instance-id" +K2HR3_ROLE_FILE="\${CLOUDINIT_DATA_DIR}/k2hr3-role" +K2HR3_RESOURCE_FILE="\${CLOUDINIT_DATA_DIR}/k2hr3-resource" +K2HR3_API_RESOURCE_URI_FILE="\${CLOUDINIT_DATA_DIR}/k2hr3-resource-uri" + +INSTANCE_ID=\`cat \${INSTANCE_ID_FILE}\` +K2HR3_ROLE_NAME=\`cat \${K2HR3_ROLE_FILE}\` +K2HR3_RESOURCE_NAME=\`cat \${K2HR3_RESOURCE_FILE}\` +K2HR3_API_RESOURCE_URI=\`cat \${K2HR3_API_RESOURCE_URI_FILE}\` + +# +# Python +# +python --version >/dev/null 2>&1 +if [ \$? -eq 0 ]; then + PYBIN="python" +else + python3 --version >/dev/null 2>&1 + if [ \$? -eq 0 ]; then + PYBIN="python3" + else + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} The python program could not be found\${CDEF}" 1>&2 + exit 1 + fi +fi + +################################### +# Main +################################### +\${ECHO} "\${CGRN}\${CREV}[MSG]\${CDEF} \${CURRENT_TIME} Start to load resource(\${K2HDKC_CONF_NAME}) from K2HR3." 1>&2 + +# +# Check directory +# +if [ ! -d \${K2HDKC_CONF_DIR} ]; then + \${ECHO} "\${CRED}\${CREV}[WARN]\${CDEF}\${CRED} Not found \${K2HDKC_CONF_DIR} directory, thus try to create it.\${CDEF}" 1>&2 + + \${MKDIR} -p \${K2HDKC_CONF_DIR} + if [ \$? -ne 0 ];then + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} Could not create \${K2HDKC_CONF_DIR}.\${CDEF}" 1>&2 + exit 1 + fi +fi + +# +# Remove temporary file if exists +# +if [ -f \${K2HDKC_CONF_TMP_FILE} ]; then + \${ECHO} "\${CRED}\${CREV}[WARN]\${CDEF}\${CRED} Found \${K2HDKC_CONF_TMP_FILE} for temporary file, thus remove it.\${CDEF}" 1>&2 + \${RM} -f \${K2HDKC_CONF_TMP_FILE} +fi + +# +# Get resource +# +RESOURCE_RESULT=\`curl -s -S -X GET -H "Content-Type: application/json" "\${K2HR3_API_RESOURCE_URI}/\${K2HR3_RESOURCE_NAME}?\${CUK_PARAMETER}&role=\${K2HR3_ROLE_NAME}&type=string" 2>&1\` +if [ \$? -ne 0 ];then + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} Could not get resource.\${CDEF}" 1>&2 + exit 1 +fi +RESOURCE_RESULT_VALUE=\`\${ECHO} \${RESOURCE_RESULT} | \${PYBIN} -m json.tool | \${GREP} result | cut -d':' -f2,2 | \${SED} 's/^[ ,]\+\|[ ,]\+\$//g' | tr '[:lower:]' '[:upper:]'\` +if [ "X\${RESOURCE_RESULT_VALUE}" != "XTRUE" ]; then + RESOURCE_RESULT_MSG=\`\${ECHO} \${RESOURCE_RESULT} | \${PYBIN} -m json.tool | \${GREP} message | cut -d':' -f2,2 | \${SED} 's/^[ ,]\+\|[ ,]\+\$//g'\` + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} Failed to get resource by \"\${RESOURCE_RESULT_MSG}\".\${CDEF}" 1>&2 + exit 1 +fi +\${ECHO} "\${CGRN}\${CREV}[SUCCESS]\${CDEF} \${CURRENT_TIME} Get resource(\${K2HR3_RESOURCE_NAME}).\${CDEF}" 1>&2 + +# +# Save resource as K2HDKC_CONF_TMP_FILE +# +\${ECHO} \${RESOURCE_RESULT} | \${PYBIN} -m json.tool | \${GREP} '"resource": ' | \${SED} -e 's/"resource"://g' -e 's/^[ ,]\+\|[ ,]\+\$//g' -e 's/^\"//g' -e 's/\"\$//g' -e 's/\\\\n/\n/g' | \${SED} -e "s/__TROVE_K2HDKC_SELF_CUK__/\${INSTANCE_ID}/g" > \${K2HDKC_CONF_TMP_FILE} +if [ ! -f \${K2HDKC_CONF_TMP_FILE} ]; then + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} Could not make \${K2HDKC_CONF_TMP_FILE} from resource.\${CDEF}" 1>&2 + exit 1 +fi +if [ ! -s \${K2HDKC_CONF_TMP_FILE} ]; then + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} Could not make \${K2HDKC_CONF_TMP_FILE} from resource.\${CDEF}" 1>&2 + \${RM} -f \${K2HDKC_CONF_TMP_FILE} + exit 1 +fi +\${ECHO} "\${CGRN}\${CREV}[SUCCESS]\${CDEF} \${CURRENT_TIME} Save resource(\${K2HR3_RESOURCE_NAME}) to temporary file(\${K2HDKC_CONF_TMP_FILE}).\${CDEF}" 1>&2 + +# +# Check updates +# +diff \${K2HDKC_CONF_TMP_FILE} \${K2HDKC_CONF_FILE} >/dev/null 2>&1 +if [ \$? -eq 0 ]; then + # + # Nothing to update + # + \${ECHO} "\${CGRN}\${CREV}[SUCCESS]\${CDEF} \${CURRENT_TIME} There are no changes to the configuration file(\${K2HDKC_CONF_FILE}).\${CDEF}" 1>&2 + \${RM} -f \${K2HDKC_CONF_TMP_FILE} +else + # + # Update the file + # + \${MV} \${K2HDKC_CONF_TMP_FILE} \${K2HDKC_CONF_FILE} >/dev/null 2>&1 + if [ \$? -ne 0 ]; then + \${ECHO} "\${CRED}\${CREV}[ERROR]\${CDEF}\${CRED} \${CURRENT_TIME} Could not update the configuration file(\${K2HDKC_CONF_FILE}).\${CDEF}" 1>&2 + \${RM} -f \${K2HDKC_CONF_TMP_FILE} + exit 1 + fi + \${ECHO} "\${CGRN}\${CREV}[SUCCESS]\${CDEF} \${CURRENT_TIME} Updated the configuration file(\${K2HDKC_CONF_FILE}).\${CDEF}" 1>&2 +fi + +exit 0 + +# +# VIM modelines +# +# vim:set ts=4 fenc=utf-8: +# +EOF +chmod 0755 ${K2HR3_SLAVE_CHECK_CONF_SH_FILE} + +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Create ${K2HR3_SLAVE_CHECK_CONF_SH_FILE} file" | tee -a ${LOGFILE} + +#-------------------------------------------------------------- +# Start to k2hr3-slave-check-conf.timer +#-------------------------------------------------------------- +systemctl enable ${K2HR3_SLAVE_CHECK_CONF_TIMER} +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not enable ${K2HR3_SLAVE_CHECK_CONF_TIMER}, but continue..." | tee -a ${LOGFILE} + exit 1 +else + systemctl start ${K2HR3_SLAVE_CHECK_CONF_TIMER} + if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[WARN]: Could not start ${K2HR3_SLAVE_CHECK_CONF_TIMER}, but continue..." | tee -a ${LOGFILE} + else + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Started ${K2HR3_SLAVE_CHECK_CONF_TIMER}" | tee -a ${LOGFILE} + fi +fi + +#-------------------------------------------------------------- +# Set repository for packagecloud.io +#-------------------------------------------------------------- +curl -s ${PACKAGECLOUD_IO_URI} | sudo bash +if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not setup packagecloud.io repogitory, but continue..." | tee -a ${LOGFILE} +else + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Set packagecloud.io repository." | tee -a ${LOGFILE} + + ${PACKAGEMAN} install -y k2hdkc + if [ $? -ne 0 ]; then + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[ERROR]: Could not install k2hdkc package, but continue..." | tee -a ${LOGFILE} + else + echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Installed k2hdkc package." | tee -a ${LOGFILE} + fi +fi + +#-------------------------------------------------------------- +# Finish +#-------------------------------------------------------------- +echo "`date "+%Y-%m-%d %H:%M:%S,%3N"` - ${SCRIPTNAME}[INFO]: Finish to initialize information for k2hr3" | tee -a ${LOGFILE} + +exit 0 + +# +# Local variables: +# tab-width: 4 +# c-basic-offset: 4 +# End: +# vim600: expandtab sw=4 ts=4 fdm=marker +# vim<600: expandtab sw=4 ts=4 +# diff --git a/utils/k2hr3_pack/conf/production_api.templ b/utils/k2hr3_pack/conf/production_api.templ new file mode 100644 index 0000000..373ae0c --- /dev/null +++ b/utils/k2hr3_pack/conf/production_api.templ @@ -0,0 +1,110 @@ +/* + * + * K2HR3 PACK for K2HDKC DBaaS based on Trove + * + * Copyright 2020 Yahoo Japan Corporation + * + * K2HDKC DBaaS is a Database as a Service compatible with Trove which + * is DBaaS for OpenStack. + * Using K2HR3 as backend and incorporating it into Trove to provide + * DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components + * provided as AntPickax. + * + * For the full copyright and license information, please view + * the license file that was distributed with this source code. + * + * AUTHOR: Takeshi Nakatani + * CREATE: Mon Sep 14 2020 + * REVISION: + * + */ + +// +// Default(base) configuration file by json for config +// +// [NOTE] +// The 'corsips' element for our test temporary environments. +// You need to change or remove these value. +// +// k2hr3admin object is used for removing ip addresses by cuk +// (delete ip addresses), its members are tenant and role name +// for allowed client. +// +{ + 'corsips': [ + __K2HR3_APP_HOSTS__ + ], + + 'keystone': { + 'type': 'openstackapiv3', + 'eptype': 'list', + 'epfile': null, + 'eplist': { + '__OS_REGION__': '__KEYSTONE_URL__' + } + }, + 'k2hdkc': { + 'config': '__BASE_DIR__/conf/slave.ini', + 'port': __SLAVE_CTLPORT__ + }, + + 'multiproc': true, + 'scheme': 'http', + 'port': __K2HR3_API_PORT__, + 'runuser': '__RUNUSER__', + 'privatekey': '', + 'cert': '', + 'ca': '', + + 'logdir': 'log', + 'accesslogname': 'access.log', + 'consolelogname': 'error.log', + 'watcherlogname': 'watcher.log', + 'wconsolelogname': 'watchererror.log', + + 'logrotateopt': { + 'compress': 'gzip', + 'interval': '6h', + 'initialRotation': true + }, + + 'userdata': { + 'baseuri': 'http://__K2HR3_API_HOST__:__K2HR3_API_PORT__', + 'cc_templ': 'config/k2hr3-cloud-config.txt.templ', + 'script_templ': 'config/k2hr3-init.sh.templ', + 'errscript_templ': 'config/k2hr3-init-error.sh.templ', + 'algorithm': 'aes-256-cbc', + 'passphrase': 'k2hr3_regpass' + }, + + 'extdata': { + 'trove': { + 'baseuri': 'http://__K2HR3_API_HOST__:__K2HR3_API_PORT__', + 'template': 'config/extdata_k2hr3_trove.sh.templ', + 'useragent': 'extdata_k2hr3_trove', + 'contenttype': 'text/x-shellscript; charset="us-ascii"' + } + }, + + 'k2hr3admin': { + 'tenant': 'admintenant', + 'delhostrole': 'delhostrole' + }, + + 'confirmtenant': false, + + 'chkipconfig': { + 'type': 'Listener' + }, + + 'allowcredauth': true +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: expandtab sw=4 ts=4 fdm=marker + * vim<600: expandtab sw=4 ts=4 + */ diff --git a/utils/k2hr3_pack/conf/production_app.templ b/utils/k2hr3_pack/conf/production_app.templ new file mode 100644 index 0000000..bdcb5b4 --- /dev/null +++ b/utils/k2hr3_pack/conf/production_app.templ @@ -0,0 +1,175 @@ +/* + * + * K2HR3 PACK for K2HDKC DBaaS based on Trove + * + * Copyright 2020 Yahoo Japan Corporation + * + * K2HDKC DBaaS is a Database as a Service compatible with Trove which + * is DBaaS for OpenStack. + * Using K2HR3 as backend and incorporating it into Trove to provide + * DBaaS functionality. K2HDKC, K2HR3, CHMPX and K2HASH are components + * provided as AntPickax. + * + * For the full copyright and license information, please view + * the license file that was distributed with this source code. + * + * AUTHOR: Takeshi Nakatani + * CREATE: Mon Sep 14 2020 + * REVISION: + * + */ + +{ + 'scheme': 'http', + 'port': __K2HR3_APP_PORT__, + 'multiproc': true, + 'runuser': '__RUNUSER__', + 'privatekey': '', + 'cert': '', + 'ca': '', + 'validator': 'userValidateCredential', + 'lang': 'en', + + 'logdir': 'log', + 'accesslogname': 'access.log', + 'consolelogname': 'error.log', + + 'logrotateopt': { + 'compress': 'gzip', + 'interval': '6h', + 'initialRotation': true + }, + + 'apischeme': 'http', + 'apihost': '__K2HR3_API_HOST_EXT__', + 'apiport': __K2HR3_API_PORT_EXT__, + + 'appmenu': [ + { + 'name': 'Document', + 'url': 'https://k2hr3.antpick.ax/' + }, + { + 'name': 'Support', + 'url': 'https://github.com/yahoojapan/k2hr3_app/issues' + } + ], + + 'userdata': '\ +#include\n\ +{{= %K2HR3_API_HOST_URI% }}/v1/userdata/{{= %K2HR3_USERDATA_INCLUDE_PATH% }}\n\ +', + 'secretyaml': '\ +apiVersion: v1\n\ +kind: Secret\n\ +metadata:\n\ + name: k2hr3-secret\n\ + namespace: \n\ +type: Opaque\n\ +data:\n\ + K2HR3_ROLETOKEN: {{= %K2HR3_ROLETOKEN_IN_SECRET% }}\n\ +', + 'sidecaryaml': '\ +apiVersion: v1\n\ +kind: Pod\n\ +metadata:\n\ + labels:\n\ + labelName: