# Copyright 2016 EasyStack. All rights reserved. # # 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. from magnumclient.common import utils as magnum_utils from magnumclient.i18n import _ from osc_lib.command import command from osc_lib import utils as osc_utils from oslo_log import log as logging CLUSTER_TEMPLATE_ATTRIBUTES = [ 'insecure_registry', 'labels', 'updated_at', 'floating_ip_enabled', 'fixed_subnet', 'master_flavor_id', 'uuid', 'no_proxy', 'https_proxy', 'tls_disabled', 'keypair_id', 'public', 'http_proxy', 'docker_volume_size', 'server_type', 'external_network_id', 'cluster_distro', 'image_id', 'volume_driver', 'registry_enabled', 'docker_storage_driver', 'apiserver_port', 'name', 'created_at', 'network_driver', 'fixed_network', 'coe', 'flavor_id', 'master_lb_enabled', 'dns_nameserver' ] def _show_cluster_template(cluster_template): del cluster_template._info['links'] for field in cluster_template._info: if cluster_template._info[field] is None: setattr(cluster_template, field, '-') columns = CLUSTER_TEMPLATE_ATTRIBUTES return columns, osc_utils.get_item_properties(cluster_template, columns) class CreateClusterTemplate(command.ShowOne): """Create a Cluster Template.""" _description = _("Create a Cluster Template.") def get_parser(self, prog_name): parser = super(CreateClusterTemplate, self).get_parser(prog_name) parser.add_argument( 'name', metavar='', help=_('Name of the cluster template to create.')) parser.add_argument( '--coe', required=True, metavar='', help=_('Specify the Container Orchestration Engine to use.')) parser.add_argument( '--image', required=True, metavar='', help=_('The name or UUID of the base image to customize for the ' 'Cluster.')) parser.add_argument( '--external-network', dest='external_network', required=True, metavar='', help=_('The external Neutron network name or UUID to connect to ' 'this Cluster Template.')) parser.add_argument( '--keypair', metavar='', help=_('The name or UUID of the SSH keypair to load into the ' 'Cluster nodes.')) parser.add_argument( '--fixed-network', dest='fixed_network', metavar='', help=_('The private Neutron network name to connect to this ' 'Cluster model.')) parser.add_argument( '--fixed-subnet', dest='fixed_subnet', metavar='', help=_('The private Neutron subnet name to connect to Cluster.')) parser.add_argument( '--network-driver', dest='network_driver', metavar='', help=_('The network driver name for instantiating container ' 'networks.')) parser.add_argument( '--volume-driver', dest='volume_driver', metavar='', help=_('The volume driver name for instantiating container ' 'volume.')) parser.add_argument( '--dns-nameserver', dest='dns_nameserver', metavar='', default='8.8.8.8', help=_('The DNS nameserver to use for this cluster template.')) parser.add_argument( '--flavor', metavar='', default='m1.medium', help=_('The nova flavor name or UUID to use when launching the ' 'Cluster.')) parser.add_argument( '--master-flavor', dest='master_flavor', metavar='', help=_('The nova flavor name or UUID to use when launching the ' 'master node of the Cluster.')) parser.add_argument( '--docker-volume-size', dest='docker_volume_size', metavar='', type=int, help=_('Specify the number of size in GB for the docker volume ' 'to use.')) parser.add_argument( '--docker-storage-driver', dest='docker_storage_driver', metavar='', default='devicemapper', help=_('Select a docker storage driver. Supported: devicemapper, ' 'overlay. Default: devicemapper')) parser.add_argument( '--http-proxy', dest='http_proxy', metavar='', help=_('The http_proxy address to use for nodes in Cluster.')) parser.add_argument( '--https-proxy', dest='https_proxy', metavar='', help=_('The https_proxy address to use for nodes in Cluster.')) parser.add_argument( '--no-proxy', dest='no_proxy', metavar='', help=_('The no_proxy address to use for nodes in Cluster.')) parser.add_argument( '--labels', metavar='', action='append', default=[], help=_('Arbitrary labels in the form of key=value pairs to ' 'associate with a cluster template. May be used multiple ' 'times.')) parser.add_argument( '--tls-disabled', dest='tls_disabled', action='store_true', default=False, help=_('Disable TLS in the Cluster.')) parser.add_argument( '--public', action='store_true', default=False, help=_('Make cluster template public.')) parser.add_argument( '--registry-enabled', dest='registry_enabled', action='store_true', default=False, help=_('Enable docker registry in the Cluster')) parser.add_argument( '--server-type', dest='server_type', metavar='', default='vm', help=_('Specify the server type to be used for example vm. ' 'For this release default server type will be vm.')) parser.add_argument( '--master-lb-enabled', dest='master_lb_enabled', action='store_true', default=False, help=_('Indicates whether created Clusters should have a load ' 'balancer for master nodes or not.')) parser.add_argument( '--floating-ip-enabled', dest='floating_ip_enabled', action='store_true', default=True, help=_('Indicates whether created Clusters should have a ' 'floating ip or not.')) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) mag_client = self.app.client_manager.container_infra args = { 'name': parsed_args.name, 'image_id': parsed_args.image, 'keypair_id': parsed_args.keypair, 'external_network_id': parsed_args.external_network, 'coe': parsed_args.coe, 'fixed_network': parsed_args.fixed_network, 'fixed_subnet': parsed_args.fixed_subnet, 'network_driver': parsed_args.network_driver, 'volume_driver': parsed_args.volume_driver, 'dns_nameserver': parsed_args.dns_nameserver, 'flavor_id': parsed_args.flavor, 'master_flavor_id': parsed_args.master_flavor, 'docker_volume_size': parsed_args.docker_volume_size, 'docker_storage_driver': parsed_args.docker_storage_driver, 'http_proxy': parsed_args.http_proxy, 'https_proxy': parsed_args.https_proxy, 'no_proxy': parsed_args.no_proxy, 'labels': magnum_utils.handle_labels(parsed_args.labels), 'tls_disabled': parsed_args.tls_disabled, 'public': parsed_args.public, 'registry_enabled': parsed_args.registry_enabled, 'server_type': parsed_args.server_type, 'master_lb_enabled': parsed_args.master_lb_enabled, 'floating_ip_enabled': parsed_args.floating_ip_enabled, } ct = mag_client.cluster_templates.create(**args) print("Request to create cluster template %s accepted" % parsed_args.name) return _show_cluster_template(ct) class DeleteClusterTemplate(command.Command): """Delete a Cluster Template.""" _description = _("Delete a Cluster Template.") def get_parser(self, prog_name): parser = super(DeleteClusterTemplate, self).get_parser(prog_name) parser.add_argument( 'cluster-templates', metavar='', nargs='+', help=_('ID or name of the (cluster template)s to delete.')) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) mag_client = self.app.client_manager.container_infra for cluster_template in getattr(parsed_args, 'cluster-templates'): try: mag_client.cluster_templates.delete(cluster_template) print( "Request to delete cluster template %s has been accepted." % cluster_template) except Exception as e: print("Delete for cluster template " "%(cluster_template)s failed: %(e)s" % {'cluster_template': cluster_template, 'e': e}) class ListTemplateCluster(command.Lister): """List Cluster Templates.""" _description = _("List Cluster Templates.") log = logging.getLogger(__name__ + ".ListTemplateCluster") def get_parser(self, prog_name): parser = super(ListTemplateCluster, self).get_parser(prog_name) parser.add_argument( '--limit', metavar='', type=int, help=_('Maximum number of cluster templates to return')) parser.add_argument( '--sort-key', metavar='', help=_('Column to sort results by')) parser.add_argument( '--sort-dir', metavar='', choices=['desc', 'asc'], help=_('Direction to sort. "asc" or "desc".')) parser.add_argument( '--fields', default=None, metavar='', help=_('Comma-separated list of fields to display. ' 'Available fields: uuid, name, coe, image_id, public, ' 'link, apiserver_port, server_type, tls_disabled, ' 'registry_enabled' ) ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) mag_client = self.app.client_manager.container_infra columns = ['uuid', 'name'] cts = mag_client.cluster_templates.list(limit=parsed_args.limit, sort_key=parsed_args.sort_key, sort_dir=parsed_args.sort_dir) return ( columns, (osc_utils.get_item_properties(ct, columns) for ct in cts) ) class ShowClusterTemplate(command.ShowOne): """Show a Cluster Template.""" _description = _("Show a Cluster Template.") log = logging.getLogger(__name__ + ".ShowClusterTemplate") def get_parser(self, prog_name): parser = super(ShowClusterTemplate, self).get_parser(prog_name) parser.add_argument( 'cluster-template', metavar='', help=_('ID or name of the cluster template to show.')) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) mag_client = self.app.client_manager.container_infra ct = getattr(parsed_args, 'cluster-template', None) cluster_template = mag_client.cluster_templates.get(ct) return _show_cluster_template(cluster_template) class UpdateClusterTemplate(command.ShowOne): """Update a Cluster Template.""" log = logging.getLogger(__name__ + ".UpdateClusterTemplate") def get_parser(self, prog_name): parser = super(UpdateClusterTemplate, self).get_parser(prog_name) parser.add_argument( 'cluster-template', metavar='', help=_('The name or UUID of cluster template to update')) parser.add_argument( 'op', metavar='', choices=['add', 'replace', 'remove'], help=_("Operations: one of 'add', 'replace' or 'remove'")) parser.add_argument( 'attributes', metavar='', nargs='+', action='append', default=[], help=_( "Attributes to add/replace or remove (only PATH is necessary " "on remove)")) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) mag_client = self.app.client_manager.container_infra patch = magnum_utils.args_array_to_patch(parsed_args.op, parsed_args.attributes[0]) name = getattr(parsed_args, 'cluster-template', None) ct = mag_client.cluster_templates.update(name, patch) return _show_cluster_template(ct)