예제 #1
0
class MattermostNotificationService(Service):

    __tablename__ = "mattermost_notification_service"
    pretty_name = "Mattermost Notification"
    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    channel = Column(SmallString)
    body = Column(LargeString, default="")

    __mapper_args__ = {
        "polymorphic_identity": "mattermost_notification_service"
    }

    def job(self, run, payload, device=None):
        channel = (run.sub(run.channel, locals())
                   or app.settings["mattermost"]["channel"])
        run.log("info", f"Sending MATTERMOST notification on {channel}",
                device)
        result = post(
            app.settings["mattermost"]["url"],
            verify=app.settings["mattermost"]["verify_certificate"],
            data=dumps({
                "channel": channel,
                "text": run.sub(run.body, locals())
            }),
        )
        return {"success": True, "result": str(result)}
예제 #2
0
class MattermostNotificationService(Service):

    __tablename__ = "MattermostNotificationService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = Column(Boolean, default=False)
    channel = Column(SmallString)
    body = Column(LargeString, default="")

    __mapper_args__ = {"polymorphic_identity": "MattermostNotificationService"}

    def job(self,
            run: "Run",
            payload: dict,
            device: Optional[Device] = None) -> dict:
        channel = run.sub(run.channel, locals()) or app.mattermost_channel
        run.log("info", f"Sending Mattermost notification on {channel}")
        result = post(
            app.mattermost_url,
            verify=app.mattermost_verify_certificate,
            data=dumps({
                "channel": channel,
                "text": run.sub(run.body, locals())
            }),
        )
        return {"success": True, "result": str(result)}
예제 #3
0
class Result(AbstractBase):

    __tablename__ = type = "Result"
    private = True
    id = Column(Integer, primary_key=True)
    success = Column(Boolean, default=False)
    result = Column(MutableDict)
    run_id = Column(Integer, ForeignKey("Run.id"))
    run = relationship("Run",
                       back_populates="results",
                       foreign_keys="Result.run_id")
    device_id = Column(Integer, ForeignKey("Device.id"))
    device = relationship("Device",
                          back_populates="results",
                          foreign_keys="Result.device_id")
    device_name = association_proxy("device", "name")

    def __getitem__(self, key: Any) -> Any:
        return self.result[key]

    def __init__(self, **kwargs: Any) -> None:
        self.success = kwargs["result"]["success"]
        super().__init__(**kwargs)

    def __repr__(self) -> str:
        return f"{self.run} {self.device_name}"
예제 #4
0
class Syslog(Baselog):

    __tablename__ = "syslog"
    __mapper_args__ = {"polymorphic_identity": "syslog"}
    parent_type = "baselog"
    id = Column(Integer, ForeignKey("baselog.id"), primary_key=True)
    source = Column(LargeString, default="")
예제 #5
0
class NapalmTracerouteService(ConnectionService):

    __tablename__ = "napalm_traceroute_service"
    pretty_name = "NAPALM Traceroute"

    id = Column(Integer, ForeignKey("connection_service.id"), primary_key=True)
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    timeout = Column(Integer, default=60)
    optional_args = Column(MutableDict)
    destination_ip = Column(SmallString)
    source_ip = Column(SmallString)
    timeout = Column(Integer, default=0)
    ttl = Column(Integer, default=0)
    vrf = Column(SmallString)

    __mapper_args__ = {"polymorphic_identity": "napalm_traceroute_service"}

    def job(self, run, payload, device):
        napalm_connection = run.napalm_connection(device)
        destination = run.sub(run.destination_ip, locals())
        source = run.sub(run.source_ip, locals())
        run.log("info", f"NAPALM TRACEROUTE : {source} -> {destination}",
                device)
        traceroute = napalm_connection.traceroute(
            destination=destination,
            source=run.source,
            vrf=run.vrf,
            ttl=run.ttl or 255,
            timeout=run.timeout or 2,
        )
        return {"success": "success" in traceroute, "result": traceroute}
