Allow specification of ssh authorized key and token url for coreos.
1. Implements token generation mechanism for coreos. 2. Add cluster_type and discovery_token_url fields in magnum.conf. 3. Add field to bay model to specify the ssh authorized key. This value is passed into the kubenode-coreos.yaml through kubecluster-coreos.yaml. This key is used to login into the coreos instance. Implements part of bp introduce-coreos Change-Id: Id8b18a7bf016120102c8da1c3339f70564aedae4
This commit is contained in:
@@ -514,6 +514,16 @@
|
||||
# Location of template to build a k8s cluster. (string value)
|
||||
#template_path = /etc/magnum/templates/heat-kubernetes/kubecluster.yaml
|
||||
|
||||
# Define the Cluster type. (string value)
|
||||
# Whenever you want to create cluster of any of these
|
||||
# fedora-atomic,coreos, ironic then specify a cluster_type.
|
||||
#cluster_type = fedora-atomic, coreos, ironic
|
||||
|
||||
# Discovery token url for coreos cluster. (string value)
|
||||
# Forming a coreos cluster will require a discovery token if your cloud
|
||||
# has internet support otherwise uuid will generate the token for you.
|
||||
#discovery_token_url = https://discovery.etcd.io/new
|
||||
|
||||
# Number of attempts to query the Heat stack for finding out the
|
||||
# status of the created stack and getting url of the DU created in the
|
||||
# stack (integer value)
|
||||
|
||||
@@ -73,6 +73,9 @@ class BayModel(base.APIBase):
|
||||
docker_volume_size = wtypes.IntegerType()
|
||||
"""The size in GB of the docker volume"""
|
||||
|
||||
ssh_authorized_key = wtypes.text
|
||||
"""The SSH Authorized Key"""
|
||||
|
||||
links = wsme.wsattr([link.Link], readonly=True)
|
||||
"""A list containing a self link and associated baymodel links"""
|
||||
|
||||
@@ -118,6 +121,7 @@ class BayModel(base.APIBase):
|
||||
fixed_network='private',
|
||||
apiserver_port=8080,
|
||||
docker_volume_size=25,
|
||||
ssh_authorized_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB',
|
||||
created_at=datetime.datetime.utcnow(),
|
||||
updated_at=datetime.datetime.utcnow())
|
||||
return cls._convert_with_links(sample, 'http://localhost:9511', expand)
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import requests
|
||||
import uuid
|
||||
|
||||
from heatclient.common import template_utils
|
||||
from heatclient import exc
|
||||
from oslo_config import cfg
|
||||
@@ -34,6 +37,12 @@ k8s_heat_opts = [
|
||||
'kubecluster.yaml'),
|
||||
help=_(
|
||||
'Location of template to build a k8s cluster. ')),
|
||||
cfg.StrOpt('cluster_type',
|
||||
default=None,
|
||||
help=_('Cluster types are fedora-atomic, coreos, ironic.')),
|
||||
cfg.StrOpt('discovery_token_url',
|
||||
default=None,
|
||||
help=_('coreos discovery token url.')),
|
||||
cfg.IntOpt('max_attempts',
|
||||
default=2000,
|
||||
help=('Number of attempts to query the Heat stack for '
|
||||
@@ -51,12 +60,27 @@ cfg.CONF.register_opts(k8s_heat_opts, group='k8s_heat')
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_coreos_token(context):
|
||||
if cfg.CONF.k8s_heat.cluster_type == 'coreos':
|
||||
token = ""
|
||||
discovery_url = cfg.CONF.k8s_heat.discovery_token_url
|
||||
if discovery_url:
|
||||
coreos_token_url = requests.get(discovery_url)
|
||||
token = str(coreos_token_url.text.split('/')[3])
|
||||
else:
|
||||
token = uuid.uuid4().hex
|
||||
return token
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _extract_bay_definition(context, bay):
|
||||
baymodel = objects.BayModel.get_by_uuid(context, bay.baymodel_id)
|
||||
|
||||
token = _get_coreos_token(context)
|
||||
bay_definition = {
|
||||
'ssh_key_name': baymodel.keypair_id,
|
||||
'external_network_id': baymodel.external_network_id,
|
||||
'token': token,
|
||||
}
|
||||
if baymodel.dns_nameserver:
|
||||
bay_definition['dns_nameserver'] = baymodel.dns_nameserver
|
||||
@@ -75,6 +99,8 @@ def _extract_bay_definition(context, bay):
|
||||
bay_definition['docker_volume_size'] = baymodel.docker_volume_size
|
||||
if baymodel.fixed_network:
|
||||
bay_definition['fixed_network'] = baymodel.fixed_network
|
||||
if baymodel.ssh_authorized_key:
|
||||
bay_definition['ssh_authorized_key'] = baymodel.ssh_authorized_key
|
||||
|
||||
return bay_definition
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# 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.
|
||||
|
||||
"""ssh authorized key
|
||||
|
||||
Revision ID: 2d1354bbf76e
|
||||
Revises: 1afee1db6cd0
|
||||
Create Date: 2015-03-13 14:05:58.744652
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2d1354bbf76e'
|
||||
down_revision = '1afee1db6cd0'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('baymodel', sa.Column('ssh_authorized_key',
|
||||
sa.Text, nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_column('baymodel', 'ssh_authorized_key')
|
||||
@@ -27,6 +27,7 @@ from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import schema
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy.types import TypeDecorator, TEXT
|
||||
|
||||
from magnum.common import paths
|
||||
@@ -152,6 +153,7 @@ class BayModel(Base):
|
||||
dns_nameserver = Column(String(255))
|
||||
apiserver_port = Column(Integer())
|
||||
docker_volume_size = Column(Integer())
|
||||
ssh_authorized_key = Column(Text)
|
||||
|
||||
|
||||
class Container(Base):
|
||||
|
||||
@@ -41,6 +41,7 @@ class BayModel(base.MagnumObject):
|
||||
'fixed_network': obj_utils.str_or_none,
|
||||
'apiserver_port': obj_utils.int_or_none,
|
||||
'docker_volume_size': obj_utils.int_or_none,
|
||||
'ssh_authorized_key': obj_utils.str_or_none,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -53,6 +53,7 @@ class TestListBayModel(api_base.FunctionalTest):
|
||||
self.assertNotIn('external_network_id', response['baymodels'][0])
|
||||
self.assertNotIn('fixed_network', response['baymodels'][0])
|
||||
self.assertNotIn('docker_volume_size', response['baymodels'][0])
|
||||
self.assertNotIn('ssh_authorized_key', response['baymodels'][0])
|
||||
|
||||
def test_get_one(self):
|
||||
baymodel = obj_utils.create_test_baymodel(self.context)
|
||||
@@ -65,6 +66,7 @@ class TestListBayModel(api_base.FunctionalTest):
|
||||
self.assertIn('external_network_id', response)
|
||||
self.assertIn('fixed_network', response)
|
||||
self.assertIn('docker_volume_size', response)
|
||||
self.assertIn('ssh_authorized_key', response)
|
||||
|
||||
def test_detail(self):
|
||||
baymodel = obj_utils.create_test_baymodel(self.context)
|
||||
@@ -77,6 +79,7 @@ class TestListBayModel(api_base.FunctionalTest):
|
||||
self.assertIn('external_network_id', response['baymodels'][0])
|
||||
self.assertIn('fixed_network', response['baymodels'][0])
|
||||
self.assertIn('docker_volume_size', response['baymodels'][0])
|
||||
self.assertIn('ssh_authorized_key', response['baymodels'][0])
|
||||
|
||||
def test_detail_against_single(self):
|
||||
baymodel = obj_utils.create_test_baymodel(self.context)
|
||||
@@ -133,11 +136,19 @@ class TestPatch(api_base.FunctionalTest):
|
||||
def setUp(self):
|
||||
super(TestPatch, self).setUp()
|
||||
self.baymodel = obj_utils.create_test_baymodel(self.context,
|
||||
name='bay_model_example_A',
|
||||
image_id='nerdherd',
|
||||
apiserver_port=8080,
|
||||
fixed_network='private',
|
||||
docker_volume_size=20)
|
||||
name='bay_model_example_A',
|
||||
image_id='nerdherd',
|
||||
apiserver_port=8080,
|
||||
fixed_network='private',
|
||||
docker_volume_size=20,
|
||||
ssh_authorized_key='ssh-rsa AAAAB3NzaC1ycEAAAADA'
|
||||
'v0XRqg3tm+jlsOKGO81lPDH+KaSJ'
|
||||
'Q7wvmjUqszP/H6NC/m+qiGp/sTis'
|
||||
'DYucqbeuM7nmJi+8Hb55y1xWoOZI'
|
||||
'KMa71G5/4EOQxuQ/sgW965OOO2Hq'
|
||||
'X8vjlQUnTK0HijrbSTLxp/9kazWW'
|
||||
'FrfsdB8RtZBN digambar@magnum'
|
||||
)
|
||||
|
||||
def test_update_not_found(self):
|
||||
uuid = utils.generate_uuid()
|
||||
@@ -176,6 +187,8 @@ class TestPatch(api_base.FunctionalTest):
|
||||
response['fixed_network'])
|
||||
self.assertEqual(self.baymodel.docker_volume_size,
|
||||
response['docker_volume_size'])
|
||||
self.assertEqual(self.baymodel.ssh_authorized_key,
|
||||
response['ssh_authorized_key'])
|
||||
|
||||
def test_remove_singular(self):
|
||||
baymodel = obj_utils.create_test_baymodel(self.context,
|
||||
@@ -198,6 +211,8 @@ class TestPatch(api_base.FunctionalTest):
|
||||
response['fixed_network'])
|
||||
self.assertEqual(self.baymodel.docker_volume_size,
|
||||
response['docker_volume_size'])
|
||||
self.assertEqual(self.baymodel.ssh_authorized_key,
|
||||
response['ssh_authorized_key'])
|
||||
|
||||
def test_remove_non_existent_property_fail(self):
|
||||
response = self.patch_json('/baymodels/%s' % self.baymodel.uuid,
|
||||
@@ -260,6 +275,8 @@ class TestPatch(api_base.FunctionalTest):
|
||||
response['fixed_network'])
|
||||
self.assertEqual(self.baymodel.docker_volume_size,
|
||||
response['docker_volume_size'])
|
||||
self.assertEqual(self.baymodel.ssh_authorized_key,
|
||||
response['ssh_authorized_key'])
|
||||
|
||||
def test_remove_uuid(self):
|
||||
response = self.patch_json('/baymodels/%s' % self.baymodel.uuid,
|
||||
|
||||
@@ -32,6 +32,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'external_network_id': 'external_network_id',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.bay_dict = {
|
||||
'baymodel_id': 'xx-xx-xx-xx',
|
||||
@@ -62,6 +64,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -86,6 +90,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -110,6 +116,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -134,6 +142,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -158,6 +168,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'fixed_network': 'private',
|
||||
'master_flavor': 'master_flavor_id',
|
||||
'number_of_minions': '1',
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -182,6 +194,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'server_flavor': 'flavor_id',
|
||||
'number_of_minions': '1',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -206,6 +220,34 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@patch('magnum.objects.BayModel.get_by_uuid')
|
||||
def test_extract_bay_definition_without_ssh_authorized_key(self,
|
||||
mock_objects_baymodel_get_by_uuid):
|
||||
baymodel_dict = self.baymodel_dict
|
||||
baymodel_dict['ssh_authorized_key'] = None
|
||||
baymodel = objects.BayModel(self.context, **baymodel_dict)
|
||||
mock_objects_baymodel_get_by_uuid.return_value = baymodel
|
||||
bay = objects.Bay(self.context, **self.bay_dict)
|
||||
|
||||
bay_definition = bay_k8s_heat._extract_bay_definition(self.context,
|
||||
bay)
|
||||
|
||||
expected = {
|
||||
'ssh_key_name': 'keypair_id',
|
||||
'external_network_id': 'external_network_id',
|
||||
'dns_nameserver': 'dns_nameserver',
|
||||
'server_image': 'image_id',
|
||||
'master_flavor': 'master_flavor_id',
|
||||
'server_flavor': 'flavor_id',
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -231,6 +273,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'number_of_minions': '1',
|
||||
'fixed_network': 'private',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
@@ -255,6 +299,8 @@ class TestBayK8sHeat(base.TestCase):
|
||||
'fixed_network': 'private',
|
||||
'master_flavor': 'master_flavor_id',
|
||||
'docker_volume_size': 20,
|
||||
'ssh_authorized_key': 'ssh_authorized_key',
|
||||
'token': None,
|
||||
}
|
||||
self.assertEqual(expected, bay_definition)
|
||||
|
||||
|
||||
@@ -35,6 +35,14 @@ def get_test_baymodel(**kw):
|
||||
'dns_nameserver': kw.get('dns_nameserver', '8.8.1.1'),
|
||||
'apiserver_port': kw.get('apiserver_port', 8080),
|
||||
'docker_volume_size': kw.get('docker_volume_size', 20),
|
||||
'ssh_authorized_key': kw.get('ssh_authorized_key',
|
||||
'ssh-rsa AAAAB3NzaC1ycEAAAADA'
|
||||
'v0XRqg3tm+jlsOKGO81lPDH+KaSJ'
|
||||
'Q7wvmjUqszP/H6NC/m+qiGp/sTis'
|
||||
'DYucqbeuM7nmJi+8Hb55y1xWoOZI'
|
||||
'KMa71G5/4EOQxuQ/sgW965OOO2Hq'
|
||||
'X8vjlQUnTK0HijrbSTLxp/9kazWW'
|
||||
'FrfsdB8RtZBN digambar@magnum'),
|
||||
'created_at': kw.get('created_at'),
|
||||
'updated_at': kw.get('updated_at'),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user