Disconnect method added, refactoring, added CLI update
This commit is contained in:
parent
d6bbb652e6
commit
1c47ea6ed7
16
README.md
16
README.md
@ -9,9 +9,9 @@ node1 = resource.create('node1', 'x/resources/ro_node/', 'rs/', {'ip':'10.0.0.3'
|
|||||||
|
|
||||||
node2 = resource.create('node2', 'x/resources/ro_node/', 'rs/', {'ip':'10.0.0.4', 'ssh_key' : '/vagrant/tmp/keys/ssh_private', 'ssh_user':'vagrant'})
|
node2 = resource.create('node2', 'x/resources/ro_node/', 'rs/', {'ip':'10.0.0.4', 'ssh_key' : '/vagrant/tmp/keys/ssh_private', 'ssh_user':'vagrant'})
|
||||||
|
|
||||||
keystone_db_data = resource.create('mariadb_keystone_data', 'x/resources/data_container/', 'rs/', {'image' : 'mariadb', 'export_volumes' : ['/var/lib/mysql'], 'host': '', 'ssh_user': '', 'ssh_key': ''}, connections={'host' : 'node2.ip', 'ssh_key':'node2.ssh_key', 'ssh_user':'node2.ssh_user'})
|
keystone_db_data = resource.create('mariadb_keystone_data', 'x/resources/data_container/', 'rs/', {'image' : 'mariadb', 'export_volumes' : ['/var/lib/mysql'], 'ip': '', 'ssh_user': '', 'ssh_key': ''}, connections={'ip' : 'node2.ip', 'ssh_key':'node2.ssh_key', 'ssh_user':'node2.ssh_user'})
|
||||||
|
|
||||||
nova_db_data = resource.create('mariadb_nova_data', 'x/resources/data_container/', 'rs/', {'image' : 'mariadb', 'export_volumes' : ['/var/lib/mysql'], 'host': '', 'ssh_user': '', 'ssh_key': ''}, connections={'host' : 'node1.ip', 'ssh_key':'node1.ssh_key', 'ssh_user':'node1.ssh_user'})
|
nova_db_data = resource.create('mariadb_nova_data', 'x/resources/data_container/', 'rs/', {'image' : 'mariadb', 'export_volumes' : ['/var/lib/mysql'], 'ip': '', 'ssh_user': '', 'ssh_key': ''}, connections={'ip' : 'node1.ip', 'ssh_key':'node1.ssh_key', 'ssh_user':'node1.ssh_user'})
|
||||||
```
|
```
|
||||||
|
|
||||||
to make connection after resource is created use `signal.connect`
|
to make connection after resource is created use `signal.connect`
|
||||||
@ -62,17 +62,21 @@ python cli.py resource create node1 x/resources/ro_node/ rs/ '{"ip":"10.0.0.3",
|
|||||||
|
|
||||||
python cli.py resource create node2 x/resources/ro_node/ rs/ '{"ip":"10.0.0.4", "ssh_key" : "/vagrant/tmp/keys/ssh_private", "ssh_user":"vagrant"}'
|
python cli.py resource create node2 x/resources/ro_node/ rs/ '{"ip":"10.0.0.4", "ssh_key" : "/vagrant/tmp/keys/ssh_private", "ssh_user":"vagrant"}'
|
||||||
|
|
||||||
python cli.py resource create mariadb_keystone_data x/resources/data_container/ rs/ '{"image": "mariadb", "export_volumes" : ["/var/lib/mysql"], "host": "", "ssh_user": "", "ssh_key": ""}'
|
python cli.py resource create mariadb_keystone_data x/resources/data_container/ rs/ '{"image": "mariadb", "export_volumes" : ["/var/lib/mysql"], "ip": "", "ssh_user": "", "ssh_key": ""}'
|
||||||
|
|
||||||
python cli.py resource create mariadb_nova_data x/resources/data_container/ rs/ '{"image" : "mariadb", "export_volumes" : ["/var/lib/mysql"], "host": "", "ssh_user": "", "ssh_key": ""}'
|
python cli.py resource create mariadb_nova_data x/resources/data_container/ rs/ '{"image" : "mariadb", "export_volumes" : ["/var/lib/mysql"], "ip": "", "ssh_user": "", "ssh_key": ""}'
|
||||||
|
|
||||||
# View resources
|
# View resources
|
||||||
python cli.py resource show rs/mariadb_keystone_data
|
python cli.py resource show rs/mariadb_keystone_data
|
||||||
|
|
||||||
# Connect resources
|
# Connect resources
|
||||||
python cli.py connect rs/mariadb_keystone_data rs/node2 --mapping '{"host" : "node2.ip", "ssh_key":"node2.ssh_key", "ssh_user":"node2.ssh_user"}'
|
python cli.py connect rs/node2 rs/mariadb_keystone_data
|
||||||
|
|
||||||
python cli.py connect rs/mariadb_nova_data rs/node1 --mapping '{"host" : "node1.ip", "ssh_key":"node1.ssh_key", "ssh_user":"node1.ssh_user"}'
|
python cli.py connect rs/node1 rs/mariadb_nova_data
|
||||||
|
|
||||||
|
# Test update
|
||||||
|
python cli.py update rs/node2 '{"ip": "1.1.1.1"}'
|
||||||
|
python cli.py resource show rs/mariadb_keystone_data # --> IP is 1.1.1.1
|
||||||
|
|
||||||
# View connections
|
# View connections
|
||||||
python cli.py connections show
|
python cli.py connections show
|
||||||
|
17
cli.py
17
cli.py
@ -1,6 +1,7 @@
|
|||||||
import click
|
import click
|
||||||
import json
|
import json
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
|
import os
|
||||||
|
|
||||||
from x import resource as xr
|
from x import resource as xr
|
||||||
from x import signals as xs
|
from x import signals as xs
|
||||||
@ -37,6 +38,22 @@ def init_cli_resource():
|
|||||||
|
|
||||||
resource.add_command(show)
|
resource.add_command(show)
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.argument('path')
|
||||||
|
@click.argument('args')
|
||||||
|
def update(args, path):
|
||||||
|
print 'Update', path, args
|
||||||
|
args = json.loads(args)
|
||||||
|
# Need to load all resources for bubbling effect to take place
|
||||||
|
# TODO: resources can be scattered around, this is a simple
|
||||||
|
# situation when we assume resources are all in one directory
|
||||||
|
base_path, name = os.path.split(path)
|
||||||
|
all = xr.load_all(base_path)
|
||||||
|
r = all[name]
|
||||||
|
r.update(args)
|
||||||
|
|
||||||
|
resource.add_command(update)
|
||||||
|
|
||||||
|
|
||||||
def init_cli_connect():
|
def init_cli_connect():
|
||||||
@click.command()
|
@click.command()
|
||||||
|
@ -31,11 +31,11 @@ class Resource(object):
|
|||||||
|
|
||||||
def update(self, args):
|
def update(self, args):
|
||||||
for key, value in args.iteritems():
|
for key, value in args.iteritems():
|
||||||
resource_key = self.args.get(key, None)
|
self.args[key] = value
|
||||||
if resource_key:
|
self.changed.append(key)
|
||||||
self.args[key] = value
|
signals.notify(self, key, value)
|
||||||
self.changed.append(key)
|
|
||||||
signals.notify(self, key, value)
|
self.save()
|
||||||
|
|
||||||
def action(self, action):
|
def action(self, action):
|
||||||
if action in self.actions:
|
if action in self.actions:
|
||||||
@ -48,6 +48,12 @@ class Resource(object):
|
|||||||
if req not in args:
|
if req not in args:
|
||||||
raise Exception('Requirement `{0}` is missing in args'.format(req))
|
raise Exception('Requirement `{0}` is missing in args'.format(req))
|
||||||
|
|
||||||
|
# TODO: versioning
|
||||||
|
def save(self):
|
||||||
|
meta_file = os.path.join(self.base_dir, 'meta.yaml')
|
||||||
|
with open(meta_file, 'w') as f:
|
||||||
|
f.write(yaml.dump(self.metadata))
|
||||||
|
|
||||||
|
|
||||||
def create(name, base_path, dest_path, args, connections={}):
|
def create(name, base_path, dest_path, args, connections={}):
|
||||||
if not os.path.exists(base_path):
|
if not os.path.exists(base_path):
|
||||||
@ -77,8 +83,7 @@ def create(name, base_path, dest_path, args, connections={}):
|
|||||||
|
|
||||||
#save
|
#save
|
||||||
shutil.copytree(base_path, dest_path)
|
shutil.copytree(base_path, dest_path)
|
||||||
with open(meta_file, 'w') as f:
|
resource.save()
|
||||||
f.write(yaml.dump(meta))
|
|
||||||
db.resource_add(name, resource)
|
db.resource_add(name, resource)
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
|
38
x/signals.py
38
x/signals.py
@ -26,34 +26,24 @@ def guess_mapping(emitter, receiver):
|
|||||||
'ssh_user': '<receiver>.ssh_user'
|
'ssh_user': '<receiver>.ssh_user'
|
||||||
}
|
}
|
||||||
|
|
||||||
If receiver accepts inputs that are not present in emitter,
|
|
||||||
error is thrown -- such cases require manual intervention.
|
|
||||||
|
|
||||||
:param emitter:
|
:param emitter:
|
||||||
:param receiver:
|
:param receiver:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
guessed = {}
|
||||||
|
for key in emitter.requires:
|
||||||
|
if key in receiver.requires:
|
||||||
|
guessed[key] = '{}.{}'.format(emitter.name, key)
|
||||||
|
|
||||||
ret = {}
|
return guessed
|
||||||
|
|
||||||
diff = set(receiver.requires).difference(emitter.requires)
|
|
||||||
if diff:
|
|
||||||
raise Exception(
|
|
||||||
'The following inputs are not provided by emitter: {}.'
|
|
||||||
'You need to set the connection manually.'.format(diff)
|
|
||||||
)
|
|
||||||
|
|
||||||
for key in receiver.requires:
|
|
||||||
ret[key] = '{}.{}'.format(emitter.name, key)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def connect(emitter, receiver, mapping=None):
|
def connect(emitter, receiver, mapping=None):
|
||||||
if mapping is None:
|
mapping = mapping or {}
|
||||||
mapping = guess_mapping(emitter, receiver)
|
guessed = guess_mapping(emitter, receiver)
|
||||||
|
guessed.update(mapping)
|
||||||
|
|
||||||
for src, dst in mapping.items():
|
for src, dst in guessed.items():
|
||||||
CLIENTS.setdefault(emitter.name, {})
|
CLIENTS.setdefault(emitter.name, {})
|
||||||
CLIENTS[emitter.name].setdefault(src, [])
|
CLIENTS[emitter.name].setdefault(src, [])
|
||||||
CLIENTS[emitter.name][src].append((receiver.name, dst))
|
CLIENTS[emitter.name][src].append((receiver.name, dst))
|
||||||
@ -73,26 +63,28 @@ def disconnect(emitter, receiver):
|
|||||||
|
|
||||||
def notify(source, key, value):
|
def notify(source, key, value):
|
||||||
CLIENTS.setdefault(source.name, [])
|
CLIENTS.setdefault(source.name, [])
|
||||||
|
print 'Notify', source.name, key, value, CLIENTS[source.name]
|
||||||
if key in CLIENTS[source.name]:
|
if key in CLIENTS[source.name]:
|
||||||
for client, r_key in CLIENTS[source.name][key]:
|
for client, r_key in CLIENTS[source.name][key]:
|
||||||
resource = db.get_resource(client)
|
resource = db.get_resource(client)
|
||||||
|
print 'Resource found', client
|
||||||
if resource:
|
if resource:
|
||||||
resource.update({r_key: value})
|
resource.update({r_key: value})
|
||||||
else:
|
else:
|
||||||
#XXX resource deleted?
|
print 'Resource {} deleted?'.format(client)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def assign_connections(reciver, connections):
|
def assign_connections(receiver, connections):
|
||||||
mappings = defaultdict(list)
|
mappings = defaultdict(list)
|
||||||
for key, dest in connections.iteritems():
|
for key, dest in connections.iteritems():
|
||||||
resource, r_key = dest.split('.')
|
resource, r_key = dest.split('.')
|
||||||
resource = db.get_resource(resource)
|
resource = db.get_resource(resource)
|
||||||
value = resource.args[r_key]
|
value = resource.args[r_key]
|
||||||
reciver.args[key] = value
|
receiver.args[key] = value
|
||||||
mappings[resource].append((r_key, key))
|
mappings[resource].append((r_key, key))
|
||||||
for resource, r_mappings in mappings.iteritems():
|
for resource, r_mappings in mappings.iteritems():
|
||||||
connect(resource, reciver, r_mappings)
|
connect(resource, receiver, r_mappings)
|
||||||
|
|
||||||
|
|
||||||
def connection_graph():
|
def connection_graph():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user