예제 #6
0
class Link(Object):

    __tablename__ = "link"
    __mapper_args__ = {"polymorphic_identity": "link"}
    class_type = "link"
    parent_type = "object"
    id = Column(Integer, ForeignKey("object.id"), primary_key=True)
    name = Column(SmallString)
    color = Column(SmallString, default="#000000")
    source_id = Column(Integer, ForeignKey("device.id"))
    destination_id = Column(Integer, ForeignKey("device.id"))
    source = relationship(
        Device,
        primaryjoin=source_id == Device.id,
        backref=backref("source", cascade="all, delete-orphan"),
    )
    source_name = association_proxy("source", "name")
    destination = relationship(
        Device,
        primaryjoin=destination_id == Device.id,
        backref=backref("destination", cascade="all, delete-orphan"),
    )
    destination_name = association_proxy("destination", "name")
    pools = relationship("Pool",
                         secondary=pool_link_table,
                         back_populates="links")
    __table_args__ = (UniqueConstraint(name, source_id, destination_id), )

    def __init__(self, **kwargs):
        self.update(**kwargs)

    @property
    def view_properties(self):
        node_properties = ("id", "longitude", "latitude")
        return {
            **{
                property: getattr(self, property)
                for property in ("id", "type", "name", "color")
            },
            **{
                f"source_{property}": getattr(self.source, property)
                for property in node_properties
            },
            **{
                f"destination_{property}": getattr(self.destination, property)
                for property in node_properties
            },
        }

    def update(self, **kwargs):
        if "source_name" in kwargs:
            kwargs["source"] = fetch("device",
                                     name=kwargs.pop("source_name")).id
            kwargs["destination"] = fetch(
                "device", name=kwargs.pop("destination_name")).id
        kwargs.update({
            "source_id": kwargs["source"],
            "destination_id": kwargs["destination"]
        })
        super().update(**kwargs)
예제 #7
0
class Pool(AbstractPool):

    __tablename__ = "pool"
    parent_type = "abstract_pool"
    id = Column(Integer, ForeignKey("abstract_pool.id"), primary_key=True)
    name = Column(SmallString, unique=True)
    last_modified = Column(SmallString, info={"dont_track_changes": True})
    description = Column(SmallString)
    operator = Column(SmallString, default="all")
    devices = relationship("Device",
                           secondary=pool_device_table,
                           back_populates="pools")
    device_number = Column(Integer, default=0)
    links = relationship("Link",
                         secondary=pool_link_table,
                         back_populates="pools")
    link_number = Column(Integer, default=0)
    latitude = Column(SmallString, default="0.0")
    longitude = Column(SmallString, default="0.0")
    services = relationship("Service",
                            secondary=service_pool_table,
                            back_populates="pools")
    runs = relationship("Run",
                        secondary=run_pool_table,
                        back_populates="pools")
    tasks = relationship("Task",
                         secondary=task_pool_table,
                         back_populates="pools")
    never_update = Column(Boolean, default=False)

    def update(self, **kwargs):
        super().update(**kwargs)
        self.compute_pool()

    def property_match(self, obj, property):
        pool_value = getattr(self, f"{obj.class_type}_{property}")
        object_value = str(getattr(obj, property))
        match = getattr(self, f"{obj.class_type}_{property}_match")
        if not pool_value:
            return True
        elif match == "inclusion":
            return pool_value in object_value
        elif match == "equality":
            return pool_value == object_value
        else:
            return bool(search(pool_value, object_value))

    def object_match(self, obj):
        operator = all if self.operator == "all" else any
        return operator(
            self.property_match(obj, property)
            for property in properties["filtering"][obj.class_type])

    def compute_pool(self):
        if self.never_update:
            return
        self.devices = list(filter(self.object_match, fetch_all("device")))
        self.device_number = len(self.devices)
        self.links = list(filter(self.object_match, fetch_all("link")))
        self.link_number = len(self.links)
