summaryrefslogtreecommitdiffstats
path: root/laas-fog/source/api
diff options
context:
space:
mode:
authorJack Morgan <jack.morgan@intel.com>2018-01-09 00:12:25 +0000
committerGerrit Code Review <gerrit@opnfv.org>2018-01-09 00:12:25 +0000
commit37fa445afe6d63d44a3a52c2a89e4e21ae67b5a6 (patch)
treea053095a7347ca30245081b3fc44d5f6b7f645d7 /laas-fog/source/api
parent0700062b04ad49431fbebcfd7c44d4013d654bfe (diff)
parent30f389c70e8a0a8bd2ef27be09839eef243ab7f5 (diff)
Merge "Initial Commit for new LaaS Software"
Diffstat (limited to 'laas-fog/source/api')
-rw-r--r--laas-fog/source/api/__init__.py17
-rw-r--r--laas-fog/source/api/fog.py288
-rw-r--r--laas-fog/source/api/fuel_api.py306
-rw-r--r--laas-fog/source/api/libvirt_api.py331
-rw-r--r--laas-fog/source/api/vpn.py235
5 files changed, 0 insertions, 1177 deletions
diff --git a/laas-fog/source/api/__init__.py b/laas-fog/source/api/__init__.py
deleted file mode 100644
index 7bb515b..0000000
--- a/laas-fog/source/api/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""
-#############################################################################
-#Copyright 2017 Parker Berberian and others #
-# #
-#Licensed under the Apache License, Version 2.0 (the "License"); #
-#you may not use this file except in compliance with the License. #
-#You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-#Unless required by applicable law or agreed to in writing, software #
-#distributed under the License is distributed on an "AS IS" BASIS, #
-#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-#See the License for the specific language governing permissions and #
-#limitations under the License. #
-#############################################################################
-"""
diff --git a/laas-fog/source/api/fog.py b/laas-fog/source/api/fog.py
deleted file mode 100644
index 6287403..0000000
--- a/laas-fog/source/api/fog.py
+++ /dev/null
@@ -1,288 +0,0 @@
-"""
-#############################################################################
-#Copyright 2017 Parker Berberian and others #
-# #
-#Licensed under the Apache License, Version 2.0 (the "License"); #
-#you may not use this file except in compliance with the License. #
-#You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-#Unless required by applicable law or agreed to in writing, software #
-#distributed under the License is distributed on an "AS IS" BASIS, #
-#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-#See the License for the specific language governing permissions and #
-#limitations under the License. #
-#############################################################################
-"""
-
-import requests
-import sys
-import time
-
-
-class FOG_Handler:
- """
- This class talks with the REST web api for the FOG server.
-
- TODO: convert prints to logs and remove uneeded pass's
- """
-
- def __init__(self, baseURL, fogKey=None, userKey=None):
- """
- init function
- baseURL should be http://fog.ip.or.hostname/fog/
- fogKey and userKey can optionally be supplied here or later
- They can be found in fog and provide authentication.
- """
- self.baseURL = baseURL
- self.fogKey = fogKey
- self.userKey = userKey
- self.header = {}
- self.updateHeader()
-
- def setLogger(self, logger):
- """
- saves the refference to the log object as
- self.log
- """
- self.log = logger
-
- def getUserKeyFromFile(self, path):
- """
- reads the user api key from a file
- """
- self.userKey = open(path).read()
- self.updateHeader()
-
- def getFogKeyFromFile(self, path):
- """
- reads the api key from a file
- """
- self.fogKey = open(path).read()
- self.updateHeader()
-
- def setUserKey(self, key):
- """
- sets the user key
- """
- self.userKey = key
- self.updateHeader()
-
- def setFogKey(self, key):
- """
- sets the fog key
- """
- self.fogKey = key
- self.updateHeader()
-
- def updateHeader(self):
- """
- recreates the http header used to talk to the fog api
- """
- self.header = {}
- self.header['fog-api-token'] = self.fogKey
- self.header['fog-user-token'] = self.userKey
-
- def setImage(self, host, imgNum):
- """
- Sets the image to be used during ghosting to the image
- with id imgNum. host can either be a hostname or number.
- """
- try:
- host = int(host)
- except:
- host = self.getHostNumber(host)
- url = self.baseURL+"host/"+str(host)
- host_conf = requests.get(url, headers=self.header).json()
- host_conf['imageID'] = str(imgNum)
- requests.put(url+"/edit", headers=self.header, json=host_conf)
-
- def delTask(self, hostNum):
- """
- Tries to delete an existing task for the host
- with hostNum as a host number
- """
- try:
- url = self.baseURL+'fog/host/'+str(hostNum)+'/cancel'
- req = requests.delete(url, headers=self.header)
- if req.status_code == 200:
- self.log.info("%s", "successfully deleted image task")
- except Exception:
- self.log.exception("Failed to delete the imaging task!")
-
- def getHostMac(self, hostname):
- """
- returns the primary mac address if the given host.
- """
- try:
- hostNum = int(self.getHostNumber(hostname))
- url = self.baseURL + "host/"+str(hostNum)
- req = requests.get(url, headers=self.header)
- macAddr = req.json()['primac']
- return macAddr
- except Exception:
- self.log.exception('%s', "Failed to connect to the FOG server")
-
- def getHostNumber(self, hostname):
- """
- returns the host number of given host
- """
- try:
- req = requests.get(self.baseURL+"host", headers=self.header)
- hostData = req.json()
- if hostData is not None:
- for hostDict in hostData['hosts']:
- if hostname == hostDict['name']:
- return hostDict['id']
- return -1
- except Exception:
- self.log.exception('%s', "Failed to connect to the FOG server")
-
- def imageHost(self, hostName, recurse=False):
- """
- Schedules an imaging task for the given host.
- This automatically uses the "associated" disk image.
- To support extra installers, I will need to create
- a way to change what that image is before calling
- this method.
- """
- num = str(self.getHostNumber(hostName))
- url = self.baseURL+'host/'+num+'/task'
-
- try:
- req = requests.post(
- url,
- headers=self.header,
- json={"taskTypeID": 1}
- )
- if req.status_code == 200:
- self.log.info("%s", "Scheduled image task for host")
- except Exception:
- if recurse: # prevents infinite loop
- self.log.exception("%s", "Failed to schedule task. Exiting")
- sys.exit(1)
- self.log.warning("%s", "Failed to schedule host imaging")
- self.log.warning("%s", "Trying to delete existing image task")
- self.delTask(num)
- self.imageHost(num, recurse=True)
-
- def waitForHost(self, host):
- """
- tracks the imaging task to completion.
- """
- while True:
- imageTask = self.getImagingTask(host)
- if imageTask is None:
- self.log.info("%s", "Imaging complete")
- return
- state = int(imageTask['stateID'])
- if state == 1:
- self.log.info("%s", "Waiting for host to check in")
- self.waitForTaskToActive(host)
- continue
- if state == 3:
- self.waitForTaskToStart(host)
- self.waitForImaging(host)
- continue
- time.sleep(8)
-
- def waitForImaging(self, host):
- """
- Once the host begins being imaged, this tracks progress.
- """
- # print "Host has begun the imaging process\n"
- while True:
- task = self.getImagingTask(host)
- if task is None:
- return
- per = str(task['percent'])
- self.log.info("%s percent done imaging", per)
- time.sleep(15)
-
- def waitForTaskToActive(self, host):
- """
- Waits for the host to reboot and pxe boot
- into FOG
- """
- while True:
- try:
- task = self.getImagingTask(host)
- except:
- pass
- state = int(task['stateID'])
- if state == 1:
- time.sleep(4)
- else:
- return
-
- def waitForTaskToStart(self, host):
- """
- waits for the task to start and imaging to begin.
- """
- while True:
- try:
- per = str(self.getImagingTask(host)['percent'])
- except:
- pass
- if per.strip() == '':
- time.sleep(1)
- else:
- return
-
- def getImagingTask(self, host):
- """
- Sorts through all current tasks to find the image task
- associated with the given host.
- """
- try:
- taskList = requests.get(
- self.baseURL+'task/current',
- headers=self.header)
- taskList = taskList.json()['tasks']
- imageTask = None
- for task in taskList:
- hostname = str(task['host']['name'])
- if hostname == host and int(task['typeID']) == 1:
- imageTask = task
- return imageTask
- except Exception:
- self.log.exception("%s", "Failed to talk to FOG server")
- sys.exit(1)
-
- def getHosts(self):
- """
- returns a list of all hosts
- """
- req = requests.get(self.baseURL+"host", headers=self.header)
- return req.json()['hosts']
-
- def getHostsinGroup(self, groupName):
- """
- returns a list of all hosts in groupName
- """
- groupID = None
- groups = requests.get(self.baseURL+"group", headers=self.header)
- groups = groups.json()['groups']
- for group in groups:
- if groupName.lower() in group['name'].lower():
- groupID = group['id']
- if groupID is None:
- return
- hostIDs = []
- associations = requests.get(
- self.baseURL+"groupassociation",
- headers=self.header
- )
- associations = associations.json()['groupassociations']
- for association in associations:
- if association['groupID'] == groupID:
- hostIDs.append(association['hostID'])
-
- hosts = []
- for hostID in hostIDs:
- hosts.append(requests.get(
- self.baseURL+"host/"+str(hostID),
- headers=self.header
- ).json())
- return hosts
diff --git a/laas-fog/source/api/fuel_api.py b/laas-fog/source/api/fuel_api.py
deleted file mode 100644
index 0127800..0000000
--- a/laas-fog/source/api/fuel_api.py
+++ /dev/null
@@ -1,306 +0,0 @@
-"""
-#############################################################################
-#Copyright 2017 Parker Berberian and others #
-# #
-#Licensed under the Apache License, Version 2.0 (the "License"); #
-#you may not use this file except in compliance with the License. #
-#You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-#Unless required by applicable law or agreed to in writing, software #
-#distributed under the License is distributed on an "AS IS" BASIS, #
-#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-#See the License for the specific language governing permissions and #
-#limitations under the License. #
-#############################################################################
-"""
-
-import requests
-import time
-import sys
-
-
-class Fuel_api:
-
- def __init__(self, url, logger, user="admin", password="admin"):
- """
- url is the url of the fog api in the form
- http://ip.or.host.name:8000/
- logger is a reference to the logger
- the default creds for fuel is admin/admin
- """
- self.logger = logger
- self.base = url
- self.user = user
- self.password = password
- self.header = {"Content-Type": "application/json"}
-
- def getKey(self):
- """
- authenticates with the user and password
- to get a keystone key, used in the headers
- from here on to talk to fuel.
- """
- url = self.base + 'keystone/v2.0/tokens/'
- reqData = {"auth": {
- "tenantName": self.user,
- "passwordCredentials": {
- "username": self.user,
- "password": self.password
- }
- }}
- self.logger.info("Retreiving keystone token from %s", url)
- token = requests.post(url, headers=self.header, json=reqData)
- self.logger.info("Received response code %d", token.status_code)
- self.token = token.json()['access']['token']['id']
- self.header['X-Auth-Token'] = self.token
-
- def getNotifications(self):
- """
- returns the fuel notifications
- """
- url = self.base+'/api/notifications'
- try:
- req = requests.get(url, headers=self.header)
- return req.json()
-
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def waitForBootstrap(self):
- """
- Waits for the bootstrap image to build.
- """
- while True:
- time.sleep(30)
- notes = self.getNotifications()
- for note in notes:
- if "bootstrap image building done" in note['message']:
- return
-
- def getNodes(self):
- """
- returns a list of all nodes booted into fuel
- """
- url = self.base+'api/nodes'
- try:
- req = requests.get(url, headers=self.header)
- return req.json()
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def getID(self, mac):
- """
- gets the fuel id of node with given mac
- """
- for node in self.getNodes():
- if node['mac'] == mac:
- return node['id']
-
- def getNetID(self, name, osid):
- """
- gets the id of the network with name
- """
- url = self.base+'api/clusters/'
- url += str(osid)+'/network_configuration/neutron'
- try:
- req = requests.get(url, headers=self.header)
- nets = req.json()['networks']
- for net in nets:
- if net['name'] == name:
- return net['id']
- return -1
-
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def createOpenstack(self):
- """
- defines a new openstack environment in fuel.
- """
- url = self.base+'api/clusters'
- data = {
- "nodes": [],
- "tasks": [],
- "name": "OpenStack",
- "release_id": 2,
- "net_segment_type": "vlan"
- }
- try:
- req = requests.post(url, json=data, headers=self.header)
- return req.json()['id']
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def simpleNetDict(self, osID):
- """
- returns a simple dict of network names and id numbers
- """
- nets = self.getNetworks(osID)
- netDict = {}
- targetNets = ['admin', 'public', 'storage', 'management']
- for net in nets['networks']:
- for tarNet in targetNets:
- if tarNet in net['name']:
- netDict[tarNet] = net['id']
- return netDict
-
- def getNetworks(self, osID):
- """
- Returns the pythonizezd json of the openstack networks
- """
- url = self.base + 'api/clusters/'
- url += str(osID)+'/network_configuration/neutron/'
- try:
- req = requests.get(url, headers=self.header)
- return req.json()
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def uploadNetworks(self, netJson, osID):
- """
- configures the networks of the openstack
- environment with id osID based on netJson
- """
- url = self.base+'api/clusters/'
- url += str(osID)+'/network_configuration/neutron'
- try:
- req = requests.put(url, headers=self.header, json=netJson)
- return req.json()
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def addNodes(self, clusterID, nodes):
- """
- Adds the nodes into this openstack environment.
- nodes is valid json
- """
- url = self.base + 'api/clusters/'+str(clusterID)+'/assignment'
- try:
- req = requests.post(url, headers=self.header, json=nodes)
- return req.json()
-
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def getIfaces(self, nodeID):
- """
- returns the pythonized json describing the
- interfaces of given node
- """
- url = self.base + 'api/nodes/'+str(nodeID)+'/interfaces'
- try:
- req = requests.get(url, headers=self.header)
- return req.json()
-
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def setIfaces(self, nodeID, ifaceJson):
- """
- configures the interfaces of node with id nodeID
- with ifaceJson
- ifaceJson is valid json that fits fuel's schema for ifaces
- """
- url = self.base+'/api/nodes/'+str(nodeID)+'/interfaces'
- try:
- req = requests.put(url, headers=self.header, json=ifaceJson)
- return req.json()
-
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def getTasks(self):
- """
- returns a list of all tasks
- """
- url = self.base+"/api/tasks/"
- try:
- req = requests.get(url, headers=self.header)
- return req.json()
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def waitForTask(self, uuid):
- """
- Tracks the progress of task with uuid and
- returns once the task finishes
- """
- progress = 0
- while progress < 100:
- for task in self.getTasks():
- if task['uuid'] == uuid:
- progress = task['progress']
- self.logger.info("Task is %s percent done", str(progress))
- time.sleep(20)
- # Task may hang a minute at 100% without finishing
- while True:
- for task in self.getTasks():
- if task['uuid'] == uuid and not task['status'] == "ready":
- time.sleep(10)
- elif task['uuid'] == uuid and task['status'] == "ready":
- return
-
- def getHorizonIP(self, osid):
- """
- returns the ip address of the horizon dashboard.
- Horizon always takes the first ip after the public router's
- """
- url = self.base+'api/clusters/'
- url += str(osid)+'/network_configuration/neutron/'
- try:
- req = requests.get(url, headers=self.header)
- routerIP = req.json()['vips']['vrouter_pub']['ipaddr'].split('.')
- routerIP[-1] = str(int(routerIP[-1])+1)
- return '.'.join(routerIP)
- except Exception:
- self.logger.exception('%s', "Failed to talk to the Fuel api!")
- sys.exit(1)
-
- def deployOpenstack(self, clusterID):
- """
- Once openstack and the nodes are configured,
- this method actually deploys openstack.
- It takes a while.
- """
- # First, we need to provision the cluster
- url = self.base+'/api/clusters/'+str(clusterID)+'/provision'
- req = requests.put(url, headers=self.header)
- if req.status_code < 300:
- self.logger.info('%s', "Sent provisioning task")
- else:
- err = "failed to provision Openstack Environment"
- self.logger.error('%s', err)
- sys.exit(1)
-
- taskUID = ''
- tasks = self.getTasks()
- for task in tasks:
- if task['name'] == "provision" and task['cluster'] == clusterID:
- taskUID = task['uuid']
-
- self.waitForTask(taskUID)
-
- # Then, we deploy cluster
- url = self.base + '/api/clusters/'+str(clusterID)+'/deploy'
- req = requests.put(url, headers=self.header)
- if req.status_code < 300:
- self.logger.info('%s', "Sent deployment task")
- taskUID = ''
- tasks = self.getTasks()
- for task in tasks:
- if 'deploy' in task['name'] and task['cluster'] == clusterID:
- taskUID = task['uuid']
- if len(taskUID) > 0:
- self.waitForTask(taskUID)
diff --git a/laas-fog/source/api/libvirt_api.py b/laas-fog/source/api/libvirt_api.py
deleted file mode 100644
index 4e19736..0000000
--- a/laas-fog/source/api/libvirt_api.py
+++ /dev/null
@@ -1,331 +0,0 @@
-"""
-#############################################################################
-#Copyright 2017 Parker Berberian and others #
-# #
-#Licensed under the Apache License, Version 2.0 (the "License"); #
-#you may not use this file except in compliance with the License. #
-#You may obtain a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-#Unless required by applicable law or agreed to in writing, software #
-#distributed under the License is distributed on an "AS IS" BASIS, #
-#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-#See the License for the specific language governing permissions and #
-#limitations under the License. #
-#############################################################################
-"""
-
-import libvirt
-import time
-import xml.dom
-import xml.dom.minidom
-from domain import Domain
-from network import Network
-from utilities import Utilities
-
-
-class Libvirt:
- """
- This class talks to the Libvirt api.
- Given a config file, this class should create all networks and
- domains.
-
- TODO: convert prints to logging and remove uneeded pass statements
- """
-
- def __init__(self, hostAddr, net_conf=None, dom_conf=None):
- """
- init function
- hostAddr is the ip address of the host
- net_conf and dom_conf are the paths
- to the config files
- """
- self.host = hostAddr
- self.URI = "qemu+ssh://root@"+str(hostAddr)+"/system"
- self.hypervisor = None
- self.domains = []
- self.networks = []
- self.net_conf = net_conf
- self.dom_conf = dom_conf
-
- def setLogger(self, log):
- """
- Saves the logger in self.log
- """
- self.log = log
-
- def bootMaster(self):
- """
- starts the previously defined master node
- """
- for dom in self.domains:
- if 'master' in dom.name():
- try:
- dom.create()
- except Exception:
- pass
-
- def bootSlaves(self):
- """
- boots every defined vm with 'slave' in its name
- """
- for dom in self.domains:
- if 'slave' in dom.name():
- try:
- dom.create()
- self.log.info("Booting %s", dom.name())
- except Exception:
- self.log.exception("%s", "failed to boot domain")
- time.sleep(5)
-
- def getMacs(self, domName):
- """
- returns a dictionary with a network name
- mapped to the mac address of the domain on that net
- """
- try:
- dom = self.hypervisor.lookupByName(domName)
- xmlDesc = dom.XMLDesc(0)
- parsedXML = xml.dom.minidom.parseString(xmlDesc)
- interfacesXML = parsedXML.getElementsByTagName('interface')
- netDict = {}
- for iface in interfacesXML:
- src = iface.getElementsByTagName('source')[0]
- mac = iface.getElementsByTagName('mac')[0]
- netDict[src] = mac
- return netDict
- except Exception:
- self.log.exception("%s", "Domain not found")
-
- def defineVM(self, xmlConfig):
- """
- Generic method to define a persistent vm with the
- given config.
- Assumes that self.hypervisor is already connected.
- """
- if self.checkForVM(xmlConfig):
- vm = self.hypervisor.defineXML(xmlConfig)
- if vm is None:
- name = self.getName(xmlConfig)
- self.log.error("Failed to define vm %s. exiting", name)
- exit(1)
- else:
- self.log.info("Successfully created vm %s", vm.name())
- pass
- self.domains.append(vm)
-
- def checkForVM(self, xmlConfig):
- """
- Checks if another vm with the same name exists
- on the remote host already. If it does, it will
- delete that vm
- """
- allGood = False
- vms = self.hypervisor.listAllDomains(0)
- names = []
- for dom in vms:
- names.append(dom.name())
- vmName = Utilities.getName(xmlConfig)
- if vmName in names:
- self.log.warning("domain %s already exists", vmName)
- self.log.warning("%s", "Atempting to delete it")
- self.deleteVM(vmName)
- allGood = True
- else:
- allGood = True
- return allGood
-
- def deleteVM(self, name):
- """
- removes the given vm from the remote host
- """
- try:
- vm = self.hypervisor.lookupByName(name)
- except:
- return
- active = vm.isActive()
- persistent = vm.isPersistent()
- if active:
- try:
- vm.destroy()
- except:
- self.log.exception("%s", "Failed to destroy vm")
-
- if persistent:
- try:
- vm.undefine()
- except:
- self.log.exception("%s", "Failed to undefine domain")
- pass
-
- def openConnection(self):
- """
- opens a connection to the remote host
- and stores it in self.hypervisor
- """
- self.log.info("Attempting to connect to libvirt at %s", self.host)
- try:
- hostHypervisor = libvirt.open(self.URI)
- except:
- self.log.warning(
- "Failed to connect to %s. Trying again", self.host
- )
- time.sleep(5)
- try:
- hostHypervisor = libvirt.open(self.URI)
- except:
- self.log.exception("Cannot connect to %s. Exiting", self.host)
- exit(1)
-
- if hostHypervisor is None:
- self.log.error("Failed to connect to %s. Exiting", self.host)
- exit(1)
- self.hypervisor = hostHypervisor
-
- def restartVM(self, vm):
- """
- causes the given vm to reboot
- """
- dom = self.hypervisor.lookupByName(vm)
- dom.destroy()
- time.sleep(15)
- dom.create()
-
- def close(self):
- """
- Closes connection to remote hypervisor
- """
- self.log.info("Closing connection to the hypervisor %s", self.host)
- self.hypervisor.close()
-
- def defineAllDomains(self, path):
- """
- Defines a domain from all the xml files in a directory
- """
- files = Utilities.getXMLFiles(path)
- definitions = []
- for xml_desc in files:
- definitions.append(xml_desc.read())
-
- for definition in definitions:
- self.defineVM(definition)
-
- def createAllNetworks(self, path):
- """
- Creates a network from all xml files in a directory
- """
- files = Utilities.getXMLFiles(path)
- definitions = []
- for xml_desc in files:
- definitions.append(Utilities.fileToString(xml_desc))
-
- for definition in definitions:
- self.createNet(definition)
-
- def createNet(self, config):
- """
- creates the network on the remote host
- config is the xml in string representation
- that defines the network
- """
- if self.checkNet(config):
- network = self.hypervisor.networkDefineXML(config)
-
- if network is None:
- name = self.getName(config)
- self.log.warning("Failed to define network %s", name)
- network.create()
- if network.isActive() == 1:
- net = network.name()
- self.log.info("Successfully defined network %s", net)
- self.networks.append(network)
-
- def checkNet(self, config):
- """
- Checks if another net with the same name exists, and
- deletes that network if one is found
- """
- allGood = False
- netName = Utilities.getName(config)
- if netName not in self.hypervisor.listNetworks():
- return True
- else: # net name is already used
- self.log.warning(
- "Network %s already exists. Trying to delete it", netName
- )
- network = self.hypervisor.networkLookupByName(netName)
- self.deleteNet(network)
- allGood = True
- return allGood
-
- def deleteNet(self, net):
- """
- removes the given network from the host
- """
- active = net.isActive()
- persistent = net.isPersistent()
- if active:
- try:
- net.destroy()
- except:
- self.log.warning("%s", "Failed to destroy network")
-
- if persistent:
- try:
- net.undefine()
- except:
- self.log.warning("%s", "Failed to undefine network")
-
- def go(self):
- """
- This method does all the work of this class,
- Parsing the net and vm config files and creating
- all the requested nets/domains
- returns a list of all networks and a list of all domains
- as Network and Domain objects
- """
- nets = self.makeNetworks(self.net_conf)
- doms = self.makeDomains(self.dom_conf)
- return doms, nets
-
- def makeNetworks(self, conf):
- """
- Given a path to a config file, this method
- parses the config and creates all requested networks,
- and returns them in a list of Network objects
- """
- networks = []
- definitions = Network.parseConfigFile(conf)
- for definition in definitions:
- network = Network(definition)
- networks.append(network)
- self.createNet(network.toXML())
- return networks
-
- def makeDomains(self, conf):
- """
- Given a path to a config file, this method
- parses the config and creates all requested vm's,
- and returns them in a list of Domain objects
- """
- domains = []
- definitions = Domain.parseConfigFile(conf)
- for definition in definitions:
- domain = Domain(definition)
- domains.append(domain)
- self.defineVM(domain.toXML())
- return domains
-
- @staticmethod
- def getName(xmlString):
- """
- given xml with a name tag, this returns the value of name
- eg:
- <name>Parker</name>
- returns 'Parker'
- """
- xmlDoc = xml.dom.minidom.parseString(xmlString)
- nameNode = xmlDoc.documentElement.getElementsByTagName('name')
- name = str(nameNode[0].firstChild.nodeValue)
- return name
diff --git a/laas-fog/source/api/vpn.py b/laas-fog/source/api/vpn.py
deleted file mode 100644
index 336a681..0000000
--- a/laas-fog/source/api/vpn.py
+++ /dev/null
@@ -1,235 +0,0 @@
-from abc import ABCMeta, abstractmethod
-import ldap
-import os
-import random
-from base64 import b64encode
-from database import BookingDataBase
-
-
-class VPN_BaseClass:
- """
- the vpn handler abstract class / interface
-
- """
- __metaclass__ = ABCMeta
-
- @abstractmethod
- def __init__(self, config):
- """
- config is the parsed vpn.yaml file
- """
- pass
-
- @abstractmethod
- def makeNewUser(self, user=None):
- """
- This method is called when a vpn user is needed.
- This method should create a vpn user in whatever
- runs the vpn in our infrastructure. returns the
- credentials for the vpn user and some uid
- that will be associated with the booking in the
- database. This uid is used to track the vpn user and
- to delete the user when there are no bookings associated
- with that uid.
- """
- user = "username"
- passwd = "password"
- uid = "some way for you to identify this user in the database"
- return user, passwd, uid
-
- @abstractmethod
- def removeOldUsers(self):
- """
- checks the list of all vpn users against a list of
- vpn users associated with active bookings and removes
- users who dont have an active booking
-
- If you want your vpn accounts to be persistent,
- you can just ignore this
- """
- pass
-
-
-names = [
- 'frodo baggins', 'samwise gamgee', 'peregrin took', 'meriadoc brandybuck',
- 'bilbo baggins', 'gandalf grey', 'aragorn dunadan', 'arwen evenstar',
- 'saruman white', 'pippin took', 'merry brandybuck', 'legolas greenleaf',
- 'gimli gloin', 'anakin skywalker', 'padme amidala', 'han solo',
- 'jabba hut', 'mace windu', 'sount dooku', 'qui-gon jinn',
- 'admiral ackbar', 'emperor palpatine'
-]
-
-
-class VPN:
- """
- This class communicates with the ldap server to manage vpn users.
- This class extends the above ABC, and implements the makeNewUser,
- removeOldUser, and __init__ abstract functions you must override to
- extend the VPN_BaseClass
- """
-
- def __init__(self, config):
- """
- init takes the parsed vpn config file as an arguement.
- automatically connects and authenticates on the ldap server
- based on the configuration file
- """
- self.config = config
- server = config['server']
- self.uri = "ldap://"+server
-
- self.conn = None
- user = config['authentication']['user']
- pswd = config['authentication']['pass']
- if os.path.isfile(pswd):
- pswd = open(pswd).read()
- self.connect(user, pswd)
-
- def connect(self, root_dn, root_pass):
- """
- Opens a connection to the server in the config file
- and authenticates as the given user
- """
- self.conn = ldap.initialize(self.uri)
- self.conn.simple_bind_s(root_dn, root_pass)
-
- def addUser(self, full_name, passwd):
- """
- Adds a user to the ldap server. Creates the new user with the classes
- and in the directory given in the config file.
- full_name should be two tokens seperated by a space. The first token
- will become the username
- private helper function for the makeNewUser()
- """
- first = full_name.split(' ')[0]
- last = full_name.split(' ')[1]
- user_dir = self.config['directory']['user']
- user_dir += ','+self.config['directory']['root']
- dn = "uid=" + first + ',' + user_dir
- record = [
- ('objectclass', ['top', 'inetOrgPerson']),
- ('uid', first),
- ('cn', full_name),
- ('sn', last),
- ('userpassword', passwd),
- ('ou', self.config['directory']['user'].split('=')[1])
- ]
- self.conn.add_s(dn, record)
- return dn
-
- def makeNewUser(self, name=None):
- """
- creates a new user in the ldap database, with the given name
- if supplied. If no name is given, we will try to select from the
- pre-written list above, and will resort to generating a random string
- as a username if the preconfigured names are all taken.
- Returns the username and password the user needs to authenticate, and
- the dn that we can use to manage the user.
- """
- if name is None:
- i = 0
- while not self.checkName(name):
- i += 1
- if i == 20:
- name = self.randoString(8)
- name += ' '+self.randoString(8)
- break # generates a random name to prevent infinite loop
- name = self.genUserName()
- passwd = self.randoString(15)
- dn = self.addUser(name, passwd)
- return name, passwd, dn
-
- def checkName(self, name):
- """
- returns true if the name is available
- """
- if name is None:
- return False
- uid = name.split(' ')[0]
- base = self.config['directory']['user'] + ','
- base += self.config['directory']['root']
- filtr = '(uid=' + uid + ')'
- timeout = 5
- ans = self.conn.search_st(
- base,
- ldap.SCOPE_SUBTREE,
- filtr,
- timeout=timeout
- )
- return len(ans) < 1
-
- @staticmethod
- def randoString(n):
- """
- uses /dev/urandom to generate a random string of length n
- """
- n = int(n)
- # defines valid characters
- alpha = 'abcdefghijklmnopqrstuvwxyz'
- alpha_num = alpha
- alpha_num += alpha.upper()
- alpha_num += "0123456789"
-
- # generates random string from /dev/urandom
- rnd = b64encode(os.urandom(3*n)).decode('utf-8')
- random_string = ''
- for char in rnd:
- if char in alpha_num:
- random_string += char
- return str(random_string[:n])
-
- def genUserName(self):
- """
- grabs a random name from the list above
- """
- i = random.randint(0, len(names) - 1)
- return names[i]
-
- def deleteUser(self, dn):
- self.conn.delete(dn)
-
- def getAllUsers(self):
- """
- returns all the user dn's in the ldap database in a list
- """
- base = self.config['directory']['user'] + ','
- base += self.config['directory']['root']
- filtr = '(objectclass='+self.config['user']['objects'][-1]+')'
- timeout = 10
- ans = self.conn.search_st(
- base,
- ldap.SCOPE_SUBTREE,
- filtr,
- timeout=timeout
- )
- users = []
- for user in ans:
- users.append(user[0]) # adds the dn of each user
- return users
-
- def removeOldUsers(self):
- """
- removes users from the ldap server who dont have any active bookings.
- will not delete a user if their uid's are named in the config
- file as permanent users.
- """
- db = self.config['database']
- # the dn of all users who have an active booking
- active_users = BookingDataBase(db).getVPN()
- all_users = self.getAllUsers()
- for user in all_users:
- # checks if they are a permanent user
- if self.is_permanent_user(user):
- continue
- # deletes the user if they dont have an active booking
- if user not in active_users:
- self.deleteUser(user)
-
- def is_permanent_user(self, dn):
- for user in self.config['permanent_users']:
- if (user in dn) or (dn in user):
- return True
- return False
-
-
-VPN_BaseClass.register(VPN)