<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Working with IP Scope Objects
So now we're going to look at the recently implemented IP Scope Objects and supporting capabilities in the pyhpeimc library
Step1:  Viewing the Parent Scope
Say we have an existing IP address scope in the HPE IMC server. You would find this under the Reource > Terminal Access > IP Address Allocation page. We've got a pretty typical setup here where we've got a large parent scope which is assigned to a large IP address range specifically a /16 ( 255.255.0.0 ).  This gives us a LOT of ip addresses to work with for this site, but it probably needs to be broken down into child segments which are simply IP networks which fit into the parent range. 
For our examples, we're going to be looking at the 10.101.0.0/16 parent range and the child of 10.101.0.0/24 which, of course, fits cleanly inside the parent range. Everyone remembers basic subneting right? 
Cool.
The first thing we're going to do is to create our first parent object. To do this we will instantiate a new instance of the IPScope class, passing it the parent subnet, and the creds and url attributes from the auth object we created above.
Step2:  What can we do with this?
Now that the object exists, it's got a bunch of attributes and methods which we can play around with.  Remember, you can always dir(object) in python to be able to see what attributes and methods are available for a given object. Never a bad thing if you're just poking around or a little bit forgetful. 
For this object, we're just going to get right into it and print off some of the attributes.
Step3:  As you can see, the starting address for this scope is 10.101.0.1 and the last address is 10.101.254.254. This is exactly what you would expect for a /16 right?
We can also see the id, which is going to be used internally by the python library and the IMC REST API to be able to identify the specific scope we want to work with.
The last attribute is simply the network address of the object. Always good to make sure that we did what we thought we wanted to do. 
Remember I said above that this Parent scope had some child scopes underneath it? Let's take a look at one of those.
Step4:  A Child is a beautiful thing
We can see that the first child, (remember python starts counting at 0 right?), has the range 10.101.0.0/24.  Let's go ahead and create a new childscope object to check it out.
Step5:  Not the same thing
You can clearly see that the new childscope object has the starting ip of 10.101.0.1 and the ending ip of 10.101.0.254.  You can also see that the id of this is different that the parentscope, which means that they are clearly two different objects. 
Now that we've got a much smaller range, let's take a look at some of the additional methods that are available for any IPScope object. 
For example, maybe you want to know the next unassigned IP address range in your scope. You could use the nextfreeip method to be able to pull the next unassigned IP address from the eligible hosts in that specific IP Scope. 
Let's try that now
Step6:  So we can clearly see that the next available IP address is 10.101.0.3 in this /24. Right?
Maybe we have a brand new piece of kit for our lab and we need to assign a management IP address for it in this range, well now we have the IP address without having to check out any spreadsheets, although you MAY want to PING the address just to make sure your co-worker didn't forget to update the database, cause you would NEVER do that, right?
Now that we've got the new address, let's immediately allocate it in the pool so that we don't cause any problems for co-workers in the future.
Step7:  Now that we've added this new IP address allocation to the 10.101.0./24 subnet, let's update the hosts list for the childscope object
Step8:  Cleaning Up
Now that we've succesfully added the new IP allocation to the IMC System, it's time to clean up after ourselves. 
To do that, we're simply going to take the id attribute of the IP allocation we created above and use that as the input to the deallocateIP method of the childscope IPSCope object. 
This should successfully delete the IP allocation that we just created and our system is back to normal. 
Cool right?
For the last step, we wil refresh the hosts list for the childscope object again and make sure that the Juniper record we created above at IP 10.101.0.3 is, indeed, gone.
<ASSISTANT_TASK:>
Python Code:
import csv
import time
from pyhpeimc.auth import *
from pyhpeimc.objects import *
auth = IMCAuth("http://", "10.101.0.203", "8080", "admin", "admin")
Explanation: Working with IP Scope Objects
So now we're going to look at the recently implemented IP Scope Objects and supporting capabilities in the pyhpeimc library
End of explanation
mainscope = IPScope('10.101.0.0/16', auth.creds, auth.url)
Explanation: Viewing the Parent Scope
Say we have an existing IP address scope in the HPE IMC server. You would find this under the Reource > Terminal Access > IP Address Allocation page. We've got a pretty typical setup here where we've got a large parent scope which is assigned to a large IP address range specifically a /16 ( 255.255.0.0 ).  This gives us a LOT of ip addresses to work with for this site, but it probably needs to be broken down into child segments which are simply IP networks which fit into the parent range. 
For our examples, we're going to be looking at the 10.101.0.0/16 parent range and the child of 10.101.0.0/24 which, of course, fits cleanly inside the parent range. Everyone remembers basic subneting right? 
Cool.
The first thing we're going to do is to create our first parent object. To do this we will instantiate a new instance of the IPScope class, passing it the parent subnet, and the creds and url attributes from the auth object we created above.
End of explanation
print (mainscope.startip)
print (mainscope.endip)
print (mainscope.id)
print (mainscope.netaddr)
Explanation: What can we do with this?
Now that the object exists, it's got a bunch of attributes and methods which we can play around with.  Remember, you can always dir(object) in python to be able to see what attributes and methods are available for a given object. Never a bad thing if you're just poking around or a little bit forgetful. 
For this object, we're just going to get right into it and print off some of the attributes.
End of explanation
print (" There are: " + str(len(mainscope.child)) + " children scopes \n\n Let's look at the first one \n")
mainscope.child[0]
Explanation: As you can see, the starting address for this scope is 10.101.0.1 and the last address is 10.101.254.254. This is exactly what you would expect for a /16 right?
We can also see the id, which is going to be used internally by the python library and the IMC REST API to be able to identify the specific scope we want to work with.
The last attribute is simply the network address of the object. Always good to make sure that we did what we thought we wanted to do. 
Remember I said above that this Parent scope had some child scopes underneath it? Let's take a look at one of those.
End of explanation
childscope = IPScope('10.101.0.0/24', auth.creds, auth.url)
print (childscope.startip)
print (childscope.endip)
print (childscope.id)
print (childscope.netaddr)
Explanation: A Child is a beautiful thing
We can see that the first child, (remember python starts counting at 0 right?), has the range 10.101.0.0/24.  Let's go ahead and create a new childscope object to check it out.
End of explanation
childscope.nextfreeip()
Explanation: Not the same thing
You can clearly see that the new childscope object has the starting ip of 10.101.0.1 and the ending ip of 10.101.0.254.  You can also see that the id of this is different that the parentscope, which means that they are clearly two different objects. 
Now that we've got a much smaller range, let's take a look at some of the additional methods that are available for any IPScope object. 
For example, maybe you want to know the next unassigned IP address range in your scope. You could use the nextfreeip method to be able to pull the next unassigned IP address from the eligible hosts in that specific IP Scope. 
Let's try that now:
End of explanation
childscope.allocateIp('10.101.0.3', 'netmanchris', 'Juniper')
Explanation: So we can clearly see that the next available IP address is 10.101.0.3 in this /24. Right?
Maybe we have a brand new piece of kit for our lab and we need to assign a management IP address for it in this range, well now we have the IP address without having to check out any spreadsheets, although you MAY want to PING the address just to make sure your co-worker didn't forget to update the database, cause you would NEVER do that, right?
Now that we've got the new address, let's immediately allocate it in the pool so that we don't cause any problems for co-workers in the future.
End of explanation
childscope.gethosts()
for i in childscope.hosts:
    if i['ip'] == '10.101.0.3':
        print (i)
Explanation: Now that we've added this new IP address allocation to the 10.101.0./24 subnet, let's update the hosts list for the childscope object
End of explanation
childscope.deallocateIp(161)
childscope.gethosts()
for i in childscope.hosts:
    if i['ip'] == '10.101.0.3':
        print (i)
Explanation: Cleaning Up
Now that we've succesfully added the new IP allocation to the IMC System, it's time to clean up after ourselves. 
To do that, we're simply going to take the id attribute of the IP allocation we created above and use that as the input to the deallocateIP method of the childscope IPSCope object. 
This should successfully delete the IP allocation that we just created and our system is back to normal. 
Cool right?
For the last step, we wil refresh the hosts list for the childscope object again and make sure that the Juniper record we created above at IP 10.101.0.3 is, indeed, gone.
End of explanation
<END_TASK>