예제 #8
0
class PayloadValidationService(Service):

    __tablename__ = "PayloadValidationService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = Column(Boolean, default=False)
    query = Column(SmallString)
    conversion_method = Column(SmallString, default="none")
    validation_method = Column(SmallString, default="text")
    content_match = Column(LargeString, default="")
    content_match_regex = Column(Boolean, default=False)
    dict_match = Column(MutableDict)
    negative_logic = Column(Boolean, default=False)
    delete_spaces_before_matching = Column(Boolean, default=False)

    __mapper_args__ = {"polymorphic_identity": "PayloadValidationService"}

    def job(self,
            run: "Run",
            payload: dict,
            device: Optional[Device] = None) -> dict:
        result = run.eval(run.query, **locals())
        if self.conversion_method != "none":
            result = run.convert_result(result)
        match = (run.sub(run.content_match, locals()) if run.validation_method
                 == "text" else run.sub(run.dict_match, locals()))
        return {
            "query": run.query,
            "match": match,
            "negative_logic": run.negative_logic,
            "result": result,
            "success": run.match_content(result, match),
        }
예제 #9
0
class User(AbstractBase, UserMixin):

    __tablename__ = type = "User"
    id = Column(Integer, primary_key=True)
    email = Column(SmallString)
    name = Column(SmallString)
    permissions = Column(MutableList)
    pools = relationship("Pool",
                         secondary=pool_user_table,
                         back_populates="users")
    password = Column(SmallString)

    def generate_row(self, table: str) -> List[str]:
        return [
            f"""<button type="button" class="btn btn-primary btn-xs"
            onclick="showTypePanel('user', '{self.id}')">Edit</button>""",
            f"""<button type="button" class="btn btn-primary btn-xs"
            onclick="showTypePanel('user', '{self.id}', 'duplicate')">
            Duplicate</button>""",
            f"""<button type="button" class="btn btn-danger btn-xs"
            onclick="showDeletionPanel('user', '{self.id}', '{self.name}')">
            Delete</button>""",
        ]

    @property
    def is_admin(self) -> bool:
        return "Admin" in self.permissions

    def allowed(self, permission: str) -> bool:
        return self.is_admin or permission in self.permissions
예제 #10
0
class AnsiblePlaybookService(Service):

    __tablename__ = "ansible_playbook_service"
    pretty_name = "Ansible Playbook"

    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    playbook_path = Column(SmallString)
    arguments = Column(SmallString)
    options = Column(MutableDict)
    pass_device_properties = Column(Boolean, default=False)

    exit_codes = {
        "0": "OK or no hosts matched",
        "1": "Error",
        "2": "One or more hosts failed",
        "3": "One or more hosts were unreachable",
        "4": "Parser error",
        "5": "Bad or incomplete options",
        "99": "User interrupted execution",
        "250": "Unexpected error",
    }

    __mapper_args__ = {"polymorphic_identity": "ansible_playbook_service"}

    def job(self, run, payload, device=None):
        arguments = run.sub(run.arguments, locals()).split()
        command, extra_args = ["ansible-playbook"], {}
        if run.pass_device_properties:
            extra_args = device.get_properties()
            extra_args["password"] = device.password
        if run.options:
            extra_args.update(run.sub(run.options, locals()))
        if extra_args:
            command.extend(["-e", dumps(extra_args)])
        if device:
            command.extend(["-i", device.ip_address + ","])
        command.append(run.sub(run.playbook_path, locals()))
        password = extra_args.get("password")
        if password:
            safe_command = " ".join(command + arguments).replace(
                password, "*" * 10)
        run.log("info", f"Sending Ansible playbook: {safe_command}", device)
        try:
            result = check_output(command + arguments,
                                  cwd=app.path / "playbooks")
        except Exception:
            result = "\n".join(format_exc().splitlines())
            if password:
                result = result.replace(password, "*" * 10)
            results = {"success": False, "result": result}
            exit_code = search(r"exit status (\d+)", result)
            if exit_code:
                results["exit_code"] = self.exit_codes[exit_code.group(1)]
            return results
        try:
            result = result.decode("utf-8")
        except AttributeError:
            pass
        return {"command": safe_command, "result": result}
예제 #11
0
class Changelog(Baselog):

    __tablename__ = "changelog"
    __mapper_args__ = {"polymorphic_identity": "changelog"}
    parent_type = "baselog"
    id = Column(Integer, ForeignKey("baselog.id"), primary_key=True)
    severity = Column(SmallString, default="N/A")
    user = Column(LargeString, default="")
