from __future__ import print_function
import json
import getpass
from cloudmesh_client.common.Shell import Shell
from cloudmesh_client.cloud.vm import Vm
from cloudmesh_client.cloud.group import Group
from cloudmesh_client.shell.command import command
from cloudmesh_client.shell.console import Console
from cloudmesh_client.default import Default
from cloudmesh_client.cloud.network import Network
from cloudmesh_client.common.hostlist import Parameter
from cloudmesh_client.shell.command import PluginCommand, CloudPluginCommand
from builtins import input
# noinspection PyBroadException
[docs]class NetworkCommand(PluginCommand, CloudPluginCommand):
topics = {"network": "cloud"}
def __init__(self, context):
self.context = context
if self.context.debug:
print("init command network")
# noinspection PyUnusedLocal
@command
def do_network(self, args, arguments):
"""
::
Usage:
network get fixed [ip] [--cloud=CLOUD] FIXED_IP
network get floating [ip] [--cloud=CLOUD] FLOATING_IP_ID
network reserve fixed [ip] [--cloud=CLOUD] FIXED_IP
network unreserve fixed [ip] [--cloud=CLOUD] FIXED_IP
network associate floating [ip] [--cloud=CLOUD] [--group=GROUP]
[--instance=INS_ID_OR_NAME] [FLOATING_IP]
network disassociate floating [ip] [--cloud=CLOUD] [--group=GROUP]
[--instance=INS_ID_OR_NAME] [FLOATING_IP]
network create floating [ip] [--cloud=CLOUD] [--pool=FLOATING_IP_POOL]
network delete floating [ip] [--cloud=CLOUD] [--unused] [FLOATING_IP]
network list floating pool [--cloud=CLOUD]
network list floating [ip] [--cloud=CLOUD] [--unused] [--instance=INS_ID_OR_NAME] [IP_OR_ID]
network create cluster --group=demo_group
network -h | --help
Options:
-h help message
--unused unused floating ips
--cloud=CLOUD Name of the IaaS cloud e.g. india_openstack_grizzly.
--group=GROUP Name of the group in Cloudmesh
--pool=FLOATING_IP_POOL Name of Floating IP Pool
--instance=INS_ID_OR_NAME ID or Name of the vm instance
Arguments:
IP_OR_ID IP Address or ID of IP Address
FIXED_IP Fixed IP Address, e.g. 10.1.5.2
FLOATING_IP Floating IP Address, e.g. 192.1.66.8
FLOATING_IP_ID ID associated with Floating IP, e.g. 185c5195-e824-4e7b-8581-703abec4bc01
Examples:
network get fixed ip --cloud=india 10.1.2.5
network get fixed --cloud=india 10.1.2.5
network get floating ip --cloud=india 185c5195-e824-4e7b-8581-703abec4bc01
network get floating --cloud=india 185c5195-e824-4e7b-8581-703abec4bc01
network reserve fixed ip --cloud=india 10.1.2.5
network reserve fixed --cloud=india 10.1.2.5
network unreserve fixed ip --cloud=india 10.1.2.5
network unreserve fixed --cloud=india 10.1.2.5
network associate floating ip --cloud=india --instance=albert-001 192.1.66.8
network associate floating --cloud=india --instance=albert-001
network associate floating --cloud=india --group=albert_group
network disassociate floating ip --cloud=india --instance=albert-001 192.1.66.8
network disassociate floating --cloud=india --instance=albert-001 192.1.66.8
network create floating ip --cloud=india --pool=albert-f01
network create floating --cloud=india --pool=albert-f01
network delete floating ip --cloud=india 192.1.66.8 192.1.66.9
network delete floating --cloud=india 192.1.66.8 192.1.66.9
network list floating ip --cloud=india
network list floating --cloud=india
network list floating --cloud=india --unused
network list floating --cloud=india 192.1.66.8
network list floating --cloud=india --instance=323c5195-7yy34-4e7b-8581-703abec4b
network list floating pool --cloud=india
network create cluster --group=demo_group
"""
# pprint(arguments)
# Get the cloud parameter OR read default
cloudname = arguments["--cloud"] or Default.cloud
if cloudname is None:
Console.error("Default cloud has not been set!"
"Please use the following to set it:\n"
"cm default cloud=CLOUDNAME\n"
"or provide it via the --cloud=CLOUDNAME argument.")
return ""
# Fixed IP info
if arguments["get"] \
and arguments["fixed"]:
fixed_ip = arguments["FIXED_IP"]
result = Network.get_fixed_ip(cloudname,
fixed_ip_addr=fixed_ip)
Console.msg(result)
# Floating IP info
elif arguments["get"] \
and arguments["floating"]:
floating_ip_id = arguments["FLOATING_IP_ID"]
result = Network.get_floating_ip(cloudname,
floating_ip_or_id=floating_ip_id)
Console.msg(result)
# Reserve a fixed ip
elif arguments["reserve"] \
and arguments["fixed"]:
fixed_ip = arguments["FIXED_IP"]
result = Network.reserve_fixed_ip(cloudname=cloudname,
fixed_ip_addr=fixed_ip)
if result is not None:
Console.ok("Reserve fixed ip address {} complete.".format(fixed_ip))
# Un-Reserve a fixed ip
elif arguments["unreserve"] \
and arguments["fixed"]:
fixed_ip = arguments["FIXED_IP"]
result = Network.unreserve_fixed_ip(cloudname=cloudname,
fixed_ip_addr=fixed_ip)
if result is not None:
Console.ok("Un-Reserve fixed ip address {} complete.".format(fixed_ip))
# Associate floating IP
elif arguments["associate"] \
and arguments["floating"]:
# Get all command-line arguments
group_name = arguments["--group"]
instance_id = arguments["--instance"]
floating_ip = arguments["FLOATING_IP"]
# group supplied
if group_name is not None:
"""
Group name has been provided.
Assign floating IPs to all vms in the group
and return
"""
# Get the group information
group = Group.get_info(name=group_name,
category=cloudname,
output="json")
if group is not None:
# Convert from str to json
group = json.loads(group)
# For each vm in the group
# Create and assign a floating IP
for item in group:
instance_id = group[item]["value"]
floating_ip = Network.find_assign_floating_ip(cloudname=cloudname,
instance_id=instance_id)
if floating_ip is not None:
Console.ok("Created and assigned Floating IP {} to instance {}."
.format(floating_ip, instance_id))
# Refresh VM in db
self.refresh_vm(cloudname)
else:
Console.error("No group {} in the Cloudmesh database."
.format(group_name))
return ""
# floating-ip not supplied, instance-id supplied
elif not floating_ip and instance_id is not None:
"""
Floating IP has not been provided, instance-id provided.
Generate one from the pool, and assign to vm
and return
"""
floating_ip = Network.find_assign_floating_ip(cloudname=cloudname,
instance_id=instance_id)
if floating_ip is not None:
Console.ok("Associated floating IP {} to instance {}."
.format(floating_ip, instance_id))
# instance-id & floating-ip supplied
elif instance_id is not None:
"""
Floating IP & Instance ID have been provided
Associate the IP to the instance
and return
"""
Network.find_assign_floating_ip(cloudname=cloudname,
instance_id=instance_id,
floating_ip=floating_ip[0])
# Invalid parameters
else:
Console.error("Please provide at least one of [--group] OR [--instance] parameters.\n"
"You can also provide [FLOATING_IP] AND [--instance] parameters.\n"
"See 'cm network --help' for more info.")
return ""
# Refresh VM in db
self.refresh_vm(cloudname)
elif arguments["disassociate"] \
and arguments["floating"]:
# Get all command-line arguments
group_name = arguments["--group"]
instance_id = arguments["--instance"]
floating_ip = arguments["FLOATING_IP"]
# group supplied
if group_name is not None:
"""
Group name has been provided.
Remove floating IPs of all vms in the group
and return
"""
# Get the group information
group = Group.get_info(name=group_name,
category=cloudname,
output="json")
if group is not None:
# Convert from str to json
group = json.loads(group)
# For each vm in the group
# Create and assign a floating IP
for item in group:
instance_id = group[item]["value"]
# Get the instance dict
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
# Get the instance name
instance_name = instance_dict["name"]
floating_ip = instance_dict["floating_ip"]
# Floating ip argument invalid
if floating_ip is None:
Console.error("Instance{} does not have a floating_ip."
.format(instance_name))
return ""
result = Network.disassociate_floating_ip(cloudname=cloudname,
instance_name=instance_name,
floating_ip=floating_ip)
if result is not None:
Console.ok("Disassociated Floating IP {} from instance {}."
.format(floating_ip, instance_name))
else:
Console.error("No group {} in the Cloudmesh database."
.format(group_name))
return ""
# floating-ip not supplied, instance-id supplied
elif len(floating_ip) == 0 and instance_id is not None:
"""
Floating IP has not been provided, instance-id provided.
Remove floating ip allocated to vm
and return
"""
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
instance_name = instance_dict["name"]
floating_ip = instance_dict["floating_ip"]
# Floating ip argument invalid
if floating_ip is None:
Console.error("Instance{} does not have a floating_ip."
.format(instance_name))
return ""
result = Network.disassociate_floating_ip(cloudname=cloudname,
instance_name=instance_name,
floating_ip=floating_ip)
if result is not None:
Console.ok("Disassociated Floating IP {} from instance {}."
.format(floating_ip, instance_name))
# instance-id & floating-ip supplied
elif instance_id is not None:
"""
Floating IP & Instance ID have been provided
Remove the IP from the instance
and return
"""
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
floating_ip = floating_ip[0]
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
instance_name = instance_dict["name"]
_floating_ip = instance_dict["floating_ip"]
# Floating ip argument invalid
if _floating_ip != floating_ip:
Console.error("Invalid floating_ip {} for instance {}."
.format(floating_ip, instance_name))
return ""
result = Network.disassociate_floating_ip(cloudname=cloudname,
instance_name=instance_name,
floating_ip=floating_ip)
if result is not None:
Console.ok("Disassociated Floating IP {} from instance {}."
.format(floating_ip, instance_name))
# Invalid parameters
else:
Console.error("Please provide at least one of [--group] OR [--instance] parameters.\n"
"You can also provide [FLOATING_IP] AND [--instance] parameters.\n"
"See 'cm network --help' for more info.")
return ""
# Refresh VM in db
self.refresh_vm(cloudname)
# Create new floating ip under floating pool
elif arguments["create"] \
and arguments["floating"]:
floating_pool = arguments["--pool"]
result = Network.create_floating_ip(cloudname=cloudname,
floating_pool=floating_pool)
if result is not None:
Console.ok("Created new floating IP {}".format(result))
else:
Console.error("Failed to create floating IP! Please check arguments.")
# Delete a floating ip address
elif arguments["delete"] \
and arguments["floating"]:
# delete all unused floating ips
if arguments["--unused"]:
unused_floating_ips = Network.get_unused_floating_ip_list(cloudname=cloudname)
if unused_floating_ips:
for floating_ip in unused_floating_ips:
self._delete_floating_ip(cloudname=cloudname,
floating_ip=floating_ip["id"])
else:
Console.msg("No unused floating ips exist at this moment. Ok.")
return ""
# delete specified floating ips
floating_ips = Parameter.expand(arguments["FLOATING_IP"])
for floating_ip in floating_ips:
self._delete_floating_ip(cloudname=cloudname,
floating_ip=floating_ip)
# Floating IP Pool List
elif arguments["list"] \
and arguments["floating"] \
and arguments["pool"]:
result = Network.list_floating_ip_pool(cloudname)
Console.msg(result)
# Floating IP list [or info]
elif arguments["list"] \
and arguments["floating"]:
ip_or_id = arguments["IP_OR_ID"]
instance_id = arguments["--instance"]
# List unused floating addr
if arguments["--unused"]:
result = Network.list_unused_floating_ip(cloudname=cloudname)
Console.msg(result)
return ""
# Refresh VM in db
self.refresh_vm(cloudname)
# If instance id is supplied
if instance_id is not None:
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
# Read the floating_ip from the dict
ip_or_id = instance_dict["floating_ip"]
if ip_or_id is None:
Console.error("Instance with ID {} does not have a floating IP address!"
.format(instance_id))
return ""
# If the floating ip or associated ID is supplied
if ip_or_id is not None:
result = Network.get_floating_ip(cloudname,
floating_ip_or_id=ip_or_id)
if result is not None:
Console.msg(result)
else:
Console.error("Floating IP not found! Please check your arguments.")
return ""
# Retrieve the full list
else:
result = Network.list_floating_ip(cloudname)
Console.msg(result)
# Create a virtual cluster
elif arguments["cluster"] and \
arguments["create"]:
group_name = arguments["--group"] or \
Default.get(name="group", category=cloudname)
# Get the group information
group = Group.get_info(name=group_name,
category=cloudname,
output="json")
if group is not None:
# Convert from str to json
group = json.loads(group)
# var contains pub key of all vms
public_keys = ""
login_users = []
login_ips = []
# For each vm in the group
# Create and assign a floating IP
for item in group:
instance_id = group[item]["value"]
# Get the instance dict
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
# Get the instance name
instance_name = instance_dict["name"]
floating_ip = instance_dict["floating_ip"]
# If vm does not have floating ip, then create
if floating_ip is None:
floating_ip = Network.create_assign_floating_ip(cloudname=cloudname,
instance_name=instance_name)
if floating_ip is not None:
Console.ok("Created and assigned Floating IP {} to instance {}."
.format(floating_ip, instance_name))
# Refresh VM in db
self.refresh_vm(cloudname)
# Get the login user for this machine
user = input("Enter the login user for VM {} : ".format(instance_name))
passphrase = getpass.getpass("Enter the passphrase key on VM {} : ".format(instance_name))
# create list for second iteration
login_users.append(user)
login_ips.append(floating_ip)
login_args = [
user + "@" + floating_ip,
]
keygen_args = [
"ssh-keygen -t rsa -f ~/.ssh/id_rsa -N " + passphrase
]
cat_pubkey_args = [
"cat ~/.ssh/id_rsa.pub"
]
generate_keypair = login_args + keygen_args
result = Shell.ssh(*generate_keypair)
# print("***** Keygen *****")
# print(result)
cat_public_key = login_args + cat_pubkey_args
result = Shell.ssh(*cat_public_key)
public_keys += "\n" + result
# print("***** id_rsa.pub *****")
# print(result)
# print("***** public keys *****")
# print(public_keys)
for user, ip in zip(login_users, login_ips):
arguments = [
user + "@" + ip,
"echo '" + public_keys + "' >> ~/.ssh/authorized_keys"
]
# copy the public key contents to auth_keys
result = Shell.ssh(*arguments)
Console.ok("Virtual cluster creation successfull.")
else:
Console.error("No group {} in the Cloudmesh database."
.format(group_name))
return ""
return ""
[docs] @classmethod
def refresh_vm(cls, cloudname):
try:
msg = "Refreshing database for cloud {:}.".format(cloudname)
if Vm.refresh(cloud=cloudname) is not None:
Console.ok("{:} OK.".format(msg))
else:
Console.error("{:} failed".format(msg))
except Exception:
Console.error("Problem running database refresh")
@classmethod
def _delete_floating_ip(cls, cloudname, floating_ip):
result = Network.delete_floating_ip(cloudname=cloudname,
floating_ip_or_id=floating_ip)
if result is not None:
Console.ok(result)
else:
Console.error("Failed to delete floating IP address!")
@classmethod
def _assign_floating_ip(cls, cloudname, instance_id, floating_ip):
# find instance in db
instance_dict = Network.get_instance_dict(cloudname=cloudname,
instance_id=instance_id)
# Instance not found
if instance_dict is None:
Console.error("Instance {} not found in the cloudmesh database!"
.format(instance_id))
return ""
instance_name = instance_dict["name"]
result = Network.associate_floating_ip(cloudname=cloudname,
instance_name=instance_name,
floating_ip=floating_ip)
if result is not None:
Console.ok("Associated Floating IP {} to instance {}."
.format(floating_ip, instance_name))