def set_agent_user_permissions(self, volttron_agent_user, agent_uuid, agent_dir): name = self.agent_name(agent_uuid) agent_path_with_name = os.path.join(agent_dir, name) # Directories in the install path have read/execute # except agent-data dir. agent-data dir has rwx self.set_acl_for_path("rx", volttron_agent_user, agent_dir) # creates dir if it doesn't exist data_dir = self._get_agent_data_dir(agent_path_with_name) for (root, directories, files) in os.walk(agent_dir, topdown=True): for directory in directories: if directory == os.path.basename(data_dir): self.set_acl_for_path("rwx", volttron_agent_user, os.path.join(root, directory)) else: self.set_acl_for_path("rx", volttron_agent_user, os.path.join(root, directory)) # In install directory, make all files' permissions to 400. # Then do setfacl -m "r" to only agent user self._set_agent_dir_file_permissions(agent_dir, volttron_agent_user, data_dir) # if messagebus is rmq. # TODO: For now provide read access to all agents since this is used for # multi instance connections. This will not be requirement in # VOLTTRON 8.0 once CSR is implemented for # federation and shovel. The below lines can be removed then if self.message_bus == 'rmq': os.chmod(os.path.join(get_home(), "certificates/private"), 0o755) self.set_acl_for_path("r", volttron_agent_user, os.path.join(get_home(), "certificates/private", self.instance_name + "-admin.pem"))
def __init__(self, filetowatch, callback): # Protect from circular reference for file from volttron.platform import get_home super(VolttronHomeFileReloader, self).__init__([get_home() + '/' + filetowatch]) _log.debug("patterns is {}".format([get_home() + '/' + filetowatch])) self._callback = callback
def watch_file(fullpath, callback): """Run callback method whenever the file changes Not available on OS X/MacOS. """ dirname, filename = os.path.split(fullpath) _log.info("Adding file watch for %s dirname=%s, filename=%s", fullpath, get_home(), filename) observer = Observer() observer.schedule(VolttronHomeFileReloader(filename, callback), path=get_home()) observer.start() _log.info("Added file watch for %s", fullpath)
def get_aip(): """Get AIPplatform to interface with agent directories in vhome""" vhome = get_home() options = type("Options", (), dict(volttron_home=vhome)) aip = AIPplatform(options) return aip
def __init__(self): self.instance_name = get_platform_instance_name() # This is written durn the bootstrap phase of the rabbitmq installation # however for docker we don't write this at all so we need to # use the default location for this rmq_home_file = os.path.expanduser("~/.volttron_rmq_home") if os.path.isfile(rmq_home_file): with open(os.path.expanduser("~/.volttron_rmq_home")) as f: self.rabbitmq_server = f.read().strip() else: self.rabbitmq_server = os.path.expanduser( "~/rabbitmq_server/rabbitmq_server-3.7.7/") assert os.path.isdir(self.rabbitmq_server ), "Missing rabbitmq server directory{}".format( self.rabbitmq_server) self.crts = certs.Certs() self.volttron_home = get_home() self.volttron_rmq_config = os.path.join(self.volttron_home, 'rabbitmq_config.yml') self.default_pass = "******" self.config_opts = None try: self.load_rmq_config() except (IOError, yaml.YAMLError) as exc: self.config_opts = {} self._set_default_config()
def __init__(self, address, peer=None, publickey=None, secretkey=None, serverkey=None, volttron_home=None, **kwargs): self._log = logging.getLogger(__name__) self._log.debug("Connection: {}, {}, {}, {}, {}" .format(address, peer, publickey, secretkey, serverkey)) self._address = address self._peer = peer self._serverkey = None if peer is None: self._log.warn('Peer is non so must be passed in call method.') self.volttron_home = volttron_home if self.volttron_home is None: self.volttron_home = os.path.abspath(platform.get_home()) if address.startswith('ipc'): full_address = address else: parsed = urlparse.urlparse(address) if parsed.scheme == 'tcp': qs = urlparse.parse_qs(parsed.query) self._log.debug('QS IS: {}'.format(qs)) if 'serverkey' in qs: self._serverkey = qs.get('serverkey') else: self._serverkey = serverkey # Handle case when the address has all the information in it. if 'serverkey' in qs.keys() and 'publickey' in qs.keys() and \ 'secretkey' in qs.keys(): full_address = address else: full_address = build_vip_address_string( vip_root=address, serverkey=serverkey, publickey=publickey, secretkey=secretkey ) elif parsed.scheme == 'ipc': full_address = address else: raise AttributeError( 'Invalid address type specified. ipc or tcp accepted.') self._server = Agent(address=full_address, volttron_home=self.volttron_home, enable_store=False, reconnect_interval=1000, **kwargs) # TODO the following should work as well, but doesn't. Not sure why! # self._server = Agent(address=address, serverkey=serverkey, # secretkey=secretkey, publickey=publickey, # enable_store=False, # volttron_home=self.volttron_home, **kwargs) self._greenlet = None self._connected_since = None self._last_publish = None self._last_publish_failed = False self._last_rpc_call = None # Make the actual attempt to connect to the server. self.is_connected()
def store_message_bus_config(message_bus, instance_name): # If there is no config file or home directory yet, create volttron_home # and config file if not instance_name: raise ValueError("Instance name should be a valid string and should " "be unique within a network of volttron instances " "that communicate with each other. start volttron " "process with '--instance-name <your instance>' if " "you are running this instance for the first time. " "Or add instance-name = <instance name> in " "vhome/config") v_home = get_home() config_path = os.path.join(v_home, "config") if os.path.exists(config_path): config = ConfigParser() config.read(config_path) config.set('volttron', 'message-bus', message_bus) config.set('volttron', 'instance-name', instance_name) with open(config_path, 'w') as configfile: config.write(configfile) else: if not os.path.exists(v_home): os.makedirs(v_home, 0o755) config = ConfigParser() config.add_section('volttron') config.set('volttron', 'message-bus', message_bus) config.set('volttron', 'instance-name', instance_name) with open(config_path, 'w') as configfile: config.write(configfile) # all agents need read access to config file os.chmod(config_path, 0o744)
def test_file_watcher(volttron_instance, publish_agent): test_path = os.path.join(get_home(), "test.txt") with open(test_path, "w") as textfile: textfile.write("test_data") test_config = { "files": [ { "file": test_path, "topic": "platform/test_topic" } ] } watcher_uuid = volttron_instance.install_agent( agent_dir=get_ops("FileWatchPublisher"), config_file=test_config, start=True, vip_identity="health_test") with open(test_path, "w+") as textfile: textfile.write("more test_data") gevent.sleep(1) assert publish_agent.callback.call_count == 1 print(publish_agent.callback.call_args) volttron_instance.remove_agent(watcher_uuid) os.remove(test_path)
def __init__(self, address, peer=None, publickey=None, secretkey=None, serverkey=None, volttron_home=None, **kwargs): _log.debug("Connection: {}, {}, {}, {}, {}".format( address, peer, publickey, secretkey, serverkey)) self._address = address self._peer = peer self._serverkey = None if peer is None: _log.warn('Peer is non so must be passed in call method.') self.volttron_home = volttron_home if self.volttron_home is None: self.volttron_home = os.path.abspath(platform.get_home()) if address.startswith('ipc'): full_address = address else: parsed = urlparse.urlparse(address) if parsed.scheme == 'tcp': qs = urlparse.parse_qs(parsed.query) _log.debug('QS IS: {}'.format(qs)) if 'serverkey' in qs: self._serverkey = qs.get('serverkey') else: self._serverkey = serverkey # Handle case when the address has all the information in it. if 'serverkey' in qs.keys() and 'publickey' in qs.keys() and \ 'secretkey' in qs.keys(): full_address = address else: full_address = build_vip_address_string( vip_root=address, serverkey=serverkey, publickey=publickey, secretkey=secretkey) elif parsed.scheme == 'ipc': full_address = address else: raise AttributeError( 'Invalid address type specified. ipc or tcp accepted.') self._server = Agent(address=full_address, volttron_home=self.volttron_home, enable_store=False, reconnect_interval=1000, **kwargs) self._greenlet = None self._connected_since = None self._last_publish = None self._last_publish_failed = False self._last_rpc_call = None # Make the actual attempt to connect to the server. self.is_connected()
def get_agent_user_from_dir(agent_name, agent_uuid): """ :param agent_uuid: :return: Unix user ID if installed Volttron agent """ user_id_path = os.path.join(get_home(), "agents", agent_uuid, "USER_ID") with open(user_id_path, 'r') as id_file: return id_file.readline()
def __init__(self, ssl_private_key): self._ssl_private_key = ssl_private_key self._userdict = None self.reload_userdict() self._observer = Observer() self._observer.schedule( FileReloader("web-users.json", self.reload_userdict), get_home()) self._observer.start()
def main(): # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument( "--address", help="Target only device(s) at <address> for request") arg_parser.add_argument( "--range", type=int, nargs=2, metavar=('LOW', 'HIGH'), help="Lower and upper limit on device ID in results") arg_parser.add_argument( "--timeout", type=int, metavar=('SECONDS'), help="Time, in seconds, to wait for responses. Default: %(default)s", default=5) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") args = arg_parser.parse_args() _log.debug("initialization") _log.debug(" - args: %r", args) keystore = KeyStore() agent = BACnetInteraction(args.proxy_id, address=get_address(), volttron_home=get_home(), publickey=keystore.public, secretkey=keystore.secret, enable_store=False) event = gevent.event.Event() gevent.spawn(agent.core.run, event) event.wait() kwargs = {'address': args.address} if args.range is not None: kwargs['low_device_id'] = int(args.range[0]) kwargs['high_device_id'] = int(args.range[1]) try: agent.send_iam(**kwargs) except errors.Unreachable: _log.error( "There is no BACnet proxy Agent running on the platform with the VIP IDENTITY {}" .format(args.proxy_id)) else: gevent.sleep(args.timeout)
def _start_rabbitmq_without_ssl(rmq_config, conf_file, env=None): """ Check if basic RabbitMQ configuration is available. Start RabbitMQ in non ssl mode so that we can login as guest to create volttron users, exchanges, and vhost. :return: """ if not rmq_config.volttron_home: rmq_config.volttron_home = get_home() rmq_home = rmq_config.rmq_home if not rmq_home: rmq_home = os.path.join(os.path.expanduser("~"), "rabbitmq_server/rabbitmq_server-3.7.7") if os.path.exists(rmq_home): os.environ['RABBITMQ_HOME'] = rmq_home else: print("\nERROR:\n" "Missing key 'rmq_home' in RabbitMQ config and RabbitMQ is " "not installed in default path: \n" "~/rabbitmq_server/rabbitmq_server-3.7.7 \n" "Please set the correct RabbitMQ installation path in " "rabbitmq_config.yml") exit(1) else: if not os.path.exists(rmq_home) or not os.path.exists(os.path.join( rmq_home, 'sbin/rabbitmq-server')): print("\nERROR:\n" "Invalid rmq-home value ({}). Please fix rmq-home " "in {} and rerun this script".format( rmq_home, rmq_config.volttron_rmq_config)) exit(1) else: os.environ['RABBITMQ_HOME'] = rmq_home # attempt to stop stop_rabbit(rmq_home, env, quite=True) if rmq_config.amqp_port != 5672 and rmq_config.mgmt_port != 15672: # If ports if non ssl ports are not default write a rabbitmq.conf before # restarting new_conf = """listeners.tcp.default = {} management.listener.port = {}""".format(rmq_config.amqp_port, rmq_config.mgmt_port) with open(conf_file, 'w+') as r_conf: r_conf.write(new_conf) # Need to write env file even when starting without ssl mode since env file will provide the right node name, # tcp port and conf file to use. This is essential for tests as we don't use default port, paths or node name. # TODO - we should probably not use default node name even for non test use case to avoid node name class when # you have more than one instance of RMQ on the same machine write_env_file(rmq_config, conf_file, env) # Start RabbitMQ server _log.info("Starting RabbitMQ server") start_rabbit(rmq_config.rmq_home, env=env)
def __init__(self, rmq_mgmt, ssl_public_key): self._rmq_mgmt = rmq_mgmt self._ssl_public_key = ssl_public_key self._userdict = None self.reload_userdict() self._observer = Observer() self._observer.schedule( FileReloader("web-users.json", self.reload_userdict), get_home()) self._observer.start() self._certs = Certs()
def brute_force_platform_shutdown(self): for agent_uuid in self.agents.iterkeys(): _log.debug("Stopping agent UUID {}".format(agent_uuid)) self.stop_agent(agent_uuid) # kill the platform pid = None pid_file = "{vhome}/VOLTTRON_PID".format(vhome=get_home()) with open(pid_file) as f: pid = int(f.read()) if pid: os.kill(pid, signal.SIGINT) os.remove(pid_file)
def load_platform_config(vhome=None): """Loads the platform config file if the path exists.""" config_opts = {} if not vhome: vhome = get_home() path = os.path.join(vhome, 'config') if os.path.exists(path): parser = ConfigParser() parser.read(path) options = parser.options('volttron') for option in options: config_opts[option] = parser.get('volttron', option) return config_opts
def __init__(self, config_path, **kwargs): super(VolttronCentralPlatform, self).__init__(**kwargs) self._local_instance_name = None self._local_instance_uuid = None self._local_serverkey = None self._local_bind_web_address = None self._external_addresses = None self._volttron_central_reconnect_interval = 5 self._volttron_central_http_address = None self._volttron_central_tcp_address = None self._volttron_central_ipc_address = None self._volttron_central_serverkey = None self._volttron_central_publickey = None self._volttron_central_connection = None self._control_connection = None settings_path = os.path.join(get_home(), "data/vcp.settings") self._settings = load_create_store(settings_path) config = utils.load_config(config_path) self.reconfigure(**config) # Flag set after the platform has a guaranteed connection to the router. self._agent_started = False self._is_registering = False self._is_registered = False self._was_unmanaged = False self._devices = {} self._device_topic_hashes = {} self._topic_replace_map = {} # Default publish interval to 20 seconds. self._stats_publish_interval = 20 self._stats_publisher = None if config.get('stats-publish-interval') is None: config['stats-publish-interval'] = self._stats_publish_interval if self._settings.get('instance-uuid'): config['instance-uuid'] = self._settings.get('instance-uuid') if config.get('volttron-central-reconnect-interval') is None: config['volttron-central-reconnect-interval'] = \ self._volttron_central_reconnect_interval self._topic_replace_list = config.get("topic_replace_list", []) self.reconfigure(**config) # This is scheduled after first call to the reconnect function self._scheduled_connection_event = None
def vip_main(agent_class, identity=None, version='0.1', **kwargs): """Default main entry point implementation for VIP agents.""" try: # If stdout is a pipe, re-open it line buffered if isapipe(sys.stdout): # Hold a reference to the previous file object so it doesn't # get garbage collected and close the underlying descriptor. stdout = sys.stdout sys.stdout = os.fdopen(stdout.fileno(), 'w', 1) # Quiet printing of KeyboardInterrupt by greenlets Hub = gevent.hub.Hub Hub.NOT_ERROR = Hub.NOT_ERROR + (KeyboardInterrupt, ) config = os.environ.get('AGENT_CONFIG') identity = os.environ.get('AGENT_VIP_IDENTITY', identity) message_bus = os.environ.get('MESSAGEBUS', 'zmq') if identity is not None: if not is_valid_identity(identity): _log.warning('Deprecation warining') _log.warning( 'All characters in {identity} are not in the valid set.'. format(idenity=identity)) address = get_address() agent_uuid = os.environ.get('AGENT_UUID') volttron_home = get_home() from volttron.platform.certs import Certs certs = Certs() agent = agent_class(config_path=config, identity=identity, address=address, agent_uuid=agent_uuid, volttron_home=volttron_home, version=version, message_bus=message_bus, **kwargs) try: run = agent.run except AttributeError: run = agent.core.run task = gevent.spawn(run) try: task.join() finally: task.kill() except KeyboardInterrupt: pass
def __init__(self, certificate_dir=None): """Creates a Certs instance""" self.default_certs_dir = os.path.join(get_home(), 'certificates') self.root_ca_name = get_platform_instance_name() + '-root-ca' self.trusted_ca_name = get_platform_instance_name() + '-trusted-cas' self.default_root_ca_cn = '{} {}'.format(gethostname(), self.root_ca_name) if not certificate_dir: certificate_dir = self.default_certs_dir # If user provided explicit directory then it should exist if not os.path.exists(certificate_dir): if certificate_dir != self.default_certs_dir: raise ValueError('Invalid cert_dir {}'.format(self.cert_dir)) self.cert_dir = os.path.join(os.path.expanduser(certificate_dir), 'certs') self.private_dir = os.path.join(os.path.expanduser(certificate_dir), 'private') self.ca_db_dir = os.path.join(os.path.expanduser(certificate_dir), 'ca_db') self.csr_pending_dir = os.path.join(os.path.expanduser(certificate_dir), 'pending_csr') self.remote_cert_dir = os.path.join(os.path.expanduser(certificate_dir), 'remote_certs') self.certs_pending_dir = os.path.join(os.path.expanduser(certificate_dir), 'pending_certs') self.rejected_dir = os.path.join(os.path.expanduser(certificate_dir), 'rejected') required_paths = (self.cert_dir, self.private_dir, self.ca_db_dir, self.csr_pending_dir, self.remote_cert_dir, self.certs_pending_dir) try: dir_created = False for p in required_paths: if not os.path.exists(p): # explicitly provide rx to others since agent users should # have read access to these dirs os.makedirs(p) os.chmod(p, 0o755) dir_created = True else: # if one exists all of them should exist. break break if dir_created: os.chmod(os.path.expanduser(certificate_dir), 0o755) except Exception: raise RuntimeError("No permission to create certificates directory")
def get_remote_certs_dir(self): if not self.remote_certs_dir: install_dir = os.path.join(get_home(), "agents", self._core().agent_uuid) files = os.listdir(install_dir) for f in files: agent_dir = os.path.join(install_dir, f) if os.path.isdir(agent_dir): break # found sub_dirs = os.listdir(agent_dir) for d in sub_dirs: d_path = os.path.join(agent_dir, d) if os.path.isdir(d_path) and d.endswith("agent-data"): self.remote_certs_dir = d_path return self.remote_certs_dir
def main(): # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("--address", help="Target only device(s) at <address> for request") arg_parser.add_argument("--range", type=int, nargs=2, metavar=('LOW', 'HIGH'), help="Lower and upper limit on device ID in results") arg_parser.add_argument("--timeout", type=int, metavar=('SECONDS'), help="Time, in seconds, to wait for responses. Default: %(default)s", default=5) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") args = arg_parser.parse_args() _log.debug("initialization") _log.debug(" - args: %r", args) keystore = KeyStore() agent = BACnetInteraction(args.proxy_id, address=get_address(), volttron_home=get_home(), publickey=keystore.public, secretkey=keystore.secret, enable_store=False) event = gevent.event.Event() gevent.spawn(agent.core.run, event) event.wait() kwargs = {'address': args.address} if args.range is not None: kwargs['low_device_id'] = int(args.range[0]) kwargs['high_device_id'] = int(args.range[1]) try: agent.send_iam(**kwargs) except errors.Unreachable: _log.error("There is no BACnet proxy Agent running on the platform with the VIP IDENTITY {}".format(args.proxy_id)) else: gevent.sleep(args.timeout)
def __init__(self, tls_private_key=None, web_secret_key=None): self._tls_private_key = tls_private_key self._web_secret_key = web_secret_key if self._tls_private_key is None and self._web_secret_key is None: raise ValueError("Must have either ssl_private_key or web_secret_key specified!") if self._tls_private_key is not None and self._web_secret_key is not None: raise ValueError("Must use either ssl_private_key or web_secret_key not both!") self._userdict = None self.reload_userdict() self._observer = Observer() self._observer.schedule( VolttronHomeFileReloader("web-users.json", self.reload_userdict), get_home() ) self._observer.start()
def vip_main(agent_class, identity=None, version='0.1', **kwargs): """Default main entry point implementation for VIP agents.""" try: # If stdout is a pipe, re-open it line buffered if isapipe(sys.stdout): # Hold a reference to the previous file object so it doesn't # get garbage collected and close the underlying descriptor. stdout = sys.stdout sys.stdout = os.fdopen(stdout.fileno(), 'w', 1) # Quiet printing of KeyboardInterrupt by greenlets Hub = gevent.hub.Hub Hub.NOT_ERROR = Hub.NOT_ERROR + (KeyboardInterrupt,) config = os.environ.get('AGENT_CONFIG') identity = os.environ.get('AGENT_VIP_IDENTITY', identity) if identity is not None: if not is_valid_identity(identity): _log.warn('Deprecation warining') _log.warn( 'All characters in {identity} are not in the valid set.' .format(idenity=identity)) address = get_address() agent_uuid = os.environ.get('AGENT_UUID') volttron_home = get_home() agent = agent_class(config_path=config, identity=identity, address=address, agent_uuid=agent_uuid, volttron_home=volttron_home, version=version, **kwargs) try: run = agent.run except AttributeError: run = agent.core.run task = gevent.spawn(run) try: task.join() finally: task.kill() except KeyboardInterrupt: pass
def vip_main(agent_class, identity=None, **kwargs): """Default main entry point implementation for VIP agents.""" try: # If stdout is a pipe, re-open it line buffered if isapipe(sys.stdout): # Hold a reference to the previous file object so it doesn't # get garbage collected and close the underlying descriptor. stdout = sys.stdout sys.stdout = os.fdopen(stdout.fileno(), 'w', 1) # Quiet printing of KeyboardInterrupt by greenlets Hub = gevent.hub.Hub Hub.NOT_ERROR = Hub.NOT_ERROR + (KeyboardInterrupt, ) config = os.environ.get('AGENT_CONFIG') identity = os.environ.get('AGENT_VIP_IDENTITY', identity) address = get_address() agent_uuid = os.environ.get('AGENT_UUID') volttron_home = get_home() agent = agent_class(config_path=config, identity=identity, address=address, agent_uuid=agent_uuid, volttron_home=volttron_home, **kwargs) try: run = agent.run except AttributeError: run = agent.core.run task = gevent.spawn(run) try: task.join() finally: task.kill() except KeyboardInterrupt: pass
def __init__(self, tls_private_key=None, tls_public_key=None, web_secret_key=None): self.refresh_token_timeout = 240 # minutes before token expires. TODO: Should this be a setting somewhere? self.access_token_timeout = 15 # minutes before token expires. TODO: Should this be a setting somewhere? self._tls_private_key = tls_private_key self._tls_public_key = tls_public_key self._web_secret_key = web_secret_key if self._tls_private_key is None and self._web_secret_key is None: raise ValueError( "Must have either ssl_private_key or web_secret_key specified!" ) if self._tls_private_key is not None and self._web_secret_key is not None: raise ValueError( "Must use either ssl_private_key or web_secret_key not both!") self._userdict = None self.reload_userdict() self._observer = Observer() self._observer.schedule( VolttronHomeFileReloader("web-users.json", self.reload_userdict), get_home()) self._observer.start()
def __init__(self, certificate_dir=None): """Creates a Certs instance""" self.default_certs_dir = os.path.join(get_home(), 'certificates') self.root_ca_name = get_platform_instance_name() + '-root-ca' self.trusted_ca_name = get_platform_instance_name() + '-trusted-cas' self.default_root_ca_cn = '{} {}'.format(gethostname(), self.root_ca_name) if not certificate_dir: certificate_dir = self.default_certs_dir # If user provided explicit directory then it should exist if not os.path.exists(certificate_dir): if certificate_dir != self.default_certs_dir: raise ValueError('Invalid cert_dir {}'.format(self.cert_dir)) self.cert_dir = os.path.join(os.path.expanduser(certificate_dir), 'certs') self.private_dir = os.path.join(os.path.expanduser(certificate_dir), 'private') self.ca_db_dir = os.path.join(os.path.expanduser(certificate_dir), 'ca_db') self.csr_pending_dir = os.path.join(os.path.expanduser(certificate_dir), 'pending_csr') self.remote_cert_dir = os.path.join(os.path.expanduser(certificate_dir), 'remote_certs') self.certs_pending_dir = os.path.join(os.path.expanduser(certificate_dir), 'pending_certs') self.rejected_dir = os.path.join(os.path.expanduser(certificate_dir), 'rejected') required_paths = (self.cert_dir, self.private_dir, self.ca_db_dir, self.csr_pending_dir, self.remote_cert_dir, self.certs_pending_dir) for p in required_paths: if not os.path.exists(p): os.makedirs(p, 0o755)
def main(): # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument( "--address", help="Target only device(s) at <address> for request") arg_parser.add_argument( "--range", type=int, nargs=2, metavar=('LOW', 'HIGH'), help="Lower and upper limit on device ID in results") arg_parser.add_argument( "--timeout", type=int, metavar=('SECONDS'), help="Time, in seconds, to wait for responses. Default: %(default)s", default=5) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") arg_parser.add_argument("--csv-out", dest="csv_out", help="Write results to the CSV file specified.") arg_parser.add_argument("--debug", action="store_true", help="Set the logger in debug mode") args = arg_parser.parse_args() core_logger = logging.getLogger("volttron.platform.vip.agent.core") core_logger.setLevel(logging.WARN) _log.setLevel(logging.WARN) if args.debug: _log.setLevel(logging.DEBUG) core_logger.setLevel(logging.DEBUG) _log.debug("initialization") _log.debug(" - args: %r", args) csv_writer = None if args.csv_out is not None: f = open(args.csv_out, "wb") field_names = [ "address", "device_id", "max_apdu_length", "segmentation_supported", "vendor_id" ] csv_writer = csv.DictWriter(f, field_names) csv_writer.writeheader() keystore = KeyStore() agent = BACnetInteraction(args.proxy_id, csv_writer=csv_writer, address=get_address(), volttron_home=get_home(), publickey=keystore.public, secretkey=keystore.secret, enable_store=False) event = gevent.event.Event() gevent.spawn(agent.core.run, event) event.wait() kwargs = {'address': args.address} if args.range is not None: kwargs['low_device_id'] = int(args.range[0]) kwargs['high_device_id'] = int(args.range[1]) try: agent.send_iam(**kwargs) except errors.Unreachable: _log.error( "There is no BACnet proxy Agent running on the platform with the VIP IDENTITY {}" .format(args.proxy_id)) else: gevent.sleep(args.timeout)
def launch_new_app(self, ui_app_name, ui_agent_id): self.curcon.execute( "SELECT app_name, executable FROM " + db_table_application_registered + " WHERE app_name=%s", (ui_app_name, )) # 1. launch app for an agent based on the exec file and agent_id if self.curcon.rowcount != 0: app_info = self.curcon.fetchone() _exec_name = str(app_info[1]) _exec = _exec_name + "-0.1-py2.7.egg --config \"%c\" --sub \"%s\" --pub \"%p\"" data = {"agent": {"exec": _exec}, "agent_id": ui_agent_id} PROJECT_DIR = settings.PROJECT_DIR env_path = settings.PROJECT_DIR + '/env/bin/' _launch_file = os.path.join( PROJECT_DIR, "Applications/launch/" + str(ui_app_name) + "_" + str(ui_agent_id)) if debug_agent: print(_launch_file) with open(_launch_file, 'w') as outfile: json.dump(data, outfile, indent=4, sort_keys=True) if debug_agent: print(os.path.basename(_launch_file)) os.system("volttron-ctl status > app_running_agent.txt") infile = open('app_running_agent.txt', 'r') installed = False for line in infile: # print(line, end='') #write to a next file name outfile match = re.search(ui_app_name + '_' + ui_agent_id, line) if match: # The app that ui requested has not been installed. print "APP: {}, APP has actually been installed. Just starting"\ .format(ui_app_name) installed = True if not installed: os.system( # ". env/bin/activate" env_path + "volttron-pkg configure " + platform.get_home() + "/packaged/" + ui_app_name + "-3.0-py2-none-any.whl " + _launch_file + ";" + \ env_path + "volttron-ctl install " + ui_app_name+"_"+ui_agent_id + "=" + platform.get_home() + "/packaged/" + ui_app_name + "-3.0-py2-none-any.whl;") os.system("volttron-ctl start --tag " + os.path.basename(_launch_file)) os.system("volttron-ctl status") print "AppLauncher has successfully launched APP: {} for Agent: {}"\ .format(ui_app_name, ui_agent_id) # send reply back to UI _topic_appLauncher_ui = '/appLauncher/ui/' + ui_app_name + '/' + ui_agent_id + '/' + 'launch/response' _headers = { headers_mod.FROM: app_name, headers_mod.CONTENT_TYPE: headers_mod.CONTENT_TYPE.JSON, } _message = "success" self.vip.pubsub.publish('pubsub', _topic_appLauncher_ui, _headers, _message) # self.app_number += 1 self.curcon.execute( "SELECT description FROM " + db_table_application_registered + " WHERE app_name=%s", (ui_app_name, )) if self.curcon.rowcount != 0: _app_description = str(self.curcon.fetchone()[0]) print "The description of APP: {} is {}".format( ui_app_name, _app_description) else: print "AppLauncher failed to get APP: {} description".format( ui_app_name) # 2. log app that has been launched to the database _launch_file_name = str(ui_app_name) + "_" + str(ui_agent_id) _start_time = str(datetime.datetime.now()) _app_status = "running" self.curcon.execute("SELECT id FROM " + db_table_application_running) if self.curcon.rowcount != 0: # print 'cur.fetchall()' + str(max(cur.fetchall())[0]) app_no = max(self.curcon.fetchall())[0] + 1 else: #default no_app app_no = 1 self.curcon.execute( "INSERT INTO application_running(id, app_agent_id, start_time, status, app_type, app_data) " "VALUES(%s,%s,%s,%s,%s,%s)", (app_no, _launch_file_name, _start_time, _app_status, app_info[0], '{}')) self.curcon.commit() print "AppLauncher finished update table applications_running of APP: {}".format( ui_app_name) print "with launch_file: {}, at timestamp {}".format( _launch_file, _start_time) else: print "AppLauncher failed to launch APP: {} for Agent: {}".format( ui_app_name, ui_agent_id)
if k < keylen - 1: keyline += "%s," % keys[k] valueline += "%s," % output_dict[keys[k]] else: keyline += "%s" % keys[k] valueline += "%s" % output_dict[keys[k]] sys.stdout.write("%s\n%s\n" % (keyline, valueline)) if __name__ == '__main__': parser = argparse.ArgumentParser(version=__version__) parser.add_argument("-a", "--vip-address", default=get_address(), help="vip-address to connect to.") parser.add_argument("-vh", "--volttron-home", default=get_home(), help="local volttron-home for the instance.") parser.add_argument("-vr", "--volttron-root", default=get_volttron_root(), help="location of the volttron root on the filesystem.") parser.add_argument("-s", "--agent-source", required=True, help="source directory of the agent which is to be installed.") parser.add_argument("-i", "--vip-identity", default=None, help="identity of the agent to be installed (unique per instance)") parser.add_argument("-c", "--config", default=None, type=file, help="agent configuration file that will be packaged with the agent.") parser.add_argument("-wh", "--wheelhouse", default=None, help="location of agents after they have been built") parser.add_argument("-t", "--tag", default=None, help="a tag is a means of identifying an agent.") parser.add_argument("-f", "--force", action='store_true', help="agents are uninstalled by tag so force allows multiple agents to be removed at one go.")
if not inenv: mypath = os.path.dirname(__file__) correct_python = sys.executable if not os.path.exists(correct_python): log.error("Invalid location for the script {}".format(correct_python)) sys.exit(-10) # Call this script in a subprocess with the correct python interpreter. cmds = [correct_python, __file__] cmds.extend(sys.argv[1:]) process = subprocess.Popen(cmds, env=os.environ) process.wait() sys.exit(process.returncode) from volttron.platform import get_home, is_instance_running __version__ = '0.2' if __name__ == '__main__': parser = argparse.ArgumentParser(version=__version__) parser.add_argument("-vh", "--volttron-home", default=get_home()) args = parser.parse_args() result = is_instance_running(args.volttron_home) if result: result = 1 else: result = 0 sys.stdout.write("{}\n".format(int(result)))
def launch_existing_app(self, ui_app_name, ui_agent_id): self.curcon.execute( "SELECT executable FROM " + db_table_application_registered + " WHERE app_name=%s", (ui_app_name, )) # 1. launch app for an agent based on the exec file and agent_id if self.curcon.rowcount != 0: _exec_name = str(self.curcon.fetchone()[0]) _exec = _exec_name + "-3.0-py2.7.egg --config \"%c\" --sub \"%s\" --pub \"%p\"" data = { "agent": { "exec": _exec }, "agent_id": ui_app_name + '_' + ui_agent_id } PROJECT_DIR = settings.PROJECT_DIR _launch_file = os.path.join( PROJECT_DIR, "Applications/launch/" + str(ui_app_name) + "_" + str(ui_agent_id)) if debug_agent: print(_launch_file) with open(_launch_file, 'w') as outfile: json.dump(data, outfile, indent=4, sort_keys=True) if debug_agent: print(os.path.basename(_launch_file)) os.system("volttron-ctl status > app_running_agent.txt") infile = open('app_running_agent.txt', 'r') installed = False for line in infile: # print(line, end='') #write to a next file name outfile match = re.search(ui_app_name + '_' + ui_agent_id, line) if match: # The app that ui requested has not been installed. print "APP: {}, APP has actually been installed. Just starting".format( ui_app_name) installed = True break if not installed: env_path = settings.PROJECT_DIR + '/env/bin/' os.system( # ". env/bin/activate" env_path + "volttron-pkg configure " + platform.get_home() + "/packaged/" + ui_app_name + "-3.0-py2-none-any.whl " + _launch_file + ";" + \ env_path + "volttron-ctl install " + ui_app_name+"_"+ui_agent_id + "=" + platform.get_home() + "/packaged/" + ui_app_name + "-3.0-py2-none-any.whl;") os.system("volttron-ctl start --tag " + os.path.basename(_launch_file)) os.system("volttron-ctl status") print "AppLauncher has successfully launched APP: {} for Agent: {}"\ .format(ui_app_name, ui_agent_id) self.curcon.execute( "UPDATE application_running SET status=%s WHERE app_agent_id=%s", ( "running", ui_app_name + "_" + ui_agent_id, )) self.curcon.commit() # send reply back to UI _topic_appLauncher_ui = '/appLauncher/ui/' + ui_app_name + '/' + ui_agent_id + '/' + 'launch/response' _headers = { headers_mod.FROM: app_name, headers_mod.CONTENT_TYPE: headers_mod.CONTENT_TYPE.JSON, } _message = "success" self.vip.pubsub.publish('pubsub', _topic_appLauncher_ui, _headers, _message)
def get_default_path(): return os.path.join(get_home(), 'keystore')
def main(): global agent global config_writer # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("device_id", type=int, help="Device ID of the target device") arg_parser.add_argument( "--address", help= "Address of target device, may be needed to help route initial request to device." ) arg_parser.add_argument("--registry-out-file", type=argparse.FileType('w'), help="Output registry to CSV file", default=sys.stdout) arg_parser.add_argument("--driver-out-file", type=argparse.FileType('w'), help="Output driver configuration to JSON file.", default=sys.stdout) arg_parser.add_argument( "--max-range-report", nargs='?', type=float, help= 'Affects how very large numbers are reported in the "Unit Details" column of the ' 'output. Does not affect driver behavior.', default=1.0e+20) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") args = arg_parser.parse_args() _log.debug("initialization") _log.debug(" - args: %r", args) key_store = KeyStore() config_writer = DictWriter( args.registry_out_file, ('Reference Point Name', 'Volttron Point Name', 'Units', 'Unit Details', 'BACnet Object Type', 'Property', 'Writable', 'Index', 'Write Priority', 'Notes')) config_writer.writeheader() agent = build_agent(address=get_address(), volttron_home=get_home(), publickey=key_store.public, secretkey=key_store.secret, enable_store=False) bn = BACnetReader(agent.vip, args.proxy_id, bacnet_response) async_result = AsyncResult() try: bn.get_iam(args.device_id, async_result.set, args.address) except errors.Unreachable as ure: _log.error(ure) _log.error( "No BACnet proxy Agent running on the platform with the VIP IDENTITY {}" .format(args.proxy_id)) sys.exit(1) try: results = async_result.get(timeout=5.0) except gevent.Timeout: _log.error("No response from device id {}".format(args.device_id)) sys.exit(1) if args.address and args.address != results["address"]: msg = "Inconsistent results from passed address ({}) and device address ({}) using results.".format( args.address, results["address"]) _log.warning(msg) args.address = results["address"] elif results["address"]: args.address = results["address"] bn.read_device_properties(target_address=args.address, device_id=args.device_id) agent.core.stop()
def setup_rabbitmq_volttron(setup_type, verbose=False, prompt=False, instance_name=None, rmq_conf_file=None, env=None): """ Setup VOLTTRON instance to run with RabbitMQ message bus. :param setup_type: single - Setup to run as single instance federation - Setup to connect multiple VOLTTRON instances as a federation shovel - Setup shovels to forward local messages to remote instances :param verbose :param prompt :raises RabbitMQSetupAlreadyError """ if not instance_name: instance_name = get_platform_instance_name(prompt=True) # Store config this is checked at startup store_message_bus_config(message_bus='rmq', instance_name=instance_name) rmq_config = RMQConfig() if verbose: _log.setLevel(logging.DEBUG) _log.debug("verbose set to True") _log.debug(get_home()) logging.getLogger("requests.packages.urllib3.connectionpool" "").setLevel(logging.DEBUG) else: _log.setLevel(logging.INFO) logging.getLogger("requests.packages.urllib3.connectionpool" "").setLevel(logging.WARN) if prompt: # ignore any existing rabbitmq_config.yml in vhome. Prompt user and # generate a new rabbitmq_config.yml _create_rabbitmq_config(rmq_config, setup_type) # Load either the newly created config or config passed try: rmq_config.load_rmq_config() except (yaml.parser.ParserError, yaml.scanner.ScannerError, yaml.YAMLError) as exc: _log.error("Error: YAML file cannot parsed properly. Check the contents of the file") return exc except IOError as exc: _log.error("Error opening {}. Please create a rabbitmq_config.yml " "file in your volttron home. If you want to point to a " "volttron home other than {} please set it as the " "environment variable VOLTTRON_HOME".format( rmq_config.volttron_rmq_config, rmq_config.volttron_home)) _log.error("\nFor single setup, configuration file must at least " "contain host and ssl certificate details. For federation " "and shovel setup, config should contain details about the " "volttron instance with which communication needs " "to be established. Please refer to example config file " "at examples/configurations/rabbitmq/rabbitmq_config.yml") raise if not rmq_conf_file: rmq_conf_file = os.path.join(rmq_config.rmq_home, "etc/rabbitmq/rabbitmq.conf") invalid = True if setup_type in ["all", "single"]: invalid = False # Verify that the rmq_conf_file if exists is removed before continuing. message = f"A rabbitmq conf file {rmq_conf_file} already exists.\n" \ "In order for setup to proceed it must be removed.\n" if os.path.exists(rmq_conf_file): print(message) while os.path.exists(rmq_conf_file): value = prompt_response(f"Remove {rmq_conf_file}? ", y_or_n) if value in y: os.remove(rmq_conf_file) _start_rabbitmq_without_ssl(rmq_config, rmq_conf_file, env=env) _log.debug("Creating rabbitmq virtual hosts and required users for " "volttron") # Create local RabbitMQ setup - vhost, exchange etc. # should be called after _start_rabbitmq_without_ssl rmq_mgmt = RabbitMQMgmt() success = rmq_mgmt.init_rabbitmq_setup() if success and rmq_config.is_ssl: _setup_for_ssl_auth(rmq_config, rmq_conf_file, env=env) # Create utility scripts script_path = os.path.dirname(os.path.realpath(__file__)) src_home = os.path.dirname(os.path.dirname(script_path)) start_script = os.path.join(src_home, 'start-rabbitmq') with open(start_script, 'w+') as f: f.write(os.path.join(rmq_config.rmq_home, 'sbin', 'rabbitmq-server') + ' -detached') f.write(os.linesep) f.write("sleep 5") # give a few seconds for all plugins to be ready os.chmod(start_script, 0o755) stop_script = os.path.join(src_home, 'stop-rabbitmq') with open(stop_script, 'w+') as f: f.write(os.path.join(rmq_config.rmq_home, 'sbin', 'rabbitmqctl') + ' stop') os.chmod(stop_script, 0o755) # symlink to rmq log log_name = os.path.join(src_home, 'rabbitmq.log') if os.path.lexists(log_name): os.unlink(log_name) os.symlink(os.path.join(rmq_config.rmq_home, 'var/log/rabbitmq', rmq_config.node_name + "@" + rmq_config.hostname.split('.')[0] + ".log"), log_name) if setup_type in ["all", "federation"]: # Create a multi-platform federation setup invalid = False _create_federation_setup(rmq_config.admin_user, rmq_config.admin_pwd, rmq_config.is_ssl, rmq_config.virtual_host, rmq_config.volttron_home) if setup_type in ["all", "shovel"]: # Create shovel setup invalid = False if rmq_config.is_ssl: port = rmq_config.amqp_port_ssl else: port = rmq_config.amqp_port _create_shovel_setup(rmq_config.instance_name, rmq_config.hostname, port, rmq_config.virtual_host, rmq_config.volttron_home, rmq_config.is_ssl) if invalid: _log.error("Unknown option. Exiting....")
def _create_rabbitmq_config(rmq_config, setup_type): """ Prompt user for required details and create a rabbitmq_config.yml file in volttron home :param setup_type: type of rmq setup - single, federation, shovel or all """ if setup_type == 'single' or setup_type == 'all': if os.path.exists(rmq_config.volttron_rmq_config): prompt = "rabbitmq_config.yml exists in {} Do you wish to " \ "use this file to configure the instance".format( get_home()) prompt = prompt_response(prompt, valid_answers=y_or_n, default='Y') if prompt in y: return else: _log.info("New input data will be used to overwrite existing " "{}".format(rmq_config.volttron_rmq_config)) # TODO: ideally we can load existing file and set values in it # default and the compare what changed. If rmq-home changed # and existing config those should get cleared. If cert details # get changed - overwrite ca, server, admin cert and delete all # other certs. rmq_config.rmq_home = _prompt_rmq_home(rmq_config.rabbitmq_server) prompt = 'Fully qualified domain name of the system:' new_host = prompt_response(prompt, default=getfqdn()) rmq_config.hostname = new_host rmq_config.is_ssl = True if rmq_config.is_ssl: prompt = "Would you like to create a new self signed root CA" \ "certificate for this instance:" prompt = prompt_response(prompt, valid_answers=y_or_n, default='Y') if prompt in y: cert_data = {} print( "\nPlease enter the following details for root CA certificate") prompt = '\tCountry:' cert_data['country'] = prompt_response(prompt, default='US') prompt = '\tState:' cert_data['state'] = prompt_response(prompt, mandatory=True) prompt = '\tLocation:' cert_data['location'] = prompt_response(prompt, mandatory=True) prompt = '\tOrganization:' cert_data['organization'] = prompt_response(prompt, mandatory=True) prompt = '\tOrganization Unit:' cert_data['organization-unit'] = prompt_response(prompt, mandatory=True) cert_data['common-name'] = rmq_config.instance_name + '-root-ca' rmq_config.certificate_data = cert_data else: error = True while error: while True: prompt = 'Enter the root CA certificate public key file:' root_public = prompt_response(prompt, mandatory=True) if is_file_readable(root_public): break while True: prompt =\ 'Enter the root CA certificate private key file:' root_key = prompt_response(prompt, mandatory=True) if is_file_readable(root_key): break if certs.Certs.validate_key_pair(root_public, root_key): error = False cert_data = { 'ca-public-key': root_public, 'ca-private-key': root_key } rmq_config.certificate_data = cert_data else: print("Error: Given public key and private key do not " "match or is invalid. public and private key " "files should be PEM encoded and private key " "should use RSA encryption") prompt = "Do you want to use default values for RabbitMQ home, " \ "ports, and virtual host:" prompt = prompt_response(prompt, valid_answers=y_or_n, default='Y') if prompt in y: rmq_config.amqp_port = '5672' rmq_config.mgmt_port = '15672' rmq_config.amqp_port_ssl = '5671' rmq_config.mgmt_port_ssl = '15671' rmq_config.virtual_host = 'volttron' else: rmq_config.virtual_host = _prompt_vhost(rmq_config.config_opts) prompt = 'AMQP port for RabbitMQ:' rmq_config.amqp_port = prompt_port(5672, prompt) prompt = 'http port for the RabbitMQ management plugin:' rmq_config.mgmt_port = prompt_port(15672, prompt) if rmq_config.is_ssl: prompt = 'AMQPS (SSL) port RabbitMQ address:' rmq_config.amqp_port_ssl = prompt_port(5671, prompt) prompt = 'https port for the RabbitMQ management plugin:' rmq_config.mgmt_port_ssl = prompt_port(15671, prompt) # Write the new config options back to config file rmq_config.write_rmq_config() if setup_type in ['federation', 'all']: # if option was all then config_opts would be not null # if this was called with just setup_type = federation, load existing # config so that we don't overwrite existing federation configs prompt_upstream_servers(rmq_config.volttron_home) if setup_type in ['shovel', 'all']: # if option was all then config_opts would be not null # if this was called with just setup_type = shovel, load existing # config so that we don't overwrite existing list prompt_shovels(rmq_config.volttron_home)
def main(): # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("--address", help="Target only device(s) at <address> for request") arg_parser.add_argument("--range", type=int, nargs=2, metavar=('LOW', 'HIGH'), help="Lower and upper limit on device ID in results") arg_parser.add_argument("--timeout", type=int, metavar=('SECONDS'), help="Time, in seconds, to wait for responses. Default: %(default)s", default=5) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") arg_parser.add_argument("--csv-out", dest="csv_out", help="Write results to the CSV file specified.") arg_parser.add_argument("--debug", action="store_true", help="Set the logger in debug mode") args = arg_parser.parse_args() core_logger = logging.getLogger("volttron.platform.vip.agent.core") core_logger.setLevel(logging.WARN) _log.setLevel(logging.WARN) if args.debug: _log.setLevel(logging.DEBUG) core_logger.setLevel(logging.DEBUG) _log.debug("initialization") _log.debug(" - args: %r", args) csv_writer = None if args.csv_out is not None: f = open(args.csv_out, "wb") field_names = ["address", "device_id", "max_apdu_length", "segmentation_supported", "vendor_id"] csv_writer = csv.DictWriter(f, field_names) csv_writer.writeheader() keystore = KeyStore() agent = BACnetInteraction(args.proxy_id, csv_writer=csv_writer, address=get_address(), volttron_home=get_home(), publickey=keystore.public, secretkey=keystore.secret, enable_store=False) event = gevent.event.Event() gevent.spawn(agent.core.run, event) event.wait() kwargs = {'address': args.address} if args.range is not None: kwargs['low_device_id'] = int(args.range[0]) kwargs['high_device_id'] = int(args.range[1]) try: agent.send_iam(**kwargs) except errors.Unreachable: _log.error("There is no BACnet proxy Agent running on the platform with the VIP IDENTITY {}".format(args.proxy_id)) else: gevent.sleep(args.timeout)
def __init__(self, filename=None): if filename is None: filename = os.path.join(get_home(), 'known_hosts') super(KnownHostsStore, self).__init__(filename)
def main(): global agent global config_writer # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("device_id", type=int, help="Device ID of the target device" ) arg_parser.add_argument("--address", help="Address of target device, may be needed to help route initial request to device." ) arg_parser.add_argument("--registry-out-file", type=argparse.FileType('wb'), help="Output registry to CSV file", default=sys.stdout ) arg_parser.add_argument("--driver-out-file", type=argparse.FileType('wb'), help="Output driver configuration to JSON file.", default=sys.stdout) arg_parser.add_argument("--max-range-report", nargs='?', type=float, help='Affects how very large numbers are reported in the "Unit Details" column of the output. ' 'Does not affect driver behavior.', default=1.0e+20 ) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") args = arg_parser.parse_args() _log.debug("initialization") _log.debug(" - args: %r", args) key_store = KeyStore() config_writer = DictWriter(args.registry_out_file, ('Reference Point Name', 'Volttron Point Name', 'Units', 'Unit Details', 'BACnet Object Type', 'Property', 'Writable', 'Index', 'Write Priority', 'Notes')) config_writer.writeheader() agent = build_agent(address=get_address(), volttron_home=get_home(), publickey=key_store.public, secretkey=key_store.secret, enable_store=False) bn = BACnetReader(agent.vip, args.proxy_id, bacnet_response) async_result = AsyncResult() try: bn.get_iam(args.device_id, async_result.set, args.address) except errors.Unreachable: msg = "No BACnet proxy Agent running on the platform with the " \ "VIP IDENTITY {}".format(args.proxy_id) sys.exit(1) try: results = async_result.get(timeout=5.0) except gevent.Timeout: _log.error("No response from device id {}".format(args.device_id)) sys.exit(1) if args.address and args.address != results["address"]: msg = "Inconsistent results from passed address " \ "({}) and device address ({}) using results.".format( args.address, results["address"]) _log.warning(msg) args.address = results["address"] elif results["address"]: args.address = results["address"] bn.read_device_properties(target_address=args.address, device_id=args.device_id) agent.core.stop()
def main(): global agent # parse the command line arguments arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("device_id", type=int, help="Device ID of the target device" ) arg_parser.add_argument("--address", help="Address of target device, may be needed to help route initial request to device." ) arg_parser.add_argument("--registry-out-file", type=argparse.FileType('wb'), help="Output registry to CSV file", default=sys.stdout ) arg_parser.add_argument("--driver-out-file", type=argparse.FileType('wb'), help="Output driver configuration to JSON file.", default=sys.stdout) arg_parser.add_argument("--max-range-report", nargs='?', type=float, help='Affects how very large numbers are reported in the "Unit Details" column of the output. ' 'Does not affect driver behavior.', default=1.0e+20 ) arg_parser.add_argument("--proxy-id", help="VIP IDENTITY of the BACnet proxy agent.", default="platform.bacnet_proxy") args = arg_parser.parse_args() _log.debug("initialization") _log.debug(" - args: %r", args) key_store = KeyStore() agent = BACnetInteraction(args.proxy_id, address=get_address(), volttron_home=get_home(), publickey=key_store.public, secretkey=key_store.secret, enable_store=False) event = gevent.event.Event() gevent.spawn(agent.core.run, event) event.wait() async_result = AsyncResult() try: agent.get_iam(args.device_id, async_result.set, args.address) except errors.Unreachable: _log.error("There is no BACnet proxy Agent running on the platform with the VIP IDENTITY {}".format(args.proxy_id)) sys.exit(1) try: results = async_result.get(timeout=5.0) except gevent.Timeout: _log.error("No response from device id {}".format(args.device_id)) sys.exit(1) target_address = results["address"] device_id = results["device_id"] config_file_name = basename(args.registry_out_file.name) config = { "driver_config": {"device_address": str(target_address), "device_id": device_id}, "driver_type": "bacnet", "registry_config": "config://registry_configs/{}".format(config_file_name) } json.dump(config, args.driver_out_file, indent=4) _log.debug('pduSource = ' + target_address) _log.debug('iAmDeviceIdentifier = ' + str(device_id)) _log.debug('maxAPDULengthAccepted = ' + str(results["max_apdu_length"])) _log.debug('segmentationSupported = ' + results["segmentation_supported"]) _log.debug('vendorID = ' + str(results["vendor_id"])) try: device_name = read_prop(target_address, "device", device_id, "objectName") _log.debug('device_name = ' + str(device_name)) except TypeError: _log.debug('device missing objectName') try: device_description = read_prop(target_address, "device", device_id, "description") _log.debug('description = ' + str(device_description)) except TypeError: _log.debug('device missing description') config_writer = DictWriter(args.registry_out_file, ('Reference Point Name', 'Volttron Point Name', 'Units', 'Unit Details', 'BACnet Object Type', 'Property', 'Writable', 'Index', 'Write Priority', 'Notes')) config_writer.writeheader() try: object_count = read_prop(target_address, "device", device_id, "objectList", index=0) list_property = "objectList" except TypeError: object_count = read_prop(target_address, "device", device_id, "structuredObjectList", index=0) list_property = "structuredObjectList" _log.debug('object_count = ' + str(object_count)) for object_index in xrange(1,object_count+1): _log.debug('object_device_index = ' + repr(object_index)) bac_object = read_prop(target_address, "device", device_id, list_property, index=object_index) obj_type, index = bac_object process_object(target_address, obj_type, index, args.max_range_report, config_writer)
def __init__(self, filename=None): if filename is None: filename = os.path.join(get_home(), 'keystore') super(KeyStore, self).__init__(filename) if not self.isvalid(): self.generate()