예제 #12
0
class NapalmTracerouteService(Service):

    __tablename__ = "NapalmTracerouteService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = True
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    optional_args = Column(MutableDict)
    destination_ip = Column(SmallString)
    source_ip = Column(SmallString)
    timeout = Column(Integer, default=0)
    ttl = Column(Integer, default=0)
    vrf = Column(SmallString)

    __mapper_args__ = {"polymorphic_identity": "NapalmTracerouteService"}

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        napalm_connection = run.napalm_connection(device)
        destination = run.sub(run.destination_ip, locals())
        source = run.sub(run.source_ip, locals())
        run.log(
            "info",
            f"Running napalm traceroute from {source}"
            f"to {destination} on {device.ip_address}",
        )
        traceroute = napalm_connection.traceroute(
            destination=destination,
            source=run.source,
            vrf=run.vrf,
            ttl=run.ttl or 255,
            timeout=run.timeout or 2,
        )
        return {"success": "success" in traceroute, "result": traceroute}
예제 #13
0
파일: inventory.py 프로젝트: blaisep/eNMS
class Object(AbstractBase):

    __tablename__ = "object"
    type = Column(SmallString)
    __mapper_args__ = {
        "polymorphic_identity": "object",
        "polymorphic_on": type
    }
    id = Column(Integer, primary_key=True)
    name = Column(SmallString, unique=True)
    last_modified = Column(SmallString, info={"dont_track_changes": True})
    subtype = Column(SmallString)
    description = Column(SmallString)
    model = Column(SmallString)
    location = Column(SmallString)
    vendor = Column(SmallString)

    def update(self, **kwargs):
        super().update(**kwargs)
        if kwargs.get("dont_update_pools", False):
            return
        for pool in fetch_all("pool"):
            if pool.never_update:
                continue
            match = pool.object_match(self)
            relation, number = f"{self.class_type}s", f"{self.class_type}_number"
            if match and self not in pool.devices:
                getattr(pool, relation).append(self)
                setattr(pool, number, getattr(pool, number) + 1)
            if self in pool.devices and not match:
                getattr(pool, relation).remove(self)
                setattr(pool, number, getattr(pool, number) - 1)
예제 #14
0
class RestCallService(Service):

    __tablename__ = "rest_call_service"
    pretty_name = "REST Call"

    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    call_type = Column(SmallString)
    rest_url = Column(LargeString, default="")
    payload = Column(JSON, default={})
    params = Column(JSON, default={})
    headers = Column(JSON, default={})
    verify_ssl_certificate = Column(Boolean, default=True)
    timeout = Column(Integer, default=15)
    username = Column(SmallString)
    password = Column(SmallString)

    request_dict = {
        "GET": rest_get,
        "POST": rest_post,
        "PUT": rest_put,
        "DELETE": rest_delete,
        "PATCH": rest_patch,
    }

    __mapper_args__ = {"polymorphic_identity": "rest_call_service"}

    def job(self, run, payload, device=None):
        rest_url = run.sub(run.rest_url, locals())
        run.log("info", f"Sending REST Call to {rest_url}", device)
        kwargs = {
            p: run.sub(getattr(self, p), locals())
            for p in ("headers", "params", "timeout")
        }
        kwargs["verify"] = run.verify_ssl_certificate
        if self.username:
            kwargs["auth"] = HTTPBasicAuth(self.username, self.password)
        if run.call_type in ("POST", "PUT", "PATCH"):
            kwargs["data"] = dumps(run.sub(run.payload, locals()))
        response = self.request_dict[run.call_type](rest_url, **kwargs)
        if response.status_code not in range(200, 300):
            result = {
                "success": False,
                "response_code": response.status_code,
                "response": response.text,
            }
            if response.status_code == 401:
                result["error"] = "Wrong credentials supplied."
            return result
        return {
            "url": rest_url,
            "status_code": response.status_code,
            "headers": dict(response.headers),
            "result": response.text,
        }
