def show_hardware(context): hrdlist = Hardware.objects({}) if hrdlist.first(): for hrd in hrdlist: if context.admin_rights: print( f"Harware Server Name: {hrd.phySerName} Rack assigned: {hrd.rackAssigned.rackName} Available Memory size:{hrd.avMem} Available no of disks: {hrd.avNumDisks} Available no of cores : {hrd.avNumCores}" ) else: print( f"Harware Server Name: {hrd.phySerName} Rack assigned: {hrd.rackAssigned.rackName} Total Memory size:{hrd.mem} Total no of disks: {hrd.numDisks} Total no of cores : {hrd.numCores}" ) if context.admin_rights: logger.info( "COMMAND: aggiestack admin show hardware - SUCCESS - printed configuration on console" ) else: logger.info( "COMMAND: aggiestack show hardware - SUCCESS - printed configuration on console" ) else: print("no hardware servers found") if context.admin_rights: logger.info( "COMMAND: aggiestack admin show hardware - No Stored machine Configurations Found" ) else: logger.info( "COMMAND: aggiestack show hardware - No Stored machine Configurations Found" )
def show_image_caches(context, rack_name): print(f'Request to show image caches in a seperate files') if not context.admin_rights: logger.error('show imagecaches allowed only in ADMIN mode') logger.info( "COMMAND: aggiestack show imagechaces - INVALID COMMAND - add admin" ) else: rk = Rack.objects(rackName=rack_name).first() if rk: imageCacheList = rk.imgCache if imageCacheList: print("Images cached: ") for img in imageCacheList: print(img.imageName) logger.info( "COMMAND: aggiestack admin show imagechaces - SUCCESS") print( f"Available Storage on Rack to cache images: {rk.avStorage}" ) else: print("No Image caches found") print(f"Available Storage on Rack: {rk.avStorage}") logger.info( "COMMAND: aggiestack admin show imagechaces - No images caches found" ) else: print("Invalid rack name. Enter valid rack name") logger.info( "COMMAND: aggiestack show imagechaces - FAILED. Invalid rack name. Re-enter a valid rack name" )
def show_flavors(context): flvList = Flavor.objects({}) if flvList.first(): for flv in flvList: print( f"Flavor Name: {flv.flavorName} Memory size:{flv.ram} No of disks: {flv.numDisks} No of cores : {flv.vcpus}" ) logger.info( "COMMAND: aggiestack show flavors - SUCCESS - printed configuration on console" ) else: print("no flavors found") logger.info( "COMMAND: aggiestack show flavors - No Stored Flavor Configurations Found" )
def show_all_configs(context): print( "\n*************************HARDWARE CONFIGURATION********************************" ) show_hardware(context) print( "\n*************************IMAGES CONFIGURATION********************************" ) show_images(context) print( "\n*************************FLAVOR CONFIGURATION********************************" ) show_flavors(context) logger.info( "COMMAND: aggiestack show all - SUCCESS - printed configurations on console" )
def getPhyServerAllocation(instancename, image, flavor): mimage = Image.objects(imageName=image).first() mflavor = Flavor.objects(flavorName=flavor).first() if (mimage and mflavor): reqDisks = mflavor.numDisks reqRam = mflavor.ram reqvcpus = mflavor.vcpus # reqImagesize = mimage.imageSize # update later based on prof input avServers = Hardware.objects( avMem__gte=reqRam, avNumDisks__gte=reqDisks, avNumCores__gte=reqvcpus, ) if avServers.count() == 0: logger.error( f"Insufficient storage on servers to host instance {instancename} with image {image} and flavor {flavor}" ) for hrd in avServers: if (mimage in hrd.rackAssigned.imgCache): return hrd max_size = 0 hw_with_max_size = None for hrd in avServers: if hrd.rackAssigned.avStorage >= max_size: max_size = hrd.rackAssigned.avStorage hw_with_max_size = hrd #logger.info(f"max_size: {max_size}, hw_with_max_size: {hw_with_max_size.rackAssigned.avStorage}") if hw_with_max_size: if max_size < mimage.imageSize: imagelist = hw_with_max_size.rackAssigned.imgCache logger.info( f"evicting images from rack {hw_with_max_size.rackAssigned.rackName}" ) #evict logger.info("evicting images: [ ") for image in imagelist: logger.info(image.imageName, end=" ") max_size += image.imageSize hw_with_max_size.rackAssigned.avStorage += image.imageSize hw_with_max_size.rackAssigned.imgCache.remove(image) if max_size >= mimage.imageSize: break logger.info("]") hw_with_max_size.rackAssigned.save() return hw_with_max_size #return avServers elif not mimage and not mflavor: logger.error(f"image {image} and flavor {flavor} doesn't exist") elif not mimage: logger.error(f"image {image} doesn't exist") else: logger.error(f"flavor {flavor} doesn't exist")
def delete_server_instance(instance_name): logger.info(f"got request to delete instance {instance_name}") delInstance = Instance.objects(instanceName=instance_name).first() alcServer = Hardware.objects(phySerName=delInstance.phySerName).first() alcFlav = Flavor.objects(flavorName=delInstance.flavorName).first() if delInstance: logger.info("deleted instance {instance_name}") alcServer.avMem += alcFlav.ram alcServer.avNumDisks += alcFlav.numDisks alcServer.avNumCores += alcFlav.vcpus alcServer.save() alcServer.update(pull__instances=delInstance) delInstance.delete() logger.info(f" hardware server :{alcServer.phySerName} updated") logger.info( f"SUCCESS: COMMAND: aggiestack server delete {instance_name}") else: logger.error( "Instance doesn't exist. Enter a valid instance name to delete. Execute \"aggiestack server list\" for the list of instances " ) logger.info( f"FAILED: COMMAND: aggiestack server delete {instance_name}")
def cli(context, command_args): """ Display the available configurations Sub commands allowed: all: Show all the arguments hardware: Show all the hardware servers configured instances: Show all the instances flavors: Show all the flavors images: Show all the images configured imagecaches Show the image cacehes on a rack Argument: rack_name name of the rack names """ cmd = "aggiestack show" if context.admin_rights: my_logger.info("Enter the ADMIN!") cmd = "aggiestack admin show" if len(command_args) == 0: logger.error(f'no sub command added after show, $> {cmd}') logger.info(f"FAILED: COMMAND: {cmd}") if command_args[0] == 'images': show_images(context) elif command_args[0] == 'flavors': show_flavors(context) elif command_args[0] == 'hardware': show_hardware(context) elif command_args[0] == 'instances': show_instances(context) elif command_args[0] == 'imagecaches' and len(command_args) == 2: show_image_caches(context, command_args[1]) elif command_args[0] == 'all': show_all_configs(context) else: logger.error('Unknown command signature, $> {cmd} {command_args[0]}') logger.info(f"FAILED: COMMAND: {cmd} {command_args[0]}")
def show_images(context): imageList = Image.objects({}) if imageList.first(): for img in imageList: r = [] for rc in Rack.objects(imgCache__in=[img.imageName]): r.append(rc.rackName) if r: print( f"Image Name: {img.imageName} Size : {img.imageSize} location {img.imageLocation} Racks image cached on: {r}" ) else: print( f"Image Name: {img.imageName} Size : {img.imageSize} location {img.imageLocation} Racks image cached on: No racks cached on" ) logger.info( "COMMAND: aggiestack show images - SUCCESS - printed configuration on console" ) else: print("No images found") logger.info( "COMMAND: aggiestack show images - No Stored image Configurations Found" )
def list_servers(): logger.info(f"Got request to list all servers") instanceList = Instance.objects({}) if instanceList.first(): for inst in instanceList: logger.info( f"Instance Name: {inst.instanceName} Image Name: {inst.imageName} Flavor Name: {inst.flavorName}" ) else: logger.error("no instances found") logger.info("SUCCESS: COMMAND: aggiestack server list")
def show_instances(context): if not context.admin_rights: print(" add admin to see instances or use server list command") logger.info( "COMMAND: aggiestack show instances - INVALID COMMAND - add admin") return instanceList = Instance.objects({}) if instanceList.first(): for inst in instanceList: print( f"Instance Name: {inst.instanceName} Physical Server Running on:{inst.phySerName} Rack assigned to: {inst.rackAssigned}" ) logger.info( "COMMAND: aggiestack admin show instances - SUCCESS - printed configuration on console" ) else: print("no instances found") logger.info( "COMMAND: aggiestack show instances - FAILED - no instances found")
def cli(context, subcommand, command_args): """ \b Works with the following subcommands: create: creates the instance Argument: INSTANCE_NAME Options: --flavor Name of the flavor to be configured with the server --image Name of the image to be configured with the server delete: Deletes the instance Argument: INSTANCE_NAME list: Lists all the servers configured """ if len(command_args) == 0 and subcommand == "list": list_servers() elif len(command_args) >= 1 and subcommand == "create": try: instance_name, flavor, image = parse_command_args_for_values( command_args) if not instance_name: logger.error( "Instance name not provided with the server create command" ) logger.info( f"FAILED: COMMAND: aggiestack server {subcommand} {command_args}" ) return create_server_instance(instance_name, flavor, image) except IOError: logger.error('Incorrect format of args passed') logger.info( f"FAILED: COMMAND: aggiestack server {subcommand} {command_args}" ) return elif len(command_args) == 1 and subcommand == "delete": instance_name = command_args[0] delete_server_instance(instance_name) else: logger.error(f"Command '$> server {subcommand}' not defined") logger.info( f"FAILED: COMMAND: aggiestack server {subcommand} {command_args}")
def cli(context, mem, disk, vcpus, ip, rack, machine_name): """Add the machine to the system so that it may receive new instances. This is usually invoked when a "sick" server was fixed, and it is ready to work again. Argument: MACHINE_NAME""" if (not context.admin_rights): logger.error('Can allow this operation only in admin mode') logger.info( f'FAILED: COMMAND: aggiestack adming add --mem {mem} --disk {disk} --vcpus {vcpus} --ip {ip} --rack {rack} {machine_name}' ) return logger.info("Machine to be added with configuration: \n") logger.info(f"Name: {machine_name}") logger.info(f"Mem: {mem}") logger.info(f"Disk: {disk}") logger.info(f"Vpus: {vcpus}") logger.info(f"Ip: {ip}") logger.info(f"Rack Name: {rack}") rack = Rack.objects(rackName=rack).first() if not rack: logger.error(f"Rack '{rack}' doesn't exist") logger.info( f'FAILED: COMMAND: aggiestack adming add --mem {mem} --disk {disk} --vcpus {vcpus} --ip {ip} --rack {rack} {machine_name}' ) return else: hardware = Hardware.objects(ipAddress=ip).first() if hardware: logger.error(f"IP '{ip}' is already taken. Use different IP") logger.info( f'FAILED: COMMAND: aggiestack adming add --mem {mem} --disk {disk} --vcpus {vcpus} --ip {ip} --rack {rack} {machine_name}' ) return hardware = Hardware.objects(phySerName=machine_name).first() if hardware: logger.error(f"Machine '{machine_name}' already exists.") logger.info( f'FAILED: COMMAND: aggiestack adming add --mem {mem} --disk {disk} --vcpus {vcpus} --ip {ip} --rack {rack} {machine_name}' ) return hardware = Hardware(phySerName=machine_name, rackAssigned=rack, ipAddress=ip, mem=mem, numDisks=disk, numCores=vcpus, avMem=mem, avNumDisks=disk, avNumCores=vcpus) hardware.save() logger.info( f"Inserted Server: '{machine_name}' into rack '{rack.rackName}'") logger.info( f'SUCCESS: COMMAND: aggiestack adming add --mem {mem} --disk {disk} --vcpus {vcpus} --ip {ip} --rack {rack} {machine_name}' )
def cli(context, rack_name): """ Evacuates all the machines located on the same rack """ if (not context.admin_rights): logger.error('Can allow this operation only in admin mode') logger.info(f'FAILED: COMMAND: aggiestack evacuate {rack_name}') return logger.info(f"Got request to evacuate rack: {rack_name}") rack = Rack.objects(rackName=rack_name).first() if not rack: logger.error(f"Rack {rack_name} doesn't exist") logger.info(f'FAILED: COMMAND: aggiestack evacuate {rack_name}') return rack_servers = Hardware.objects(rackAssigned=rack_name) logger.info(f"rack servers: '{rack_servers.count()}'") new_server_names = [] old_server_names = [] migrated_instance_names = [] roll_back = False for server in rack_servers: if roll_back: break for instance in server.instances: logger.info( f"migrating instance '{instance.instanceName}' image: '{instance.imageName}' flavor: {instance.flavorName}" ) new_server = utility.getPhyServerAllocation( instance.imageName, instance.flavorName, rack_name) if not new_server: logger.error( f"cannot migrate instance: '{instance.instanceName}' image:'{instance.imageName}'" ) roll_back = True break else: utility.insertInstanceOnServer(instance.instanceName, instance.flavorName, instance.imageName, new_server.phySerName) migrated_instance_names.append(instance.instanceName) old_server_names.append(server.phySerName) new_server_names.append(new_server.phySerName) if roll_back: logger.error(f'Cannot evacuate rack {rack_name}') logger.error("rolling back servers") for i in range(len(migrated_instance_names) - 1, -1, -1): logger.info( f"rolling back server: '{new_server_names[i]}' for instance: '{migrated_instance_names[i]}' to its previous server: '{old_server_names[i]}'" ) # rolling back instance migrated_instance = Instance.objects( instanceName=migrated_instance_names[i]).first() migrated_instance.phySerName = old_server_names[i] migrated_instance.save() flavor = Flavor.objects( flavorName=migrated_instance.flavorName).first() image = Image.objects( imageName=migrated_instance.imageName).first() # rolling back the server to which instance it was assigned new_server = Hardware.objects( phySerName=new_server_names[i]).first() new_server.avMem += flavor.ram new_server.avNumDisks += flavor.numDisks new_server.avNumCores += flavor.vcpus new_server.instances.remove(migrated_instance) new_server.save() logger.info(f'FAILED: COMMAND: aggiestack admin evacuate {rack_name}') else: logger.info(f"migrated #'{len(migrated_instance_names)}' instances") for server in rack_servers: server.delete() logger.info(f"removed all servers from rack {rack_name}") rack = Rack.objects(rackName=rack_name).first() rack.delete() logger.info(f"evicted rack {rack_name}") logger.info(f'SUCCESS: COMMAND: aggiestack admin evacuate {rack_name}') logger.info(f'Successfully evacuated rack {rack_name}')
def create_server_instance(instance_name, flavor, image): """Creates an instance named INSTANCE_NAME to be boot from IMAGE and configured as indicated in FLAVOR_NAME """ logger.info(f"Got request to create a server with configuration:") logger.info(f"Instance name: {instance_name}") logger.info(f"Flavor name: {flavor}") logger.info(f"Image name: {image}") alcServer = getPhyServerAllocation(instance_name, image, flavor) if alcServer: selFlavor = Flavor.objects(flavorName=flavor).first() selImage = Image.objects(imageName=image).first() reqRam = selFlavor.ram reqDisks = selFlavor.numDisks reqvcpus = selFlavor.vcpus newInstance = Instance.objects(instanceName=instance_name).first() rckname = alcServer.rackAssigned.rackName if newInstance: newInstance.phySerName = alcServer.phySerName newInstance.imageName = image newInstance.flavorName = flavor newInstance.rackAssigned = rckname newInstance.save() logger.info(f"instance {instance_name} updated") else: newInstance = Instance(instanceName=instance_name) newInstance.phySerName = alcServer.phySerName newInstance.imageName = image newInstance.flavorName = flavor newInstance.rackAssigned = rckname newInstance.save() logger.info(f"instance {instance_name} created") alcServer.avMem = alcServer.avMem - reqRam alcServer.avNumDisks = alcServer.avNumDisks - reqDisks alcServer.avNumCores = alcServer.avNumCores - reqvcpus alcServer.save() alcServer.update(push__instances=newInstance) if selImage not in alcServer.rackAssigned.imgCache: alcServer.rackAssigned.update(push__imgCache=selImage) alcServer.rackAssigned.update(dec__avStorage=selImage.imageSize) print( f"Added to server {alcServer.phySerName} (on rack {alcServer.rackAssigned.rackName}) current memmory {alcServer.mem} availble memory {alcServer.avMem})" ) logger.info( f"Added to server {alcServer.phySerName} (on rack {alcServer.rackAssigned.rackName}) current memmory {alcServer.mem} availble memory {alcServer.avMem})" ) logger.info( f"SUCCESS: COMMAND: aggiestack server create --image {image} --flavor {flavor} {instance_name}" ) else: logger.info( f"FAILED: COMMAND: aggiestack server create --image {image} --flavor {flavor} {instance_name}" )
def cli(context, hardware, images, flavors): if hardware: check = check_hardware_pattern(open(hardware, 'r')) if check: logger.error("COMMAND: aggiestack config --hardware '%s' : %s", hardware, check) logger.info( f"FAILED: COMMAND: aggiestack config --hardware {hardware}") return else: input_content = utility.file_read(hardware) arg_hardware = hardware # reading rack information # handle update or duplicates! for i in range(1, int(input_content[0]) + 1): attrs = input_content[i].split(" ") logger.info("Racks parsed -- '%s'", attrs) rack = Rack.objects(rackName=attrs[0]).first() if not rack: rack = Rack(rackName=attrs[0], storageCapacity=attrs[1], avStorage=attrs[1]).save() logger.info("Inserted Rack: '%s'", attrs) else: rack.avStorage += int(attrs[1]) - rack.storageCapacity rack.storageCapacity = attrs[1] rack.save() logger.info("Updated Rack: '%s'", attrs) # reading hardware information # fails when no hardware is present after rack info for line in input_content[int(input_content[0]) + 2:]: attrs = line.split(" ") logger.info("Hardware parsed -- '%s'", attrs) rack = Rack.objects(rackName=attrs[1]).first() if rack: hardware = Hardware.objects(phySerName=attrs[0]).first() if not hardware: hardware = Hardware( phySerName=attrs[0], rackAssigned=Rack.objects.get(rackName=attrs[1]), ipAddress=attrs[2], mem=attrs[3], numDisks=attrs[4], numCores=attrs[5], avMem=attrs[3], avNumDisks=attrs[4], avNumCores=attrs[5]) hardware.save() logger.info("Inserted Hardware: '%s'", attrs) else: hardware.phySerName = attrs[0] hardware.rackAssigned = Rack.objects.get( rackName=attrs[1]) hardware.avMem += int(attrs[3]) - hardware.mem hardware.avNumDisks += int( attrs[4]) - hardware.numDisks hardware.avNumCores += int( attrs[5]) - hardware.numCores hardware.mem = attrs[3] hardware.numDisks = attrs[4] hardware.numCores = attrs[5] hardware.save() logger.info("Updated Hardware: '%s'", attrs) logger.info("SUCCESS: COMMAND: aggiestack config --hardware %s", arg_hardware) elif images: # todo modify check function # check = check_image_pattern(open(images, 'r')) # remove this and below line after modifying check check = None if check: logger.error("COMMAND: aggiestack config --images '%s' : %s", images, check) logger.info( f"FAILED: COMMAND: aggiestack config --images {image}") else: input_content = utility.file_read(images) arg_image = images # write to mongo # handle update for line in input_content[1:]: attrs = line.split(" ") logger.info("Images parsed -- '%s'", attrs) image = Image.objects(imageName=attrs[0]).first() # confirm with dileep if not image: image = Image(imageName=attrs[0], imageSize=attrs[1], imageLocation=attrs[2]).save() logger.info("Inserted Image: '%s'", attrs) else: image.imageSize = attrs[1] image.imageLocation = attrs[2] image.save() logger.info("Updated Image: '%s'", attrs) logger.info("SUCCESS: COMMAND: aggiestack config --images %s", arg_image) elif flavors: check = check_flavor_pattern(open(flavors, 'r')) if check: logger.error("COMMAND: aggiestack config --flavor '%s' : %s", flavors, check) logger.error( f"FAILED: COMMAND: aggiestack config --flavor {flavor}") else: input_content = utility.file_read(flavors) arg_flavor = flavors # write to mongo # handle update, dont duplicate record for line in input_content[1:]: attrs = line.split(" ") logger.info("Flavor parsed -- '%s'", attrs) flavor = Flavor.objects(flavorName=attrs[0]).first() if not flavor: flavor = Flavor(flavorName=attrs[0], ram=attrs[1], numDisks=attrs[2], vcpus=attrs[3]).save() logger.info("Inserted Flavor: '%s'", attrs) else: flavor.ram = attrs[1] flavor.numDisks = attrs[2] flavor.vcpus = attrs[3] flavor.save() logger.info("Updated Flavor: '%s'", attrs) logger.info("SUCCESS: COMMAND: aggiestack config --flavors %s", arg_flavor) else: my_logger.error( 'You must enter an argument with the config command. Check with --help for available options' )
def cli(context, machine_name): """ Remove the machine name from the view of the datacenter """ if (not context.admin_rights): logger.error('Can allow this operation only in admin mode') logger.info(f'FAILED: COMMAND: aggiestack remove {machine_name}') return logger.info(f"Got request to evacuate machine: {machine_name}") server = Hardware.objects(phySerName=machine_name).first() if len(server.instances) == 0: server.delete() logger.info(f"Removed machine {machine_name}") logger.info(f"Removed machine {machine_name}") logger.info( f'SUCCESS: COMMAND: aggiestack admin remove {machine_name}') else: logger.error( f"Can't remove machine '{machine_name}', it has {len(server.instances)} instances associated with it." ) logger.info( f'FAILED: COMMAND: aggiestack admin remove {machine_name}')