def handle_add(self, hostname, device_type, worker_name, description, dictionary, pipeline, public, online): try: dt = DeviceType.objects.get(name=device_type) except DeviceType.DoesNotExist: self.stderr.write("Unable to find device-type '%s'" % device_type) sys.exit(1) try: worker = Worker.objects.get(hostname=worker_name) except Worker.DoesNotExist: self.stderr.write("Unable to find worker '%s'" % worker_name) sys.exit(1) status = Device.IDLE if online else Device.OFFLINE Device.objects.create(hostname=hostname, device_type=dt, description=description, worker_host=worker, is_pipeline=pipeline, status=status, is_public=public) if dictionary is not None: data = jinja2_to_devicedictionary(dictionary.read()) if data is None: self.stderr.write("Invalid device dictionary") sys.exit(1) element = DeviceDictionary(hostname=hostname) element.hostname = hostname element.parameters = data element.save()
def parse_template(device_file): if not os.path.exists(os.path.realpath(device_file)): print "Unable to find file '%s'\n" % device_file sys.exit(2) with open(device_file, 'r') as fileh: content = fileh.read() return jinja2_to_devicedictionary(content)
def parse_template(device_file): if not os.path.exists(os.path.realpath(device_file)): print "Unable to find file '%s'\n" % device_file sys.exit(2) with open(device_file, 'r') as fileh: content = fileh.read() return jinja2_to_devicedictionary(content)
def test_vland_jinja2(self): """ Test complex device dictionary values The reference data can cross lines but cannot be indented as the pprint object in utils uses indent=0, width=80 for YAML compatibility. The strings read in from config files can have indenting spaces, these are removed in the pprint. """ data = """{% extends 'vland.jinja2' %} {% set interfaces = ['eth0', 'eth1'] %} {% set sysfs = {'eth0': '/sys/devices/pci0000:00/0000:00:19.0/net/eth0', 'eth1': '/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/eth1'} %} {% set mac_addr = {'eth0': 'f0:de:f1:46:8c:21', 'eth1': '00:24:d7:9b:c0:8c'} %} {% set tags = {'eth0': ['1G', '10G'], 'eth1': ['1G']} %} {% set map = {'eth0': {'192.168.0.2': 5}, 'eth1': {'192.168.0.2': 7}} %} """ result = { 'interfaces': ['eth0', 'eth1'], 'sysfs': { 'eth1': '/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/eth1', 'eth0': '/sys/devices/pci0000:00/0000:00:19.0/net/eth0' }, 'extends': 'vland.jinja2', 'mac_addr': { 'eth1': '00:24:d7:9b:c0:8c', 'eth0': 'f0:de:f1:46:8c:21' }, 'tags': { 'eth1': ['1G'], 'eth0': ['1G', '10G'] }, 'map': { 'eth0': { '192.168.0.2': 5 }, 'eth1': { '192.168.0.2': 7 } } } dictionary = jinja2_to_devicedictionary(data_dict=data) self.assertEqual(result, dictionary) jinja2_str = devicedictionary_to_jinja2(data_dict=dictionary, extends='vland.jinja2') # ordering within the dict can change but each line needs to still appear for line in str(data).split('\n'): self.assertIn(line, str(jinja2_str)) # create a DeviceDictionary for this test vlan = DeviceDictionary(hostname='vlanned1') vlan.parameters = dictionary vlan.save() del vlan vlan = DeviceDictionary.get('vlanned1') cmp_str = str(devicedictionary_to_jinja2(vlan.parameters, 'vland.jinja2')) for line in str(data).split('\n'): self.assertIn(line, cmp_str)
def test_vland_jinja2(self): """ Test complex device dictionary values The reference data can cross lines but cannot be indented as the pprint object in utils uses indent=0, width=80 for YAML compatibility. The strings read in from config files can have indenting spaces, these are removed in the pprint. """ data = """{% extends 'vland.jinja2' %} {% set interfaces = ['eth0', 'eth1'] %} {% set sysfs = {'eth0': '/sys/devices/pci0000:00/0000:00:19.0/net/eth0', 'eth1': '/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/eth1'} %} {% set mac_addr = {'eth0': 'f0:de:f1:46:8c:21', 'eth1': '00:24:d7:9b:c0:8c'} %} {% set tags = {'eth0': ['1G', '10G'], 'eth1': ['1G']} %} {% set map = {'eth0': {'192.168.0.2': 5}, 'eth1': {'192.168.0.2': 7}} %} """ result = { 'interfaces': ['eth0', 'eth1'], 'sysfs': { 'eth1': '/sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/eth1', 'eth0': '/sys/devices/pci0000:00/0000:00:19.0/net/eth0' }, 'extends': 'vland.jinja2', 'mac_addr': { 'eth1': '00:24:d7:9b:c0:8c', 'eth0': 'f0:de:f1:46:8c:21' }, 'tags': { 'eth1': ['1G'], 'eth0': ['1G', '10G'] }, 'map': { 'eth0': { '192.168.0.2': 5 }, 'eth1': { '192.168.0.2': 7 } } } dictionary = jinja2_to_devicedictionary(data_dict=data) self.assertEqual(result, dictionary) jinja2_str = devicedictionary_to_jinja2(data_dict=dictionary, extends='vland.jinja2') # ordering within the dict can change but each line needs to still appear for line in str(data).split('\n'): self.assertIn(line, str(jinja2_str)) # create a DeviceDictionary for this test vlan = DeviceDictionary(hostname='vlanned1') vlan.parameters = dictionary vlan.save() del vlan vlan = DeviceDictionary.get('vlanned1') cmp_str = str(devicedictionary_to_jinja2(vlan.parameters, 'vland.jinja2')) for line in str(data).split('\n'): self.assertIn(line, cmp_str)
def handle_set(self, options): """ Set device properties """ hostname = options["hostname"] try: device = Device.objects.get(hostname=hostname) except Device.DoesNotExist: self.stderr.write("Unable to find device '%s'" % hostname) sys.exit(1) status = options["status"] if status is not None: device.status = self.device_status[status] health = options["health"] if health is not None: device.health_status = self.health_status[health] description = options["description"] if description is not None: device.description = description worker_name = options["worker"] if worker_name is not None: try: worker = Worker.objects.get(hostname=worker_name) device.worker_host = worker except Worker.DoesNotExist: self.stderr.write("Unable to find worker '%s'" % worker_name) sys.exit(1) public = options["public"] if public is not None: device.is_public = public dictionary = options["dictionary"] if dictionary is not None: data = jinja2_to_devicedictionary(dictionary.read()) if data is None: self.stderr.write("Invalid device dictionary") sys.exit(1) element = DeviceDictionary.get(hostname) if element is None: element = DeviceDictionary(hostname=hostname) element.hostname = hostname element.parameters = data element.save() # Save the modifications device.save()
def import_device_dictionary(self, hostname, jinja_str): """ Name ---- `import_device_dictionary` (`device_hostname`, `jinja_string`) Description ----------- [superuser only] Import or update the device dictionary key value store for a pipeline device. This action will be logged. Arguments --------- `device_hostname`: string Device hostname to update. `jinja_str`: string Jinja2 settings to store in the DeviceDictionary Return value ------------ This function returns an XML-RPC binary data of output file. """ self._authenticate() if not self.user.is_superuser: raise xmlrpclib.Fault( 403, "User '%s' is not superuser." % self.user.username ) try: device = Device.objects.get(hostname=hostname) except DeviceType.DoesNotExist: raise xmlrpclib.Fault( 404, "Device '%s' was not found." % hostname ) try: device_data = jinja2_to_devicedictionary(jinja_str) except (ValueError, KeyError, TypeError): raise xmlrpclib.Fault( 400, "Unable to parse specified jinja string" ) if not device_data or 'extends' not in device_data: raise xmlrpclib.Fault( 400, "Invalid device dictionary content - %s - not updating." % jinja_str ) try: template = prepare_jinja_template(hostname, jinja_str, system_path=True) except (jinja2.TemplateError, yaml.YAMLError, IOError) as exc: raise xmlrpclib.Fault( 400, "Template error: %s" % exc ) if not template: raise xmlrpclib.Fault(400, "Empty template") element = DeviceDictionary.get(hostname) msg = '' if element is None: msg = "Adding new device dictionary for %s\n" % hostname element = DeviceDictionary(hostname=hostname) element.hostname = hostname element.parameters = device_data element.save() msg += "Device dictionary updated for %s\n" % hostname device.log_admin_entry(self.user, msg) return msg
def import_device_dictionary(self, hostname, jinja_str): """ Name ---- `import_device_dictionary` (`device_hostname`, `jinja_string`) Description ----------- [superuser only] Import or update the device dictionary key value store for a pipeline device. Arguments --------- `device_hostname`: string Device hostname to update. `jinja_str`: string Jinja2 settings to store in the DeviceDictionary Return value ------------ This function returns an XML-RPC binary data of output file. """ self._authenticate() if not self.user.is_superuser: raise xmlrpclib.Fault( 403, "User '%s' is not superuser." % self.user.username ) try: Device.objects.get(hostname=hostname) except DeviceType.DoesNotExist: raise xmlrpclib.Fault( 404, "Device '%s' was not found." % hostname ) try: device_data = jinja2_to_devicedictionary(jinja_str) except (ValueError, KeyError, TypeError): raise xmlrpclib.Fault( 400, "Unable to parse specified jinja string" ) if not device_data or 'extends' not in device_data: raise xmlrpclib.Fault( 400, "Invalid device dictionary content - %s - not updating." % jinja_str ) try: template = prepare_jinja_template(hostname, jinja_str, system_path=True) except (jinja2.TemplateError, yaml.YAMLError, IOError) as exc: raise xmlrpclib.Fault( 400, "Template error: %s" % exc ) if not template: raise xmlrpclib.Fault(400, "Empty template") element = DeviceDictionary.get(hostname) msg = '' if element is None: msg = "Adding new device dictionary for %s\n" % hostname element = DeviceDictionary(hostname=hostname) element.hostname = hostname element.parameters = device_data element.save() msg += "Device dictionary updated for %s\n" % hostname return msg