예제 #15
0
class PayloadValidationService(Service):

    __tablename__ = "payload_validation_service"
    pretty_name = "Payload Validation"
    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    query = Column(SmallString)

    __mapper_args__ = {"polymorphic_identity": "payload_validation_service"}

    def job(self, run, payload, device=None):
        return {"query": run.query, "result": run.eval(run.query, **locals())}
예제 #16
0
class NapalmBackupService(Service):

    __tablename__ = "NapalmBackupService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    configuration_backup_service = True
    has_targets = True
    number_of_configuration = Column(Integer, default=10)
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    optional_args = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "NapalmBackupService"}

    def generate_yaml_file(self, path, device):
        data = {
            "last_failure": device.last_failure,
            "last_runtime": device.last_runtime,
            "last_update": device.last_update,
            "last_status": device.last_status,
        }
        with open(path / "data.yml", "w") as file:
            yaml.dump(data, file, default_flow_style=False)

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        try:
            now = datetime.now()
            path_configurations = Path.cwd() / "git" / "configurations"
            path_device_config = path_configurations / device.name
            path_device_config.mkdir(parents=True, exist_ok=True)
            napalm_connection = run.napalm_connection(device)
            run.log("info",
                    f"Fetching configuration on {device.name} (Napalm)")
            config = controller.str_dict(napalm_connection.get_config())
            device.last_status = "Success"
            device.last_runtime = (datetime.now() - now).total_seconds()
            if device.configurations:
                last_config = device.configurations[max(device.configurations)]
                if config == last_config:
                    return {"success": True, "result": "no change"}
            device.configurations[str(
                now)] = device.current_configuration = config
            with open(path_device_config / device.name, "w") as file:
                file.write(config)
            device.last_update = str(now)
            self.generate_yaml_file(path_device_config, device)
        except Exception as e:
            device.last_status = "Failure"
            device.last_failure = str(now)
            self.generate_yaml_file(path_device_config, device)
            return {"success": False, "result": str(e)}
        if len(device.configurations) > self.number_of_configuration:
            device.configurations.pop(min(device.configurations))
        return {"success": True, "result": "Get Config via Napalm"}
예제 #17
0
class Result(AbstractBase):

    __tablename__ = type = "result"
    private = True
    id = Column(Integer, primary_key=True)
    success = Column(Boolean, default=False)
    runtime = Column(SmallString)
    endtime = Column(SmallString)
    result = Column(MutableDict)
    run_id = Column(Integer, ForeignKey("run.id"))
    run = relationship("Run",
                       back_populates="results",
                       foreign_keys="Result.run_id")
    parent_runtime = Column(SmallString)
    device_id = Column(Integer, ForeignKey("device.id"))
    device = relationship("Device",
                          back_populates="results",
                          foreign_keys="Result.device_id")
    device_name = association_proxy("device", "name")
    service_id = Column(Integer, ForeignKey("service.id"))
    service = relationship("Service", foreign_keys="Result.service_id")
    service_name = association_proxy("service", "name")
    workflow_id = Column(Integer, ForeignKey("workflow.id"))
    workflow = relationship("Workflow", foreign_keys="Result.workflow_id")
    workflow_name = association_proxy("workflow", "name")

    def __repr__(self):
        return f"{self.service_name} on {self.device_name}"

    def __getitem__(self, key):
        return self.result[key]

    def __init__(self, **kwargs):
        self.success = kwargs["result"]["success"]
        self.runtime = kwargs["result"]["runtime"]
        self.endtime = kwargs["result"]["endtime"]
        super().__init__(**kwargs)
        self.parent_runtime = self.run.parent_runtime

    @property
    def table_success(self):
        btn = "success" if self.success else "danger"
        label = "Success" if self.success else "Failure"
        return (f'<button type="button" class="btn btn-{btn}"'
                f'style="width:100%">{label}</button>')

    def generate_row(self, table):
        return [
            f"""<button type="button" class="btn btn-info btn-sm"
            onclick="showResult('{self.id}')">Results</button>""",
            f"""<input type="radio" name="v1" value="{self.id}"/>""",
            f"""<input type="radio" name="v2" value="{self.id}"/>""",
        ]
