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'})
|
||||
|
||||
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`
|
||||
@ -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 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
|
||||
python cli.py resource show rs/mariadb_keystone_data
|
||||
|
||||
# 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
|
||||
python cli.py connections show
|
||||
|
17
cli.py
17
cli.py
@ -1,6 +1,7 @@
|
||||
import click
|
||||
import json
|
||||
import networkx as nx
|
||||
import os
|
||||
|
||||
from x import resource as xr
|
||||
from x import signals as xs
|
||||
@ -37,6 +38,22 @@ def init_cli_resource():
|
||||
|
||||
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():
|
||||
@click.command()
|
||||
|
@ -31,11 +31,11 @@ class Resource(object):
|
||||
|
||||
def update(self, args):
|
||||
for key, value in args.iteritems():
|
||||
resource_key = self.args.get(key, None)
|
||||
if resource_key:
|
||||
self.args[key] = value
|
||||
self.changed.append(key)
|
||||
signals.notify(self, key, value)
|
||||
self.args[key] = value
|
||||
self.changed.append(key)
|
||||
signals.notify(self, key, value)
|
||||
|
||||
self.save()
|
||||
|
||||
def action(self, action):
|
||||
if action in self.actions:
|
||||
@ -48,6 +48,12 @@ class Resource(object):
|
||||
if req not in args:
|
||||
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={}):
|
||||
if not os.path.exists(base_path):
|
||||
@ -77,8 +83,7 @@ def create(name, base_path, dest_path, args, connections={}):
|
||||
|
||||
#save
|
||||
shutil.copytree(base_path, dest_path)
|
||||
with open(meta_file, 'w') as f:
|
||||
f.write(yaml.dump(meta))
|
||||
resource.save()
|
||||
db.resource_add(name, 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'
|
||||
}
|
||||
|
||||
If receiver accepts inputs that are not present in emitter,
|
||||
error is thrown -- such cases require manual intervention.
|
||||
|
||||
:param emitter:
|
||||
:param receiver:
|
||||
:return:
|
||||
"""
|
||||
guessed = {}
|
||||
for key in emitter.requires:
|
||||
if key in receiver.requires:
|
||||
guessed[key] = '{}.{}'.format(emitter.name, key)
|
||||
|
||||
ret = {}
|
||||
|
||||
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
|
||||
return guessed
|
||||
|
||||
|
||||
def connect(emitter, receiver, mapping=None):
|
||||
if mapping is None:
|
||||
mapping = guess_mapping(emitter, receiver)
|
||||
mapping = mapping or {}
|
||||
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[emitter.name].setdefault(src, [])
|
||||
CLIENTS[emitter.name][src].append((receiver.name, dst))
|
||||
@ -73,26 +63,28 @@ def disconnect(emitter, receiver):
|
||||
|
||||
def notify(source, key, value):
|
||||
CLIENTS.setdefault(source.name, [])
|
||||
print 'Notify', source.name, key, value, CLIENTS[source.name]
|
||||
if key in CLIENTS[source.name]:
|
||||
for client, r_key in CLIENTS[source.name][key]:
|
||||
resource = db.get_resource(client)
|
||||
print 'Resource found', client
|
||||
if resource:
|
||||
resource.update({r_key: value})
|
||||
else:
|
||||
#XXX resource deleted?
|
||||
print 'Resource {} deleted?'.format(client)
|
||||
pass
|
||||
|
||||
|
||||
def assign_connections(reciver, connections):
|
||||
def assign_connections(receiver, connections):
|
||||
mappings = defaultdict(list)
|
||||
for key, dest in connections.iteritems():
|
||||
resource, r_key = dest.split('.')
|
||||
resource = db.get_resource(resource)
|
||||
value = resource.args[r_key]
|
||||
reciver.args[key] = value
|
||||
receiver.args[key] = value
|
||||
mappings[resource].append((r_key, key))
|
||||
for resource, r_mappings in mappings.iteritems():
|
||||
connect(resource, reciver, r_mappings)
|
||||
connect(resource, receiver, r_mappings)
|
||||
|
||||
|
||||
def connection_graph():
|
||||
|
Loading…
Reference in New Issue
Block a user