Allow multiple networks to be created per cluster
Added a NodeGroup model. NodeGroups can be created and modified via the Fuel API. Clusters are created with a default node group and the cluster networks are tied to that default node group. Upon creation of a node group a set of networks will be generated. When a node group is deleted those networks will be deleted as well. See previous change: Ic30a1b46112599022645b06f7bef2223ff4c6475 DocImpact Change-Id: I8bbe6b8c6338d6586c7e9a61542939ae2a19828b Implements: blueprint multiple-cluster-networks
This commit is contained in:
@@ -25,6 +25,7 @@ from fuelclient.cli.actions.interrupt import ResetAction
|
||||
from fuelclient.cli.actions.interrupt import StopAction
|
||||
from fuelclient.cli.actions.network import NetworkAction
|
||||
from fuelclient.cli.actions.node import NodeAction
|
||||
from fuelclient.cli.actions.nodegroup import NodeGroupAction
|
||||
from fuelclient.cli.actions.release import ReleaseAction
|
||||
from fuelclient.cli.actions.role import RoleAction
|
||||
from fuelclient.cli.actions.settings import SettingsAction
|
||||
@@ -49,7 +50,8 @@ actions_tuple = (
|
||||
SnapshotAction,
|
||||
HealthCheckAction,
|
||||
UserAction,
|
||||
PluginAction
|
||||
PluginAction,
|
||||
NodeGroupAction
|
||||
)
|
||||
|
||||
actions = dict(
|
||||
|
||||
@@ -33,7 +33,7 @@ class NodeAction(Action):
|
||||
"""
|
||||
action_name = "node"
|
||||
acceptable_keys = ("id", "status", "name", "cluster", "ip",
|
||||
"mac", "roles", "pending_roles", "online")
|
||||
"mac", "roles", "pending_roles", "online", "group_id")
|
||||
|
||||
def __init__(self):
|
||||
super(NodeAction, self).__init__()
|
||||
@@ -49,7 +49,7 @@ class NodeAction(Action):
|
||||
Args.get_delete_from_db_arg(
|
||||
"Delete specific nodes only from fuel db.\n"
|
||||
"User should still delete node from cobbler"),
|
||||
Args.get_provision_arg("Provision specific nodes.")
|
||||
Args.get_provision_arg("Provision specific nodes."),
|
||||
),
|
||||
group(
|
||||
Args.get_default_arg(
|
||||
|
||||
106
fuelclient/cli/actions/nodegroup.py
Normal file
106
fuelclient/cli/actions/nodegroup.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuelclient.cli.actions.base import Action
|
||||
from fuelclient.cli.actions.base import check_all
|
||||
import fuelclient.cli.arguments as Args
|
||||
from fuelclient.cli.arguments import group
|
||||
from fuelclient.cli.error import ActionException
|
||||
from fuelclient.cli.formatting import format_table
|
||||
from fuelclient.objects.node import Node
|
||||
from fuelclient.objects.nodegroup import NodeGroup
|
||||
from fuelclient.objects.nodegroup import NodeGroupCollection
|
||||
|
||||
|
||||
class NodeGroupAction(Action):
|
||||
"""Show or modify node groups
|
||||
"""
|
||||
action_name = "nodegroup"
|
||||
acceptable_keys = ("id", "cluster", "name")
|
||||
|
||||
def __init__(self):
|
||||
super(NodeGroupAction, self).__init__()
|
||||
self.args = (
|
||||
Args.get_env_arg(),
|
||||
Args.get_list_arg("List all node groups."),
|
||||
Args.get_name_arg("Name of new node group."),
|
||||
Args.get_group_arg("ID of node group."),
|
||||
Args.get_node_arg("List of nodes to assign specified group to."),
|
||||
group(
|
||||
Args.get_create_arg(
|
||||
"Create a new node group in the specified environment."
|
||||
),
|
||||
Args.get_assign_arg(
|
||||
"Download current network configuration."),
|
||||
Args.get_delete_arg(
|
||||
"Verify current network configuration."),
|
||||
)
|
||||
)
|
||||
self.flag_func_map = (
|
||||
("create", self.create),
|
||||
("delete", self.delete),
|
||||
("assign", self.assign),
|
||||
(None, self.list)
|
||||
)
|
||||
|
||||
def create(self, params):
|
||||
"""Create a new node group
|
||||
fuel --env 1 nodegroup --create --name "group 1"
|
||||
"""
|
||||
NodeGroup.create(params.name, int(params.env))
|
||||
|
||||
def delete(self, params):
|
||||
"""Delete the specified node groups
|
||||
fuel --env 1 nodegroup --delete --group 1
|
||||
fuel --env 1 nodegroup --delete --group 2,3,4
|
||||
"""
|
||||
ngs = NodeGroup.get_by_ids(params.group)
|
||||
for n in ngs:
|
||||
if n.name == "default":
|
||||
raise ActionException(
|
||||
"Default node groups cannot be deleted."
|
||||
)
|
||||
NodeGroup.delete(n.id)
|
||||
|
||||
@check_all("env")
|
||||
def assign(self, params):
|
||||
"""Assign nodes to specified node group:
|
||||
fuel --env 1 nodegroup --assign --node 1 --group 1
|
||||
fuel --env 1 nodegroup --assign --node 2,3,4 --group 1
|
||||
"""
|
||||
nodes = [n.id for n in map(Node, params.node)]
|
||||
ngs = map(NodeGroup, params.group)
|
||||
if len(ngs) > 1:
|
||||
raise ActionException(
|
||||
"Nodes can only be assigned to one node group."
|
||||
)
|
||||
NodeGroup.assign(ngs[0].id, nodes)
|
||||
|
||||
def list(self, params):
|
||||
"""To list all available node groups:
|
||||
fuel nodegroup
|
||||
|
||||
To filter them by environment:
|
||||
fuel --env-id 1 nodegroup
|
||||
"""
|
||||
group_collection = NodeGroupCollection.get_all()
|
||||
if params.env:
|
||||
group_collection.filter_by_env_id(int(params.env))
|
||||
self.serializer.print_to_output(
|
||||
group_collection.data,
|
||||
format_table(
|
||||
group_collection.data,
|
||||
acceptable_keys=self.acceptable_keys,
|
||||
)
|
||||
)
|
||||
@@ -337,6 +337,14 @@ def get_delete_arg(help_msg):
|
||||
return get_boolean_arg("delete", help=help_msg)
|
||||
|
||||
|
||||
def get_assign_arg(help_msg):
|
||||
return get_boolean_arg("assign", help=help_msg)
|
||||
|
||||
|
||||
def get_group_arg(help_msg):
|
||||
return get_set_type_arg("group", help=help_msg)
|
||||
|
||||
|
||||
def get_release_arg(help_msg, required=False):
|
||||
return get_int_arg(
|
||||
"release",
|
||||
|
||||
87
fuelclient/objects/nodegroup.py
Normal file
87
fuelclient/objects/nodegroup.py
Normal file
@@ -0,0 +1,87 @@
|
||||
# Copyright 2014 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from operator import attrgetter
|
||||
|
||||
from fuelclient.objects.base import BaseObject
|
||||
|
||||
|
||||
class NodeGroup(BaseObject):
|
||||
|
||||
class_api_path = "nodegroups/"
|
||||
instance_api_path = "nodegroups/{0}/"
|
||||
|
||||
@property
|
||||
def env_id(self):
|
||||
return self.get_fresh_data()["cluster"]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.get_fresh_data()["name"]
|
||||
|
||||
@classmethod
|
||||
def create(cls, name, cluster_id):
|
||||
return cls.connection.post_request(
|
||||
cls.class_api_path,
|
||||
{'cluster_id': cluster_id, 'name': name},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, group_id):
|
||||
return cls.connection.delete_request(
|
||||
cls.instance_api_path.format(group_id)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def assign(cls, group_id, nodes):
|
||||
return cls.connection.post_request(
|
||||
cls.instance_api_path.format(group_id),
|
||||
nodes
|
||||
)
|
||||
|
||||
|
||||
class NodeGroupCollection(object):
|
||||
|
||||
def __init__(self, groups):
|
||||
self.collection = groups
|
||||
|
||||
@classmethod
|
||||
def init_with_ids(cls, ids):
|
||||
return cls(map(NodeGroup, ids))
|
||||
|
||||
@classmethod
|
||||
def init_with_data(cls, data):
|
||||
return cls(map(NodeGroup.init_with_data, data))
|
||||
|
||||
def __str__(self):
|
||||
return "node groups [{0}]".format(
|
||||
", ".join(map(lambda n: str(n.id), self.collection))
|
||||
)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.collection)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return map(attrgetter("data"), self.collection)
|
||||
|
||||
@classmethod
|
||||
def get_all(cls):
|
||||
return cls(NodeGroup.get_all())
|
||||
|
||||
def filter_by_env_id(self, env_id):
|
||||
self.collection = filter(
|
||||
lambda group: group.env_id == env_id,
|
||||
self.collection
|
||||
)
|
||||
Reference in New Issue
Block a user