예제 #18
0
class NapalmGettersService(Service):

    __tablename__ = "NapalmGettersService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = True
    validation_method = Column(SmallString, default="dict_included")
    dict_match = Column(MutableDict)
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    getters = Column(MutableList)
    negative_logic = Column(Boolean, default=False)
    optional_args = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "NapalmGettersService"}

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        napalm_connection, result = run.napalm_connection(device), {}
        run.log(
            "info",
            f"Fetching NAPALM getters ({', '.join(run.getters)}) on {device.name}",
        )
        for getter in run.getters:
            try:
                result[getter] = getattr(napalm_connection, getter)()
            except Exception as e:
                result[getter] = f"{getter} failed because of {e}"
        match = (run.sub(run.content_match, locals()) if run.validation_method
                 == "text" else run.sub(run.dict_match, locals()))
        return {
            "match": match,
            "negative_logic": run.negative_logic,
            "result": result,
            "success": run.match_content(result, match),
        }
예제 #19
0
class UpdateInventoryService(Service):

    __tablename__ = "UpdateInventoryService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = True
    update_dictionary = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "UpdateInventoryService"}

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        for property, value in run.update_dictionary.items():
            setattr(device, property, value)
        return {"success": True, "result": "properties updated"}
예제 #20
0
class UpdateInventoryService(Service):

    __tablename__ = "update_inventory_service"
    pretty_name = "Update Inventory"

    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    update_dictionary = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "update_inventory_service"}

    def job(self, run, payload, device):
        for property, value in run.update_dictionary.items():
            setattr(device, property, value)
        return {"success": True, "result": "properties updated"}
예제 #21
0
class GenericFileTransferService(Service):

    __tablename__ = "GenericFileTransferService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = True
    direction = Column(SmallString)
    protocol = Column(SmallString)
    source_file = Column(SmallString)
    destination_file = Column(SmallString)
    missing_host_key_policy = Column(Boolean, default=False)
    load_known_host_keys = Column(Boolean, default=False)
    look_for_keys = Column(Boolean, default=False)
    source_file_includes_globbing = Column(Boolean, default=False)

    __mapper_args__ = {"polymorphic_identity": "GenericFileTransferService"}

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        ssh_client = SSHClient()
        if run.missing_host_key_policy:
            ssh_client.set_missing_host_key_policy(AutoAddPolicy())
        if run.load_known_host_keys:
            ssh_client.load_system_host_keys()
        source = run.sub(run.source_file, locals())
        destination = run.sub(run.destination_file, locals())
        run.log("info", "Transferring file {source} on {device.name}")
        success, result = True, f"File {source} transferred successfully"
        ssh_client.connect(
            device.ip_address,
            username=device.username,
            password=device.password,
            look_for_keys=run.look_for_keys,
        )

        if run.source_file_includes_globbing:
            glob_source_file_list = glob(source, recursive=False)
            if not glob_source_file_list:
                success = False
                result = f"Glob pattern {source} returned no matching files"
            else:
                pairs = []
                for glob_source in glob_source_file_list:
                    path, filename = split(glob_source)
                    if destination[-1] != "/":
                        destination = destination + "/"
                    glob_destination = destination + filename
                    pairs.append((glob_source, glob_destination))
                info(f"Preparing to transfer glob file {glob_source}")
                run.transfer_file(ssh_client, pairs)
        else:
            run.transfer_file(ssh_client, [(source, destination)])
        ssh_client.close()
        return {"success": success, "result": result}
예제 #22
0
파일: unix_command.py 프로젝트: swamim/eNMS
class UnixCommandService(Service):

    __tablename__ = "unix_command_service"
    pretty_name = "Unix Command"
    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    command = Column(SmallString)

    __mapper_args__ = {"polymorphic_identity": "unix_command_service"}

    def job(self, run, payload, device):
        command = run.sub(run.command, locals())
        run.log("info", f"Running UNIX command: {command}", device)
        return {
            "command": command,
            "result": check_output(command.split()).decode()
        }
예제 #23
0
파일: inventory.py 프로젝트: cantops/eNMS
class Object(AbstractBase):

    __tablename__ = "Object"
    type = Column(SmallString)
    __mapper_args__ = {"polymorphic_identity": "Object", "polymorphic_on": type}
    id = Column(Integer, primary_key=True)
    hidden = Column(Boolean, default=False)
    name = Column(SmallString, unique=True)
    subtype = Column(SmallString)
    description = Column(SmallString)
    model = Column(SmallString)
    location = Column(SmallString)
    vendor = Column(SmallString)
예제 #24
0
class NapalmRollbackService(Service):

    __tablename__ = "NapalmRollbackService"

    id = Column(Integer, ForeignKey("Service.id"), primary_key=True)
    has_targets = True
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    optional_args = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "NapalmRollbackService"}

    def job(self, run: "Run", payload: dict, device: Device) -> dict:
        napalm_connection = run.napalm_connection(device)
        run.log("info", f"Configuration rollback on {device.name} (Napalm)")
        napalm_connection.rollback()
        return {"success": True, "result": "Rollback successful"}
예제 #25
0
class WorkflowEdge(AbstractBase):

    __tablename__ = type = "workflow_edge"
    id = Column(Integer, primary_key=True)
    name = Column(SmallString)
    label = Column(SmallString)
    subtype = Column(SmallString)
    source_id = Column(Integer, ForeignKey("service.id"))
    source = relationship(
        "Service",
        primaryjoin="Service.id == WorkflowEdge.source_id",
        backref=backref("destinations", cascade="all, delete-orphan"),
        foreign_keys="WorkflowEdge.source_id",
    )
    destination_id = Column(Integer, ForeignKey("service.id"))
    destination = relationship(
        "Service",
        primaryjoin="Service.id == WorkflowEdge.destination_id",
        backref=backref("sources", cascade="all, delete-orphan"),
        foreign_keys="WorkflowEdge.destination_id",
    )
    workflow_id = Column(Integer, ForeignKey("workflow.id"))
    workflow = relationship("Workflow",
                            back_populates="edges",
                            foreign_keys="WorkflowEdge.workflow_id")

    def __init__(self, **kwargs):
        self.label = kwargs["subtype"]
        super().__init__(**kwargs)
예제 #26
0
class PingService(Service):

    __tablename__ = "ping_service"
    pretty_name = "ICMP / TCP Ping"
    id = Column(Integer, ForeignKey("service.id"), primary_key=True)
    protocol = Column(SmallString)
    ports = Column(SmallString)
    count = Column(Integer, default=5)
    timeout = Column(Integer, default=2)
    ttl = Column(Integer, default=60)
    packet_size = Column(Integer, default=56)

    __mapper_args__ = {"polymorphic_identity": "ping_service"}

    def job(self, run, payload, device):
        if run.protocol == "ICMP":
            command = ["ping"]
            for x, property in (
                ("c", "count"),
                ("W", "timeout"),
                ("t", "ttl"),
                ("s", "packet_size"),
            ):
                value = getattr(self, property)
                if value:
                    command.extend(f"-{x} {value}".split())
            command.append(device.ip_address)
            run.log("info", f"Running PING ({command})", device)
            try:
                output = check_output(command).decode().strip().splitlines()
            except CalledProcessError:
                return {"success": False, "error": "Device not pingable"}
            total = output[-2].split(",")[3].split()[1]
            loss = output[-2].split(",")[2].split()[0]
            timing = output[-1].split()[3].split("/")
            return {
                "success": True,
                "result": {
                    "probes_sent": run.count,
                    "packet_loss": loss,
                    "rtt_min": timing[0],
                    "rtt_max": timing[2],
                    "rtt_avg": timing[1],
                    "rtt_stddev": timing[3],
                    "total rtt": total,
                },
            }
        else:
            result = {}
            for port in map(int, run.ports.split(",")):
                s = socket()
                s.settimeout(run.timeout)
                try:
                    connection = not s.connect_ex((device.ip_address, port))
                except (gaierror, timeout, error):
                    connection = False
                finally:
                    s.close()
                result[port] = connection
            return {"success": all(result.values()), "result": result}
예제 #27
0
class NapalmBackupService(ConnectionService):

    __tablename__ = "napalm_backup_service"
    pretty_name = "NAPALM Operational Data Backup"
    parent_type = "connection_service"
    id = Column(Integer, ForeignKey("connection_service.id"), primary_key=True)
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    timeout = Column(Integer, default=60)
    optional_args = Column(MutableDict)
    configuration_getters = Column(MutableList)
    operational_data_getters = Column(MutableList)
    replacements = Column(MutableList)

    __mapper_args__ = {"polymorphic_identity": "napalm_backup_service"}

    def job(self, run, payload, device):
        path = Path.cwd() / "network_data" / device.name
        path.mkdir(parents=True, exist_ok=True)
        try:
            device.last_runtime = datetime.now()
            napalm_connection = run.napalm_connection(device)
            run.log("info", "Fetching Operational Data", device)
            for data_type in ("configuration_getters",
                              "operational_data_getters"):
                result = {}
                for getter in getattr(run, data_type):
                    try:
                        output = app.str_dict(
                            getattr(napalm_connection, getter)())
                        for r in self.replacements:
                            output = sub(
                                r["pattern"],
                                r["replace_with"],
                                output,
                                flags=M,
                            )
                        result[getter] = output
                    except Exception as e:
                        result[getter] = f"{getter} failed because of {e}"
                result = app.str_dict(result)
                setattr(device, data_type, result)
                with open(path / data_type, "w") as file:
                    file.write(result)
            device.last_status = "Success"
            device.last_duration = (
                f"{(datetime.now() - device.last_runtime).total_seconds()}s")
            device.last_update = str(device.last_runtime)
            run.generate_yaml_file(path, device)
        except Exception as e:
            device.last_status = "Failure"
            device.last_failure = str(device.last_runtime)
            run.generate_yaml_file(path, device)
            return {"success": False, "result": str(e)}
        return {"success": True}
예제 #28
0
class User(AbstractBase, UserMixin):

    __tablename__ = type = "user"
    id = Column(Integer, primary_key=True)
    name = Column(SmallString, unique=True)
    email = Column(SmallString)
    permissions = Column(MutableList)
    password = Column(SmallString)
    group = Column(SmallString)
    small_menu = Column(Boolean,
                        default=False,
                        info={"dont_track_changes": True})

    def update(self, **kwargs):
        if app.settings["security"][
                "hash_user_passwords"] and "password" in kwargs:
            kwargs["password"] = argon2.hash(kwargs["password"])
        super().update(**kwargs)

    @property
    def is_admin(self):
        return "Admin" in self.permissions

    def allowed(self, permission):
        return self.is_admin or permission in self.permissions
예제 #29
0
class NapalmRollbackService(ConnectionService):

    __tablename__ = "napalm_rollback_service"
    pretty_name = "NAPALM Rollback"
    parent_type = "connection_service"
    id = Column(Integer, ForeignKey("connection_service.id"), primary_key=True)
    driver = Column(SmallString)
    use_device_driver = Column(Boolean, default=True)
    timeout = Column(Integer, default=60)
    optional_args = Column(MutableDict)

    __mapper_args__ = {"polymorphic_identity": "napalm_rollback_service"}

    def job(self, run, payload, device):
        napalm_connection = run.napalm_connection(device)
        run.log("info", "Configuration Rollback with NAPALM", device)
        napalm_connection.rollback()
        return {"success": True, "result": "Rollback successful"}
예제 #30
0
class Baselog(AbstractBase):

    __tablename__ = "baselog"
    type = Column(SmallString)
    __mapper_args__ = {
        "polymorphic_identity": "baselog",
        "polymorphic_on": type
    }
    id = Column(Integer, primary_key=True)
    time = Column(SmallString)
    content = Column(LargeString, default="")

    def update(self, **kwargs):
        kwargs["time"] = str(datetime.now())
        super().update(**kwargs)

    def generate_row(self, table):
        return []